How to stop some javascript file from loading? - javascript

Some third party javascript is included in my HTML page.
It adds some sharing buttons to my webpage, and is called as like
<script src=http://something/something.js></script>
But sometimes I would like not to load this javascript at all. It could be solved on the server side, which would block, under some conditions, the above mentioned line from appearing at the webpage. But this is not possible to remove this tag from the HTML at all due to technical reasons, neither by server side (like PHP) nor by javascript (eg. by using document.write to put the tag there only when needed). I need to resolve this in javascript only, and I need to BLOCK the script tag if condition is met, meaning the tag always exists in the HTML.
Is there any possibility to block the something.js URL mentioned above from loading? So I would, for example, execute some other javascript before or after it. I thought that it would be possible this way, but it doesn't seem to work:
<script>
(function(){
var scripts=document.getElementsByTagName('script');
for (var i=0; i<scripts.length; i++)
if (scripts[i].src && scripts[i].src=='http://something...')
scripts[i].parentNode.removeChild(scripts[i]);
})();
</script>
<script src=http://something/something.js></script>
This doesn't work because when the script is called, it cannot see another <script> tag below at that moment. If I put the script below, it detects the script with src attribute, but it is too late to remove the element since it has already executed (and pasted sharing button elements to the webpage).
Is there any other way to stop loading of the third party script? Thank you
EDIT: updated the fact that the third party javascript needs to be in the HTML every time due to some internal reasons (despite the fact I disagree with that, I can do nothing about it).

a simple solution could be:
<script>
if(yourcondition){
document.write('<script src=\"http://something/something.js\" type=\"text/javascript\"><\/script>');
}
else{
document.write('<script src=\"http://something/OTHER.js\" type=\"text/javascript\"><\/script>');
}
</script>
yourcondition can be a boolean stored in a cookie or localstorage. Or you can set it to true or false depending your needs.
Also note that the source value in your script tag must be encapsulated between "

If the script relies on being in the document during the initial parsing because it outputs HTML where it appears (e.g., via document.write), as it seems to from your hidemeifnecessary example, then your "hide me" approach is probably the best you can do client-side.
If the script didn't need to be in the page during the main parsing, you could lazy-load it, but from your question that doesn't seem to be the case.
As you said in the question, the right answer here really is to deal with this server-side.

You have to make sure your script is loaded as soon as possible. I load mine right after the opening head tag. In that script select all tags you want to block (in my case script, iframe and img) and iterate through them. Add the event listener "beforescriptexecute" to them and trigger preventDefault like this:
bsePd = element.addEventListener('beforescriptexecute', e => {
e.preventDefault();
e.target.removeEventListener('beforescriptexecute', bsePd);
console.log('Prevented script from execution:', e.target.src);
});
With that you catch already existing scripts. For those added dynamically you can add the event Listener DOMNodeInserted and wait for them to come.
Thats how I made a cookie consent manager I needed for a site where it was not possible to do it whit PHP because of heavy caching mechanisms.

Related

What happen if an exactly the same JS dynamic load fails the second time after successful load the first time? [duplicate]

