I'm trying to add Reddit buttons to my site, but they are not asynchronous, and Reddit tends to lag, slowing down page loads. When I look at what the script returns, I get something like this:
(function () {
var write_string = ...
document.write(write_string);
})()
I try to inject it into my page after a page load. I've tried both these methods in javascript after page load to no avail:
placeholder.innerHTML = '<script type="text/javascript" src="http://www.reddit.com/buttonlite.js?i=5"></script>'
var js = document.createElement('script');
js.type = 'text/javascript';
js.src = 'http://www.reddit.com/buttonlite.js?i=5';
placeholder.appendChild(js);
where placeholder is a DOM element <div class="reddit-button"></div>. Any ideas on how I could go about this?
You can "override" the document.write method:
window.onload = function() {
var oScript = document.createElement("script");
document.write = function(text) {
document.getElementById("placeholder").innerHTML += text;
};
oScript.src = "http://www.reddit.com/buttonlite.js?i=0";
document.body.appendChild(oScript);
};
This way the external code can call document.write as much as it wants to and you push the HTML to the proper place in your document.
Live test case - Tested OK under Chrome, Firefox and IE9 so guess it should be enough.
Related
I have the following problem:
I load a page inside a modal dialog. This page uses jQuery as dependency. Since I already use jQuery on the main page, for me, it is always available. Now we have the usecase, that also different pages (hosted on different domains) need to load that page if necessary.
So, I check if the jQuery variable exists on this page and if yes, just go on with my code.
If it does not exist, on top of the template, I dynamically create a script element like this:
<script>
if(!window.jQuery)
{
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "path/to/jQuery";
document.getElementsByTagName('head')[0].appendChild(script);
}
</script>
And at the end of the template, I use a IIFE (to scope the jquery variable)
(function ($) {
.... code ....
})(jQuery);
However, since with this method, the script gets loaded asynchronously, sometimes I get the error: jQuery is undefined.
Now I came up by loading it synchronously, like this:
var xhrObj = new XMLHttpRequest();
// open and send a synchronous request
xhrObj.open('GET', "jquery.min.js", false);
xhrObj.send('');
// add the returned content to a newly created script tag
var se = document.createElement('script');
se.type = "text/javascript";
se.text = xhrObj.responseText;
document.getElementById('placeholder').appendChild(se);
This works fine, but the warning "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. to the end user's experience." made me think.
However, now I changed my code and just said
if (!window.jQuery) {
document.write('<scr' + 'ipt src="jquery.js"' + '>' + '</scr' + 'ipt>');
}
on top of my Template.
Dear javascript gurus, is this a reliable solution?
Use the onload attribute in async javascript
<script async src="siteScript.js" onload="window.MyInitialisation()"></script>
In javascript it would look like this:
<script>
if(!window.jQuery)
{
var script = document.createElement('script');
script.type = "text/javascript";
script.async = "async";
script.defer = "defer";
script.onload = function() {window.MyInitialisation()}
script.src = "path/to/jQuery";
document.getElementsByTagName('head')[0].appendChild(script);
}
</script>
I'm trying to pass a script into an iframe dynamically so it will run there (content in the example comes from the server) using this snippet:
content = '<script type="text/javascript">document.write("bla"");</script>';
el = document.getElementById('iframeName');
iframeDoc = el.contentWindow.document;
tempEl = iframeDoc.createElement('div');
tempEl.innerHTML = content;
It runs great on new browsers but when I try to run it on IE8 and lower, the innerHTML comes up null.
I tried different approaches but the inner HTML is the only option i can think of that can run the script i'm passing in to tempEl. Any ideas on how to pass content into tempEl.innerHTML so it will run the script and also work on IE8-?
Have you tried injecting the script element into the head of the document?
I am not to sure about script tags, but you must inject link and style elements into the head of a document for it to be interpreted correctly by older IE browsers.
var script = document.createElement('script');
script.type = 'text/javascript';
script.rel = 'JavaScript';
script.innerHTML = 'document.write("bla");';
var el = document.getElementById('iframeName');
iframeDoc = el.contentWindow.document;
iframeDoc.head.appendChild(script);
The solution I went with is:
el = document.getElementById('iframeName');
iframeDoc = el.contentWindow.document;
iframeDoc.write(content);
it's a lot shorter and is cross-browser (instead of using innerHTML).
Developing phonegap application which loads google map. Using below two javascript for google map. One javascript is loaded from locally while other javascript loaded from server.
var script = document.createElement('script');
script.src = 'http://maps.google.com/maps/api/js?sensor=true';
script.type = 'text/javascript';
document.head.appendChild(script);
script.onload = function () {
var script1 = document.createElement('script');
script1.src = 'js/jquery.ui.map.js';
script1.type = 'text/javascript';
document.head.appendChild(script1);
script1.onload = function () {
alert(google.maps.LatLng);
}
};
Both javascripts should be loaded after html page is loaded. Tried below code and referred various blogs, but its not working.
If same scripts written in header tag of html page, then it working perfectly. but in my application i need it to be loaded dynamically.
Please help....
Solved:
var doc_write = document.write; // Remember original method;
document.write = function(s) {$(s).appendTo('body')};
$.getScript('http://maps.google.com/maps/api/js?sensor=true').done(function()
{
$.getScript('js/jquery.ui.map.js').done(function()
{
document.write = doc_write; // Restore method
setTimeout(function()
{
alert(google.maps.LatLng);
},1000);
})
.fail(function(jqxhr, settings, exception)
{
alert(exception); // this gets shown
document.write = doc_write; // Restore method
});
}).fail(function()
{
alert('failed to load google maps');
});
Problem:
It takes some time to initialise.
Call your javascript function after device get ready function. Because if you are using phone gap through Xcode, the device get ready function take some time to load and your script is called before it.
Don't do it in this way
Load it in footer section of your application
The company which developped my website just added this javascript code on the Zend Guard encrypted index.php file (I saw it with "View source") :
(function ()
{
var smrs = document.createElement("script");
smrs.type = "text/javascript";
smrs.async = true;
smrs.src = document.location.protocol + "//www.domain.com/file.js";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(smrs, s);
})();
It injects a very agressive javascript code which adds a image link to their website (with a SetInterval each 10sec), at the bottom of the page.
The problem ? A local competitor, which is currently being accused of significant fraud, have the same CMS and the same image link.
Being associated with that competitor is prejudicial for me. I would like to know if there is a way to block the "www.domain.com/file.js" loading with a .htaccess.
Thanks.
You can't (using htaccess). This javascript creates a script tag to load the external javascript. The call never passes through the server. So apache (htaccess) can't block that.
The easiest way is to search in the source code and remove the script (if you have access).
UPDATE:
I see the script is encrypted... If you can insert a script at the very beginning (before the code gets executed you can create a hook on the insertBefore method. Here is a working fiddle
var ALLOWED_DOMAINS = ['www.klaartjedevoecht.be', 'jsfiddle.net'];
function creatHook(){
function getDomain(url) {
return url.match(/:\/\/(.[^/]+)/)[1];
}
var insertBefore = Element.prototype.insertBefore;
Element.prototype.insertBefore = function(new_node,existing_node){
if(new_node.tagName.toLowerCase() === 'script' && ALLOWED_DOMAINS.indexOf(getDomain(new_node.src)) > -1){
insertBefore.call(this, new_node, existing_node);
}
}
}
creatHook();
//TESTING CODE:
var smrs = document.createElement("script");
smrs.type = "text/javascript";
smrs.async = true;
smrs.src = document.location.protocol + "//www.klaartjedevoecht.be/test.js";
//var smrs = document.createElement("img");
// smrs.src= "http://img52.imageshack.us/img52/7653/beaverl.gif";
var s = document.getElementsByTagName("div")[0];
s.parentNode.insertBefore(smrs, s);
I agree it's a bit hacking, but at least its cleaner then the timer solution. If you can't remove it, there is no clean solution.
I am loading scripts and style-sheets dynamically from javascript like this.
The problem is that browser does not wait for the script to load.
consider i have a function named functionToBeCalled() inside a script file named script-file.js
i have a function to load script file.
<script type="text/javascript">
var listOfJavaScriptsLoaded = new Array();
function LoadScriptFile(scriptUrl){
var isScriptLoaded = false;
var i = 0;
for(i = 0; i < listOfJavaScriptsLoaded.length; i ++){
if(listOfJavaScriptsLoaded[i] == scriptUrl){
isScriptLoaded = true;
break;
}
}
if(isScriptLoaded == false){
var headTag= document.getElementsByTagName('head')[0];
var scriptTag= document.createElement('script');
scriptTag.type= 'text/javascript';
scriptTag.src= scriptUrl;
headTag.appendChild(scriptTag);
listOfJavaScriptsLoaded.push(scriptUrl);
}
}
LoadScriptFile("script-file.js");
functionToBeCalled();
</script>
now, what happens is that the browser does not wait for the script tag to load and goes to the next command. I get a "undefined functionToBeCalled()" error. this is natural. But the fact is that when i inspect in firebug, the script tag has been formed and the file has loaded.
So how do i make the browser to pause loading and resume after the asset has been loaded?
Edit1: This problem occurs only when i am loading the page in ajax and not in normal page loads
Edit2: Or is there a possibility to read a script/css file from javascript and write it directly in the markup within script tags
If i use window.stop() the loading stops completely. how can i make it resume from the same line?
Or is it possible to make the browser to consider that the loading is still happening and reset it in the onload event?
You may have specific reasons to load the script dynamically, but to present the option, if you write out the script element in your HTML output like so:
<script src="script-file.js"></script>
<script>functionToBeCalled();</script>
the browser will halt parsing until that script has been loaded, and interpreted.
This is also valid in the BODY.
Check out LABjs ( http://labjs.com/ ) by Getify Solutions. LABjs allows script-inserted scripts to be loaded concurrently but run in order.
pretty much every tag which loads a resource has an onload event. so in plain javascript this means in your case something like this:
var s = document.createElement('script');
s.src = "script-file.js";
s.type = 'text/javascript';
head.appendChild(s);
s.onload = function(){
functionToBeCalled();
}
I would recommend looking at Cuzillion. It will allow you to experiment with calling javascript and css in many different ways to see how they react in the browser.
This should answer your question. Just execute it before your page is done loading the body.
<script type="text/javascript">
var loadScriptFile = (function(){
var listOfJavaScriptsLoaded = [];
return function(scriptUrl){
var isScriptLoaded = false;
for(var i = 0; i < listOfJavaScriptsLoaded.length; i ++){
if(listOfJavaScriptsLoaded[i] == scriptUrl){
isScriptLoaded = true;
break;
}
}
if(!isScriptLoaded){
document.write('<scr' + 'ipt type="text/javascript" src="' + scriptUrl + '"></scr' + 'ipt>');
}
};
}());
loadScriptFile("script-file.js");
functionToBeCalled();
</script>