Load script after the rest of the page without deferring it? [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have an image scroller that is blocking resources from loading until it has loaded.
I have tried deferring the script but it then doesnt want to work when its deferred.
What would be the simplest method for getting it to load after the rest of the page?
Ive looked at some jquery methods but its like reading chinese to me

Here are some various options:
Place the <script> tag right before the </body> tag. This will allow the rest of the DOM to load before your script even starts to load.
Construct some code to dynamically load the script and don't run that code until either $(document).ready() fires or perhaps even $(window).load() fires depending upon how many resources you want to wait for before starting your script. You can dynamically load the script in jQuery with $.getScript() or it's fairly simple to just dynamically insert a script tag too.
Troubleshoot your code to figure out why the defer attribute doesn't work because it's designed for situations like yours where you want other things to load first. My guess this was because you added defer loading for the library, but didn't delay your own code that attempts to use the library thus that code didn't work when you deferred the loading of the library.
Some references on script loading:
load and execute order of scripts
Script Tag - async & defer
improving website performance by dynamically loading javascript?
pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it
In looking at your actual page code, a reason why your script wouldn't work when you add defer to it is that you have code that depends on that script that can't be run until after the dynamic scroll code has been loaded. In looking at your code, I see this block of code and one other block similar to it:
<script type="text/javascript">
if ( DYN_WEB.Scroll_Div.isSupported() ) {
DYN_WEB.Event.domReady( function() {
// arguments: id of scroll area div, id of content div
var wndo = new DYN_WEB.Scroll_Div('wn', 'lyr1');
// see info online at http://www.dyn-web.com/code/scrollers/continuous/documentation.php
wndo.makeSmoothAuto( {axis:'h', bRepeat:true, repeatId:'rpt1', speed:100, bPauseResume:true} );
var wndo2 = new DYN_WEB.Scroll_Div('wn2', 'lyr2');
wndo2.makeSmoothAuto( {axis:'h', bRepeat:true, repeatId:'rpt2', speed:60, bPauseResume:true} );
});
}
</script>
Both of these have to be run AFTER the scroll library is loaded. So, if you delay the loading of the scroll library, then this code has to be run after the library is loaded.
If you're moving the scroll library to right before </body>, then place these blocks of code right after it (without using the defer tag on any).

Try this:
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(window).bind("load", function() {
// code here
});
</script>
or this:
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(window).bind("load", function() {
if ( DYN_WEB.Scroll_Div.isSupported() ) {
DYN_WEB.Event.domReady( function() {
// arguments: id of scroll area div, id of content div
var wndo = new DYN_WEB.Scroll_Div('wn', 'lyr1');
// see info online at http://www.dyn-web.com/code/scrollers/continuous/documentation.php
wndo.makeSmoothAuto( {axis:'h', bRepeat:true, repeatId:'rpt1', speed:100, bPauseResume:true} );
var wndo2 = new DYN_WEB.Scroll_Div('wn2', 'lyr2');
wndo2.makeSmoothAuto( {axis:'h', bRepeat:true, repeatId:'rpt2', speed:60, bPauseResume:true} );
});
}
});
</script>

Related

Execute jQuery after Other JS file Dynamically loads content

I'm working to modify some content which is dynamically loaded via another script(let's call is script #1) onto my site. Script #1 loads some markup and content and I've been using the setTimeout() function to call my script (Script #2) using a delay of a few seconds, in order to wait to be sure that Script #1 has executed and the content is present in the DOM.
My issue is that Script#1 has different loading times, based on the server load and can be slow or fast depending on these factors, and right now, playing it safe with setTimeout() I'm often left with a second or two where my scripts are still waiting to be fired and Script #1 has already loaded the content.
How can I execute my script as soon as Script#1 successfully loads it's dynamic content?
I've found this post which does seem to address the same issue but using the setInterval function as #Matt Ball has laid out there doesn't work at all for some reason. I'm using the code below where 'div.enrollment' is meant to find in the DOM which is dynamically loaded and execute..
jQuery(window).load(function ($)
{
var i = setInterval(function ()
{
if ($('div.enrollment').length)
{
clearInterval(i);
// safe to execute your code here
console.log("It's Loaded");
}
}, 100);
});
Any help on guidance on this would be greatly appreciated! Thanks for your time.
It seems that the healcode.js is doing a lot of stuff. There is a whole lot of markup added to the <healcode-widget> tag.
I would try to add another tag with an id inside and test for its existence:
<healcode-widget ....><div id="healCodeLoading"></div></healcode-widget>
Test in an interval for the existence of healCodeLoading inside <healcode-widget>: (Assuming jQuery)
var healCodeLoadingInterval = setInterval(function(){
var healCodeLoading = jQuery('healcode-widget #healCodeLoading');
if (healCodeLoading.length == 0) {
clearInterval(healCodeLoadingInterval);
// Everything should be loaded now, so you can do something here
}
}, 100);
healcode.js should replace everything inside <healcode-widget></healcode-widget> during init. So, if your <div>-element is no longer inside, the widget has loaded and initialized.
Hope that helps.
If you just want to load some markup and content and then run some script afterwards, you can use jQuery. You should use something like the following in script#1 to run a function in script#2
$.get( "ajax/test.html", function( data ) {
// Now you can do something with your data and run other script.
console.log("It's Loaded");
});
The function is called, after ajax/test.html is loaded.
Hope that helps

How to execute code before window.load and after DOM has been loaded?

Here is the circumstance:
I have 2 pages:
1 x html page
1 x external Javascript
Now in the html page, there will be internal Javascript coding to allow the placement of the window.onload, and other page specific methods/functions.
But, in the external Javascript I want certain things to be done before the window.onload event is triggered. This is to allow customized components to be initialized first.
Is there a way to ensure initialization to occur in the external Javascript before the window.onload event is triggered?
The reason I have asked this, is to attempt to make reusable code (build once - use all over), to which the external script must check that it is in 'order/check' before the Javascript in the main html/jsp/asp/PHP page takes over. And also I am not looking for a solution in jQuery #_#
Here are some of the links on Stack Overflow I have browsed through for a solution:
Javascript - How to detect if document has loaded (IE 7/Firefox 3)
How to check if page has FULLY loaded(scripts and all)?
Execute Javascript When Page Has Fully Loaded
Can someone help or direct me to a solution, your help will be muchness of greatness appreciated.
[updated response - 19 November 2012]
Hi all, thanks for you advice and suggested solutions, they have all been useful in the search and testing for a viable solution.
Though I feel that I am not 100% satisfied with my own results, I know your advice and help has moved me closer to a solution, and may indeed aid others in a similar situation.
Here is what I have come up with:
test_page.html
<html>
<head>
<title></title>
<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript" src="test_script_1.js"></script>
<script type="text/javascript" src="test_script_2.js"></script>
<script type="text/javascript">
window.onload = function() {
document.getElementById("div_1").innerHTML = "window.onload complete!";
}
</script>
<style type="text/css">
div {
border:thin solid #000000;
width:500px;
}
</head>
<body>
<div id="div_1"></div>
<br/><br/>
<div id="div_2"></div>
<br/><br/>
<div id="div_3"></div>
</body>
</html>
loader.js
var Loader = {
methods_arr : [],
init_Loader : new function() {
document.onreadystatechange = function(e) {
if (document.readyState == "complete") {
for (var i = 0; i < Loader.methods_arr.length; i++) {
Loader.method_arr[i]();
}
}
}
},
load : function(method) {
Loader.methods_arr.push(method);
}
}
test_script_1.js
Loader.load(function(){initTestScript1();});
function initTestScript1() {
document.getElementById("div_1").innerHTML = "Test Script 1 Initialized!";
}
test_script_2.js
Loader.load(function(){initTestScript2();});
function initTestScript2() {
document.getElementById("div_2").innerHTML = "Test Script 2 Initialized!";
}
This will ensure that scripts are invoked before invocation of the window.onload event handler, but also ensuring that the document is rendered first.
What do you think of this possible solution?
Thanking you all again for the aid and help :D
Basically, you're looking for this:
document.onreadystatechange = function(e)
{
if (document.readyState === 'complete')
{
//dom is ready, window.onload fires later
}
};
window.onload = function(e)
{
//document.readyState will be complete, it's one of the requirements for the window.onload event to be fired
//do stuff for when everything is loaded
};
see MDN for more details.
Do keep in mind that the DOM might be loaded here, but that doesn't mean that the external js file has been loaded, so you might not have access to all the functions/objects that are defined in that script. If you want to check for that, you'll have to use window.onload, to ensure that all external resources have been loaded, too.
So, basically, in your external script, you'll be needing 2 event handlers: one for the readystatechange, which does what you need to be done on DOMready, and a window.onload, which will, by definition, be fired after the document is ready. (this checks if the page is fully loaded).
Just so you know, in IE<9 window.onload causes a memory leak (because the DOM and the JScript engine are two separate entities, the window object never gets unloaded fully, and the listener isn't GC'ed). There is a way to fix this, which I've posted here, it's quite verbose, though, but just so you know...
If you want something to be done right away without waiting for any event then you can just do it in the JavaScript - you don't have to do anything for your code to run right away, just don't do anything that would make your code wait. So it's actually easier than waiting for events.
For example if you have this HTML:
<div id=one></div>
<script src="your-script.js"></script>
<div id=two></div>
then whatever code is in your-script.js will be run after the div with id=one but before the div with id=two is parsed. Just don't register event callbacks but do what you need right away in your JavaScript.
javascript runs from top to bottom. this means.. if you include your external javascript before your internal javascript it would simply run before the internal javascript runs.
It is also possible to use the DOMContentLoaded event of the Window interface.
addEventListener("DOMContentLoaded", function() {
// Your code goes here
});
The above code is actually adding the event listener to the window object, though it's not qualified as window.addEventListener because the window object is also the global scope of JavaScript code in webpages.
DOMContentLoaded happens before load, when images and other parts of the webpage aren't still fully loaded. However, all the elements added to the DOM within the initial call stack are guaranteed to be already added to their parents prior to this event.
You can find the official documentation here.

Trying to load an API and a JS file dynamically

I am trying to load Skyscanner API dynamically but it doesn't seem to work. I tried every possible way I could think of and all it happens the content disappears.
I tried console.log which gives no results; I tried elements from chrome's developers tools and while all the content's css remains the same, still the content disappears (I thought it could be adding display:none on the html/body sort of). I tried all Google's asynch tricks, yet again blank page. I tried all js plugins for async loading with still the same results.
Skyscanner's API documentation is poor and while they offer a callback it doesn't work the way google's API's callback do.
Example: http://jsfiddle.net/7TWYC/
Example with loading API in head section: http://jsfiddle.net/s2HkR/
So how can I load the api on button click or async? Without the file being in the HEAD section. If there is a way to prevent the document.write to make the page blank or any other way. I wouldn't mind using plain js, jQuery or PHP.
EDIT:
I've set a bounty to 250 ontop of the 50 I had previously.
Orlando Leite answered a really close idea on how to make this asynch api load although some features doesn't work such as selecting dates and I am not able to set styling.
I am looking for an answer of which I will be able to use all the features so that it works as it would work if it was loading on load.
Here is the updated fiddle by Orlando: http://jsfiddle.net/cxysA/12/
-
EDIT 2 ON Gijs ANSWER:
Gijs mentioned two links onto overwriting document.write. That sounds an awesome idea but I think it is not possible to accomplish what I am trying.
I used John's Resig way to prevent document.write of which can be found here: http://ejohn.org/blog/xhtml-documentwrite-and-adsense/
When I used this method, I load the API successfuly but the snippets.js file is not loading at all.
Fiddle: http://jsfiddle.net/9HX7N/
I belive what you want is it:
function loadSkyscanner()
{
function loaded()
{
t.skyscanner.load('snippets', '1', {'nocss' : true});
var snippet = new t.skyscanner.snippets.SearchPanelControl();
snippet.setCurrency('GBP');
snippet.setDeparture('uk');
snippet.draw(document.getElementById('snippet_searchpanel'));
}
var t = document.getElementById('sky_loader').contentWindow;
var head = t.document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.onreadystatechange= function() {
if(this.readyState == 'complete') loaded();
}
script.onload= loaded;
script.src= 'http://api.skyscanner.net/api.ashx?key=PUT_HERE_YOUR_SKYSCANNER_API_KEY';
head.appendChild(script);
}
$("button").click(function(e)
{
loadSkyscanner();
});
It's load skyscanner in iframe#sky_loader, after call loaded function to create the SearchPanelControl. But in the end, snippet draws in the main document. It's really a bizarre workaround, but it works.
The only restriction is, you need a iframe. But you can hide it using display:none.
A working example
EDIT
Sorry guy, I didn't see it. Now we can see how awful is skyscanner API. It puts two divs to make the autocomplete, but not relative to the element you call to draw, but the document.
When a script is loaded in a iframe, document is the iframe document.
There is a solution, but I don't recommend, is really a workaround:
function loadSkyscanner()
{
var t;
this.skyscanner;
var iframe = $("<iframe id=\"sky_loader\" src=\"http://fiddle.jshell.net/orlleite/2TqDu/6/show/\"></iframe>");
function realWorkaround()
{
var tbody = t.document.getElementsByTagName("body")[0];
var body = document.getElementsByTagName("body")[0];
while( tbody.children.length != 0 )
{
var temp = tbody.children[0];
tbody.removeChild( temp );
body.appendChild( temp );
}
}
function snippetLoaded()
{
skyscanner = t.skyscanner;
var snippet = new skyscanner.snippets.SearchPanelControl();
snippet.setCurrency('GBP');
snippet.setDeparture('uk');
snippet.draw(document.getElementById('snippet_searchpanel'));
setTimeout( realWorkaround, 2000 );
}
var loaded = function()
{
console.log( "loaded" );
t = document.getElementById('sky_loader').contentWindow;
t.onLoadSnippets( snippetLoaded );
}
$("body").append(iframe);
iframe.load(loaded);
}
$("button").click(function(e)
{
loadSkyscanner();
});
Load a iframe with another html who loads and callback when the snippet is loaded. After loaded create the snippet where you want and after set a timeout because we can't know when the SearchPanelControl is loaded. This realWorkaround move the autocomplete divs to the main document.
You can see a work example here
The iframe loaded is this
EDIT
Fixed the bug you found and updated the link.
the for loop has gone and added a while, works better now.
while( tbody.children.length != 0 )
{
var temp = tbody.children[0];
tbody.removeChild( temp );
body.appendChild( temp );
}
For problematic cases like this, you can just overwrite document.write. Hacky as hell, but it works and you get to decide where all the content goes. See eg. this blogpost by John Resig. This ignores IE, but with a bit of work the trick works in IE as well, see eg. this blogpost.
So, I'd suggest overwriting document.write with your own function, batch up the output where necessary, and put it where you like (eg. in a div at the bottom of your <body>'). That should prevent the script from nuking your page's content.
Edit: OK, so I had/took some time to look into this script. For future reference, use something like http://jsbeautifier.org/ to investigate third-party scripts. Much easier to read that way. Fortunately, there is barely any obfuscation/minification at all, and so you have a supplement for their API documentation (which I was unable to find, by the way -- I only found 'code wizards', which I had no interest in).
Here's an almost-working example: http://jsfiddle.net/a8q2s/1/
Here's the steps I took:
override document.write. This needs to happen before you load the initial script. Your replacement function should append their string of code into the DOM. Don't call the old document.write, that'll just get you errors and won't do what you want anyway. In this case you're lucky because all the content is in a single document.write call (check the source of the initial script). If this weren't the case, you'd have to batch everything up until the HTML they'd given you was valid and/or you were sure there was nothing else coming.
load the initial script on the button click with jQuery's $.getScript or equivalent. Pass a callback function (I used a named function reference for clarity, but you can inline it if you prefer).
Tell Skyscanner to load the module.
Edit #2: Hah, they have an API (skyscanner.loadAndWait) for getting a callback once their script has loaded. Using that works:
http://jsfiddle.net/a8q2s/3/
(note: this still seems to use a timeout loop internally)
In the skyrunner.js file they are using document.write to make the page blank on load call back... So here are some consequences in your scenario..
This is making page blank when you click on button.
So, it removes everything from page even 'jQuery.js' that is why call back is not working.. i.e main function is cannot be invoked as this is written using jQuery.
And you have missed a target 'div' tag with id = map(according to the code). Actually this is the target where map loads.
Another thing i have observed is maps is not actually a div in current context, that is maps api to load.
Here you must go with the Old school approach, That is.. You should include your skyrunner.js file at the top of the head content.
So try downloading that file and include in head tag.
Thanks

