Set response data from external JS script - javascript

I have this script
<script>
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('/script/script.js', function() {
// put your code here to run after script is loaded
});
</script>
And I can't figure out how can I get response data from the script I'm trying to load.
Basically, this script contains a function that does something and then returns some value.
I know that in jQuery analog in would be just data argument in getScript function, but I only have native JS here.
What and where should I add to get response data in my script?

Assuming that your script contains a function declared in a global scope, you can simply include this script and then execute any function / access any member from this script:
After your script has been loaded and executed, you can work with it just like with a simple script which is a part of your current document.
Here is a demo which loads jQuery script from Google CDN and then outputs jQuery version (which is a part of jQuery library):
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
console.log("typeof jQuery: " + typeof jQuery); // jQuery not loaded
loadJS("https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js", function() {
console.log("typeof jQuery: " + typeof jQuery + ", version = " + jQuery.fn.jquery); // jQuery has been loaded
});

Related

Load scripts if not already loaded, and then use them

I have 4 javascript libraries I would like to load if the are not already loaded. Then, I want to use their functions.
My problem is that I am getting Uncaught ReferenceError: sbjs is not defined, the scripts get loaded but I can't actually use them.
I have it working perfectly to where it will add the scripts above the </body> tag if they are not already loaded, but I can't seem to get them to work.
Here is my code:
<script>
window.onload = myapp_scripts;
function myapp_scripts () {
var myapp_script;
if (!window.jQuery) {
myapp_script = document.createElement('script');
document.body.appendChild(myapp_script);
myapp_script.src = 'http://myapp.dev/js/jquery.min.js';
console.log('load jquery');
}
if (!window.Cookies) {
myapp_script = document.createElement('script');
document.body.appendChild(myapp_script);
myapp_script.src = 'http://myapp.dev/js/cookie.min.js';
console.log('load cookies');
}
if (typeof url == 'undefined') {
myapp_script = document.createElement('script');
document.body.appendChild(myapp_script);
myapp_script.src = 'http://myapp.dev/js/url.min.js';
console.log('load url');
}
if (typeof sbjs == 'undefined') {
myapp_script = document.createElement('script');
document.body.appendChild(myapp_script);
myapp_script.src = 'http://myapp.dev/js/sourcebuster.min.js';
console.log('load sbjs');
}
myapp_init();
}
function myapp_init () {
sbjs.init();
console.log(Cookies.get('source_id'));
console.log(url('source_id'));
console.log(sbjs.get.current);
$('#myapp_form').submit(function (event) {
event.preventDefault();
console.log('form submitted');
});
}
</script>
How do I make it so I can also use the scripts I've loaded dynamically?
I think your problem is because myapp_init() is executed before scripts are loaded
You need to manage script load event and after call myapp_init()
some like this inside each if() condition:
var myapp_script;
var scripts_loaded = 0;
if (!window.jQuery) {
myapp_script = document.createElement('script');
document.body.appendChild(myapp_script);
myapp_script.src = 'http://myapp.dev/js/jquery.min.js';
console.log('load jquery');
myapp_script.onload = function(){
scripts_loaded ++;
if(scripts_loaded === 4){ //4 because in your example you have 4 scripts to load
myapp_init();
}
}
}else{
scripts_loaded ++;
}
//...
//And so on with others if conditions
Is not a elegant solution but is only one the idea: to check in some way if all scripts are loaded and after that call myapp_init();

Defer Loading of javascript for google page insights

