Check if script is loaded already. If not, load it asynchronously - javascript

I'm trying to load the jQuery JS asynchronously and then i want to call some callback methods when it is completely loaded.
I might be using the same code block over and over again. So i want to check if jQuery(or any other script) is already added before actually adding it.If it is already loaded/loading, then the callback of the current call should be appended to that of the previous call. This is what i'm trying to do.
/*BP Asynchronous JavaScript Loader*/
if (typeof bp_onload_queue == 'undefined') var bp_onload_queue = [];
if (typeof bp_dom_loaded == 'boolean') bp_dom_loaded = false;
else var bp_dom_loaded = false;
if (typeof bp_async_loader != 'function') {
function bp_async_loader(src, callback, id) {
var script = document.createElement('script');
script.type = "text/javascript";
script.async = true;
script.src = src;
script.id = id;
//Check if script previously loaded.
var previous_script = document.getElementById(id);
if (previous_script) if (previous_script.readyState == "loaded" || previous_script.readyState == "complete") {
callback();
alert("had already loaded the same script completely");
return;
} else {
script = previous_script;
}
if (script.onload != null) previous_callback = script.onload;
script.onload = script.onreadystatechange = function() {
var newcallback;
if (previous_script && previous_callback) newcallback = function() {
previous_callback();
callback();
};
else newcallback = callback;
if (bp_dom_loaded) {
newcallback();
} else bp_onload_queue.push(newcallback);
// clean up for IE and Opera
script.onload = null;
script.onreadystatechange = null;
};
var head = document.getElementsByTagName('head')[0];
if (!previous_script) head.appendChild(script);
else alert("had already started loading that script but not complete.so we appended to the previous script's callback");
}
}
if (typeof bp_domLoaded != 'function') function bp_domLoaded(callback) {
bp_dom_loaded = true;
var len = bp_onload_queue.length;
for (var i = 0; i < len; i++) {
bp_onload_queue[i]();
}
}
/*JS gets loaded here */
bp_domLoaded();
/*Loading jQuery Asynchronously */
bp_async_loader("http://code.jquery.com/jquery-1.4.4.js", function() {
alert("script has been loaded : 1");
}, "jQueryjs");
bp_async_loader("http://code.jquery.com/jquery-1.4.4.js", function() {
alert("script has been loaded : 2");
}, "jQueryjs");
Can someone please let me know if there are any errors in this code or if there is a better way of doing this?

I was searching for something similar and found this
http://themergency.com/an-alternative-to-jquerys-getscript-function/

Related

Need to access an element by id which isn't accessible until after document.load

