Delaying the loading onset of elements - javascript

I have a webpage that is rich in content such as graphics and javascript. Now the problem is that my page loads too slow, especially with slower internet connections. Now at the bottom of my webpage I have a jquery slider, which is the least important item on my website.
now...
Is there a way I can postpone or delay the loading of that whole slider(which has a div ID as parent element) until directly after everything else has loaded on my page, and not alongside the rest of the more important content?

Absolutely, you might want to look up javascript loader like RequireJS or LABjs.
The principle is that you inject the script-tag that loads your javascript. For instance, you could have the following code as the last element before your </body>-tag:
<script type='text/javascript'>
var head = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = 'url/to/script.js';
head.appendChild(newScript);
</script>

Related

Count number of async scripts in the DOM

I have a script script.js that calls in advertisements into the DOM. It is invserted after #closeImage if some test is true:
<div id="overlay">
<img id="closeImage" src="close100x100.png">
</div>
If the test is true I call my script.
if (test) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'script.js';
$("#closeImage").append(script);
script.js might not find an advertisement. In this case from within script.js, script01.js which will be inserted into the DOM to look for different advertisements. If nothing is found script03.js will be called from within script02.js and so my div might end looking like this:
<div id="overlay">
<img id="closeImage" src="close100x100.png">
<script src="script.js"></script>
<script src="script01.js"></script>
<script src="script02.js"></script>
<!-- actual banner html -->
</div>
Only the first script is being inserted by the original document.createElement(). How do I count the number of scripts in #overlay? - This did not work:
$(document).ready(function () {
var loaded = $('div#ADF_overlay script').length;
});
EDIT (Restated the problem differently based on feedback)
My main guess here is that you have a timing issue. You are inserting a script, which has to load and then execute, which may then insert another script which has to load and then execute and you don't actually know when that process is done so you can check how many scripts were loaded in total.
$(document).ready() will not wait for that process to be done - it only waits for the original HTML of the document to be parsed (and any inline scripts that were there in the original HTML and don't have the defer or async attributes will run).
The only way to know when a cascade of dynamically loaded scripts are actually done is to have the last script somehow mark when it's done (either by calling a function, triggering an event, setting a variable or marking something in the DOM). Without the script telling you when it's done inserting new script tags, you can't know whether the next script is still loading and waiting to run which might insert some more scripts, etc...
We could probably help better with ideas for solving your overall problem (what you are actually trying to accomplish) if you described the overall problem rather than just this one piece that you're trying to use.
If you just want to count how many dynamically insert scripts there are, then it would be simplest to just maintain a javascript counter as you insert them and then you can use that counter sometime later.
var scriptsInserted = 0;
if (seenOverlay('served') === 'false') {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'script.js';
$("#closeImage").append(script);
++scriptsInserted;
}
Then, some time later, you can just refer to your variable scriptsInserted to access the count.
Alternatively, you can put a class name on your script elements and just query for that:
if (seenOverlay('served') === 'false') {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'script.js';
script.className = "adScript";
$("#closeImage").append(script);
++scriptsInserted;
}
And, some time later:
$(".adScript").length;
If you're dynamically inserting a cascade of scripts (insert one, which loads, runs and then inserts another, and so on), then when do you know to check to see how many scripts were actually inserted? The timing of when to check may also be an issue for you because if you're checking that in $(document).ready(), then that process may not be done yet as each dynamically inserted script is loaded asynchronously and $(document).ready() can easily fire before that process is done because it doesn't wait for dynamically inserted scripts to load or run.
It appears that you may potentially have other issues because inserting a script into a particular place in an already loaded document will usually not insert content at that place in the document because a dynamically loaded script element can't use document.write() to insert content into the existing document in the same way that a normal inline <script> tag can.

Site content shifts vertically on certain pages

I'm in the process of building a new website for my wife's business, using Squarespace. Don't tell her, since it's one of her Christmas presents. :)
However, I'm experiencing a weird issue. About half of the pages on the site include content from a third-party widget called Healcode. Those pages have a strange jerkiness to them on pageload, where the logo and navbar move around -- ultimately winding up in the right spot, but looking bad while doing so. Pages that don't have a third-party widget don't have this jerkiness.
Example of page that jerks: https://coconditioning.squarespace.com/yoga-classes/
Example of page that doesn't jerk: https://coconditioning.squarespace.com/private-coaching/
The Healcode widget is javascript code that looks like this:
<script type="text/javascript">
healcode_widget_id = "ay12237c4nc";
healcode_widget_name = "schedules";
healcode_widget_type = "mb";
document.write(unescape("%3Cscript src='https://www.healcode.com/javascripts/hc_widget.js' type='text/javascript'%3E%3C/script%3E"));
// Healcode Schedule Widget for Conscious Conditioning L.L.C. : Weekly Schedule New
</script>
<noscript>Please enable Javascript in order to get HealCode functionality</noscript>
Any help would be MUCH appreciated. Thank you in advance!
You could hide the page until the body loads:
<body style = 'display: none'; />
And in your javascript, adding window.onload():
healcode_widget_id = "ay12237c4nc";
healcode_widget_name = "schedules";
healcode_widget_type = "mb";
document.write( unescape("%3Cscript src='https://www.healcode.com/javascripts/hc_widget.js' type='text/javascript'%3E%3C/script%3E"));
// Healcode Schedule Widget for Conscious Conditioning L.L.C. : Weekly Schedule New
window.onload = function()
{
document.body.style.display = 'block';
};
Also, is document.write() the best solution for you?
Don't try to use document.write if possible as with document.write JS parser doesn't know where to put it. at best, the browser will ignore it. at worst, it could write over the top of your current document. Use appendChild
function loadHealCodeScript () {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://www.healcode.com/javascripts/hc_widget.js'
document.body.appendChild(script);
}
window.onload = loadHealCodeScript; // load healcode after page has been loaded
The jittering effect is happening because the healcode is loading its script before the page has completely loaded. If possible place all you javascripts after the body tag rather than head
As suggested by google also https://developers.google.com/maps/documentation/javascript/tutorial?hl=en#asynch