jQuery ready() and script sequence

I'm an jQuery noob and I'm wondering how fix this issue:
I have an external .js script, let's take reflection.js as example.
Reflection.js creates canvas reflection for every class="reflect" image.
I'm appending a few images trough different JS script that starts when ('document').ready.
Of course reflection.js doesn't work for images created by the script above.
How to avoid that?
I guess I'll need callback (?). Unfortunately I'm not getting idea of callbacks idea even after reading documentation.
[edit]
<script src="js/reflection.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery().ready(function() {
jQuery('#thumbs li').each(function(){
jQuery('.'+id+' a').append('<img src="' + imgURL + '" class="reflect" /></a>');
});
});
</script>
Image loading events do not bubble. You cannot hook into those.
Since your images have the class "reflect" it means you have some control over the source. So I recommend your reflection code publishes an API for you to call.
window.Reflect = function(img) {
...
};
...
var img = $("<img></img");
img.attr({
...
});
Reflect(img);
...
If you do not want to do this then you can poll the document for new images.
(function poll() {
var images = $("img.reflect");
...
images.removeClass("reflect")
setTimeout(poll, 500);
})();
If I understand this correctly, you have 2 functions under "ready" sequence and one script depends on other.
The way how I solved this problem, I have build my own includeJS as well as additional ready-checking layer on top of the one which jQuery has.
https://github.com/atk4/atk4/blob/master/templates/js/start-atk4.js
So my code looks like this:
$(function(){
$.atk4.includeJS('reflection.js');
$.atk4.includeJS('different.js');
$.atk4(function(){
$('.reflect').reflection();
});
});
What happens is, after document is ready, jQuery launches above code. It appends 2 scripts and evaluates them (by adding tag). When evaluation is complete, function atk4.get will execute readiness chain very similar to how jQuery does it.

