What are the difference of adding javascript src vs textual javascript? - javascript

What is the difference of adding
<script type="text/javascript" src="helloworld.js">
in document head
vs
adding
<script type="text/javascript">document.write("Hello World"); //content of helloworld.js</script>
I am trying to override Sencha Touch injectScriptElement function by pulling the JS content from Database. Not sure what i am doing wrong:
Ext.apply(Ext.Loader, {
injectScriptElement: function(url, onLoad, onError, scope, charset) {
var script = document.createElement('script'),
me = this,
onLoadFn = function() {
me.cleanupScriptElement(script);
onLoad.call(scope);
},
onErrorFn = function() {
me.cleanupScriptElement(script);
onError.call(scope);
};
script.type = 'text/javascript';
//script.src = url;
script.text = me.getContentFromDatabaseByUrl(url);
script.onload = onLoadFn;
script.onerror = onErrorFn;
script.onreadystatechange = function() {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
onLoadFn();
}
};
if (charset) {
script.charset = charset;
}
me.documentHead.appendChild(script);
return script;
}
});

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 ...

Dynamically load several JS files and fire a callback when all are ready

I have several JS and CSS files which need to be appended to the DOM dynamically with JavaScript. The method described here works fine for 1 file. However I have several of them and they should be appended/loaded in certain order:
var resources = {
"jquery" : "jquery.js",
"jqueryui" : "jquery_ui.js",
"customScript" : "script.js"
}
If that matters - the resources can be in an array rather than in an object.
What I think should be done is to load each next resource in the callback of the previous one. And the callback of the last resource should call another function, which, in my case will render the HTML. However I'm not sure how to organize it with the code given in the link above. Another important aspect is that this should be done with pure JavaScript.
Any clues?
Thanks!
I would suggest you to make an array of your resources rather than an object if you care about the order of their loading. I hope this solution will solve your issue.
var urls = ['https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.js',
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.slim.js'
];
var i = 0;
var recursiveCallback = function() {
if (++i < urls.length) {
loadScript(urls[i], recursiveCallback)
} else {
alert('Loading Success !');
}
}
loadScript(urls[0], recursiveCallback);
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);
}
Working Fiddle : https://jsfiddle.net/nikdtu/6uj0t0hp/
I haven't tested but in concept this should work. Loop through your object. Each time you loop through create a script element then add your script to the to the source of the script element you just created. Get the last script of your resource (lastObj) and compare it with resource[key] if they are equivalent call the onload function, this will determine when the last script is loaded.
var resources = {
"jquery": "jquery.js",
"jqueryui": "jquery_ui.js",
"customScript": "script.js"
}
var lastObj = resources[Object.keys(resources)[Object.keys(resources).length - 1]]
var script = [];
index = 0;
for (var key in resources) {
script[index] = document.createElement('script');
if (lastObj === resources[key]) {
script[index].onload = function() {
alert("last script loaded and ready");
};
}
script[index].src = resources[key];
document.getElementsByTagName('head')[0].appendChild(script[index]);
index++;
}
If you don't care about old browsers you can use the following modification to load them.
index.html
<!DOCTYPE html>
<html>
<head>
<title>Stack Overflow</title>
<link rel="stylesheet" type="text/css" href="css/jquery-ui.min.css">
<script type="text/javascript" src="scripts/loader.js" ></script>
</head>
<body>
<h1>Test javascript loading strategy</h1>
<p id="result">Loading...</p>
<p>Date: <input type="text" id="datepicker"></p>
</body>
</html>
loader.js
function loadScript(url){
return new Promise(function(resolve, reject) {
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;
resolve();
}
};
} else { //Others
script.onload = function(){
resolve();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
});
}
var resources = [
"scripts/jquery.js",
"scripts/jquery_ui.js",
"scripts/script.js"
]
function loadAllResources() {
return resources.reduce(function(prev, current) {
return prev.then(function() {
return loadScript(current);
});
}, Promise.resolve());
}
loadAllResources().then(function() {
$('#result').text('Everything loaded');
});
custom script script.js
$( "#datepicker" ).datepicker();
Working JSFiddle

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);

Include the jquery file dynamically [duplicate]

This question already has answers here:
Load jQuery with Javascript and use jQuery
(9 answers)
Closed 9 years ago.
I want to include the jquery file dynamically when I need to it.
But there is a problem, the error message that appear $ is not defined
What I done:
// include the file dynamically.
var parent, script;
parent = document.getElementsByTagName('head')[0];
script = document.createElement('script');
script.type = "text/javascript";
script.src = "includes/jquery.js";
parent.appendChild(script);
// The usage
$('#box').remove();
For IE, I think you need to use the onreadystatechange callback. E.g.
script.onload = script.onreadystatechange = function() {
if (!script.readyState || script.readyState == 'loaded' ||
script.readyState == 'complete') {
$('#box').remove();
}
};
Handle onload event to make sure your script is loaded before you use it
script.onload = function () { $('#box').remove() }
parent.appendChild(script);
try this:
(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("includes/jquery.js", function () {
//jQuery loaded
console.log('jquery loaded');
$('#box').remove();
});
})();

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