I am including some related content on misc. web pages by adding a <script> tag near the end of the <body> tag, which then loads other javascript files. The flow is a little convoluted, so I’ll try to explain it before asking my question:
A browser loads a page with our <script> element near the end of the <body> element
The src attribute of the script tag points to a javascript file which (in some cases) injects a second <script> element
The src attribute of the injected <script> element points to yet another javascript file, which finally injects some content on the appropriate part of the page.
We are using this two-stage approach to be able to do some basic processing before deciding whether to include the final content, which could take some time to load.
The problem is that IE8 (and maybe older versions) loads the last javascript twice. It appears that the act of setting the src attribute will trigger a load, but so will appending the script tag to the DOM. Is there any way to avoid this?
I have created a bare-bones demo of the problem. If you have some way of tracing the HTTP requests, you will see that IE8 loads js_test2.js twice.
The root difference is that IE executes a script element the first time it is added to a parent element's childNodes, regardless of whether the parent element is actually in the document. Other browsers only execute script when it is added to a node inside the document's tree of childNodes.
jQuery's domManip function (line 524 of jQuery 1.3.2), which is called by append and other similar jQuery methods, tries to be clever and calls evalScript for any <script> elements it finds in the final parsed HTML, to execute the script (by doing AJAX requests if necessary for external scripts). (The actual script elements have been removed from the parsed childNodes to stop them getting executed on insertion into the document, presumably so that scripts are only executed once when content containing them is appended into multiple elements at once.)
However, because the previous clean function, whilst parsing the HTML, appended the script element to a wrapper div, IE will have already executed the script. So you get two executions.
The best thing to do is avoid using domManip functions like append with HTML strings when you're doing anything with scripts.
In fact, forget putting your content in a serialised HTML string and getting jQuery to parse it; just do it the much more reliable plain DOM way:
var s= document.createElement('script');
s.type= 'text/javascript';
s.charset= 'UTF-8';
s.src= 'js_test2.js';
document.getElementById('some_container').appendChild(s);
(To be honest, after viewing the stomach-churning source code of the clean function, I'm having serious doubts about using jQuery's HTML-string-based DOM manipulations for anything at all. It's supposed to fix up browser bugs, but the dumb-regex processing seems to me likely to cause as many problems as it solves.)
Incidentally with this initial call:
document.write(unescape("%3Cscript src='js_test1.js' type='text/javascript'%3E%3C/script%3E"));
You don't need to unescape here; I don't know why so many people do. The sequence </ needs to be avoided in an inline script as it would end the <script> tag, and if you're doing XHTML < and & should be avoided too (or ]]> if you're using a CDATA wrapper), but there's an easier way of doing all that with just JavaScript string literals:
document.write('\x3Cscript src="js_test1.js" type="text/javascript">\x3C/script>"));
I've seen that behavior happening on other versions of IE under similar circumstances (such as cloning of <script> nodes) and I never got to know how to stop the script from executing twice, so what I ended up doing was adding a guard on the script code for it not to run twice. It was something like:
if (typeof(loaded) == 'undefined') {
// the whole code goes in here
var loaded = true;
}
If you can't find a way of preventing the script to execute twice, you may want to try that approach instead.
It would seem that jquery is fetching the second instance of js_test2 using XmlHttpRequest.
Why I don't know but its the behaviour of JQuery you need to investigate.
You can check to see if a script is already in the document before loading it-
function fetchscript(url, callback){
var S= document.getElementsByTagName('script'), L= S.length;
while(L){
if(S[--L].src== url) return true;
}
//create and append script and any callbacks
}
I find the same problem,only happen in IE.
jQuery‘s html() method chains is: html>append>domManip>clean
clean() method use innerHTML make string to DOM, innerHTML in IE has a bug that script tag will immediately load(first load), jQuery evalScript script tags at the end of domManip method(ajax load).then script file load twice in IE.
I think jQuery should fix this problem,update the clean() method
It's possible that this is because you use document.write when you're already in a <script> element. Have you tried appending to <head> instead of document.write?

Load pages via AJAX and execute javascript and CSS

I've been searching for a while now, but I can't figure out how to load an entire page via AJAX and still execute all javascript and css.
Mostly I just end up with the plain text without any CSS.
Is there a way to do this? I tried jQuery.get, jQuery.load and jQuery.ajax, but none really work like that.
I have a different solution. You may try it with an iframe. Use jQuery to append an iframe script including all relevant codes into some part of your page (like some div). This may do it for you including CSS, like;
$('<iframe src="your_page.html"/>').appendTo('#your_div');
Or you may try something like;
$('<iframe src="your_page.html"/>').load(function(){
alert('the iframe is done loading');
}).appendTo('#your_div');
I have solved similar problem as following.
Download the webpage over ajax
Iterate it over and find any <script> and </script> tags
Get content from within these tags as text
Create new <script> element and insert there the code
Append the tag to your webpage
Another thing is you will need to somehow call the script..
I have done it this way:
I set standardized function names like initAddedScript callback which I am calling after appending the script to the page. Same as I have deinitScript called when I do not need the code (and its variables,..) anymore.
I must say this is awful solution, which likely means you have bad application architecture so as I have had:)
With css is it the same, but you do not need any handlers. Just append the style tag to your documents head.
If the page you load doesn't have any style data, then the external stylesheets must have relative paths that are not correct relative to the invoking document. Remember, this isn't an iFrame - you aren't framing an external document in your document, you're combining one document into another.
Another problem is that loading your complete page will also load the doctype, html, head, and body tags - which modern browsers will cope with most of the time, but the results are undefined because it's not valid HTML to jam one document into another wholesale. And this brings me to the third reason why it won't work: CSS links outside of the head section aren't valid, and the misplaced head section caused by your haphazard document-in-document collage.
What I'd do for compliance (and correct rendering) is this, which would be implemented in the Success callback:
Copy all link elements to a new jQuery element.
Copy the contents of all script in the head section
Copy the .html() contents from the loaded document's body tag
Append the link elements (copied out in step 1) to your host document's head
Create a new script tag with your copied script contents and stick it in the head too
Done!
Complicated? Kind of, I guess, but if you really want to load an entire page using AJAX it's your only option. It's also going to cause problems with the page's JavaScript no matter what you do, particularly code that's supposed to run during the initial load. There's nothing you can do about this. If it's a problem, you need to either rewrite the source page to be more load-friendly or you could figure out how to make an iFrame suit your needs.
It's also worth considering whether it'd work to just load your external CSS in the host document in the first place.
I suppose you are looking for something like this:
your page div --> load --> www.some-site.com
After a quik search the closest solution seems to be the one by "And": Load website into DIV
You have to run a web server and create a proxy.php page with this content:
Then your JQuery load() function should be like this:
$("#your_div_id").load("proxy.php?url=http://some-site.com");
NB. I have tested this solution and it should not load all the CSS from the target page, probably you'll have to recreate them. For example the image files stored on the remote server will not loaded, I suppose due to authentication policy.
You will be also able to view only the target page without the possibility to browse the target site.
Anyway I hope this could be a step forward to your solution.
Get your entire webpage as text using ajax
document.open();
document.write(this.responseText);
document.close();
OR
document.documentElement.outerHTML = this.responseText;
But you need to change the path of css and js pages in original webpage if the resulting webpage is in another directory.