Load jQuery in an iframe

I'm writing a script which requires some stuff to be carried out in an iframe. It's a userscript for a site which I do not own, so because of cross-domain issues, I cannot just set the src of the iframe to a page with my own code. Instead, I am dynamically building the iframe.
To do this, I have
function childScripts(){
//Stuff that must be injected into the iframe.
//Needs jQuery
}
//because I'm lazy:
var iframeWin=$('#my-iframe')[0].contentWindow;
//Load jQuery:
var script = iframeWin.document.createElement("script");
script.type = "text/javascript";
script.src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"
iframeWin.document.head.appendChild(script);
//Inject script
var script = iframeWin.document.createElement("script");
script.type = "text/javascript";
script.textContent="("+childScripts.toString()+")()";
iframeWin.document.body.appendChild(script);
Now, the injected script needs jQuery, but for some reason, jQuery isn't loaded when the injected script runs--even though jQuery is in <head> and the injected script is in <body>.
I've tried other workarounds--making the injected script run onload. I don't like the idea of setting a timeout and checking for the existence of jQuery, I'd prefer a more elegant solution.
I've also tried copying the $ object to iframeWin.$, but of course that doesn't work, since it just backreferences to the parent $ and manipulates the parent document.
It's easier to manipulate iframes using jQuery. Please try:
$('<iframe id="my-iframe"/>').load(function(){
$('#my-iframe').contents().find('body').append('asd').end()
.find('body').append('<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"><\/script>').end()
.find('body').append('<script>$(function() {alert("hello from jquery");console.log("hello from jquery"); })<\/script>');
}).appendTo("body");
Placement:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$('<iframe id="my-iframe"/>').load(function(){.....
</script>
</body>
</html>

Cross browser alternatives to eval

My html page dynamically loads pages via Ajax for dynamic panels on the page. I need the script tags in the dynamically loaded pages to be executed. I fixed the code from a SO question. It works fine on FF/Safari/Chrome.
But dom nodes of type script work differently on IE. -- I can't seem to add text to a script node in IE 7:
// variable "data" holds the script element's content from an
// incoming html page loaded via ajax
var script = document.createElement("script");
script.type = "text/javascript";
script.appendChild(document.createTextNode(data)); // doesn't work on ie
// also doesn't work on IE 7:
script.innerHTML = data;
script.innerText = data;
Any ideas for getting the sw to work on IE? (Other than using eval.)
You should simple call eval(data).
Although it is true that eval should usually be avoided, this is one of the few exceptions.
EDIT: Without eval, you can do it like this:
var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.text = data;
document.head.appendChild(scriptNode);
document.head.removeChild(scriptNode); //Optional
You have a few options I can think of (other than using eval).
The script could be served from a separate path; setting the src of the script element instead of its content should work, even in IE.
The script to be executed could be attached to the onload listener of an image or other element, which can be appended to the document as you are doing with the script element.
use Function instead of eval. This will at least keep the evaluated code out of the local scope: new Function(data)();

JavaScript is blocking images from loading

I'm using the following code to allow parallel JavaScript downloading on my website
var head = document.getElementsByTagName("head")[0];
var sTag1 = document.createElement("script");
sTag1.type = sTag1.type = "text/javascript";
sTag1.src = "http://example.com/one.js";
var sTag2 = document.createElement("script");
sTag2.type = sTag2.type = "text/javascript";
sTag2.src = "http://example.com/two.js";
var sTag1 = document.createElement("script");
sTag3.type = sTag3.type = "text/javascript";
sTag3.src = "http://example.com/three.js";
head.appendChild(sTag1);
head.appendChild(sTag2);
head.appendChild(sTag3);
However, using YSlow, it shows that even though one.js, two.js and three.js are downloading in parallel - images are not loading until the last JavaScript is fully downloaded.
What can I do to allow images to not be blocked from loaded due to my JavaScript files downloading.
Load your Javascript files right above the </body> tag.
Where are you triggering that code from? Because you could wait to execute your quoted code until you see the window.load event, e.g.:
<script type='text/javascript'>
function loadMyScripts() {
/* ...your loading code here...*/
}
window.onload = loadMyScripts; // Or use addEventListener/attachEvent to do it
</script>
The window.load event isn't fired until all of the images are loaded, so you'll be sure the scripts aren't getting in the way. Of course, it also leaves quite a large margin of time for the user to start doing things with the page, so you need to be sure the page doesn't need that JavaScript to be functional.

Categories

Resources