`ImportNode` in Firefox and extracting an element from an `iframe` - javascript

I am trying to understand importNode in html using the following example.
Suppose we have a content.html:
<html>
<body>
<nav id="sidebar1" class="sidebar">
Hi there!
</nav>
</body>
</html>
and a main.html:
<html>
<body>
<iframe src='content.html' hidden='true'></iframe>
<script>
var idframe = document.getElementsByTagName("iframe")[0];
var oldNode = idframe.contentWindow.document.getElementsByTagName("nav")[0];
var newNode = document.importNode(oldNode, true);
document.getElementsByTagName("body")[0].appendChild(newNode);
alert("HI!!!");
</script>
</body>
</html>
I am getting the error:
TypeError: Argument 1 of Document.importNode is not an object.
var newNode = document.importNode(oldNode, true);
What is the proper way to get an element form an iframe and insert it into my html?

You can only access content of the iframe document after the iframe document has been loaded. This can be accomplished different ways:
either by putting your accessing code into load handler of the main (that contains iframe element) document window,
or inside a DOMContentLoaded event listener of the document loaded in iframe.
Below is example of using load event of window of the main document:
window.addEventListener('load', function() {
var iframe = document.getElementsByTagName("iframe")[0];
var oldNode = iframe.contentWindow.document.getElementById("myNode");
var newNode = document.importNode(oldNode, true);
document.body.insertBefore(newNode, document.body.firstChild);
}, false);
Otherwise, iframe content is not yet loaded when you try to access it.
See the live example at JSFiddle (iframe content is placed encoded in the srcdoc attribute of the iframe just because I'm not aware of ability to create subdocuments at JSFiddle without creating a separate fiddle).

Related

Cannot get content of iframe

I am loading a local html document in an iframe, then trying to get access to its document from a script.
This is the javascript:
let ifrm = document.getElementById('iframeid');
console.log(ifrm);
let doc = ifrm.contentWindow.document;
console.log(doc);
This is the declaration of my iframe:
<iframe src="untitled.html" style="display:none" id="iframeid"></iframe>
This is the result:
As you can see, the content of the iframe disappears when I try to get the document. What am I doing wrong?
For some reason, you have to wait for the onload event.
Take a look here: http://plnkr.co/edit/fNEZLyWkjT952a7e3WNy?p=preview

How to add a click event to p elements in iframe (using jQuery)

How to add a click event to <p> elements in iframe (using jQuery)
<iframe frameborder="0" id="oframe" src="iframe.html" width="100%" name="oframe">
There's a special jQuery function that does that: .contents(). See the example for how it's works.
Your best best bet is to invoke the iframe AS LONG AS it's part of your domain.
iframe.html
<html>
<head>
<script>
window.MyMethod = function()
{
$('p').click();
}
</script>
</head>
<body></body>
</html>
And then use
document.getElementById('targetFrame').contentWindow.MyMethod();
To invoke that function.
another way is to access the iframe via window.frames.
<iframe name="myIframe" src="iframe.html"/>
and the javascript
child_frame = window.frames['myIframe'].document;
$('p',child_frame).click(function(){
alert('This click as bound via the parent frame')
});
That should work fine.
Wanted to add this, as a complete, copy-paste solution (works on Firefox and Chrome). Sometimes it is easy to miss to remember to call the event after the document, and so the iframe, is fully loaded:
$('#iframe').on('load', function() {
$('#iframe').contents().find('#div-in-iframe').click(function() {
// ...
});
});
The iframe must be on the same domain for this to work.
By giving a reference to the IFrame document as the second parameter to jQuery, which is the context:
jQuery("p", document.frames["oframe"].document).click(...);
To access any element from within an iframe, a simple JavaScript approach is as follows:
var iframe = document.getElementById("iframe");
var iframeDoc = iframe.contentDocument || iframe.contentWindow;
// Get HTML element
var iframeHtml = iframeDoc.getElementsByTagName("html")[0];
Now you can select any element using this html element
iframeHtml.getElementById("someElement");
Now, you can bind any event you want to this element. Hope this helps. Sorry for incorrect English.

Remove body element

How to remove HTML <body> element with all of its content?
var e = document.getElementsByTag('html');
e.removeChild('body');
Does not work.
The simple solution would be
document.body.innerHTML = "";
But why on earth would you want to do this?
By the way:
var e = document.getElementsByTag('html');
should be
var e = document.getElementsByTagName('html')[0];
and
e.removeChild('body');
should be
e.removeChild(document.body);
getElementsByTagName returns a collection of nodes, not a single node
removeChild takes a node, not a string containing a tag name
var e = document.body;
e.parentNode.removeChild(e);
… however HTML documents require a body element, so this may have unexpected behavior.
...
document.body.parentNode.removeChild(document.body);
I think this will remove it
var html = document.getElementsByTagName('html')[0];
var body = document.getElementsByTagName('body')[0];
html.removeChild(body);
The body itself has a method which does just that:
document.body.remove();
document.body.parentNode.removeChild(document.body)
or
document.body = document.createElement("body")
or
while(document.body.childNodes.length != 0) {
document.body.removeChild(document.body.childNodes[0])
}
Try this code it will remove all the content of body tag on click on the button
And if you want to remove content onload then use this onload="document.body.innerHTML = '';"
<html>
<body>
This is example Text<br>
<button onclick="document.body.innerHTML = '';">Click me to remove body contents</button>
</body>
</html>
Several people on this page have asked why one might even wish to remove a <body> element from an HTML Document.
Admittedly, it's a seldom-seen approach, but it's almost always because one wishes to remove the current <body> from a document (while keeping the <head>) and then create a new <body> element (to follow the same <head> as before).
So why not, simply empty the existing <body> element via:
document.body.innerHTML = '';
or
while (HTMLSourceTab.document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
The answer might be:
If the HTML Document in question is being opened in a new browser tab, these processes (above) can only execute after the DOMContentLoaded event fires.
And they may not execute quickly enough to prevent a brief Flash Of Legacy Body.
Whereas:
document.body.remove();
will normally execute quickly enough after DOMContentLoaded to prevent that flash.
Once the legacy <body> has been removed, a new <body> can be created and added via:
let newBody = document.createElement('body');
document.documentElement.appendChild(newBody);
or (if adding an empty <body>) simply:
document.body = document.createElement('body');
Full code for opening an existing document in a new tab, removing the existing <body> and adding a new <body>:
myNewTab = window.open(myNewTabURL, '_blank');
myNewTab.addEventListener('DOMContentLoaded', () => {
myNewTab.document.body.remove();
setTimeout(() => myNewTab.document.body = myNewTab.document.createElement('body'), 800);
});
myNewTab.focus();

how to detect ,on load of the html document, whether the body of the iframe document is ready to be displayed?

Suppose a HTML document has a iframe.
Using javascript,I want to detect ,on load of the html document, whether the body of the iframe document is ready to be displayed.
I want to be able to overwrite the body contents (before it actullay loads) of the iframe.
Any suggestions? can I do it with jquery?
say if ,HTML doc is
<html>
<head>
</head>
<body>
<iframe id="ifrmId" src="http://www.google.com" >
</iframe>
</body>
</html>
You can use the onload event on the iframe element:
var iframe = document.getElementById('ifrmId');
iframe.onload = function () {
// iframe loaded
var innerDocument = iframe.contentDocument || iframe.contentWindow.document;
};
Edit: With jQuery, exactly the same idea:
$('#ifrmId').load(function () {
// iframe loaded
var innerDocument = $(this).contents();
});
Keep in mind that if you want to manipulate the iframe's inner document, the file needs to be on the same domain, this is because the same origin policy restrictions.

Unloading/Removing content from an iFrame

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 !!!!!!!!!!!!!!!!

Categories

Resources