Javascript non-blocking scripts, why don't simply put all scripts before </body> tag?

In order to avoid javascript to block webpage rendering, can't we just put all all our JS files/code to be loaded/executed simply before the closing </body> tag?
All JS files and code would be downloaded and executed only after the all page has being rendered, so what's the need for tricks like the one suggested in this article about non blocking techniques to load JS files. He basically suggests to use code like:
document.getElementsByTagName("head")[0].appendChild(script);
in order to defer script laod while letting the webpage to be rendered, thus resulting in fast rendering speed of the webpage.
But without using this type of non-blocking technique (or other similar techniques), wouldn't we achieve the same non-blocking result by simply placing all our JS files (to be loaded/executed) before the closing </body> tag?
I'm even more surprised because the author (in the same article) suggests to put his code before the closing </body> tag (see the "Script placement" section of the article), so he is basically loading the scripts before the closing </body> tag anyway. What's the need for his code then?
I'm confused, any help appreciated, thanks!
UPDATE
FYI Google Analytics is using similar non-blocking technique to load their tracking code:
<script type="text/javascript">
...
(function()
{
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = 'your-script-name-here.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s); //why do they insert it before the 1st script instead of appending to body/head could be the hint for another question.
})();
</script>
</head>
Generally saying no. Even if scripts will be loaded after all the content of the page, loading and executing of the scripts will block the page. The reason for that is possibility of presence of write commands in your scripts.
However if all you want to achieve is the speed of loading page contents, the result of placing script tags right before </body> tag is the same as for creating script tags dynamically. The most significant difference is that when you load scripts in common static way they are executed one by one, in other words no parallel execution of script file (in old browsers the same true is for downloading of the script too).
If you want asynchonous scripts.
Use the (HTML5) async tag if it is availble in the browser you're in. This is what Google Analytics is doing in the code you posted (specifically the line ga.async = true MDN Link, scroll down for async).
However, this can cause your script to load at arbitrary times during the page load - which might be undesirable. It's worth asking yourself the following questions before choosing to use async.
Don't need user input? Then using the async attribute.
Need to respond to buttons or navigation? Then you need to put them at the top of the page (in head) and not use the async tag.
Async scripts run in any order, so if your script is depending on (say) jQuery, and jQuery is loaded in another tag, your script might run before the jQuery script does - resulting in errors.
Why don't people put things at the bottom of the body tag? If the script is taking enough time to load that it's slowing/pausing the load of the website, it's quite possible that that script is going to pause/hang the website after the website has loaded (expect different behaviour on different browsers) - making your website appear unresponsive (click on a button and nothing happens). In most cases this is not ideal, which is why the async attribute was invented.
Alternatively if your script is taking a long time to load - you might want to (after testing) minify and concatenate your script before sending it up to the server.
I recommend using require.js for minifying and concatenation, it's easy to get running and to use.
Minifying reduces the amount of data that needs to be downloaded.
Concatenating scripts reduces the number of "round-trips" to the server (for a far away server with 200ms ping, 5 requests takes 1 second).
One advantage of asynchronous loading (especially with something like the analytics snippet) is, at least if you would place it on the top, that it would be loaded as soon as possible without costing any time in rendering the page. So with analytics the chances to actually track a user before he leaves the page (maybe before the page was fully loaded) will be higher.
And the insertBefore is used instead of append, because if I remember correctly there was a bug (I think in some IE versions, see also link below theres something in the comments about that).
For me this link:
Async JS
was the most useful I found so far. Especially because it also brings up the issue, that even with googles analytic code the onload event will still be blocked (at least in some browsers). If you want this to not happen, better attach the function to the onload event.
For putting the asynchronous snippet on the bottom, that is actually explained in the link you posted. He seems to just do it to make sure that the DOM is completely loaded without using the onload event. So it may depend on what you're scripts are doing, if you're not manipulating the DOM there should be no reason for adding it on the bottom of body. Besides that, I personally would prefer adding it to the onload-event anyway.

