is there any way to load jQuery file if it's not present without using document.write
<script>
window.jQuery || document.write('<script src="/path/to/your/jquery"><\/script>');
</script>
this way is good but it has major issue because if the visitor has slow connection the browser will prevent it from executing
when it happen I get this warning
file is invoked via document.write. The network request for this script MAY
be blocked by the browser in this or a future page load due to poor
network connectivity
I tried many solutions but nothing worked
You can pass a load callback to the IFFE that will be executed when the script loads or invoked immediately if jQuery exists.
var load = function(){
// your jQuery code goes here
$('#hello').html('jQuery Loaded');
};
(function(window, loadCallback){
if(!window.jQuery){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://code.jquery.com/jquery-3.3.1.min.js";
script.onload = loadCallback;
document.head.appendChild(script);
}else{
loadCallback();
}
})(window, load);
<div id="hello"></div>
Related
This question already has answers here:
'onload' handler for 'script' tag in internet explorer
(2 answers)
Closed 7 years ago.
I know my subject is quite tricky but i dont know how to much more ellaborate it on the subject alone.
so here how it goes.
i have a button
Load IT!
on the script tag:
function loadTheFile() {
var script = $("<script><\/script>");
script.attr("type", "text/javascript");
script.attr('src','http://www.thisismyexternalloadingjsfile"');
$('body').append(script);
alert("done! the file has been loaded");
}
the script well, when loaded will automatically have a modal box.
but the problem is, my alert seems to fire first than what is one the script
so how will i know if i have finished to load the script?
update for the first attempt to answer:
function loadTheFile() {
var script = $("<script><\/script>");
script.attr("type", "text/javascript");
script.attr('src','http://www.thisismyexternalloadingjsfile"');
$('body').append(script);
$(document).ready(function() {
alert("done! the file has been loaded")};
}
same problem
alert does indeed run before the script has been loaded. All that appending the script tag to the page does is append the script tag to the page. Then the browser has to download the script and, once received, run it. That will be after your loadTheFile function has exited.
So you need to get a callback when the script has actually be loaded and run. This is more standard than it used to be, but still has some cross-browser hassles. Fortunately for you, jQuery's already solved this problem for you (since you're using jQuery already):
function loadTheFile() {
$.getScript('http://www.thisismyexternalloadingjsfile"')
.then(function() {
alert("done! the file has been loaded");
});
}
Re your comment:
but my script file has data-* attributes
Assuming you're talking about data-* attributes on the script tag, then you'll have to do a bit more work, but it's still fairly straightfoward:
function loadTheFile() {
var load = $.Deferred();
var script = document.createElement('script');
script.src = 'http://www.thisismyexternalloadingjsfile"';
// No need for `type`, JavaScript is the default
script.setAttribute("data-foo", "bar");
script.onreadystatechange = function() {
if (script.readyState === "loaded") {
load.resolve();
}
};
script.onload = function() {
load.resolve();
};
load.then(function() {
alert("done! the file has been loaded");
});
document.body.appendChild(script); ;// Or wherever you want to put it
}
The onreadystatechange bit is to handle older versions of IE.
Rather than forge the script with text and jQuery, just use native Javascript:
var s = document.createElement('script');
s.onload = scriptLoaded;
s.src = '/path/to/my.js';
document.body.appendChild(s);
function scriptLoaded() {
console.log('Script is loaded');
}
Try something along these lines:
Your main page:
function whenScriptIsReady(){
alert('This function is called when the other script is loaded in!')
}
function loadTheFile() {
var script = $("<script><\/script>");
script.attr("type", "text/javascript");
script.attr('src','myotherjs.js');
$('body').append(script);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Load IT!
myotherjs.js:
alert('This will automatically run when the JS is loaded in!');
whenScriptIsReady();
JavaScript is executed asynchronously, so you alert will be executed before the browser can load the new script. If you want to execute logic after the script has been loaded, you could add an event listener to your script that will call the function 'loadFunc` once the script load is completed:
var loadFunc = function() {
alert("External Javascript File has been loaded");
};
//Other browsers trigger this one
if (script.addEventListener)
script.addEventListener('load', loadFunc, false);
I have senerio, where I need to render my HTML page by using dynamic JavaScript.
I am using loadScript function to load external JavaScript and passing callback funtion. In my HTML page , I am loading this script for my header.
My header section is working perfectly after the script is loaded and I my head section I can see my new script.
However , when I am trying to use the variables from this script its undefined.
function loadScript(url,callback){
var script = document.createElement("script");
script.type = "text/javascript";
script.id="acvDataRequest";
document.getElementsByTagName("head")[0].appendChild(script);
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
alert(dataHeader) // I CAN SEE MY OBJECT FROM LOADED SCRIPT
callback();
};
}
script.src = url;
alert(dataHeader); // IT SAYS UNDEFINED
}
calling a script using :
var actionName ="JSONdata/json.js";
loadScript(actionName,mergeTemplateJSONScript);
Please advice , why i can't see my variables even if my script is there.
Inside script.onload , I am able to see my variable but not outside
The line script.src = url; triggers the loading of the script file. If you call alert immediately after it your external script has not been loaded yet. You can only access variables from the json once the onreadystatechange or onload functions have been called.
What you should do is using it like this:
var actionName ="JSONdata/json.js";
loadScript(actionName,function(){
alert(dataHeader);
});
What you assign:
script.src = url;
that just starts the loading of the dynamic script. When you call the second alert() on the very next line your script has not yet loaded (it is loading in the background at that point). You can only reliably access the variables from the newly loaded script from within the onload handler or in some function called from the onload handler.
Keep in mind that the dynamic loading of scripts is asynchronous. That means it happens in the background while other scripts keep running (thus your second alert() runs before the script has finished). And, then the script finishes loading some time later and when it does the onload handler is called.
So, when you dynamically load scripts, all code that uses those scripts needs to either be in the onload handler, in some function called from the onload handler or guarenteed not to execute until some time later (such as in an event handler that you're sure won't happen before the script finishes loading).
To explain further, I've added some annotations to your code:
function loadScript(url,callback){
var script = document.createElement("script");
script.type = "text/javascript";
script.id="acvDataRequest";
document.getElementsByTagName("head")[0].appendChild(script);
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
// ** your script is now loaded here **
alert(dataHeader) // I CAN SEE MY OBJECT FROM LOADED SCRIPT
callback();
};
}
script.src = url;
// ** your script is in the process of loading here and has likely not completed **
alert(dataHeader); // IT SAYS UNDEFINED
}
What am I trying to do? In an attempt to speed up my website I am loading non-essential javascript after the browser load event. (So the JS files are not render blocking) This is currently functioning correctly.
What is the problem? The problem is sometimes the non-essential javascript depends on other libraries and plus those libraries need to load first.
What have I tried to do to fix the problem? In an attempt to fix the problem I have added a delay event to library dependent javascript. While this works sometimes, the load times of a JS file varies between refreshes and at times can load before the library even with a delay.
QUESTION: Does anyone know of a better way for me the load JS files only after the first JS file has loaded? (See code below)
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
var element2 = document.createElement("script");
var delay=40;
element.src = "http://119.9.25.149/sites/all/themes/bootstrap/bootstrap_nova/js/highcharts.js";
element2.src = "http://119.9.25.149/sites/all/themes/bootstrap/bootstrap_nova/js/future-plastic.js";
document.body.appendChild(element);
setTimeout(function(){
document.body.appendChild(element2);
},delay);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
As you can see from the above, I am trying to load the highcharts js file before I load the future-plastic file.
You're not the first to have this problem, thankfully. There's a lot of difficult solutions around this problem, including using a module loader as suggested in the comment (which I agree is the best long term solution, because they account for more browsers and flexibility, but it's a lot to learn to solve one small problem).
The place to start learning about this problem and the ways to tackle it are all over the web. This is a pretty good resource: http://www.html5rocks.com/en/tutorials/speed/script-loading/
You may want to try defer if you don't have to support Opera Mini or IE9. Or, you can load sync and execute as it loads- their examples is this:
[
'//other-domain.com/1.js',
'2.js'
].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
The reason why this might work (different browser implement this differently) is because the default is to load dynamically generated script tags are set to async by default, if you set it to false: "they’re executed outside of document parsing, so rendering isn’t blocked while they’re downloaded"
You should use ScriptElement.onload:
var pre = onload;
onload = function(){
if(pre)pre();
var doc = document, bod = doc.body;
function C(t){
return doc.createElement(t);
}
function downloadJSAtOnload(){
var s = C('script'), ns = C('script'), h = doc.getElementsByTagName('head')[0];
var u = 'http://119.9.25.149/sites/all/themes/bootstrap/bootstrap_nova/js/';
s.type = ns.type = 'text/javascript'; s.src = u+'highcharts.js'; h.appendChild(s);
s.onload = function(){
ns.src = u+'future-plastic.js'; h.appendChild(ns);
}
}
downloadJSAtOnload();
}
Note: The first onload is window.onload, since window is implicit.
I want to source a javascript file from facebook http://connect.facebook.net/en_US/all.js
The organization I work for has a firewall that blocks access to Facebook, it just goes to an html page that says "Access Denied blah blah blah"
I want to be able to put a javascript src tag <script src="http://... "> </script> and detect and suppress the warnings when the browser tries to evaluate the html as javascript.
Anyone know how?
Looks like jQuery.getScript is what you need as was mentioned. Or you can manually execute:
$.ajax({
url: url,
dataType: 'script',
success: function(){document.write('<script src="http://... "> </script>');}
});
And append your html on successful load with the <script></script> tag.
With the standard <script> tag, not possible. There's nothing really running at the time when the script's src is hit and content downloaded, so you can't wrap that in a try/catch block. There's some tips here on how to dynamically load scripts. Maybe the browsers will add some stuff to the DOM element created there which you can check for.
This is a workaround, not a direct answer, but you could simply set up a reverse proxy outside the firewall for Facebook and load the script from there. Instead of failing more gracefully, it would allow the script not to fail.
Try this, and see if it works for you:
<script type="text/javascript" onerror="throw('An error occurred')" src="http://connect.facebook.net/en_US/all.js"></script>
Alternatively, if you have access to a proxy script to grab external content I would use it via an xmlHttpRequest to grab the JS content. If it is successful, eval the content (yes, eval is evil, I know).
I would add that if you know the JS will fail, then why bother?
Why do you not do this in very simple way?:
if(!window.FB) { // or (typeof window.FB === "undefined")
alert ("ERROR: http://connect.facebook.net/en_US/all.js is not loaded");
}
if(!window.jQuery) { // or (typeof window.jQuery === "undefined")
alert ("ERROR: jQuery is not loaded");
}
// and so on
Please try the function below, it will only call the onload_function if the script has loaded. You can set a timeout to cancel the script.
function include_js(url, onload_function) {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) {
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
onload_function();
}
};
} else {
script.onload = function(){
onload_function();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
In Firefox and IE, you should be able to use window.onerror for this. You can take advantage of the fact that scripts run in the order they are listed in the HTML to wrap an error handler around just the facebook script:
<script>
// Remember old error handler, if there is one.
var oldOnError = window.onerror;
// Special error handler for facebook script
window.onerror = function(message, url, linenumber) {
// Potentially alert the user to problem
alert('Problem with facebook: ...');
// Return true to suppress default error handling
return true;
}
</script>
<!-- Load facebook script -->
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
// Remove error handler for facebook script
window.onerror = oldOnError;
</script>
I'm loading a few YUI scripts dynamically in my code in response to an Ajax request. The DOM and the page is fully loaded when the request is made - it's a response for an user event.
I add the <scripts> tag to head as children, but I stumbled in a few problems:
I add two YUI scripts hosted at the Yahoo! CDN and an inlined script of my own responsible for creating object, adding event listeners and rendering the YUI widgets. But I when my script run the YUI scripts are not loaded yet giving me errors and not running as I expect.
There's a way to only run my script (or define a function to be run) when YUI scripts are fully loaded?
Have you tried an onload event?
Edited:(thanks Jamie)
var script = document.createElement("script");
script.type = "text/javascript";
script.src = src;
//IE:
if(window.attachEvent && document.all) {
script.onreadystatechange = function () {
if(this.readyState === "complete") {
callback_function(); //execute
}
};
}
//other browsers:
else {
script.onload = callback_function; //execute
}
document.getElementsByTagName("head")[0].appendChild(script);
If you're using YUI 2.x I highly recommend using the YUI Get utility, as it's designed to handle just this sort of a problem.
If you are loading multiple individual script files from the Yahoo! CDN, you'll need to makes sure both are loaded before executing your dependent code. You can avoid this using the combo handler. See the Configurator to get what the script url should be to load both/all needed YUI files from one url.
http://developer.yahoo.com/yui/articles/hosting/
With that in mind, assuming you must load the YUI files asynchronously, you should use an onload/onreadystatechange handler as noted by digitalFresh.
I would recommend the following pattern, however:
(function (d) {
var s = d.createElement('script'),
onEvent = ('onreadystatechange' in s) ? 'onreadystatechange' : 'onload';
s[onEvent] = function () {
if (("loaded,complete").indexOf(this.readyState || "loaded") > -1) {
s[onEvent] = null;
// Call your code here
YAHOO.util.Dom.get('x').innerHTML = "Loaded";
}
};
// Set the src to the combo script url, e.g.
s.src = "http://yui.yahooapis.com/combo?2.8.1/...";
d.getElementsByTagName('head')[0].appendChild(s);
})(document);
You could use a setTimeout() to run some function that just checks if it's loaded - check something like
if (typeof YUI_NAMESPACED_THING !== "undefined") runCode()
EDIT Thanks, CMS
If I understand this correctly, your ajax response with this:
<script href="yui-combo?1"></script>
<script href="yui-combo?2"></script>
<p>some text here</a>
<script>
// using some of the components included in the previous combos
// YAHOO.whatever here...
</script>
If this is the case, this is a clear case in which you should use dispatcher plugin. Dispatcher will emulate the browser loading process for AJAX responses. Basically it will load and execute every script in the exact order.
Best Regards,
Caridy