This is my code
<script>
var body = "dddddd"
var script = "<script>window.print();</scr'+'ipt>";
var newWin = $("#printf")[0].contentWindow.document;
newWin.open();
newWin.close();
$("body",newWin).append(body+script);
</script>
<iframe id="printf"></iframe>
This works but it prints the parent page, how do I get it to print just the iframe?
I would not expect that to work
try instead
window.frames["printf"].focus();
window.frames["printf"].print();
and use
<iframe id="printf" name="printf"></iframe>
Alternatively try good old
var newWin = window.frames["printf"];
newWin.document.write('<body onload="window.print()">dddd</body>');
newWin.document.close();
if jQuery cannot hack it
Live Demo
document.getElementById("printf").contentWindow.print();
Same origin policy applies.
Easy way (tested on ie7+, firefox, Chrome,safari ) would be this
//id is the id of the iframe
function printFrame(id) {
var frm = document.getElementById(id).contentWindow;
frm.focus();// focus on contentWindow is needed on some ie versions
frm.print();
return false;
}
an alternate option, which may or may not be suitable, but cleaner if it is:
If you always want to just print the iframe from the page, you can have a separate "#media print{}" stylesheet that hides everything besides the iframe. Then you can just print the page normally.
You can use this command:
document.getElementById('iframeid').contentWindow.print();
This command basically is the same as window.print(), but as the window we would like to print is in the iframe, we first need to obtain an instance of that window as a javascript object.
So, in reference to that iframe, we first obtain the iframe by using it's id, and then it's contentWindow returns a window(DOM) object. So, we are able to directly use the window.print() function on this object.
I had issues with all of the above solutions in IE8, have found a decent workaround that is tested in IE 8+9, Chrome, Safari and Firefox. For my situation i needed to print a report that was generated dynamically:
// create content of iframe
var content = '<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">'+
'<head><link href="/css/print.css" media="all" rel="stylesheet" type="text/css"></head>'+
'<body>(rest of body content)'+
'<script type="text/javascript">function printPage() { window.focus(); window.print();return; }</script>'+
'</body></html>';
Note the printPage() javascript method before the body close tag.
Next create the iframe and append it to the parent body so its contentWindow is available:
var newIframe = document.createElement('iframe');
newIframe.width = '0';
newIframe.height = '0';
newIframe.src = 'about:blank';
document.body.appendChild(newIframe);
Next set the content:
newIframe.contentWindow.contents = content;
newIframe.src = 'javascript:window["contents"]';
Here we are setting the dynamic content variable to the iframe's window object then invoking it via the javascript: scheme.
Finally to print; focus the iframe and call the javascript printPage() function within the iframe content:
newIframe.focus();
setTimeout(function() {
newIframe.contentWindow.printPage();
}, 200);
return;
The setTimeout is not necessarily needed, however if you're loading large amounts of content i found Chrome occasionally failed to print without it so this step is recommended. The alternative is to wrap 'newIframe.contentWindow.printPage();' in a try catch and place the setTimeout wrapped version in the catch block.
Hope this helps someone as i spent a lot of time finding a solution that worked well across multiple browsers. Thanks to SpareCycles.
EDIT:
Instead of using setTimeout to call the printPage function use the following:
newIframe.onload = function() {
newIframe.contentWindow.printPage();
}
At this time, there is no need for the script tag inside the iframe. This works for me (tested in Chrome, Firefox, IE11 and node-webkit 0.12):
<script>
window.onload = function() {
var body = 'dddddd';
var newWin = document.getElementById('printf').contentWindow;
newWin.document.write(body);
newWin.document.close(); //important!
newWin.focus(); //IE fix
newWin.print();
}
</script>
<iframe id="printf"></iframe>
Thanks to all answers, save my day.
If you are setting the contents of IFrame using javascript document.write() then you must close the document by newWin.document.close(); otherwise the following code will not work and print will print the contents of whole page instead of only the IFrame contents.
var frm = document.getElementById(id).contentWindow;
frm.focus();// focus on contentWindow is needed on some ie versions
frm.print();
I was stuck trying to implement this in typescript, all of the above would not work. I had to first cast the element in order for typescript to have access to the contentWindow.
let iframe = document.getElementById('frameId') as HTMLIFrameElement;
iframe.contentWindow.print();
Use this code for IE9 and above:
window.frames["printf"].focus();
window.frames["printf"].print();
For IE8:
window.frames[0].focus();
window.frames[0].print();
I am wondering what's your purpose of doing the iframe print.
I met a similar problem a moment ago: use chrome's print preview to generate a PDF file of a iframe.
Finally I solved my problem with a trick:
$('#print').click(function() {
$('#noniframe').hide(); // hide other elements
window.print(); // now, only the iframe left
$('#noniframe').show(); // show other elements again.
});
Related
The below piece of code is not working in IE8, but, it is working perfectly on FireFox and Google Chorome, Even, there is no error thrown by IE8, but, output is not coming. Any Idea? What is the actual problem?
<html>
<head/>
<body>
<script type="text/javascript">
(function(){
var inpEle = document.createElement("div");
inpEle.setAttribute("id", "div1");
var texEle = document.createTextNode("This is my Sample Para. I am testing it again my own level that prove How i am capable of.");
inpEle.appendChild(texEle);
document.body.appendChild(inpEle);
})();
(function(){
var inpEle1 = document.createElement("input");
inpEle1.setAttribute("type", "button");inpEle1.setAttribute("value", "Show");inpEle1.setAttribute("onclick", "Show()");
document.body.appendChild(inpEle1);
var inpEle2 = document.createElement("input");
inpEle2.setAttribute("type", "button");inpEle2.setAttribute("value", "Hide");inpEle2.setAttribute("onclick", "Hide()");
document.body.appendChild(inpEle2);
})();
</script>
<script type="text/javascript">
window.onload= function(){
document.getElementById('div1').style.display="none";
}
Show = function (){
document.getElementById('div1').style.border="2pt solid green";
document.getElementById('div1').style.display="";
}
Hide = function(){
document.getElementById('div1').style.border="";
document.getElementById('div1').style.display="none";
}
</script>
</body>
</html>
You may not be able to use document.body.appendChild() in IE8 before the </body> tag has been parsed and your code is trying to append to the body while it is still being parsed. Early versions of IE like IE6 might just abort (e.g. literally crash) when you did this. Later versions (like IE8) will just simply ignore your request.
You can use document.write() to add content while the body is being parsed.
You can postpone calling your code until after the body has finished loading and parsing (such a <body onload="xxx()"> handler) or when an event such as window.onload fires.
You can appendChild() to an element that has finished parsing (something that is before your script).
The simplest solution is probably to put a <div id="container"></div> in the body before your script and append to that instead of the body or put your code in a function and have the body onload event call your function.
See this article for description of the issue.
don't use setattribute use anonymous function for events
inpEle1.onclick = function() {
Show();
};
Also it works in IE tester in IE8, but not IE7, do you have it using IE7 compatibility
Go to Internet Options - Security Tab - Internet - click on the "Custom" button then scroll down to the Miscellaneous section."Allow script-initiated windows without size or position constraints" Find "Active Scripting" then check enable.
I noticed than element.style.display doesn't always work with IE8.
Here is a method to improve compatibility :
if (element.style.setAttribute)
element.style.setAttribute("display", value);
else
element.style.display = value;
Best regards,
I haven't been able to make sense of the answers to related questions so far(down to my knowledge level), so...
I have a simple script(using jQuery) that opens a new window and adds certain content from the parent into a specified container inside the child. I'm not sure if it's my approach that's wrong or I'm just missing a step - the script to run on the new window runs in IE when it's outside of the window.onload function, but this breaks FF, and FF is happy when it's inside of the window.onload, but then the new window in IE doesn't appear to be doing anything(no alert, no add of content, nada).
Please can anybody explain to me why this is the case/what I'm doing wrong? Is it something to do with the reference to window.open?
This is the script:
var printPage = function(container){
$('.printButton').click(function(){
var printWindow = window.open('printWindow.html');
var contentFromParent = $(container).eq(0).html();
/*works for IE, but not FF
printWindow.alert('works for IE, but not FF');
printWindow.document.getElementById('wrap').innerHTML = contentFromParent;*/
/*works for FF and Chrome but not IE:*/
printWindow.onload = function(){
printWindow.alert('works for FF and Chrome but not IE');
printWindow.document.getElementById('wrap').innerHTML = contentFromParent;
}
/*I also tried:
$(printWindow.document).ready(function(){
printWindow.alert('load the page, fill the div');
printWindow.document.getElementById('wrap').innerHTML = contentFromParent;
}); //works for IE, not working for FF/Chrome*/
})
}
printPage('#printableDiv');
The HTML:
<div id="wrap">
<button href="#" class="printButton">Print</button>
<div id="printableDiv">
<p>I want to see this content in my new window please</p>
</div>
</div>
UPDATE
Thanks for your pointers about onload in the new window - I've gone with this solution for now: Setting OnLoad event for newly opened window in IE6 - simply checking the DOM and delaying the onload - working for IE7/8/9.
I'm not sure if you'd call it an 'elegant' solution, but it's working! Further comments, especially if you think this is flawed, would be appreciated. Thanks.
var newWinBody;
function ieLoaded(){
newWinBody = printWindow.document.getElementsByTagName('body');
if (newWinBody[0]==null){
//page not yet ready
setTimeout(ieLoaded, 10);
} else {
printWindow.onload = function(){
printWindow.alert('now working for all?');
printWindow.document.getElementById('wrap').innerHTML = contentFromParent;
}
}
}
IEloaded();
Can it be that the page you open fires the 'onload' event before you set the event handler printWindow.onload = ... ?
You might consider including some javascript in your 'printWindow.html' page. Let's say you add a short <script>var printWindowLoaded = true;</script> at the end of your page. Then your main script would do something like this:
function doStuff() {
//...
}
if (printWindow.printWindowLoaded)
doStuff();
else
printWindow.onload = doStuff;
Edit: Just found out this is a chrome problem, the code works fine in firefox
I have an iframe on a webpage that shows a book formatted as html. I would like to insert some javascript within this iframe to make the book more dynamic (e.g. click on sentences, show animations etc). The iframe content is in the same domain as the parent page.
I can insert the javascript into the iframe but get an error calling a function in the inserted javascript. I've described the different bits of code below:
My parent page javascript is:
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
iFrameID.contentWindow.initialiseApi()
}
and the html containing the iframe is:
<iframe id="preview-iframe" width="640" height="240" frameborder="0" src="./testpage.htm" onload="iframeLoaded()" scrolling="no"></iframe>
The contents of iframeAPI.js is:
window.initialiseApi = function() { alert("Hello world") }
Looking at the iFrame's html in the browser shows that the iFrameAPI.js tag is inserted ok into the iframe head, but I don't get the alert popup when the page is loaded. The error appears on the following line:
iFrameID.contentWindow.initialiseApi()
Uncaught TypeError: Object [object Window] has no method 'initialiseApi'
However I can run this line in the browser's javascript console and the alert popup works fine.
Any help would be much appreciated.
Thanks,
Brian
Edit: I've just tried with an onload event to make sure the page is loaded and I still have the problem:
My parent page javascript is now :
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
jsLink.onLoad= iFrameLoaded();
}
function iFrameLoaded()
{
alert("Iframe loaded"); // Alert works ok
var iFrameID = document.getElementById('preview-iframe');
iFrameID.contentWindow.initialiseApi(); // Same error message on this line
}
It sounds like you are trying to use the function before the content has loaded.
try this instead:
var t = setTimeout(iFrameID.contentWindow.initialiseApi(),500);
This will wait half a second before trying the function which should give the page tiem to load. Delay times are given in milliseconds.
An even better approach is to try using Jquery and its ready() method but this requires the jquery library to be loaded as well. Its well worth it though in my opinion, see http://api.jquery.com/ready/.
You would try something like:
$("body",iFrameID.contentWindow.document).ready(iFrameID.contentWindow.initialiseApi())
You're executing it right away without giving the script a chance to load. Hook up an onload event to your script block and run your main function then.
Try, in the page included in the iFrame, accessing the main page by doing something like:
window.parent.xyz = something;
Where something is what you want exposed to the main page. Could be a function or an object of functions. Now in the main page you can just do:
something(); // or something.somefunction();
You could also send window references, I think, but I have not tried that.
The easiest way is to call the initialiseApi function in the iframeAPI.js itself as it will be called as soon as it's loaded. The iframeAPI.js could look like that:
function initialiseApi() {
alert("Hello world");
}
initialiseApi();
There is no callback or timeout needed.
In javascript, how can I set the innerHTML of an iframe? I mean: how to set, not get.
window["ifrm_name"].document.innerHTML= "<h1>Hi</h1>" does not work, and the same for other solutions.
Iframe and parent document are on the same domain.
I would need to set html of the whole document iframe, not its body.
I would need to avoid jquery solution.
A really simple example ...
<iframe id="fred" width="200" height="200"></iframe>
then the following Javascript is run, either inline, part of an event, etc ...
var s = document.getElementById('fred');
s.contentDocument.write("fred rules");
the "contentDocument" is the equivalent of the "document" you get in the main window, so you can make calls against this to set the body, head, any elements inside ... etc.
I've only tested this in IE8, Chrome and Firefox ... so you may want to test in IE6/7 if you have copies available.
In Firefox and Chrome (don't know about Opera), you can use the data: URI scheme.
<iframe src=".... data: URI data here ......">
JSFiddle example
Here is a tool to generate data:URI encoded data.
This does not work in IE:
For security reasons, data URIs are restricted to downloaded resources. Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements.
If however as you say in the comment, getting/setting the document's body is enough, you are much easier off using one of the linked examples.
There is also the srcdoc attribute:
<iframe srcdoc="<p><h1>Hello</h1> world</p>"></iframe>
Demo, Polyfill.
In improving my file uploads in an AJAXS env I had the same need. This worked for me in ie8 and ff 22.0. Both the body innerhtml and div innerhtml work.
function copyframedata(data) {
var x = document.getElementById("photo_mgr_frame");
var y = x.contentWindow || x.contentDocument;
if (y.document) y = y.document;
y.getElementById('photo_mgr_mb').innerHTML = data;
}
got it from w3
I came across the same problem but here's an easy fix.
function Run(){
var txt = "<h1>Hello World</h1>";
var frame = document.getElementById('frame');
var frame = (frame.contentWindow || frame.contentDocument);
if (frame.document) frame = frame.document;
frame.open();
frame.write(txt);
frame.close();
}
<iframe id='frame'>
</iframe>
<button onclick='Run()'>Run</button>
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 !!!!!!!!!!!!!!!!