Possible to modify DOM during/before initial DOM parsing? - javascript

Is it possible to modify the DOM during or before the initial DOM parsing? Or do I have to wait until the DOM is parsed and built before interacting with it? More specifically, is it possible to hinder a script element in DOM from running using userscripts/content scripts or similar in chrome or firefox?
Tried using eventListeners on DOMNodeInserted before the DOM is parsed, but these are only fired after the DOM is built.

These are two separate questions:
1. Is it possible to modify the DOM during or before the initial DOM parsing?
Yes. As soon as the browser builds the root element, then you can start querying and mutating the DOM. Note that when your script runs, some of the page may still yet be unparsed, perhaps even still in transit on the network. Your script generally has access to any element declared in the source before the script tag containing/calling your script. This includes parent elements containing your script tag.
2. Is it possible to hinder a script element in DOM from running using userscripts/content scripts or similar in chrome or firefox?
No. All scripts are executed and one script can't prevent another script's initial execution. However, you can perhaps go back through and remove event handlers, and otherwise attempt to counteract the effects of a script. Although this scenario seems a bit shady and/or against the grain of normal JavaScript usage.

I've actually looked into this a lot while developing an adblocker for Chrome. Basically, you can't use just Javascript to stop Javascript, especially since it would run simultaneously with the script element in question. So even if it would work it would cause a race condition.

you can modify elements during document parsing, but after than this element has added to dom.
for example
<div id="example"></div>
<script>
document.getElementById('example').innerHTML = 'hello';
</script>
<div>something else</div>

Is it possible to modify the DOM during or before the initial DOM parsing?
Yes it is possible.
Start by completely preventing the document from getting parsed altogether then on the side, fetch the same document, do any processing on this document and then inject the resulting document in the page.
Here is how I currently do just that https://stackoverflow.com/a/36097573/6085033

Related

Need to replace the text within a <h1> tag dynamically.

So I'm attempting to build a completely dynamic calender web-app, simply for some practice, but I'm struggling to dynamically replace this H1 elements text.
I've applied all months to the creatively named "month" variable, and is outputting correctly, but I can't seem to replace my placeholder
<h1 id="replace">Month</h1>
using
function title(){
var myReplace = document.getElementById("replace");
myReplace.innerHTML = month;
}
There's nothing syntactically incorrect with your code. You're most likely executing it at the wrong time. Try running on DOMContentLoaded or some other event that's more appropriate.
document.addEventListener('DOMContentLoaded', title);
Browsers render pages of HTML top-down. Retrieving and executing scripts as they're encountered, unless stated otherwise (async attribute). All the while, events are being triggered and any handlers to those events are subsequently executed.
DOMContentLoaded is one of those events that are triggered, specifically after the content has loaded. This is usually a good time to execute scripts as you're safe to manipulate the DOM as all of it's content has loaded. When you execute your scripts depends on the use-case/scenario.
Mozilla's has a good reference on many of the subscribe-able events.

Is it really necessary to wait for DOM ready to manipulate the DOM?

