I have to dynamically create an Iframe and fill it with content, so I am doing the following:
var ifrm = document.createElement("iframe");
ifrm.id = 'myIframe';
document.getElementById('myIframe').contentWindow.document.write(myIframeContent);
The issue is that the iframe content relies on jquery. Jquery is included in the head of myIframeContent like so:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
However using jquery selectors (e.g. $('#myDiv')) in the iframe results in the variable being undefined. I assume because there is a problem loading jquery, but I'm not sure why. Is it due to how the iframe is being created? Other scripts included in the iframe content are working correctly.
Perhaps you just need to escape the <script><\/script>
SO cannot run this due to security errors
var ifrm = document.createElement("iframe");
ifrm.id = 'myIframe';
const myIframeContent = `<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"><\/script>
<div id="myDiv">Hello</div>
<script>$("#myDiv").html("Hello there")<\/script>`;
document.getElementById("content").appendChild(ifrm);
document.getElementById("myIframe").contentWindow.document.write(myIframeContent);
<div id="content"></div>
I've written a widget which relies on having to inject a css file onto the html page.
I am using the following code to inject the css-sheet:
var link = document.createElement("link");
link.href = "http://myurl.com/style.css";
link.rel = "stylesheet";
document.body.appendChild(link);
This works in all browsers except for IE, for this to work in IE i have to do a:
window.onload
Like this:
window.onload=function() {
//inject here
}
I want to find a way to accomplish this without having to use window.onload, since window.onload only loads my widget when all of the pages has loaded, for bigger pages it takes forever to load the widget.. Is there any workaround for this?
I am assuming the this script is in the body. Append it to the head and not the body
document.getElementsByTagName("head")[0].appendChild(link);
I'm writing a script which requires some stuff to be carried out in an iframe. It's a userscript for a site which I do not own, so because of cross-domain issues, I cannot just set the src of the iframe to a page with my own code. Instead, I am dynamically building the iframe.
To do this, I have
function childScripts(){
//Stuff that must be injected into the iframe.
//Needs jQuery
}
//because I'm lazy:
var iframeWin=$('#my-iframe')[0].contentWindow;
//Load jQuery:
var script = iframeWin.document.createElement("script");
script.type = "text/javascript";
script.src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"
iframeWin.document.head.appendChild(script);
//Inject script
var script = iframeWin.document.createElement("script");
script.type = "text/javascript";
script.textContent="("+childScripts.toString()+")()";
iframeWin.document.body.appendChild(script);
Now, the injected script needs jQuery, but for some reason, jQuery isn't loaded when the injected script runs--even though jQuery is in <head> and the injected script is in <body>.
I've tried other workarounds--making the injected script run onload. I don't like the idea of setting a timeout and checking for the existence of jQuery, I'd prefer a more elegant solution.
I've also tried copying the $ object to iframeWin.$, but of course that doesn't work, since it just backreferences to the parent $ and manipulates the parent document.
It's easier to manipulate iframes using jQuery. Please try:
$('<iframe id="my-iframe"/>').load(function(){
$('#my-iframe').contents().find('body').append('asd').end()
.find('body').append('<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"><\/script>').end()
.find('body').append('<script>$(function() {alert("hello from jquery");console.log("hello from jquery"); })<\/script>');
}).appendTo("body");
Placement:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$('<iframe id="my-iframe"/>').load(function(){.....
</script>
</body>
</html>
My html page dynamically loads pages via Ajax for dynamic panels on the page. I need the script tags in the dynamically loaded pages to be executed. I fixed the code from a SO question. It works fine on FF/Safari/Chrome.
But dom nodes of type script work differently on IE. -- I can't seem to add text to a script node in IE 7:
// variable "data" holds the script element's content from an
// incoming html page loaded via ajax
var script = document.createElement("script");
script.type = "text/javascript";
script.appendChild(document.createTextNode(data)); // doesn't work on ie
// also doesn't work on IE 7:
script.innerHTML = data;
script.innerText = data;
Any ideas for getting the sw to work on IE? (Other than using eval.)
You should simple call eval(data).
Although it is true that eval should usually be avoided, this is one of the few exceptions.
EDIT: Without eval, you can do it like this:
var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.text = data;
document.head.appendChild(scriptNode);
document.head.removeChild(scriptNode); //Optional
You have a few options I can think of (other than using eval).
The script could be served from a separate path; setting the src of the script element instead of its content should work, even in IE.
The script to be executed could be attached to the onload listener of an image or other element, which can be appended to the document as you are doing with the script element.
use Function instead of eval. This will at least keep the evaluated code out of the local scope: new Function(data)();
Is there anyway to unload a page that has been loaded inside an iframe? I do not want to change the iframe src to a blank page if possible. I am basically looking for something that will do something like this $('#frameID').attr("src",""); except that code does not seem to clear the previously loaded page.
Is there a "unload" function that I can call which will reset the iframe so that it does not have any content loaded inside?
The other solutions use innerHTML, which won't always work in XHTML. They also only clear document.body (anything in the <head> is still present). Here is a solution that uses the DOM:
var frame = document.getElementById("myFrame"),
frameDoc = frame.contentDocument || frame.contentWindow.document;
frameDoc.removeChild(frameDoc.documentElement);
This solution uses innerHTML:
var frame = document.getElementById("myFrame"),
frameDoc = frame.contentDocument || frame.contentWindow.document;
frameDoc.documentElement.innerHTML = "";
If you generate dynamically the content of your iframe, all scripts/variable loaded will leak from one write to another. Thus the solution provided by #Eli of clearing the dom element will not work.
In short:
To clean, wrap your iframe into a div element and replace its dom content.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="wrapper">
<iframe id="test"></iframe>
</div>
</body>
</html>
To clean:
var wrapper = document.getElementById('wrapper');
wrapper.innerHTML= "<iframe id='test'></iframe>";
In details: Demo of script leakage
Example of script leakage between two iframe writes (tested with Chrome):
var iframe = document.getElementById('test');
// define variable 'a'
var content = "<html><body><script>var a=555;</script></body></html>";
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(content);
iframe.contentWindow.document.close();
// uncomment this to clean the iframe
//document.getElementById('wrapper').innerHTML= "<iframe id='test'></iframe>";
// write 'a' if defined
var content2 = "<html><body><div id='content'></div><script>document.getElementById('content').innerHTML=typeof a === 'undefined' ? 'undefined' : a;</script></body></html>";
var iframe2 = document.getElementById('test');
iframe2.contentWindow.document.open();
iframe2.contentWindow.document.write(content2);
iframe2.contentWindow.document.close();
If you run this code, you will see the output of the second iframe is 555 although it has been defined in the first iframe.
If you uncomment the middle part it will work as expected.
Related question: Avoiding memory leaks loading content into an iframe
Try this,
$("iframe").contents().find("body").html('');
It only clears innerHTML of your tag inside and not actually unload your iframe so you can reuse your iframe without reloading it and its working in all browsers and quite simple!!
$('#frameID').contentWindow.document.body.innerHTML
= '';
As with any iframe, this only works if you're on the same domain.
var frame = document.getElementById("myframe");
frame.src = "about:blank";
This worked from me and prevented memory leaks too.
In my case I had to destroy the parent too. In that case you have to destroy the parent with some delay to prevent memory leak
Removing and recreating the iframe is the safest solution here.
By removing only the innerHTML of the iframe you don't flush the variables stored, the bound eventListeners etc.
Be careful with this, it might cause a lot of problems (like memory leaks, multiple triggers of the same event etc).
$("#frameId").contents().find("div#SomeDIVinsideFrame").remove(); // removes some div content inside iframe
$("#FrameId").remove(); // removes frame
had same problem to show iframe news on http://www.livepage.info
This worked for me, cleared everything within the iframe tag; body, head, html and all:
$("iframe").contents().empty();
If you had previously loaded content by setting the src property of the iframe, you cannot empty the content as it is a violation of cross site scripting.
You can then just set the src property to '' which will make the browser discard the whole content.
$('iframe').prop('src', '');
First, get the document of the frame:
var frame = $('#frameId').get(0);
var frameDoc = frame.contentDocument || frame.contentWindow.document;
Then, blank it:
frameDoc.getElementsByTagName('body')[0].innerHTML = "";
I think this should work too:
$('body', frameDoc).html("");
Now, you might want to do something with any scripts that might be loaded in the head, but this should get you started.
You can trigger unload event of that iframe like
$('body').trigger('unload');
and then remove the iframe from the parent window and reload a new iframe with new src when needed.
$('#iframe_wrapper').html('');
$('#iframe_wrapper').html('<iframe src="...">');
function getContentFromIframe(iFrameName)
{
var myIFrame = document.getElementById(iFrameName);
var content = myIFrame.contentWindow.document.body.innerHTML;
//Do whatever you need with the content
}
it will definitely work !!!!!!!!!!!!!!!!