How to observe all programmatical changes of textarea content? - javascript

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?

Related

<textarea>: ctrl + z breaks after changing the value content through javascript

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.

How do I locate the function that is stealing DOM focus?

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.

How to manipulate the DOM of a React webapp (with Chrome DevTools)?

I'm using Chrome DevTools to inspect a React webapp. The app has an upload button with a hidden input field. I'm attempting to make the input field visible (and iteractable) in two different ways:
1) In the Elements tab, I find the input HTML tag and click on it. In the Styles panel on the right, I can see that the element has a CSS style applied to it, which sets "display: none!important;". When I uncheck this line in the Styles panel, the style gets disabled, and the input element shows up on the page (and I can click on it to open the file chooser). So far, all this makes sense to me.
2) In the Sources tab, I create a new snippet and I programmatically change the display style of the same element:
form = ...
input = form.getElementsByTagName('input')[0];
console.log(input);
computedStyle = getComputedStyle(input);
console.log(computedStyle['display']);
input.style.setProperty("display", "inline", "important")
console.log(computedStyle['display']);
When I run this, the console output makes sense: I confirm that I'm finding the correct element, the first time I print the display it's "none", and the second time it's "inline". However, nothing changes on the page, I don't see the input as in the other approach.
I'm still wrapping my head around React, and I suspect this is related to the fact that React can and will decide to recreate the actual DOM elements very often (so perhaps the input I'm changing is not the input I'm seeing?). But I'm not super clear, and either way, I was expecting these two approaches to have the same results. What happening here? And how can I programmatically change the hidden input to be not hidden?
You manipulate dom (in react) by changing props and state. There is a browser extension which let's you do that in browser. For chrome is here. There is extension for firefox as well.
I am guessing that your snippet change did not induce a React refresh, thus the shadow DOM was modified but React did not see a reason to update the DOM. Perhaps you could add a forceUpdate() in your snippet?

Firefox Document Inspector, Firebug & Webkit Developer Tools (Chrome/Safari) not updating HTML to reflect checked status of checkboxes loaded via AJAX

This one is absolutely baffling to me as a veteran UX developer.
I have some content being loaded via an AJAX request initiated when a user checks a box at the beginning of an unordered list. When the box is checked, the list is populated with list items each containing their own check boxes, which default to state "checked".
From this point forward, if I right-click the checkboxes and "Inspect Element", the results are pretty strange. Upon checking or unchecking the top-most box, the results are as expected: the box is checked or unchecked, and in the inspector, this is reflected within the HTML. Therefore, when checked, a new attribute is created (checked="checked") and the state reflects what is seen in the HTML within the page itself.
For those check boxes which were loaded via AJAX, the results are NOT as straightforward (or correct). It IS possible to check and uncheck the boxes in the list, and when submitting the form, the results ARE accurate. When calculated on the fly using jQuery or regular JavaScript, the values of these checkboxes are reported accurately.
However, within the Chrome Developer Tools, or the Firefox Document Inspector, or in Firebug, the HTML for these recently-loaded boxes is not accurate. They DO load with the same state as expected (i.e. they all load with their state set to on; e.g. checked="checked" in all cases). Nevertheless, when changing the state via the browser window, the HTML in the inspector is NOT updating. The reverse is also true: when updating the HTML inside the Inspector window, the browser window is not updating.
While I'm not sure if this is relevant to the problem, I'll include it just in case: the list in question is also being contained within a Bootstrap accordion (which resides, by default, in the "collapsed" state, but expands as the content is loaded via AJAX to provide a fluid UX experience).
I have tested this so far on Windows and Mac OSX Mountain Lion, using Google Chrome, Mozilla Firefox and Apple Safari. The results are consistent in all cases. I cannot figure out why this would happen in this manner. Any feedback is appreciated.
One last note: because of the AJAX request involved in this process, and because the server that provides the requisite response resides behind a firewall (as this is a subscription-based site that I'm working on), I'm not sure that I can provide an example of this via JS Fiddle. If, however, someone has input on how that might work, I'm open to the suggestion and would be happy to provide an example of this frustrating bug.
UPDATE:
I noticed when looking at the jQuery API documentation at http://api.jquery.com/prop/ that the W3C specification for checkboxes indicates that "the checked attribute value does not change with the state of the checkbox, while the checked property does". So, this might be a partial explanation of what's going on here. It doesn't however, explain why changing the attribute on non-AJAX-loaded content causes the page to reflect the changed state, and vice-versa.
After a careful review of the W3C standards surrounding this issue, it seems clear that this is a browser bug (albeit not a serious one). The discrepancy exists because the non-AJAX method being used was presumably chosen to be more "friendly" and maintain consistency between the code and the presentation, whereas the AJAX method is more respectful of the true W3C specification. Such is the result of any collaborative development effort.
For those who are hoping to avoid any such inconsistencies, I recommend you use the following syntax:
$('#some-id').prop('checked', true); // Preferred method for checking a box or radio button
... instead of:
/* DON'T USE THIS CODE!
$('#some-id').attr('checked', 'checked'); // Deprecated method for checking a box or radio button
IF YOU DO, IT'S ON YOU. */

Detect text selection changes in UIWebView text selection

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];
}

Categories

Resources