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

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?

Related

JavaScript DOM changes and can longer interact with page

Iā€™m making a chrome extension and it's working. In this extension I parse data from a dynamic page, and then insert it into a new div which I then hide and unhide with the CSS visibility rule (via JavaScript DOM)
Problem is, after I hide the new div when done looking at it, the underlying page is no longer interactive. Can't click anything. Can't type into the interactive field to make updates etc.
Any ideas, anyone ever have an issue similar to this that they had to solve?!
The visibility attribute makes the element invisible, but it's still there and it takes up space. That is probably why it is blocking you from interacting with the content behind it.
Try instead using display: none;.

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.

Find out what file/line in JS is changing the text of an element

I'm working on a pretty large (a lot of files) and poorly organized web project for a client. Somewhere in the mess of things there is some JavaScript that is truncating H3 tags and adding ellipsis to them. I would like to find that line of script and remove it. I just need to find out where it is...
Manually searching through all of the files on the site could take forever (since, due to the poor code of the site, the JS that produces the dom manipulation could exist in a PHP file somewhere, or in a JS file, or...who knows).
I know that with Chrome, for example, you can do DOM manipulation breakpoints. The problem is that from what I can tell the Subtree modifications and Attributes modifications breakpoints don't actually break on simple text modifications.
Are there any options in any browser to listen on the DOM element and see where the script is that is modifying it?
Add debugger calls in each one of your js files to force the execution to pause on each file. If the h3 changes after jumping a specific stop point, chances are the guilty script is in that page (or the function is being called on that page).
To check whether the change happens on the server or client side you should first check the network reponses. If the text is truncated inside the server response, then the change already happens on the server side. If not, it happens on the client side. When it happens on the client side, it may be done either through JavaScript or through CSS.
Firebug
Check server response
Switch to the Net panel, focus the search field, ensure that the Response Bodies option is checked, then enter the heading (untruncated). If it is found, then the change happens on the client side.
Check CSS
In case the change happens on the client side, it may be part of some CSS.
E.g. there is a CSS property called text-overflow, which allows to add an ellipsis to the text.
To check that inspect the related element and search within the Styles or Computed side panel whether the text-overflow property is set for the element.
The ellipsis may also be achieved via some trick setting the content property to an ellipsis.
If you cannot find any CSS like that, the change probably happens via JavaScript.
Check JavaScript
you can stop the script execution at the line that changes it by right-clicking the element you want to inspect within the HTML panel and choose Break On Child Addition or Removal.
Once the text is changed, the script execution stops at the related line.
Example
<p>foo</p>
<button onclick="changeText()">Change text</button>
<script>
function changeText() {
var p = document.querySelector("p");
p.textContent = "bar";
}
</script>
Set the Break On Child Addition or Removal for the <p>foo</p> element to try it out.
Note: Unfortunately Firebug doesn't always jump to the right script or position, but at least it does stop when the change happens within JavaScript.
Chrome DevTools
Check server response
Switch to the Network panel and search for the untruncated heading in the response bodies of the network requests. (As far as I know, there is no way to search automatically within the response bodies.) If it is found, then the change happens on the client side.
Check CSS
As described above, the change may also be part of CSS.
To check that inspect the related element and search within the Styles or Computed side panel whether the text-overflow or the content property is set for the element.
If you cannot find any CSS like that, the change probably happens via JavaScript.
Check JavaScript
Within the Chrome DevTools it works similar like in Firebug. So, in case the change happens on the client side, right-click the element within the Elements panel and choose Break on > Subtree modifications from the context menu.
Once the text is changed, the script execution stops at the related line.

Chrome Developer Tools - Dynamically Created Element

