Javascript - Passing a script to innerHTML on older browsers - javascript

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).

Related

How do I access jQuery from a new window?

In my app I open a new window with var w = window.open(). I access the CanvasJS API with:
var canvas = w.document.createElement('script');
canvas.type = "text/javascript";
canvas.src = "https://canvasjs.com/assets/script/canvasjs.min.js";
w.document.head.appendChild(canvas);
This works perfectly fine. I did the same thing with jQuery and made sure to append it before my own script yet I get this error: ReferenceError: $ is not defined
Here is what my code looks like:
var w = window.open('','_blank',width,height);
w.document.body.innerHTML = '<body> //create chart container here </body>';
var jQuery = w.document.createElement('script');
var canvas = w.document.createElement('script');
var script = w.document.createElement('script');
canvas.type = "text/javascript";
canvas.src = "https://canvasjs.com/assets/script/canvasjs.min.js";
jQuery.type = "text/javascript";
jQuery.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js";
script.textContent = "//my script content here, this is where I use the '$' jQuery object";
w.document.head.appendChild(jQuery);
w.document.head.appendChild(canvas);
w.document.head.appendChild(script);
Even though you have inserted the script tag in the head but this does not mean that the script have been downloaded completely. You code runs before the browser is able to download jQuery. Dynamically inserted script tags perform async operation.
I suggest that you setup an interval and check if jQuery is available. Once it is available execute your code. Name the script element created for jQuery something else as it will interfere with checking for jquery within your interval.
var jqueryCheck = setInterval(function() {
if(window.jQuery) {
clearInterval(jqueryCheck);
// execute your code
}
}, 100);

Can I Load CSS Using the "load.js" Library?

I recently found out about load.js, but I can't seem to find any indication of whether or not this is possible... (Note: I can't find a 'load.js' tag..)
I've got load.js successfully loading all my JS files, so I know it works. Has anyone got it working for loading CSS files as well?
Update: remyabel's solution worked perfectly for loading the physical files, but it seems there are a few quirks to this process...
For some reason, the order in which the CSS files are loaded and whether they're all done in one load(file1,file2); or in stages with load(file1).then(file2); seems to affect how the style rules are applied to the markup. I'm going to set up a few test cases on my local machine to try work out how or why this happens, but for now at least the files are being loaded.
Final Note:
Following on from the solution posted below, I've decided to use head.appendChild(script); instead of head.insertBefore(script, head.firstChild); to add the CSS elements to the DOM (still uses the original method for JS files).
This doesn't affect the order in which files are fetched and processed, but it makes Load.js insert my CSS links in the same order they were listed and at the end of the header instead of the beginning.
Direct from the source code
function asyncLoadScript(src) {
return function (onload, onerror) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
My suggestion is to modify the script (which doesn't seem to contain much) to mirror the function but for a link tag, rather than a script tag.
to reflect OP's comment
The script is built on top of chain.js so it may be more complicated than expected.
Unless you want something else, I'm pretty sure what I wrote above is what you need to change, so it would look like:
function asyncLoadScript(src) {
return function (onload, onerror) {
// Get file extension
var ext = src.split('.').pop();
if (ext == "js")
{
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
} else if (ext == "css")
{
var script = document.createElement('link');
script.type = 'text/css';
script.href = src;
script.rel = "stylesheet";
}
Theoretically that should work. Make another comment if it doesn't work.

Trying to inject javascript into my page

For reasons too complicated to get into now, I have an ajax call that returns some dynamically created Javascript that I want to inject into my page. The following code works on Chrome, but not in IE:
var node = document.getElementsByTagName("head")[0] || document.body;
if (node)
{
var script = document.createElement("script");
script.type = "text/javascript";
//script.innerHTML = json.javascript;
var textnode = document.createTextNode(json.javascript);
script.appendChild(textnode);
node.appendChild(script);
}
In IE, I get "SCRIPT65535: Unexpected call to method or property access." As you can see from the commented out code, before I tried the textnode, I tried just inserting it with script.innerHTML. That also worked in Chrome, but in IE I got "SCRIPT600:Unknown runtime error".
Is there a way to stick some javascript into the DOM in IE?
And of course, as soon as I post this, I find http://www.phpied.com/dynamic-script-and-style-elements-in-ie/
var node = document.getElementsByTagName("head")[0] || document.body;
if (node)
{
var script = document.createElement("script");
script.type = "text/javascript";
script.text = json.javascript;
node.appendChild(script);
}

Dynamically create entire page, including scripts and styles

I'm playing around with the following code. The intention is to open a new window and create a basic document from scratch, rather than loading it from file.
function openNew() {
var win = window.open('', 'new') ;
win.document.write('<html><head><title>New</title></head><body><div id="wrap">Hello World</div></body></html>') ;
var head = win.document.getElementsByTagName('head')[0] ;
var style = win.document.createElement('link') ;
style.rel = "stylesheet" ;
style.type = "text/css" ;
style.href = "/css/main.css" ;
head.appendChild(style) ;
var script = win.document.createElement('script') ;
script.type = "text/javascript" ;
script.src = "/js/main.js" ;
head.appendChild(script) ;
return false ;
}
The document.write part seems to work, but the rest does nothing. Or at least nothing that I can tell, I get no errors or anything. I tried to just write the script part in the document.write with the rest of the document but that didn't help. Also tried using innerHTML instead of write() but that didn't work at all, nor did creating the whole document (html, head and body tags) with createElement.
If it has any importance, the script that needs to be loaded is the same one that does the opening in the first place. I don't know if that somehow creates a conflict though I'm not sure why it would do that. Just mentioning it for good measure.
Is this possible to do?
Trying closing the document, before accessing it.
var win = window.open('...');
win.document.open();
win.document.write('...');
win.document.close();
Other option is to build up the string and just add it all at once and not append to it.

making reddit's buttons asynchronous

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.

Categories