Page loading blocks by remote javascript - javascript

I am loading external javascript on my site through:
<script language="javascript" type="text/javascript">
document.write("<script src='http://remoteserver/banner.php?id=10&type=image&num=3&width=200'><\/script>");
</script>
Everything was fine, but today was a big timeout from the remote server and page loading on site was blocking.
Is there possibility to load javascript asynchronous or to load it after page loads?
I don't want page load interruption while remote server not working.
I know there are tag async in HTML5, but it's not working, i think because this script is more complex than javascript (its ending with ".php").
Also i know it's better to put javascript files before /body tag to prevent this problem, but it's not the best solution.
Do you know other solutions?

Sync script blocks the parser...
Incorrect Method:
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
</script>
Async script will not block the rendering of your page:
Correct method:
<script type="text/javascript">
(function(){
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = "https://apis.google.com/js/plusone.js";
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
Source: http://www.youtube.com/watch?feature=player_detailpage&v=Il4swGfTOSM&t=1607

You can easily do it by creating DOM nodes.
<script>
var scriptEl = document.createElement("script"); //Create a new "script" element.
scriptEl.src = "http://remoteserver/banner.php?id=10&type=image&num=3&width=200";
// ^ Set the source to whatever is needed.
document.body.appendChild(scriptEl);
// Append the script element at the bottom of the body.
</script>

Related

how to solve the Defer parsing of JavaScript?

How to solve the following error:
826.9KiB of JavaScript is parsed during initial page load. Defer parsing JavaScript to reduce blocking of page rendering.
My Javascript code is:
{foreach $javascript.external as $js}
<script type="text/javascript" src="{$js.uri}" {$js.attribute} ></script>
{/foreach}
Assuming you are adding scripts in the head tag ,you can defer blocking of page rendering by adding the script near closing body tag instead of in header.
Alternatively create a IIFE and load the scripts after page has rendered
(function() {
function loadJS() {
var s = document.createElement('script'),
getScriptTag = document.getElementsByTagName('script')[0];
s.type = 'text/javascript';
s.async = true;
s.src = 'script location';
getScriptTag.parentNode.insertBefore(s, x);
}
(window.attachEvent) ? window.attachEvent('onload', loadJS): window.addEventListener('load', loadJS, false)
}());

How to dynamically add script which will be executed right now?

There is the simple page:
<html>
<head>
<script type="text/javascript" src="scripts/x.js"></script>
</head>
<body>
<script type="text/javascript">
console.log($);
</script>
</body>
</html>
'scripts.x.js':
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://code.jquery.com/jquery-1.12.3.min.js';
script.async = false;
script.defer = false;
document.currentScript.parentNode.insertBefore(script, document.currentScript.nextSibling);
This script just adds a new external script tag right after current script, but it doesn't work, because 'console.log' writes error 'index.html:8 Uncaught ReferenceError: $ is not defined'. What am I doing wrong? Thanks in advance!
The problem is that because of the asynchronous I/O model of JavaScript the script doesn't do what you expect. You probably think the script will stop executing while jQuery is loading, then continue once the external script (https://code.jquery.com/jquery-1.12.3.min.js in your case) is loaded.
What actually happens is that the I/O operation is done by another thread and by the time the JS interpreter reaches the console.log call, the I/O hasn't finished yet and therefore $ hasn't been initialized yet.
I suggest that you try requirejs - it handles loading of external scripts asynchronously.

Javascript pulling in Jquery possible?

Question is: is it possible to pull in Jquery using Javascript.
Here is my code :
<html><head></head><body>
<div id="ttt">replace me!</div>
<div id="apxtoo"></div>
<script type="text/javascript">
var sc = document.createElement('script');
sc.src = 'http://code.jquery.com/jquery-1.5.js';
sc.type = 'text/javascript';
document.getElementById("apxtoo").appendChild(sc);
</script>
<script type="text/javascript">
$("#ttt").text = "Cancel";
</script>
</body></html>
But the Jquery section does not run...any ideas how I can fix it?
You need to wait for the script to load before executing any commands that are dependent on it.
http://jsfiddle.net/EZ8uL/
<div id="ttt">replace me!</div>
<div id="apxtoo"></div>
<script type="text/javascript">
var sc = document.createElement('script');
sc.src = 'http://code.jquery.com/jquery-1.5.js';
sc.type = 'text/javascript';
document.getElementById("apxtoo").appendChild(sc);
sc.onload = function(){ // this is quick and dirty, use attachEvent or addEventListener
$("#ttt").text("Cancel");
}
</script>​
You could as well use document.write but it is controversial, check out this tread:
Why is document.write considered a "bad practice"?
Then again, you will come across it, so it is worth knowing how it works.
It is for example in the Html5 Boilerplate.
https://github.com/h5bp/html5-boilerplate/blob/master/index.html
Another informative read is here:
http://www.stevesouders.com/blog/2012/04/10/dont-docwrite-scripts/
I think Google Analytics had their snippet with document.write, but not anymore.

How to add jQuery CDN fallback in XHTML?

It is good practice to load a CDN-hosted jQuery but to fallback to a local file. E.g. HTML5 Boilerplate does it like this:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.0.min.js"><\/script>')</script>
But how can the same be implemented in XHTML? As document.write() doesn't work in proper XHTML (sent as application/xhtml+xml), is there an alternative?
This code creates a new <script/> element and appends it before first <script/> element on your page:
if (!window.jQuery) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'js/vendor/jquery-1.8.0.min.js';
var firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);
}
createElement, setAttribute, appendChild as per usual when replacing document.write or innerHTML
Expanding on Maxim Vi.'s reply, I made it closer to the original idea to insert it where it is called:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script type="text/javascript" id="jQuery">
if (!window.jQuery) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/js/jquery-1.8.0.min.js';
var jQueryScript = document.getElementById('jQuery');
jQueryScript.parentNode.insertBefore(script, jQueryScript);
}
</script>
This way you can keep your scripts in the footer (in case you have other scripts inside the page, it won't get inserted too early or in different locations).
Edit: I had problems in some browsers with that solution, but moving the id="jQuery" further down solved it. I adjusted the code accordingly.

how to: dynamically load google ajax api into chrome extension content script

I'm trying to make use of google's ajax apis in a chorme extension's "content script". On a regular html page, I would just do this:
<script src="http://www.google.com/jsapi"></script>
<script>
google.load("language", "1");
</script>
But since I'm trying to load the tranlation library dynamically from js code, I've tried:
script = document.createElement("script");
script.src = "http://www.google.com/jsapi";
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
google.load('language','1')
but the last line throws the following error:
Uncaught TypeError: Object #<an Object> has no method 'load'
Funny enough, when i enter the same "google.load('language','1')" in chrome's js console, it works as intended...
I've also tried with jquery's .getScript() but the same problem persists...
Does anybody have any clue what might be the problem and how it could be solved?
Many thanks in advance!
I have got this working like this:
<script type="text/javascript">
var headID = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = 'http://www.google.com/jsapi';
headID.appendChild(newScript);
</script>
<script type="text/javascript">
google.load("language", "1");
</script>
It returned no errors.
Content scripts may access only the functions of itself or other content scripts. Since you add google api loader to the document's scripts, you can't call it from your content script. :)
If you need to load apis into the document's scripts, you can do it by specifying autoload parameter :
"https://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22language%22%2C%22version%22%3A%221%22%7D%5D%7D"
http://code.google.com/apis/loader/autoloader-wizard.html

Categories

Resources