I have a code for defer loading of javascript I am wondering if the code will load the scripts in order (JQuery.min first) according to where they are in the code ?
function downloadJSAtOnload() {
var element01 = document.createElement("script");
element01.src = "js/jquery.min.js";
document.body.appendChild(element01);
var element02 = document.createElement("script");
element02.src = "js/plugins.js";
document.body.appendChild(element02);
var element03 = document.createElement("script");
element03.src = "js/scripts.js";
document.body.appendChild(element03);
var element04 = document.createElement("script");
element04.src = "js/SmoothScroll.min.js";
document.body.appendChild(element04);
var element05 = document.createElement("script");
element05.src = "js/contact-form.js";
document.body.appendChild(element05);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
If this doesn't load JQuery.min first and then the other js files how can you make JQuery.min the first script to load and then the rest after that has loaded?
Also I am guessing for example the contact-form.js will be one of the first to finish loading as it's small so this could cause the Uncaught ReferenceError: $ is not defined I'm guessing because the JQuery.min hasn't finished downloading so how would you solved this ? I'm guessing an listener / if finished loading load the others else wait...
Thanks in advance
found here Load jQuery with JavaScript using Promises
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);
});
}
function loadjQuery() {
if (window.jQuery) {
// already loaded and ready to go
return Promise.resolve();
} else {
return loadScript('https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js');
}
}
// Usage:
loadjQuery().then(function() {
// code here that uses jQuery
}, function() {
// error loading jQuery
});
This is quick, but I think it should work.
function downloadJSAtOnload() {
var element01 = document.createElement("script");
element01.src = "js/jquery.min.js";
document.body.appendChild(element01);
element01.onload = function() {
var element02 = document.createElement("script");
element02.src = "js/plugins.js";
document.body.appendChild(element02);
var element03 = document.createElement("script");
element03.src = "js/scripts.js";
document.body.appendChild(element03);
var element04 = document.createElement("script");
element04.src = "js/SmoothScroll.min.js";
document.body.appendChild(element04);
var element05 = document.createElement("script");
element05.src = "js/contact-form.js";
document.body.appendChild(element05);
}
}

can't run jQuery functions after appending jQuery from same file

I'm appending into my page multiple scripts including jQuery, jQuery migrate... all from same .js file
this is how it looks:
function appendScript(pathToScript, run) {
var head = document.getElementsByTagName("head")[0];
var js = document.createElement("script");
js.type = "text/javascript";
if(run == true){
js.onreadystatechange = function () {
if (this.readyState == 'complete') runFunctions();
}
js.onload = runFunctions;
}
js.src = pathToScript;
head.appendChild(js);
}
appendScript("http://code.jquery.com/jquery-latest.min.js");
appendScript("http://code.jquery.com/jquery-migrate-1.3.0.min.js", true);
function runFunctions(){
console.log('test') // all good till here
// here i have only jquery functions
$('#myDiv').addClass('test');
alert("this doesn't work");
....
}
My problem is that I can't run $(document).ready or any jQuery function, only javascript.
Tried with timeout too. Also I already have 1 x $(window).bind("load", function(){...} so I don't need 1 more
Since jQuery Migrate depends on jQuery, you need to wait until loading the next script.
Here is a working example (I also cleaned up some variables).
function appendScript(src, callback) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.type = "text/javascript";
if (callback) {
script.onload = callback;
}
script.src = src;
head.appendChild(script);
}
appendScript("https://code.jquery.com/jquery-latest.min.js", function() {
appendScript("https://code.jquery.com/jquery-migrate-1.3.0.min.js", function() {
document.body.innerHTML = 'Loaded jQuery version ' + jQuery.fn.jquery;
});
});
See working jsfiddle.

how to namespace jquery to be used throughout my site

in my script below, I use javascript to load jquery dynamically first. Once loaded, I want to namespace jquery's $ so that I may use another name for it throughout my site. For instance, instead of calling $('body'). , I want to call MYNAMESPACE('body'). But I can't get the namaspacing done correctly. Please help me on that part. Thanks..
(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("/plugins/system/conversekit/js/jquery.js", function () {
//jQuery loaded
alert('jquery loaded');
var cKit = (function($){
var loadScripts = function(){
var jq = $.noConflict();
return jq;
}
return {
ConversekitJs : loadScripts// I expect this to return namespaced jquery
};
}
})(jQuery);
var js = cKit.ConversekitJs(); //function call
//so that I may use jq instead of $ or jQuery
js('body').css('background-color', '#ff0000');
});
})();
EDIT based on answer suggested by R.J:
var myNameSpace = jQuery.noConflict();
(function(myNameSpace) {
//Use your namespace
myNameSpace('body').css('background-color', '#ff0000');//works
myNameSpace.getScript("/js/events.js");//in this file myNameSpace has no effect..
})(myNameSpace)
In events.js
myNameSpace('body').css('background-color', '#ff0000');//doesn't work
But if I add var myNameSpace = jQuery.noConflict(); on top of the page it would work..This is what I want to avoid. Instead of declaring this in each page, I would like to define once in top level.
You can use jQuery.noConflict with IIFE
var myNameSpace = jQuery.noConflict();
(function(myNameSpace) {
//Use your namespace
myNameSpace('body').css('background-color', '#ff0000');
})(myNameSpace)
It is possible, but you would have to edit the jQuery source code somewhat.
/*!
* jQuery library
*/
( function( global, factory ) {
...
})(window);
var myNamespace = myNamespace || {};
myNamespace.$ = myNamespace.jQuery = jQuery.noConflict(true);
This should give you the jquery function or the $ shortcut under your own namespace.