Is it really necessary to wait for the "ready" (or "window.onload") events if your code only manipulates DOM elements that have already been parsed entirely?
The jQuery documentation for the "ready()" function demonstrates how you could wait to perform actions until the DOM is entirely ready but the example is for code (script tags) that are listed before the DOM elements in question. But it seems that code which appears after the necessary DOM elements in an HTML document has access to them since, presumably, the DOM is built as the browser parses the document.
For example, is it safe to assume that the following code is reliable in all situations or is it still necessary (or beneficial somehow) to use a ready/onload handler?
<body>
<div id="foo"/>
<script type="text/javascript">
var foo = document.getElementById('foo');
foo.innerHTML = 'The element #foo is loaded!';
</script>
</body>
This SO question is very similar but I wanted to bump it to see if there is any more information.
If your JavaScript code is below the DOM elements and only modifies them exclusively, you don't need to wait for the DOM ready event.
However, keep in mind editing a DOM element which contains a script element (or more specifically, before the element's closing tag) used to cause big problems in IE6 (thanks T.J. Crowder) and IE7.
However, this requires inline scripts which can be a maintenance problem. It is preferred to have your JavaScript stored externally (and many speak of the benefits of including them before the closing body tag) for many benefits such as ease of maintenance and fine grained cache control.
in your case it is fine because the browser will render your code line by line and in your code id="foo" comes first so it will get that div....but suppose you wrote this script in head tag then the script will run first and it wont get the div with id="foo" because its not yet loaded..its better to write in document.ready method
Yes, it's safe if you js code is after dom but usually it's not relly good idea to mix html and js.
Document is loaded in linear fashion so your code works correctly.
Sometimes programmers do not use document ready for performance purpose when the javascript is not depends on the DOM below it. Here is some example.

Accessing DOM after big innerHTML injection

I have some code that looks like this
//create a long string of html, which includes a div with id="mydiv"
someElement.innerHTML = s; //s is the string above
document.getElementById('mydiv')
Now, after I set the innerHTML, it is going to take a while for the browser to actual render the DOM that includes id="mydiv" . So, will the javascript sit and wait for the dom to be properly rendered after the innerHTML injection, or will it move right along and call the getElementById which is now unsafe since the DOM for that id may not be created yet?
Here's an example that inserts nearly 12,000 elements into the DOM using innerHTML, then calls getElementById() to find the one element at the end that has an ID.
It successfully finds the element.
Example: http://jsfiddle.net/fzUUU/
There is no standard for innerHTML. So literally anything is allowed to happen including not being implemented (I believe Opera toyed with this once). It's just a hack introduced by Microsoft in IE.
However. Implementing innerHTML in any way that diverges from the way IE does it will break lots of pages on the web. So browser makers are forced to implement it the way IE does it. And here's how IE does it: when innerHTML is running the script interpreter stops. That is to say innerHTML blocks until the DOM is fully parsed.
So it should be safe to access the DOM directly after innerHTML for all current browsers and, due to the number of pages on the web that requires it, in the foreseeable future.
Additional answer:
It appears that the draft HTML5 spec specifies innerHTML: http://www.w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml0
It basically describes what IE already does. It should be noted that it doesn't specifically say weather the operation is bolcking or non-blocking but as mentioned earlier a non-blocking implementation will break lots of pages on the web.

How to dynamically add a Javascript function (and invoke)

Based on a click event on the page, via ajax I fetch a block of html and script, I am able to take the script element and append it to the head element, however WebKit based browsers are not treating it as script (ie. I cannot invoke a function declared in the appended script).
Using the Chrome Developer Tools I can see that my script node is indeed there, but it shows up differently then a script block that is not added dynamically, a non-dynamic script has a text child element and I cannot figure out a way to duplicate this for the dynamic script.
Any ideas or better ways to be doing this? The driving force is there is potentially a lot of html and script that would never be needed unless a user clicks on a particular tab, in which case the relevant content (and script) would be loaded. Thanks!
You could try using jQuery... it provides a method called .getScript that will load the JavaScript dynamically in the proper way. And it works fine in all well known browsers.
How about calling eval() on the content you receive from the server? Of course, you have to cut off the <script> and </script> parts.
If you're using a library like jQuery just use the built-in methods for doing this.
Otherwise you'd need to append it to the document rather than the head like this:
document.write("<scr" + "ipt type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\"></scr" + "ipt>");
In all honesty, I have no idea why the script tag is cut like that, but a lot of examples do that so there's probably a good reason.
You'll also need to account for the fact that loading the script might take quite a while, so after you've appended this to the body you should set up a timer that checks if the script is loaded. This can be achieved with a simple typeof check on any global variable the script exports.
Or you could just do an eval() on the actual javascript body, but there might be some caveats.
Generally speaking though, I'd leave this kind of thing up to the browser cache and just load the javascript on the page that your tabs are on. Just try not to use any onload events, but rather call whatever initializers you need when the tab is displayed.

Initiate onclick faster than with document.onload

I have html-pages with links where i want to attach a function to their onclick event. One way to do it is of course:
Save
But I know this is not the best practice. So instead I wait for window.onload, loop through the links and attach the save-function to the links with rel="save". The problem with this is that it waits until the whole page has finished loading which can be several seconds after the link is displayed and clickable.
So is there another way to do this? Avoiding onclick in the html but that makes it work immediately when the link is rendered.
Internet Explorer has a handy attribute for <script> tags called defer. It's for delaying the parsing of a script until the document has finished loading. For other browsers that support it, you can use DOMContentLoaded, as someone else suggested and for browsers that don't support either you can fall back to onload.
<script type="text/javascript" defer>
//- Run this code when the DOM parsing has completed
</script>
I did a quick Google search for "DOMContentLoaded defer" and found the following page that might help:
http://tanny.ica.com/ica/tko/tkoblog.nsf/dx/domcontentloaded-event-for-browsers
In your case, you can just leave that as it is. Stick to the simplest possible thing, even if it is not the general best practice.
You could try DOMContentLoaded event instead of load. IE also gives you the defer attribute for script tags, which defers execution until the DOM is loaded. If those don't work for you, then you are stuck with the solutions you mention, as far as I know.
I don't know if this is appropriate for your solution, but you could insert script immediately below the are with the links you need altered. This script would not be wrapped in a function, allowing the browser to execute it immediately when seen. The effect is that you can run script before the full page is loaded, altering only the items that exist above the script being run. (If you reference something below the script, it will fail.)
BTW, this is almost certainly not a best practice, and some would probably label it a worst practice.
How about this?
Save
Note: This solution requires to users to have Javascript enabled. Not exactly best practice, but may be suitable for your scenario.
The ideal here would be to use the ideas of Unobtrusive Javascript.
In this way, if the Javascript isn't loaded the link would still do something. It's a link right, so it leads the user to another piece of content? - this should work without Javascript. And if the functionality attached to the links can ONLY work with Javascript you should create and insert them into the DOM with Javascript (they aren't clickable if they aren't there...).
(Otherwise how about delegating the click event to a wrapper element? Does that work before the element is complete?)
edit: Oh, and "save" sounds very much like it ought to be a button in a form rather than a link. The Unobtrusive JS stuff still applies though.

Categories

Resources