How do I print an IFrame from javascript in Safari/Chrome - javascript

Can someone please help me out with printing the contents of an IFrame via a javascript call in Safari/Chrome.
This works in firefox:
$('#' + id)[0].focus();
$('#' + id)[0].contentWindow.print();
this works in IE:
window.frames[id].focus();
window.frames[id].print();
But I can't get anything to work in Safari/Chrome.
Thanks
Andrew

Here is my complete, cross browser solution:
In the iframe page:
function printPage() { print(); }
In the main page
function printIframe(id)
{
var iframe = document.frames
? document.frames[id]
: document.getElementById(id);
var ifWin = iframe.contentWindow || iframe;
iframe.focus();
ifWin.printPage();
return false;
}
Update: Many people seem to be having problems with this in versions of IE released since I had this problem. I do not have the time to re-investigate this right now, but, if you are stuck I suggest you read all the comments in this entire thread!

Put a print function in the iframe and call it from the parent.
iframe:
function printMe() {
window.print()
}
parent:
document.frame1.printMe()

I used Andrew's script but added a piece before the printPage() function is called. The iframe needs focus, otherwise it will still print the parent frame in IE.
function printIframe(id)
{
var iframe = document.frames ? document.frames[id] : document.getElementById(id);
var ifWin = iframe.contentWindow || iframe;
iframe.focus();
ifWin.printPage();
return false;
}
Don't thank me though, it was Andrew who wrote this. I just made a tweak =P

In addition to Andrew's and Max's solutions, using iframe.focus() resulted in printing parent frame instead of printing only child iframe in IE8. Changing that line fixed it:
function printIframe(id)
{
var iframe = document.frames ? document.frames[id] : document.getElementById(id);
var ifWin = iframe.contentWindow || iframe;
ifWin.focus();
ifWin.printPage();
return false;
}

I had to make few modifications in order to make it with in IE8 (didn't test with other IE flavours)
1) document.frames[param] seem to accept a number, not ID
printIframe(0, 'print');
function printIframe(num, id)
{
var iframe = document.frames ? document.frames[num] : document.getElementById(id);
var ifWin = iframe.contentWindow || iframe;
ifWin.focus();
ifWin.printPage();
return false;
}
2) I had a print dialog displayed upon page load and also there was a link to "Click here to start printing" (if it didn't start automatically). In order to get it work I had to add focus() call
<script type="text/javascript">
$(function(){
printPage();
});
function printPage()
{
focus();
print();
}
</script>

Use firefox window.frames but also add the name property because that uses the iframe in firefox
IE:
window.frames[id]
Firefox:
window.frames[name]
<img src="print.gif" onClick="javascript: window.frames['factura'].focus(); parent['factura'].print();">
<iframe src="factura.html" width="100%" height="400" id="factura" name="factura"></iframe>

One thing to note is if you are testing this locally using file:///, it will not work on chrome as the function in the iframe will appear as undefined. However once on a web server it will work.

You can use
parent.frames['id'].print();
Work at Chrome!

You can also use
top.iframeName.print();
or
parent.iframeName.print();

The 'framePartsList.contentWindow.print();' was not working in IE 11 ver11.0.43
Therefore I have used
framePartsList.contentWindow.document.execCommand('print', false, null);

In Chrome:
Press Ctrl+Shift+C to select the iframe.
Click anywhere in the iframe.
Go to the console tab and type window.print();
This works because in Chrome Dev Tools, the window element adjusts to whatever <html> context you are in.

Use this:
window.onload = setTimeout("window.print()", 1000);

Related

Remove id from iframe

I have an iframe of a certain page from a site that I'm using, but I don't want all the parts of that page to be displayed with the iframe. Particularly, there's a navigation sidebar on the page that I don't want to be in the iframe. I'm trying to achieve this with the javascript seen below, but I can't quite figure it out.
<iframe width="800" height="800" src="scores/new?site_id=193">
<script>
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
</script>
</iframe>
For security reasons you can't run javascript through iframes. There are some exceptions if you're on the same domain but for the most part you should really avoid it.
If the iframe isn't a site you can control then there's pretty much nothing you can do. If you do control the other site and it's a different domain you might be able to work with the postMessage functions.
Edit: Check out the docs that Mozilla has up here https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
You'd need to create a listener on the inside that handles a message and hides your sidebar. Then on the parent send a message to the iframe to trigger that function.
Parent:
var iframe = document.getElementById('#iframeID');
iframe.contentWindow.postMessage('iframeTrigger');
Iframe:
window.addEventListener('iframeTrigger', hideSidebar);
function hideSidebar() {
//do stuff
}
You can insert a control in the iframed page
//inside the iframed page
var iframe = (function() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
})();
if(iframe === true) {
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
}
Hope this could suit your need.
This should work theoretically, and it works in console. But this doesn't work in the HTML, although you are trying it from the same domain, because of security reasons. I just wanted to tell my view and I tried this:
<iframe src="http://output.jsbin.com/figujeyiyo" frameborder="0" id="ifrm">
Sorry, iframes not supported.
</iframe>
<script>
console.log(document.getElementById("ifrm").contentDocument.documentElement.getElementsByTagName("div"));
e = document.getElementById("ifrm").contentDocument.documentElement.getElementsByTagName("div")[0];
console.log(e);
e.parentNode.removeChild(element);
</script>
You need to execute the code when the page loads, you can do it like this:
document.addEventListener('DOMContentLoaded', function() {
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
});