jQuery .load() does not load plug-ins [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a main page with 2 links that load external files via .load(). The first file has a simple JavaScript rollover, which works when the content is loaded. The second file has a jQuery plug-in that does not work when loaded via .load() - but works fine when the data file is viewed by itself.
Main file: http://gator1105.hostgator.com/~carc/test-load.html
Second data file that works by itself, but not from .load(): (same URL as above, but the file is test-load-two.html - StackOverflow will allow me to create only 1 hyperlink)
Rather than paste my source code here, you can just view it from the pages themselves.
How can I get the second file with the slideshow to work when loaded with .load()?
I acutally did something similar with a site I'm working on. What you'll want to do is make a callback function for each page for the $.load() call on the main page.
See the following code from the jquery.load() documenation:
$('#result').load('ajax/test.html', function() {
alert('Load was performed.');
});
In your particular case, you'd want something like this on the main test-load.html page.
$(document).ready(
function(){
$('li').click(function(){
var showThisContent = this.id;
$('#content').load('test-load-'+showThisContent+'.html', function(){
if (showThisContent == "one"){
//Do logic for test-load-one.html
//Pre-load your images here.
//You may have to assign a class to your anchor tag
//and do something like:
$('a.assignedClass').mouseover(function(){});
$('a.assignedClass').mouseout(function(){});
} //end if
if (showThisContent =="two"){
//Do logic for test-load-two.html here
$('.slideshow').cycle({
fx: 'fade',
speed: 500,
timeout: 0,
next: '.nextSSimg',
prev: '.prevSSimg',
pager: '#SSnav',
cleartype: true,
cleartypeNoBg: true
}); //end .cycle()
} //end if
); //end .load(location, callback function())
}); //end $('li).click()
}); //end $(document).ready()
Now, obviously I didn't convert all your code, but what's happening here is that once document.ready is complete, the callback function will run, and since the elements like '.slideshow' are now loaded into the DOM, you're callback code will bind to them appropriately.
You could switch this code around in several ways to have the same result (i.e., wrap 2 $.load()s into conditions rather than doing the conditional logic in the .load callback, and/or put a callbackOne() and callbackTwo() function above document.ready and then call them appropriately) but that's your preference. You should be able to do what you want to using the callback function argument of the $.load().
Ignore this answer
Your second file does its initialization in a "document.ready" block. That's not going to be run when your content loads via AJAX. Try taking the code in the second page that's inside "document.ready" out of that, so that it's just a bare script block.
[edit] Oh I see - not only is the script inside a "document.ready" block (well, it's not anymore), but that second page is a complete HTML document. You can't really load a complete HTML document into the middle of another document; it doesn't make sense, and jQuery is only going to grab what's in the body. Thus, try moving your script tag into the body and see what happens. (You still don't want "document.ready", I don't think.)
[edit again] actually I take that back - I don't think jQuery strips anything out; I just bet the browser gets confused.
[edit yet again] ok, ok I see that you've changed it again - let me take a really close look.
OK here's a better answer: for reasons I don't understand, when you load a fragment (or a whole page; whatever) with jQuery using the special "selector" trick to pluck out just a portion of the document:
var showThisContent = this.id;
$('#content').load('test-load-' + showThisContent + '.html #content-area');
the jQuery library strips out the scripts completely from the content, and doesn't ever run them. Why? I don't know.
I know that you probably don't trust me anymore, but here's what I did with your source code: I took that second file (test-load-two) and stripped out the head and stuff; basically I made it a fragment containing only the "content-area". (I also got rid of the script tag that loads jquery, as you don't really need that since the outer page already has it.) Then I changed the main page (test-load) so that when it calls "load" it just passes in the URL without that '#content-area' selector. That works.
[edit] I just posted a question to the jQuery forum: http://forum.jquery.com/topic/the-load-function-and-script-blocks
Don't go for $.load. Try $.get instead, which might seem less comfortable, but it worked for me in a different case. Sample code as following.
$(li).click(function() {
// your code for finding the id
$.get('test-load-' + id + '.html', function(responseHtml){
$('div#content-area').empty().append($(responseHtml)); // remove all elements from #content-area
// $('...').html(responseHtml) will not work
});
});
I hope this solves your problem.

Categories