There are lots of guides on how to get the selected text in UIWebView but I can't seem to find any on how to detect the change in selection. I understand that I could simply detect taps elsewhere and always get the latest selection, but I'd like to create a standalone view that wraps all this functionality.
I currently have a view that holds the UIWebView instance and handles the parsing and passing the content to the web view. As far as I know, detecting taps would require a custom window implementation (instructed here). I'd like to follow separation of concerns and avoid any custom window implementations if possible.
Any ideas how could I achieve this within a view? I already tried javascript but I guess I was
not that competent with it.
You can use document.addEventListener("selectionchange") which fires whenever the selection changes, and forward those changes to Obj-C through a bridge.
Bridges:
WebViewJavascriptBridge
JavaScriptCore
Example Code:
document.addEventListener("selectionchange", function(){
bridge.send("selectionchange"); // WebViewJavaScriptBridge
bridge.selectionChanged(); // JavaScriptCore
}, false);
If I'm not totally mistaken, there's no way to detect if the selection range changes when using UIWebView and javascript combination. My solution was to poll the selection range instead of notifying of its changes. Currently I have no need for real-time updates, so it will be sufficient only to know if there's a selection or not. The text selection is retrieved on demand and for the selection change, I use the UITapGestureRecognizer.
For the clearing of the selection I had to use a small delay. The selection is not cleared instantly after the tap.
- (void)tap:(id)sender
{
[self updateSelection];
// A simple hack to detect when selection is cleared.
[self performSelector:#selector(updateSelection) withObject:self afterDelay:0.5];
}
Related
I am making an HTML textarea that accepts tab key input using JavaScript.
When I searched for a solution on the web, I found this answer, but after some fiddling, I found out that ctrl+z stops working after I hit tab key.
Doing some more experiments revealed that changing the value attribute was likely the culprit of this problem. Here is a small scale code example that you can hopefully reproduce this behavior yourself.
https://codepen.io/MartianLord/pen/gORKPGp?editors=1010
I managed to find a workaround using document.execCommand to simulate the user input, but this method is deprecated as you can see here, so I am looking for a more up to date solution.
To support ctrl+z while using tab in <textarea>, you need to implement undo, redo functions to connect with <textarea>. When the <textarea> changes, record the changes in the history, and revert when ctrl+z key input occurs.
UndoRedojs is a library for this task.
I think there will be a lot of work to be done, such as setting the selection position, in order to fully implement it. I recommend using a text editor that has already been created.
I'm trying to debug the integration between my app and Stripe's Elements component library. Everything works fine in sandbox mode, but we ran into a problem on production in the 3D Secure authentication process. This involves loading an iframe, into our app, that contains a form from the credit card's issuer (usually via a technology partner, like Arcot).
The form loads correctly and its buttons are working as expected, but the element (for a SMS one time code) is not behaving. Every time I click on the input, something is immediately pushing the focus back to the element of the iframe. This makes it impossible to type anything in, since by the time I touch a key, the input is not in focus. For reference, it is possible to change the input's value using document.getElementById('enterPIN').value = '123456';
I'm not sure if my app is triggering focus() calls (I don't think so) or if it is some part of the iframe code or even Stripe's. Is there a good way to monitor DOM events and do a stack trace for the trigger of each one?
I tried two tactics. Neither gave an obvious answer, but they did point my search in the right direction.
I opened the Event Listeners panel (in the Elements tab of my browser's developer tools) and removed everything I could find, but it seems that this doesn't actually change the behavior of the page- focus kept being stolen away. Luckily, I also noticed some listeners that were defined by the Material UI library.
I used monitorEvents() to get a few more details, but the src & target values were not much help and event.relatedTarget was always null.
In the end, I found this discussion and realized that my MUI Dialog component was stealing focus whenever I clicked on the iframe triggered by its content. This was easily fixed by adding the disableEnforceFocus attribute.
I'm looking for a way to track the text selection on a web page. I need some code to be executed whenever there is a change in selection. I have successfully done this on all major desktop browsers, but the same does not seem to be working on Firefox for Android.
I tried three approaches (none of them worked!):
Tried catching the "mouseup" event and checking if there is a
non-empty text selection. Problem is "mouseup" isn't getting
triggered if a selection was made during the mousedown-move-up
sequence!
Tried doing the same with the "touchend" event - Same result.
Tried catching the "selectionchange" event. I saw that it isn’t
triggered when the selection changes as it needs the config key
"dom.select_events.enabled" to be set. This is false by default and I obviously can't ask my visitors to tweak browser settings :-)
Also, as expected, the first two events don't get triggered if the selection is extended or reduced by dragging the selection start/end markers.
The only solution I can think of now is a periodic poller (using setInterval) that checks if there is a text selection. This is definitely unclean and anti-performance.
Any alternatives and/or advice will be very helpful.
1) Native Text Selection Events
Currently, polling seems to be the only work-around.
However, the selectionchange event is currently experimentally implemented in Firefox for Android Nightly. It can be enabled by setting the dom.select_events.enabled flag to true (defaults to false).
In Nightly builds, this flag already defaults to true, so there is a chance you can use it normally in a couple of months.
2) Find events that work
(UNTESTED!!)
Even if onselectstart cannot be used productively in Firefox for Android yet, the only viable easy solution is polling.
To improve performance and reduce costs, polling can be started on the window blur event. Because whenever the user is making a selection, the focus should be set off the viewport (untested though).
window.addEventListener('blur', function(){
// start polling for text selections
});
When the focus is given back, polling can be stopped.
window.addEventListener('focus', function(){
// stop polling
});
To check if the browser actually supports text selection events, you can use this function:
var browserSupportsTextSelectionEvents = function(){
return !!('onselectstart' in document.body);
}
3) Hacking
A third idea is to disable text selection for mobile Firefox users via CSS (-moz-user-select: none), implement a custom text selection function based on touch start and end positions and pushing the native selection range back to the browser via HTMLElement.setSelectionRange().
I'm developing a chrome extension for Blogger.com, and I need to perform some actions when textarea with post is changed programmaticaly by Blogger modules. For example after image insert. Some changes made by raw XmlHttpRequest, other made in some mystical way that I don't understand.
jQuery on change, on input etc don't work, because changes aren't made by user. MutationObserver doesn't catch any mutations related to textarea, because they aren't affect DOM. Periodically check textarea value looks like brute workaround for me. Right now, I'm observing moment when specific modal windows, for example image upload windows is closed, and then check whether textarea value was changed. But this mutation can easily occur in other circumstances too.
Is there any more appropriate technique?
I want to build a lightweight online text editor like google doc, but quite quite lighter than that.
What I mean is, I only want to realize the following three functions:
input/delete characters
create/delete a new line
indent
But I'm not quite sure how to build it.
Here is my idea:
Treat every line as a single div.
Monitor the keyboard event, when user hit enter, create a new div
According to my method, I need to set the div's contentEditable=true
However, after that, whenever I hit enter, a newline is created inside the div.
So, how to stop that? (can it only be solved by using javascript?)
Or, is there any other way to achieve my goal?
Just use event.preventDefault(); like so:
$(document).bind("keydown keypress", function(event) {
if ( event.which == 13 ) {
event.preventDefault();
// Your code here
}
});
I think you mean text editors like tinymce or CKEditor. You can make them as lighter as you want.
Be careful about letting people do this on your webpage -- if you're not properly escaping/monitoring input, they can wreak havoc on the page itself preventing them from being able to save things, etc.
Most of these editors implement their editor as an embedded iframe. Since it's being served from the same port, protocol and host, you have full script access to it.
So you make a tag in the iframe editable, and leave all the controls outside the iframe. When they click on a control, you make that happen in the iframe.
When they save, you just grab the contents of the iframe's div.
I would read the keyboard events and just modify the DOM to reflect those keyboard changes. The biggest problem you will have is to position the 'caret' (vertical line').View this SO question to do this correctly -> calculate-text-width-with-javascript
Another alternativ, and one that I prefer, is to use the tag. Its a more lightweight solution and comes with text measurement built-in. Google Closure library has a lot of support for this built in -> Closure Library, and example with text selection -> Canvas Text