Javascript .onload not firing in IE? window.open reference issue?

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;

script dont work with chrome, only ie and firefox

i looked for a javascript script that will change the height of an iframe, according to the loaded page in it, i found a code but it works for me only in IE and FireFox.. what should i change?
<SCRIPT type="text/javascript" LANGUAGE="javascript">
function reSize()
{
try{
var oBody = ifrm.document.body;
var oFrame = document.getElementById("ifrm");
oFrame.style.height = oBody.scrollHeight + (oBody.offsetHeight - oBody.clientHeight);
}
//An error is raised if the IFrame domain != its container's domain
catch(e)
{
window.status = 'Error: ' + e.number + '; ' + e.description;
}
}
</SCRIPT>
the iframe code:
<iframe width=940px onload=reSize() src="html/guides.html" id="ifrm" name="iframe_main" frameborder="0"></iframe>
thanks for helping!
For starters:
document.all has been obsolete for quite some time.
You should use getElementById.
Also if the iframe is not in your domain (e.g. you're in www.mydomain.com and the iframe loads content from www.someotherdomain.com) you WON'T be able to get the iframe's document.body with the normal security settings of most modern browsers... See here for details
Try var oBody = ifrm.contentDocument.body || ifrm.contentWindow.document.body;
Give an id to your iframe. I gave "myIframe" and after that use this line in your function instead of yours. it'll work everywhere:
document.getElementById("myIframe").setAttribute("height",600)​;

Javascript Print iframe contents only

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

How to clear the content of an IFRAME?

How do I clear the content of my IFRAME element, using javascript, without loading a blank page into it?
I can figure out to do this: iframe_element.src = "blank.html", but there must be a better, instant, method.
about:blank
is a "URL" that is blank. It's always clear
You can set the page's source to that, and it will clear.
var iframe = document.getElementById("myiframe");
var html = "";
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();
tested in IE, Firefox and Chrome ... it did it :)
Your technique is the most robust. Its the one I use myself. At times content may be delivered over HTTPS and the use of about:blank can cause warning messages to appear to the effect of "do you want to include content from unsecure location" or some such thing.
Something being instant is a matter of perception however if you have a single Blank.html file on your site configured with a long cache expiry the client will only ever fetch the page once (at the most once per-session).
Or you can do this :
var iframe_element = window.frames['iframe_name'];
iframe_element.document.open();
iframe_element.document.close();
I have had difficulties with "about:blank" on pages with many IFrames. It does not seem to be a valid location in every browser (I never found out for sure, though). Anyway, I am happy with javascript:void(0);
You could also do this:
<html>
<head>
<script>
var doc = null;
window.onload = function() {
alert("Filling IFrame");
doc = document.getElementById("test");
if( doc.document ) {
document.test.document.body.innerHTML = "<h1>test</h1>"; //Chrome, IE
}else {
doc.contentDocument.body.innerHTML = "<h1>test</h1>"; //FireFox
}
setTimeout(function() {
alert("Clearing IFrame");
if( doc.document ) {
document.test.document.body.innerHTML = ""; //Chrome, IE
}else {
doc.contentDocument.body.innerHTML = ""; //FireFox
}
}, 1000);
};
</script>
</head>
<body>
<iframe id="test" name="test">
</iframe>
</body>
</html>
// First I get the window from its Id.
var my_content = document.getElementById('my_iframe').contentWindow.document;
// Then I clear it by setting the body tag inner HTML to an empty string.
my_content.body.innerHTML="";
// Now when I write my new content it does not get appended to the end of the body and the iframe body will contain only fresh content.
my_content.write(new_content);
Just do it:
var iframe = document.getElementById("iframe");
iframe.removeAttribute('srcdoc');
Work in Chrome
Just get the Iframe and remove the documentElement from it. The Iframe will be blank
var frame = document.getElementById("YourFrameId"),
frameDoc = frame.contentDocument || frame.contentWindow.document;
frameDoc.removeChild(frameDoc.documentElement);
function getContentFromIframe(iFrameName)
{
var myIFrame = document.getElementById(iFrameName);
var content = myIFrame.contentWindow.document.body.innerHTML;
//Do whatever you need with the content
}
$("#iframe").contents().find("body").html('');

Categories

Resources