Is it OK to put javascript code anywhere in HTML code?

I see that Javascript code is normally in heading part of HTML code.
<head>
<script type="text/javascript" language="javascript" src="core.js"></script>
...
</head>
Is it OK to put the Javascript code in a body part of HTML code? I tested it, but it seems to work.
<body>
<script type="text/javascript" language="javascript" src="core.js"></script>
...
</body>
If so, why the examples of Javascript books put the javascript code in heading part?
If not, what's the difference between putting the javascript code in body/heading part?
Not only is it OK, it's actually better, since it lets the content come first.
If your viewers have a slow (eg, mobile) connection, it's better to send the actual content first, so that they can read it while the browser downloads the Javascript.
All the people saying it is better only applies if you are talking about at the bottom of the page (and that is an up for debate thing) from a code quality point of view, it is NOT ok to sprinkle script tags through your html. All references to javascript should be in a single place on the page, either the head (where they should be), or the very bottom (as a perf optimization)
Edit:
Basically, a web page is made up of 3 pieces; style (css), structure (html), and behavior (javascript). These pieces are all very distinct, so it makes sense to keep them as separate as possible. That way if you need to change some javascript, it is all in one place. If it is sprinkled through the file, it becomes much more difficult to find the code you are looking for, and that code basically becomes noise when you are just looking at structure.
It is the same arguments as why not sprinkle db access code all over your page. It has nothing to do with technical reasons, purely an architectural/design decision. Code that does different things should be kept separate for readability, maintainability, and by extension, refactorability (not sure if that last one is actually a word...)
You can do it, and people often do.
For example, people like to put their script tags just before the closing </body> to make web pages render quicker.
Also, if you do a script block after an element is created, you don't need to wait for DOM ready.
Be warned though, don't add, or remove an element from an unclosed ancestor in the markup tree (not including the script block's immediate parent element), or you will get the dreaded Operation Aborted error in IE.
Just something to add on:
I have preference of putting Javascript file right before </body>. My reasons being that:
Content can load and be shown first. If you load huge Javascript files first, which most are meaningless until the page is loaded, the user won't be able to see anything until the JS files are loaded.
Most Javascript code require to work with the UI can only run after the UI has been loaded. Placing the codes at the end of the html file reduces the need to use the onload event handler.
It is very bad habit to place Javascript snippets all over the HTML file. Placing all at the back of the HTML file allows you to manage your Javascript more efficiently.
It is legal according to the spec.
Most examples use them in the header as the headers come first and the browser will be able to parse the reference and download the JS files faster.
Additionally, these are links and are not part of the display, so traditionally, put in the header.
It is perfectly legal but there seem to be some differing opinions about it. Those who say to put all the javascript references in the head argue that the script is downloaded before the rest of the page become visible and dependent on it. So your user will not see an object on screen, attempt to interact with it and get an error because the javascript code is not yet loaded.
On the other hand, the argument goes that it takes longer to load all the script before the user sees the page and that can have a negative impact on perceived speed of your site.
JavaScripts inside body will be executed immediately while the page loads into the browser
Placing javascript at the end of the body will defer javascript load (ie: the page will render faster), but remember that any javascript function used for an event should be loaded before the event declaration, it is mainly because users may be able to fire an event before the page is completely loaded (so before the function is loaded)!
I used to put it in the head, then I've heard that it takes longer for the page to load so I started placing the scripts at the very bottom. However, I found out the most 'clean' way to do it is to place it in the head BUT you place the script inside a document.ready function. This way you have the best of both worlds. It is cleaner because it is in the head and it is not loaded before the content has been loaded, so there aren't any problems performance wise either.
With jQuery for instance, you can do it like this:
$(document).ready(function() {
alert('test');
});
The alert will only popup when the page has been fully loaded, even though the script is in the head.