Is there a way to find out which JS script created a dynamic element in Chrome's Developer Tools? If I do 'view page source' on the page, the element isn't there. I can see the element though in Chrome's Developer Tools. Is there a way to find out specifically which JavaScript file and what line in my JavaScript file created the element?
To help clarify: I know which element is created...what I don't know is which .js file created it and specifically what line in that .js file
Updated answer:
Below you've said:
I know which element it is...what I don't know is which .js file created it and specifically what line in that .js file
That's not how the question originally read. :-)
If you know which element it is, two options for you:
You can use Dev Tools to trigger a breakpoint when its parent element is modified:
Load the page
Open Dev Tools
Go to the Elements panel
Navigate to the parent element that the target element will eventually be added to
Right-click the parent element and click Break on... > Subtree Modifications
Now, Chrome will trigger a breakpoint when the parent element's subtree is modified, and so you can see what JavaScript code is adding the element.
Unfortuantely, it won't fire that breakpoint if the element is added during the main loading of the page (e.g., during the parsing of the HTML, by script that runs immediately rather than waiting).
If there's any text in the element that seems specific to it (content, id, class, some attribute, whatever), once the page is loaded you can use Chrome's powerful search feature to try to find that text:
Load the page
Open Dev Tools
Go to the Sources tab
Click Ctrl+Shift+F, which is "find in files" ā€” it looks in all of the files associated with the page, not just the "current" file
Type the text that you think might help you identify the code adding the element
Press Enter, all matches will be shown below
You can even use regular expressions.
Original answer:
No, there's no simple way to differentiate an element created via JavaScript after page load from ones created by the initial HTML parsing.
Or at least, there isn't without adding JavaScript to the page that runs before any other JavaScript on the page runs, which I'm guessing is a requirement.
But if you can add JavaScript to the page before any other JavaScript runs, it's actually really easy to do:
Array.prototype.forEach.call(document.querySelectorAll("*"), function(element) {
element.setAttribute("data-original", "");
});
That marks every single element on the page with an attribute that tells you it was there when that code ran. You can see those attributes in the Elements panel of the Dev Tools. And so, if you see an element that doesn't have that attribute, you know it was added later.
document.querySelectorAll("*") is a big hammer you probably wouldn't want to use in production code, but for temporary use when debugging/developing, it's fine.
And if you want to know about the elements that have been created by other code later, you can do this in the console:
Array.prototype.forEach.call(document.querySelectorAll("*"), function(element) {
if (element.getAttribute("data-original") === null) {
console.log(element);
}
});
That'll output every element that wasn't on the page when you ran the earlier code, and Chrome's console is really cool ā€” you can right-click the element display in the console and choose "Reveal in Elements panel" to see exactly where that element is.
You can use chrome-devtools-protocol's experimental feature.
Check this, https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-getNodeStackTraces
First, send 'DOM.setNodeStackTracesEnabled' to chrome dev protocl.
Second, use 'DOM.getNodeStackTraces' message.
So, you can get call stack information from dynamic creation element.
I wrote my own program using these functions.
Image: https://imgur.com/a/TtL5PtQ
Here is my project: https://github.com/rollrat/custom-crawler

How to find out what event is firing on what element

Is there a tool (or something in firebug) that will tell me what events just fired and more importantly on what elements they were bound to?
I have a number of javascript "includes", some minified, some not. I am experiencing some odd behaviour that I want to turn off, but I cannot find what is causing it.
I have a form showing in a "popup" and when I try to click on one of the input boxes, the "popup" closes, so some event bind somewhere is causing this.
The problem is, I don't know what element has this spurious event bound to it. The problem also occurs if I click anywhere inside the popup (and on the background mask that is covering the rest of the page, but that's acceptable)
I am using firefox, so anything I can type in the console is also an option. The eventys in the multiple javascript files are done in various ways, some through jquery, some using inline attributes (eg. onclick="..."), some using just javascript.
I certainly don't want to go and add some line of code to every possible event in every javascript file.
I have spent over an hour trying to hunt down this dom element and have already eliminated the obvious ones like the divs containing the popup and the body tag.
DOM modifications can be tracked down using the Break On Mutate option within Firebug. It can be activated by clicking the related button ( ) within the HTML panel. Note that the Script panel has to be enabled for this to work.
There are also several other Break On ... features, which may help you finding the right position within the code for a specific event.
Furthermore Firebug 2.0 introduced an Events side panel, which displays all events bound to the element selected within the HTML panel. If libraries like jQuery are used, it will even allow you to investigate the user-defined function wrapped by the library function in case you enable the option Show Wrapped Listeners as described in the answer to a related question.

Categories

Resources