Get data from server before loading next script - javascript

I have a few web pages that load Javascript files with the same basic structure.
page.html
<script src="js/common.js"></script>
<script src="js/page_specific.js"></script>
I now want to make a change to my pages to load some data from a backend server before running the page_specific.js.
The way I have done this so far is to remove the page_specific.js script tag from the HTML, create a Promise in the common.js that resolves once it has the data from the server. Then in the page.html I load the page_specific.js once the Promise is resolved:
// Load the options first (in common.js) and then load page specific js.
loadOptions.then(() => {
var js = document.createElement("script");
js.onload = () => {
page_specific.Init();
}
js.src = "js/page_specific.js";
document.body.appendChild(js);
});
This works but it, of course, means I have to change each of my pages (remove the script tag and add JS to load it dynamically later as per above).
Is there a way to achieve something similar that doesn't require changing every page (e.g. within common.js)? If not, is there any downside to the above method?
ETA: there is also a page specific function that is called from the HTML (different names). I've added the onload in code above.

Related

Is there any advantage to add 'defer' to a new script tag after $(document).ready()?

I have some javascript that is not required for my initial page load. I need to load it based on some condition that will be evaluated client-side.
$(document).ready(function() {
let someCondition = true; // someCondition is dynamic
if (someCondition) {
var element = document.createElement('script');
element.src = 'https://raw.githubusercontent.com/Useless-Garbage-Institute/useless-garbage/master/index.js';
element.defer = true; // does this make a difference?
element.onload = function() {
// do some library dependent stuff here
document.getElementById("loading").textContent = "Loaded";
};
document.body.appendChild(element);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id="loading">Loading...</h1>
Does it make a difference (in terms of how browser will treat the script tag), if a new tag created using javascript, after document is ready, has 'defer' attribute or not? I think there is no difference, but how can I say for sure?
I believe I understand how deferred scripts behave when script tag is part of the initial html (as described here). Also, this question is not about whether element.defer=true can be used or not (subject of this question).
No that doesn't make any difference, the defer attribute is ignored in case of "non-parser-inserted" scripts:
<script defer src="data:text/javascript,console.log('inline defer')"></script>
<script>
const script = document.createElement("script");
script.src = "data:text/javascript,console.log('dynamic defer')";
script.defer = true;
document.body.append(script);
</script>
<!-- force delaying of parsing -->
<script src="https://deelay.me/5000/https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Look at your browser's console or pay attention to the logs timestamps to see that the dynamically inserted script actually did execute while we were waiting for the delayed script to be fetched.
There's a difference between adding them to the function and adding directly the CDN ( especially in your case ).
Let's look at the code execution of the above-mentioned code first,
You have added the jquery CDN first ( without defer ) so that loads first.
$(document).ready will be fired once after the complete load of jquery.
There'll be the creation and insertion of a new script tag to the dom.
Download the https://raw.githubusercontent.com/Useless-Garbage-Institute/useless-garbage/master/index.js asynchronously.
Let's look at another approach: adding CDN to the code:
Your DOM will have 2 script tags.
Both will start loading based on the type of load parallelly ( defer async etc ).
Notice you are not waiting for the dom ready event to load the second script.
I suggest adding only the main JS part in a js file and adding it to the CDN. Others can wait load with the delay.
In case you are really needed with a js src, then don't load it the first way since it waits for the complete page load.
I suggest you read and look at web-vitals and SEO for this.
and for your other question, yes you can add defer attribute with element.defer=true to the elements while creating and loading to DOM.
Hope this answer helps you!
Feel free to comment if you get any errors or doubts.
I think the JQuery Arrive lib will solve your case.

Write a js script in a div

I am trying to get a script from another website using jQuery then document.write it
here is my code
var url = "https://code.jquery.com/jquery-1.10.2.js";
var dam = $.getScript(url);
document.write(dam);
But this doesn't work!!
all what I get on the page is [object Object]
Can this be achieved without XHR?
jsfiddle
Don't use document.write, it does not do what you think it does. What it does not do is write some data at the end of the document. What it does instead, is pipe data into the current write stream. And if there is no write stream, it will make a new one, resetting the document's content. So calling document.write(dam) means you just wiped your document. document.write is a low level JS function from an earlier era of JavaScript, don't use it.
Instead, you want to use modern DOM manipulation functions, so in jQuery, that's stuff like:
$(document.head).append($("<script>").attr("src", url));
where
$("<script>")
builds a new script element,
$(...).attr("src", url)
sets the "src" attribute to what you need it to be, and:
$(document.head).append(...)
or
$(document.body).append(...)
to get the script loaded into your document. If it's a plain script with src attribute, it can basically go anywhere, and if it's a script with text content that should run, you can only make that happen through document.head.
Although if it's just a script you need to load in and run, you can use getScript, but then you don't need to do anything else, it's just:
var url = "https://code.jquery.com/jquery-1.10.2.js";
jQuery.getScript(url);
Done, jQuery will load the script and execute it. Nothing gets returned.
Of course, the code you're showing is loading jQuery, using jQuery, so that's kind of super-odd. If you just want to load jQuery on your page, obviously you just use HTML:
<!doctype html>
<html>
<head>
...
</head>
<body>
...
<script src="http://https://code.jquery.com/jquery-1.10.2.js"></script>
</body>
</html>
with the script load at the end so the script load doesn't block your page. And then finally: why on earth are we loading jQuery version 1.x instead of 2.x? (if you need to support IE8: that's not even supported by Microsoft anymore, so you probably don't need to).
And finally, if we don't want to load the script, but we really just want its content, as plain text, there's only a million answers on Stackoverflow already that tell you how to do that. With jQuery, that's:
$.get("http://https://code.jquery.com/jquery-1.10.2.js", function(data) {
$(document.body).append($("div").text(data));
});
But you knew that already because that's been asked countless times on Stackoverflow and you remembered to search the site as per the how to ask instructions before asking your question, right?
executing the script on the page is not my goal!. I want to get the
script content and put it a div (USING JAVASCRIPT - NO XHR) , is that
possible ?
Try utilizing an <iframe> element
<div>
<iframe width="500" height="250" src="https://code.jquery.com/jquery-1.10.2.js">
</iframe>
</div>
jsfiddle http://jsfiddle.net/snygv469/3/
Make it easier... use my fiddle
http://jsfiddle.net/wwwfzya7/1/
I used javascript to create an HTML element
var url = "https://code.jquery.com/jquery-1.10.2.js";
var script = document.createElement("SCRIPT"); //creates: <script></script>
script.src = url; //creates: <script src="long_jquery_url.js"></script>
document.body.appendChild(script); //adds the javascript-object/html-element to the page.!!!
Use this way, it can fix your problems.
$.get( "https://code.jquery.com/jquery-1.10.2.js", function( data ) {
alert(data);
});
You can try adding
<script src="http://code.jquery.com/jquery-1.8.3.min.js" ></script>
Then an AJAX call, but it pulls data from CACHE. It looks like an AJAX but when <script> is added file goes in cache, then read from cache in the ajax. In cases where it is not stored in cache read it using normal AJAX.
jQuery.cachedScript = function(url, options) {
// Allow user to set any option except for dataType, cache, and url
options = $.extend(options || {}, {
dataType: "text",
cache: true,
url: url
});
// Use $.ajax() since it is more flexible than $.getScript
// Return the jqXHR object so we can chain callbacks
return jQuery.ajax(options);
};
$(document).on('ready', function() {
// Usage
$.cachedScript("http://code.jquery.com/jquery-1.8.3.min.js").done(function(script, textStatus) {
console.log(script);
});
});
Normal Solution
If you are ready to use AJAX look at this fiddle
How to fetch content of remote file and paste it on your document and execute that js code
I guess you want to get content written on remote file and want to write that content in your HTML. to do this you can use load() function.
To do this follow the following steps:
1. Create a file index.html Write the following code in it:
<pre id="remote_script"></pre>
<script>
$(document).ready(function() {
//var url = "https://code.jquery.com/jquery-1.10.2.js";
var url = "remote_script.html";/* For testing*/
$('#remote_script').load(url,function(){
eval($('#remote_script').text()); /* to execute the code pasted in #remote_script*/
});
});
</script>
2. Create another file remote_script.html for testing write alert('a'); in it without any <script> tag and run the above code.

Run an java script after controller has been loaded in CodeIgniter

I'm creating a Java Script widget for the site based on CodeIgniter. The site using templates and Blade library. I need to load my java script right after the page has been loaded. I have added it into template scripts.blade.php:
<script src="{{apps_url('assets/my_widget/js/my_widget.js')}}"></script>
Unfortunately, it seems, what my script was executed before controller has been loaded and therefore the script can not find required SVG object:
(function() {
var container = d3.select(".myContainer");
alert("container: " + container);
})();
This alert show what container is null even if the myContainer object actually exists on the page and was recognized by CSS. The d3 library has been loaded properly and there is no errors in the Firefox console.
Is there a way to execute this script right after the object has been loaded?
use
$(document).ready(function() {
(function() {
var container = d3.select(".myContainer");
alert("container: " + container);
})();
});

Rerun Javascript in dynamically filled iframe

On a page i try to fill an empty <iframe id="myFrame"></iframe> with the HTML code of an ajax result. That works well, except script tags in the code are not being executet, so i have to readd them to the iframe's page:
$.post('page.php', function(code) {
$("#myFrame").contents().find("html").get(0).innerHTML = code;
$("#myFrame").contents().find("script").each(function() {
$old_script = $(this);
$frame = document.getElementById("myFrame");
$new_script = $frame.contentWindow.document.createElement("script");
$new_script.type = "text/javascript";
$new_script.src = $old_script.attr("src");
$old_script.remove();
$frame.contentWindow.document.head.appendChild($new_script);
});
});
That works basically, but the document seems to load the Javascript files in a different order. There are 3 js files to load: jquery.min.js, a jquery plugin and a main.js file to control the bahavior inside the iframe:
// main.js:
$(document).ready(function() {
alert("frame document loaded");
// call the jquery plugins etc...
});
The page alerts me "frame document loaded", but cannot execute the jquery plugins. Double-checked the script paths, but they're right. Seems that the jquery.min.js and main.js are loaded before the plugin files.
How could i achieve to load the javascript files one by one as specified originally in the code returned by the ajax request?
EDIT: Forgot to say that sometimes everything works well and the javascript seems to be loaded correctly. On reload it breaks again.

Unload external .js file

I'm loading some HTML and JS with AJAX:
main-page.html loads vía AJAX a page called page-to-load.html.
<!-- main-page.html -->
<html>
...
<script>
$.ajax({
type:"POST",
url:"page-to-load.html",
success:function(data) {
$("#some_id").html(data);
}
});
</script>
...
</html>
page-to-load.html includes html and a js file:
<!-- page-to-load.html --->
<script src="scripts-for-this-html.js"></script>
<p>This is a HTML page working with above external .js file</p>
As you can see, i'm loading a js file, scripts-for-this-html.js
This works perfectly. The problem is that if I loaded again (I mean, "#some_id" gets empty and loaded with page-to-load.html again) all the script (scripts-for-this-html.js) remains in the browsers memory (for example, if I have an event in this .js file, this event gets repeated as many times I had loaded the file, even if i have deleted the script element from the DOM).
Is there any way to get this work? I don't want to include all the .js files at once (ther are too many), I want to loaded and unloaded them by demand.
JavaScript unloading could theoretically be done by removing the script tag (as you are doing with .html and by eliminating all references to any objects associated with the script. This involves deleting every reference and event listener. Even one left could keep that variable's functional scope in memory causing a leak.
It would be smart to use regular expressions to remove the scripts if the have been loaded already. (Credit to #JCOC611 for the idea of stripping tags.) Something like:
var usedScripts = {};
html = html.replace(/<script\s+src="([^"]+)"><\/script>/gi, function(str, file) {
if(usedScripts[file]) {
return "";
} else {
usedScripts[file] = true;
return str;
}
});
If you have a finite number of pages, what I prefer to do is have an object:
{
myPage: {
html: 'myhtml.html',
script: 'myscript.js'
}
}
Then have a loader function which simultaneously loads the script with document.createElement('script') and loads the page with HTML. You could easily check if that script has been used and skip loading.

Categories

Resources