Javascript - Loading multiplescripts on page dynamically with dependencies

I am trying to develop a page constructor made all with javascript. The problem comes when I dynamically add 2 scripts on the page that depends on the other. In this example I am loading the jQuery from the CDN, and in the second script I call a jQuery function to modify the text of the title, and, because the first is not already loaded, I get the error ReferenceError: $ is not defined.
What is the best way? Maybe wait to load the next script until previous one gets loaded?
One tip, I dont want to use external libraries like RequireJS (this would need to be updating the page everytime the plugin updates, and it would never be possible in this case).
EXAMPLE
Thats my JS classes:
NS.Script = function(nHasCode, nType, nSrc, nContent){
this.hasCode = nHasCode;
this.src = nSrc;
this.type = nType;
this.content = nContent;
};
NS.Page = function(){
this.id;
this.isIndex;
this.title;
this.metas = [];
this.links = [];
this.styles = [];
this.scripts = [];
this.body;
};
NS.Page.prototype.addScript = function(hasCode, type, src = null, content = null){
var aux = new NS.Script(hasCode, type, src, content);
var pageScripts = this.scripts;
pageScripts.push(aux);
};
NS.Pages = {
load: function(page){
//document.write(page.body);
document.body.innerHTML = page.body;
document.title = page.title;
page.scripts.forEach(function(pageScript) {
if(pageScript.hasCode){
document.write("<script type="+pageScript.type+">"+pageScript.content+"<\/script>");
}else{
var s = document.createElement( 'script' );
s.setAttribute( 'type', pageScript.type );
s.setAttribute( 'src', pageScript.src );
if (s.readyState){ //IE
script.onreadystatechange = function(){
if (s.readyState == "loaded" ||
s.readyState == "complete"){
s.onreadystatechange = null;
//maybe here I have to call the script load of every dependance
}
};
} else { //Others
s.onload = function(){
//callback();
//maybe here I have to call the script load of every dependance
};
}
document.getElementsByTagName("head")[0].appendChild( s );
}
});
}
};
Finally I create a page and add two scripts:
var pagina = NS.Pages.new("Prueba", "Pagina 1");
pagina.title = "Page title";
pagina.isIndex = true;
pagina.body = "<h1 id='title'>Page title with H1</h1><p>This could be a paragraph</p>";
pagina.addScript(false, 'text/javascript', 'https://code.jquery.com/jquery-2.2.3.min.js');
pagina.addScript(true, 'text/javascript', null, "$('#title').text('The new title configured with jQuery');");
NS.Pages.load(pagina);
<script type="text/javascript">
function loadJavaScriptSync(filePath)
{
var req = new XMLHttpRequest();
req.open("GET", filePath, false); // 'false': synchronous.
req.send(null);
var headElement = document.getElementsByTagName("head")[0];
var newScriptElement = document.createElement("script");
newScriptElement.type = "text/javascript";
newScriptElement.text = req.responseText;
headElement.appendChild(newScriptElement);
}
loadJavaScriptSync("file1.js");
loadJavaScriptSync("file2.js");
</script>
Code snippet taken from: http://trevweb.me.uk/javascripthtml-synchronous-and-asynchronous-loading/
Looks like a chicken and egg problem. It stems from the fact that dynamically inserted <script> tags get a default "async" property and are executed in unpredictable order. According to Mozilla, you can request them to be synced:
var s = document.createElement( 'script' );
s.setAttribute( 'type', pageScript.type );
s.setAttribute( 'src', pageScript.src );
s.async = false;

Categories