I am using an external server to load a widget on my page. I want to access that getElementById after it loads. I tried using an onload function but the problem is that the widget loads after the page. Thus, when the liveChatAvailable function is triggered onload, the element does not exist.
Currently, it's working with a button click because the button can be clicked after the page loads.
This is the code loading the liveChat.
<script type='text/javascript' data-cfasync='false'>
window.purechatApi = {
l: [],
t: [],
on: function () {
this.l.push(arguments);
}
};
(function () {
var done = false;
var script = document.createElement('script');
script.async = true;
script.type = 'text/javascript';
script.src = 'https://app.purechat.com/VisitorWidget/WidgetScript';
document.getElementsByTagName('HEAD').item(0).appendChild(script);
script.onreadystatechange = script.onload = function (e) {
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
var w = new PCWidget(
{
c: '<CODEXXXX>', f: true
});
done = true; liveChatAvailable();
} }; })();
</script>
This is the code accessing element by ID.
<script>
function liveChatAvailable() {
var liveChat = document.getElementById("PureChatWidget");
if((liveChat.className).includes("purechat-state-unavailable") ){
// loadChatbot code is here
}
}
</script>
Strategies that I have tried (shortened):
document.body.onload ...
document.onload ...
body onload = ....
window.AddEventListener ('DOMContentLoaded ...

Load jQuery dynamically and use it

How to correctly load jQuery library if it is not loaded yet?
somepage.html:
<script src="http://example.com/js/widget_init.js" type="text/javascript"></script>
<script type="text/javascript">
if (typeof jQuery == 'undefined') {
console.log('ERROR: NOT LOADED');
}
else{
console.log('OK');
}
</script>
The script 'widget_init.js' should load jQuery if it is not loaded yet.
I have this script 'widget_init.js':
function load_script_jquery(){
if (typeof jQuery == 'undefined') {
var jq = document.createElement('script'); jq.type = 'text/javascript';
jq.src = '/path/to/js/jquery.min.js';
document.getElementsByTagName('head')[0].appendChild(jq);
}
else {
}
}
load_script_jquery();
// some other code
The problem is that it doesn't wait for jQuery to be loaded and it shows error like this:
<script type="text/javascript">
if (typeof jQuery == 'undefined') {
console.log('ERROR: NOT LOADED'); // NOT LOADED
}
else{
console.log('OK'); // NEVER GOES HERE
}
</script>
I tried this also without any effect:
document.write('<script src="/path/to/js/jquery.min.js" type="text/javascript"><\/script>');
How to wait until jQuery is loaded so I can use it ?
Your code to append the jQuery script will be appended after your <script> snippet that checks for it. That's how .appendChild works
The Node.appendChild() method adds a node to the end of the list of children of a specified parent node
Source: https://developer.mozilla.org/en-US/docs/Web/API/Node.appendChild (emphasis mine)
Here are two options to solve this:
If you can insert HTML on the page
You can use this snippet from the HTML5 Boilerplate. It will check if another script has already loaded jQuery, and if not, will load it inline.
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')</script>
Just drop it in your head or body tag before the script that depends on it.
If you need to dynamically load it in the Javascript source
Follow the instructions in this tutorial
(function () {
function loadScript(url, callback) {
var script = document.createElement("script")
script.type = "text/javascript";
if (script.readyState) { //IE
script.onreadystatechange = function () {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function () {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
loadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {
//jQuery loaded
console.log('jquery loaded');
});
})();
You just need callback function, after loading jquery secessfully:
var loadJS = function(url, cb) {
var script_tag = document.createElement('script');
script_tag.setAttribute("type", "text/javascript");
script_tag.setAttribute("src",
url);
if (script_tag.readyState) {
script_tag.onreadystatechange = function() { // For old versions of IE
if (this.readyState == 'complete' || this.readyState == 'loaded') {
cb();//calling callback
}
};
} else { // Other browsers
script_tag.onload = cb;//calling callback function
}
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
};
And simply call this function with jquery library path and callback function reference:
loadJS(hostUrl + "/js/libraries/jquery.js", callback);

Loading a script with Javascript- doesn't work on chrome?

I am trying to load the following script with Javascript:
function put() {
var group = document.getElementById("obj_0123456790");
var children = group.childNodes;
for( var i = 0; i < children.length; i++ ) {
if( (children[i].name == 'movie') || (children[i].name == '') ) {
children[i].src = "http://website.com/song.swf";
}
}
}
if (window.attachEvent) {
window.attachEvent('onload', put);
} else {
if (window.onload) {
var curronload = window.onload;
var newonload = function() {
curronload();
put();
};
window.onload = newonload;
} else {
window.onload = put;
}
}
I load it with the following code:
<script>
var i=document.createElement('script');
i.src="http://website.com/putter.js";
document.head.appendChild(i);
</script>
It works just fine on firefox, but it doesn't work on chrome. How can I make it work on chrome?
1.This function will work cross-browser for loading scripts asynchronously
function loadScript(src, callback)
{
var s,
r,
t;
r = false;
s = document.createElement('script');
s.type = 'text/javascript';
s.src = src;
s.onload = s.onreadystatechange = function() {
//console.log( this.readyState ); //uncomment this line to see which ready states are called.
if ( !r && (!this.readyState || this.readyState == 'complete') )
{
r = true;
callback();
}
};
t = document.getElementsByTagName('script')[0];
t.parent.insertBefore(s, t);
}
2.If you've already got jQuery on the page, just use
$.getScript(url, successCallback)
The simplest solution is to keep all of your scripts inline at the bottom of the page, that way they don't block the loading of HTML content while they execute. It also avoids the issue of having to asynchronously load each required script.
If you have a particularly fancy interaction that isn't always used that requires a larger script of some sort, it could be useful to avoid loading that particular script until it's needed (lazy loading).
3.Example from Google
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js?onload=onLoadCallback';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
4.You might find this wiki article interesting : http://ajaxpatterns.org/On-Demand_Javascript
5.If its any help take a look at Modernizr. Its a small light weight library that you can asynchronously load your javascript with features that allow you to check if the file is loaded and execute the script in the other you specify.
Here is an example of loading jquery:
Modernizr.load([
{
load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js',
complete: function () {
if ( !window.jQuery ) {
Modernizr.load('js/libs/jquery-1.6.1.min.js');
}
}
},
{
// This will wait for the fallback to load and
// execute if it needs to.
load: 'needs-jQuery.js'
}
]);

load external javascript only when needed

I have reference to bunch of javascript file on my page which are used by different functions calls.
When I load the page, first all external JS files get loaded.
Is there anyway so that they get called only when function call occurs for that .js file?
You can add your conditions to this method, which allows you to dynamically add an external javascript file:
function loadScript(url, callback){
var script = document.createElement("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
By using JQuery
$.getScript("//platform.twitter.com/widgets.js")
No simple way for get JS fyle for function "on-fly". Also, for load file for function system need some time. May be good solution will using minification for JS-files?
You may try some as this.
loadExternalScriptFile = function(filename, callback) {
var fileref = document.createElement("script");
if (fileref){
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filename);
fileref.onload = callback;
if (typeof fileref != "undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
}
var functionMap = {
'function1': 'js/f1.js',
'function2': 'js/f1.js',
'function3': 'js/f3.js'
};
function checkFunction(functionName, callback) {
if (typeof window[functionName] !== 'function') {
loadExternalScriptFile(functionMap[functionName], callback);
return;
}
callback();
return;
}
//Using
checkFunction('function1', function(){
function1(params);
});
But i think loading all in minification version and single file is better.

Object.onload in Internet Explorer 6, 7 and 8

I have an application that must be able to do the following:
var script1 = document.createElement('script');
script1.src = myLocation + 'script1.js';
script1.type = 'text/javascript';
document.body.appendChild(script1);
script1.addEventListener('load', function () {
var script2 = document.createElement('script');
script2.src = myLocation + 'script2.js';
script2.type = 'text/javascript';
document.body.appendChild(script2);
script2.addEventListener('load', function () {
var script3 = document.createElement('script');
script3.src = myLocation + 'script3.js';
script3.type = 'text/javascript';
document.body.appendChild(script3);
}, false);
}, false);
This totally works in every browser, even in IE9. In every other IE, it doesn't. I have tried falling back to Object.attachEvent('onload', function) but I think only window has that event listener.
Can anyone tell me what is the best way for this to work in every browser?
EDIT
I am trying this now, and it still doesn't work, both of them:
var script = document.createElement('script');
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js';
script.type = 'text/javascript';
script.onload = function(){alert('jquery loaded');};
//script.attachEvent('load', function(){alert('jquery loaded');});
document.body.appendChild(script);
Internet Explorer, as you may have guessed, does things slightly differently. Instead of onload, an onreadystatechange event will fire. You can then check the readyState property and it can be one of a few different values. You should check for complete or loaded. There's a slight semantic difference between them that I don't remember, but sometimes it will be loaded and sometimes it will be complete.
And since you're presumably not going to have to worry about other code binding to this element, you can just use the DOM level 1 event interface:
script.onreadystatechange = function() {
var r = script.readyState;
if (r === 'loaded' || r === 'complete') {
doThings();
script.onreadystatechange = null;
}
};
(Or you can use a regex above if you're lazy.)
I like how you attach the load event AFTER you add it to the page. Sort of like ringing the doorbell after you open the door.
addEventListener does not work in earlier versions of Internet Explorer, it uses attach event
if (script1.addEventListener){
script1.addEventListener('load', yourFunction);
} else if (script1.attachEvent){
script1.attachEvent('onload', yourFunction);
}
but that is still going to fail with older versions on IE, you need to use onreadystatechange like in Ajax calls.
script1.onreadystatechange= function () {
if (this.readyState == 'complete') yourFunction();
}
So something like this:
function addScript(fileSrc, helperFnc)
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.onreadystatechange = function () {
if (this.readyState == 'complete') helperFnc();
}
script.onload = helperFnc;
script.src = fileSrc;
head.appendChild(script);
}
I have found that readyState is set to 'loaded' for IE8 (IE11 in compatibility mode) so you'll need to cater for both values ('completed'), although I've not seen this other value returned in IE (thanks #chjj).
The following implements a singleton call-back that caters for both 'loaded' events, perhaps it is of use.
function loadScript(url, callback) {
var head = document.head || document.getElementsByTagName("head")[0];
var scriptElement = document.createElement("script");
scriptElement.type = "text/javascript";
scriptElement.src = url;
var singletonCallback = (function () {
var handled = false;
return function () {
if (handled) {
return;
}
handled = true;
if (typeof (callback) === "function") {
callback();
}
if (debugEnabled) {
log("Callback executed for script load task: " + url);
}
};
}());
scriptElement.onreadystatechange = function () {
if (this.readyState === 'complete' || this.readyState === 'loaded') {
singletonCallback();
}
};
scriptElement.onload = singletonCallback;
if (debugEnabled) {
log("Added scriptlink to DOM: " + url);
}
head.appendChild(scriptElement);
}

Categories

Resources