I have been trying to save resources on the page by not loading the Zendesk Widget unless required.
If i manually add to a page the following tag everything works just fine:
<script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=[MyKey]> </script>
As part of my page i have somewhere a div tag always present:
<div id="ze-snippet"> </div>
What i would like to have is, to do a "dynamic script load" of that <script> tag when a user clicks a button.
My current attempt looks like this:
window.onload = function () {
var zendeskWidgetOn = false;
document.getElementById('enable-zendesk-widget').addEventListener('click', function( event ) {
if (!zendeskWidgetOn) {
zendeskWidgetOn=true;
(function(d, script) {
script = d.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.onload = function(){
console.log('script finished loading ...');
};
script.src = 'https://static.zdassets.com/ekr/snippet.js?key=[my key]';
d.getElementsByTagName('head')[0].appendChild(script);
}(document));
}
}, false);
};
The error i keep getting and i can't for the life of me figure out how to work around it is:
To have the widget script load only upon clicking the button, you just have to insert this to your html:
<script>
function loadZendeskWidget() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.id = 'ze-snippet';
script.async = true;
script.src = 'https://static.zdassets.com/ekr/snippet.js?key=<key>';
document.getElementsByTagName('head')[0].appendChild(script);
};
</script>
Just replace "key" with your own widget key.
Hope this helps.
Related
I want to import jQuery in a JS file dynamically. Here is my code:
(function() {
var head = document.querySelector("head")[0];
if (head.classList.contains("En-Script") == true) {
head.classList.add("En-Script");
var script = document.createElement("SCRIPT");
let EnScript = document.querySelector(".En-Script");
script.type = "text/javascript";
script.src = "./jquery-3.6.0.min.js";
EnScript.appendChild("script");
} else {
console.log("class_list_added_for_further_process");
}
$(document).ready(function() {
console.log("jquery added successfully")
});
})();
There's a few things wrong, you were checking if head had the class "En-Script" and then adding the class to the head, so I changed the validation so it makes sense.
Then, you were selecting the head using querySelector which only returns 1 value and using [0] which would work if you were using querySelectorAll instead.
Then you should add the jquery function $(document) after the script has loaded, so I added a script.onload to achieve this.
Also when you append a child you should send the object you created, not a string, so instead of this EnScript.appendChild("script"); I used head.appendChild(script);
(function() {
var head = document.querySelector("head");
if (!head.classList.contains("En-Script")) {
head.classList.add("En-Script");
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js";
script.onload = function() {
$(document).ready(function() {
console.log("jquery added successfully")
});
};
head.appendChild(script);
} else {
console.log("class_list_added_for_further_process");
}
})();
There are various problems in your code.
querySelector returns one element, and not an array, so document.querySelector("head")[0]makes no sense.
With if (head.classList.contains("En-Script") == true) { you test if head has the class En-Script, which makes no sense in combination with head.classList.add("En-Script")
Also adding a class to the head to check if the script is loaded is probably not the best approach, if you want to do that add a class or data attribute to the script element you append.
If you already have head why do you use let EnScript = document.querySelector(".En-Script"); to query for it again?
EnScript.appendChild("script"); tries to append test string with the content script to EnScript and not the element you created and stored in the script variable.
$(document).ready(function() { would not wait for the script to be loaded.
Calling .ready( for when you loaded jQuery dynamically also does not make much sense because the DOM is already read.
That's how loading a script could look like:
(function() {
var head = document.querySelector("head");
var script = document.createElement("script");
script.type = "text/javascript";
script.onload = function() {
// called when the script is loaded and ready to use
console.log("jquery added successfully")
}
script.src = "https://code.jquery.com/jquery-3.6.0.slim.min.js";
head.appendChild(script);
})();
I have the following code in a script.js file that I call in my html file:
function loadScript(url)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.async = false;
head.appendChild(script);
}
loadScript('https://polyfill.io/v3/polyfill.min.js?features=es6')
loadScript('https://cdn.jsdelivr.net/npm/mathjax#3/es5/tex-mml-chtml.js')
loadScript('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js')
hljs.initHighlightingOnLoad();
I use this code because I want to call only one .js file in my html instead of multiple .js files.
The first two scripts that I load to call MathJax work fine. The third script to call highlight.js however does not run.
When I paste all the code from the file 'highlight.min.js' into the my script.js file, the javascript does run normally when I open the html.
I don't understand why loading the 'highlight.min.js' file with the loadScript() does not work, or what I can do to get it to work. Any help is appreciated.
The script loading is asyncronous, so when hljs.initHighlightingOnLoad() is called the scripts are not loaded yet.
Alternative 1
You can modify your loadScript() function to make it work with promises, which resolve when the script is loaded (taken from here):
function loadScript(url) {
return new Promise(function(resolve, reject) {
var script = document.createElement("script");
script.onload = resolve;
script.onerror = reject;
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
});
}
Now you can call your code and be sure that all libraries are loaded before calling hljs.initHighlightingOnLoad():
(async function init() {
await loadScript('https://polyfill.io/v3/polyfill.min.js?features=es6');
await loadScript('https://cdn.jsdelivr.net/npm/mathjax#3/es5/tex-mml-chtml.js')
await loadScript('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js')
hljs.initHighlightingOnLoad();
})()
Alternative 2
You can modify your loadScript() function to make it load the scripts using defer and add an optional onload handler that you can use to call hljs.initHighlightingOnLoad():
function loadScript(url, onload)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.async = false;
script.onload = onload;
head.appendChild(script);
}
loadScript('https://polyfill.io/v3/polyfill.min.js?features=es6')
loadScript('https://cdn.jsdelivr.net/npm/mathjax#3/es5/tex-mml-chtml.js')
loadScript('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/highlight.min.js', () => {hljs.initHighlightingOnLoad()})
Wheres your onload handler?
script.onload = function(){};
Lets not worry about errors for now...
https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement
If the libs require each other then you need to defer because the child may be smaller than the parent.
I need to add in some javascript code onto my page after an onclick. I have the following code but nothing happens on the button click and the page just outputs:
'); }); }); [button]
Here is my code:
<button type="submit" id="btn">button</button>
<div id="code"></div>
<script>
jQuery(document).ready(function () {
jQuery('#btn').click(function(){
jQuery('#code').append('<script>alert("WORKING");</script>');
});
});
</script>
This is actually a surprisingly simple task and doesnt require Jquery -- although you can execute the function with or without Jquery, however you like.
function AddNewExternalScriptToThisPage(ExternalScriptURLPath) {
var headID = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = ExternalScriptURLPath;
headID.appendChild(newScript);
}
You can also add in an onload event if you want:
function AddNewExternalScriptToThisPage(ExternalScriptURLPath) {
var headID = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = ExternalScriptURLPath;
newScript.onload=scriptHasLoadedContinue;
headID.appendChild(newScript);
}
I got it to work by escaping the forward slash in </script>. The closing script tag is not allowed in inline Javascript, as it messes with the way the code is parsed:
jQuery('#code').append('<script>alert("WORKING");<\/script>');
I have a js file that in which i want to include jquery. in order to include the jquery script i am using this clode:
var script = document.createElement('script');
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
this works, I can see that incuded the script correctly. My inspector shows that it loaded the script but jquery wont work.
any ideas?
You need to make sure the script you are dynamically loading is actually loaded before attempting to use it.
To do so, use script.onload to fire a callback once the load is completed.
var script = document.createElement('script');
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head') [0].appendChild(script);
script.onload = function () {
/* jquery dependent code here */
console.log($);
};
MDN has an example that's more adaptable to a callback you specify -
// from https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement#Dynamically_importing_scripts
function loadError (oError) {
throw new URIError("The script " + oError.target.src + " is not accessible.");
}
function importScript (sSrc, fOnload) {
var oScript = document.createElement("script");
oScript.type = "text\/javascript";
oScript.onerror = loadError;
if (fOnload) { oScript.onload = fOnload; }
document.currentScript.parentNode.insertBefore(oScript, document.currentScript);
oScript.src = sSrc;
}
Your jQuery code is not working may be caused by jQuery is not loaded yet while browser executing your jQuery code. Use function below to dynamically load jQuery with callback. Put your jQuery code inside a callback function.
function loadScript(url, callback) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = url;
if (typeof(callback) === 'function') {
s.onload = s.onreadystatechange = function(event) {
event = event || window.event;
if (event.type === "load" || (/loaded|complete/.test(s.readyState))) {
s.onload = s.onreadystatechange = null;
callback();
}
};
}
document.body.appendChild(s);
}
/* Load up jQuery */
loadScript('https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function() {
// Put your jQuery code here.
});
You need to include jQuery inside the HTML code. jQuery won't work for you because your script is loaded before jQuery is loaded.
I have a JavaScript file, which also uses jQuery in it too. To load it, I wrote this code:
function include(filename)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
head.appendChild(script)
}
include('http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js');
alert("1");
$(document).read(function(){});
alert("2");
This fires alert("1"), but the second alert doesn't work. When I inspect elements, I see an error which says that $ in not defined.
How should I solve this problem?
You need to execute any jQuery specific code only once the script is loaded which obviously might happen at a much later point in time after appending it to the head section:
function include(filename, onload) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
script.onload = script.onreadystatechange = function() {
if (script.readyState) {
if (script.readyState === 'complete' || script.readyState === 'loaded') {
script.onreadystatechange = null;
onload();
}
}
else {
onload();
}
};
head.appendChild(script);
}
include('http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js', function() {
$(document).ready(function() {
alert('the DOM is ready');
});
});
And here's a live demo.
You may also take a look at script loaders such as yepnope or RequireJS which make this task easier.
The problem here is probably that, even though you include the script, it doesn't mean it is loaded when you try to do $(document).ready(function(){});. You could look into Google Loader to prevent this problem http://code.google.com/intl/fr-FR/apis/loader/