I'm accessing a webpage via headless chrome that should be running a script to append a few elements to the DOM. However, I can't figure out a way to get ahold of these elements
Trying to access them via DOM.querySelector within my Page.loadEventFired callback gives me nothing. I thought maybe this was because the script to append them hadn't finished executing by the time the querySelector was run, so I tried attaching a handler to the DOM.childNodeInserted event (both in the context of Page.loadEventFired and before navigating to the page) as follows:
DOM.childNodeInserted((params) => {
console.log("we have a child!!");
});
But the event never fires. My next approach was the DOM.setChildNodes event combined with DOM.requestChildNodes on the container elements for the inserted elements. I execute DOM.requestChildNodes within Page.loadEventFired. This event fires successfully, but reports no child nodes.
At this point, I'm confused as to whether the script is even running. Can anyone offer some advice?
Related
According to the official docs window.onbeforeprint allow[s] pages to change their content before printing starts (perhaps to remove a banner, for example).
However, this doesn’t work in my cases, since window.onbeforeprint is fired asynchronously — like any event in JS. I do change the DOM content in my event handler, but the changes are not in the print preview. Only, when I cancel the first print attempt and hit Cmd+P again, the changes (of the first event) inside the DOM are part of the print preview.
I’m not talking about long-running processes here like fetching something from the net. Just simple copy/paste inside the DOM.
So I wonder if I’m doing anything wrong here, or if window.onbeforeprint is pretty much pointless for changing content prior to printing.
After some additional troubleshooting, I can confirm, that window.onbeforeprint actually allows DOM manipulations to happen before the print view is generated. The problem in my case was the framework: Vue.js. The Vue component didn’t update in time. If I manipulate the DOM directly inside the event handler, it works.
I am injecting a Javascript-File via a Chrome-Extension on a webpage that uses SAPUI5.
I want to get the model in the binding context of some UI5-Input elements and in order to do so, I need to get to the inputs via document.getElementsByTagName. (or is there another way?)
This only works if they are already rendered. Unfortunately the ready or load events fire too early, when not everything is rendered yet.
Is there a way for me to know when the inputs have rendered?
Edit: I do not have access to the source code of the page, everything I do has to be in the injected script.
To make sure everything is renedered before firing your events, sapui5 has the function onAfterRendering.
All logic written in that function will only be executed after the control is rendered.
When a rerender of the control is rendered, the onAfterRendering is triggered again.
In the end I did it like this:
I already had event listeners attached to click and key events. Every time the handler is called, I check if document.getElementsByTagName('input') returns the inputs I need.
If yes e. g. the rendering of the inputs is complete, I set a boolean that the page is loaded completely and execute my code.
So I have a dynamically generated but sandboxed iframe, a playground, that will execute and render user written code i.e. JavaScript. The user is able to write anything in HTML and attach events to the nodes they write using JS. Think Codepen.
On the parent, I have some interactions that determines and juggles the iframe around including removing it from the DOM completely. In this moment of removal there is a need to first detached events from the content of iframe… or do whatever is recommended to avoid memory leakage.
Any suggestions/tips on this?
You do not need to detach event listeners manually before removing your iframe.
When your iframe is removed, make sure that you null out any references pointing to it. Then, the contained document and all nodes within it (and event listeners attached to these nodes) will be automatically queued for garbage collection.
I have two questions on placing JS inside HTML. I can't find where these two points were answered here.
Questions are basically
Let's say I put Javascript in the head, and say the script tries to get some HTML element by ID, and register a click handler for it. Now since, the HTML has not been loaded yet (because the script is called in head), will this work?
On the other hand, if register a function in head which gets called when DOM is loaded, and inside that function I put code which registers handler for click on some button, then as I understand user has chance to click button but the handler will not be called because the whole DOM was not loaded yet (and that is where the button click handler is registered). Am I correct?
What is the solution and best way to put Javascript in HTML considering above two points?
Let's say I put Javascript in the head, and say the script tries to
get some HTML element by ID, and register a click handler for it. Now
since, the HTML has not been loaded yet (because the script is called
in head), will this work?
No, this won't work. Whenever <script> tag is seen, javascript is executed right away before going further with DOM building. (if javascript is external, it will wait to fetch it over network and execute it) It will act upon the current snapshot of DOM if the javascript is using DOM APIs like getElementById. When script tries to get the element by id, it tries to get it from DOM, (All DOM APIs acts on DOM) which is being built right now. As the element is not yet added to DOM (we are processing head) it won't be able to get the element. As it cannot get the element it will throw error if you try to access addEventListener or onclick of null.
On the other hand, if register a function in head which gets called
when DOM is loaded, and inside that function I put code which
registers handler for click on some button, then as I understand user
has chance to click button but the handler will not be called because
the whole DOM was not loaded yet (and that is where the button click
handler is registered). Am I correct?
Yes, you are correct. DOM load generalises the condition that all elements are added to the DOM and is ready for any operation on any element defined by HTML.
Also, window.load will be triggered only after DOM is loaded and all the external resources like images, videos are also loaded. Using it can delay the event attachments further.
What if I want to add event listener immediately?
If you want to immediately bind an event you can do it with inline scripts, just after the element although usually not a requirement and neither a good practice.
<p>whatever</p>
<button id="mybutton">Click me</button>
<script>
document.getElementById('mybutton').addEventListener(...
</script>
<p>rest of HTML</p>
This also opens another possibility, if you put your scripts at the end of HTML instead of head, it makes sure that all elements are added to the DOM and DOM is practically ready for any operations using DOM APIs. This was used widely when listening to DOM load event was not that easy. Although I can't find the correct reference, this was a recommendation by Doug Crockford.
I’m trying to write a Chrome extension that programmatically sends a click event to a particular link on the page. This particular link has known click event handlers on the page that I can see with Chrome’s web inspector.
I’m sending this click event with a jQuery .click() in a content_page script in my Chrome extension, but it looks like the handlers are not firing. When console-logging the result of the jQuery .click() call, I can see that the expected return value is coming back, so I know that this code is actually running.Ch
I know that this jQuery code works, as I can paste this same line in Chrome’s console in that page and get the result I expect.
Am I crazy in thinking that I can trigger DOM events from the extension’s content_page? I know that the content_page executes in a separate environment, but I was pretty sure that triggered DOM events were bubbled through both environments.
(If I’m not crazy, how would you proceed in debugging?)
The answer is YES – click events do propagate, but there’s something odd happening when I target the DOM element I want to send a .click() to with jQuery, but it works when using native DOM traversal functions like getElementsByClassName().
Mystery solved: just use vanillaJS approaches to call click() on the DOM element itself instead of the jQuery-wrapped version.