Why call $.getScript instead of using the <script> tag directly?

I don't understand the reason for replacing this:
<script src="js/example.js"></script>
with this:
$.getScript('js/example.js', function() {
alert('Load was performed.');
});
Is there a particular reason to use the jQuery version?
The only reason I can think of is that you get the callback when the script is loaded. But you can get that callback using a script tag, too, by using the load event (or on really old IE, onreadystatechange).
In contrast, there are several negatives to doing it this way, not least that getScript is subject to the Same Origin Policy, whereas a script tag is not.
Even if you need to load a script dynamically (and there are several reasons you might need to do that), frankly unless you really need the callback, I'd say you're better off just loading the script by adding a script tag:
$('head:first').append("<script type='text/javascript' src='js/examplejs'><\/script>");
(Note: You need the otherwise-unnecessary \ in the ending tag in the above to avoid prematurely ending the script tag this code exists within, if it's in an inline script tag.)
script tags added in this way are not subject to the Same Origin Policy. If you want the load callback, then:
$("<script type='text/javascript' src='js/examplejs'><\/script>")
.on("load", function() {
// loaded
})
.appendTo('head:first');
(As I said, for really old IE, you'd have to do more than that, but you shouldn't need to deal with them these days.)
I can think of three reasons you might use the jQuery form:
You want all of your script declarations at the top of your document, but you also know that placing script declarations there forces the browser to download them in their entirety before proceeding further in the page rendering process. This can introduce measurable delay. The jQuery form will schedule the script loads until after the document is finished downloading, similar to the effect of placing all of your <script> tags at the end of the document, only without the syntactic weirdness.
The <script> mechanism is not available to scripts that do not live in the HTML document itself; that is, if a script included on the page with <script> wants to load a script, it has no option but to use a JavaScript-based approach, such as calling the jQuery function.
The jQuery form allows notification of the script's successful execution, in the form of a supplied callback function.
No need to do that..
You do that if you want to load the script dynamically (when needed, and not from the beginning)
The script might depend on jQuery, so it would be a way to prevent the browser trying to load it if it hasn't loaded jQuery.
There are a number of reasons that jQuery might not load, from a simple network failure to a CDN not being whitelisted by a NoScript user.
maybe to control when a script is loaded? On a javascript heavy page, it may be worth waiting to load some things that are non essential until after essential things are loaded.

Categories

Resources