Can I print a page from a string? (JavaScript) [duplicate] - javascript

I have a .Net application that dynamically creates a small HTML page and pops it up in a new window using the javascript document.open method. Everything with that functionality is working fine.
Now I want to add a button to the HTML page that prints the page. I have tried using the following code to no avail:
<a href='print.html' onClick='window.print();return false;'>
<img src='images/printer.png' height='32px' width='32px'></a>
When the button is clicked in the popup window, nothing happens. But when the source code of of this page is saved and loaded in a browser as a separate page, the print button works perfectly. So it would appear that the problem is caused by the fact that the code is in a popup window. [The problem now appears to be that the code in written to the popup window after it is opened.] Does anyone know a way to fix this problem or any alternatives?
EDIT:
Other method that I have tried with the same results:
<input type='button' onclick='window.print()' value='Print' />
and
<a href='javascript:window.print()'>
<img src='images/printer.png' height='32px' width='32px'></a>
EDIT AGAIN:
The above code works in Firefox, but not in IE7. Any ideas on a work around for IE?
EDIT YET AGAIN:
Here is a test case using the code that npup posted below. Instead of the code for the popup window living in a separate html file, I am opening a blank url and then writing the code to it. This step appears to be what is causing the problem.
<html>
<head>
<title>main</title>
</head>
<body>
<h1>
Pop & print</h1>
<button onclick="pop();">
Pop</button>
<script type="text/javascript">
var POP;
function pop() {
var newWin = window.open('', 'thePopup', 'width=350,height=350');
newWin.document.write("<html><head><title>popup</title></head><body><h1>Pop</h1>" +
"<p>Print me</p><a href='print.html' onclick='window.print();return false;'>" +
"<img src='images/printer.png' height='32px' width='32px'></a></body></html>");
}
</script>
</body>
</html>

Here is a solution that worked for me:
newWin.document.write( newhtml );
newWin.window.location.reload(); // this is the secret ingredient
newWin.focus(); // not sure if this line is necessary
newWin.print();
I'm not 100% sure why this works but I think it has to do with one of the following: (1) an IE security issue, (2) a scope issue (i.e. after creating a new document, IE is confused about which document to print), or (3) a timing issue - the document is not ready to 'accept' a print command yet. In any case, after the reload the print dialogue appears without a problem.

It might be because you are doing a return false in the onclick event of the anchor tag.
Try this:
<input type="button" onclick="window.print()" value="Print" />

You can try:
<input type="button" onclick="self.print()" value="Print" />
or:
<input type="button" onclick="window.focus();window.print()" value="Print" />
But this might not work in MSIE due to restrictions in Cross-Frame Scripting. The best way to do this, I think, is to put the print button on the main window.
<script language="javascript">
var winref = window.open('print.html','windowName','width=400,height=400');
</script>
<form>
<input type="button" value="Print Popup" onclick="if (window.print) winref.print()">
</form>

There must be something more to it than the code shown. I think it works fine (been testing some now).
Here's a miniscule test case. Try it in your setup and see what happens! My checking was under Windows Vista, IE7 and IE8.
main.html:
<html>
<head>
<title>main</title>
</head>
<body>
<h1>Pop & print</h1>
<button onclick="pop();">Pop</button>
<script type="text/javascript">
var POP;
function pop() {
POP = window.open('popup.html', 'thePopup', 'width=350,height=350');
}
</script>
</body>
</html>
popup.html:
<html>
<head>
<title>popup</title>
</head>
<body>
<h1>Pop</h1>
<p>Print me</p>
<a href="print.html" onclick="window.print();return false;">
<img src="images/printer.png" height="32px" width="32px">
</a>
</body>
</html>

I have solved the problem by creating a blank HTML page with the standard HTML markup. I then added the content by creating a new DOM element and editing the innerHTML. The resulting code is the same as in the example, simply replacing the newWin.document.write command with the following:
var newDiv = newWin.document.createElement( 'div' );
newDiv.innerHTML = "<h1>Pop</h1>" +
"<p>Print me</p><a href='print.html' onclick='window.print();return false;'>" +
"<img src='images/printer.png' height='32px' width='32px'></a>"
newWin.document.body.appendChild(newDiv);
While the issue has been resolved, I am honestly not sure what was the exact cause of the problem. If anyone has any ideas, I would be glad to hear them.

You forgot the:
newWin.document.close();
Document must be closed before msie can print it.

This works in Chrome:
<body ><img src="image.jpg" alt="" style="display: block; width: 100%; height: 100%;">
<script type="text/javascript">
window.onload = function() {
window.print();
setTimeout(function() {
window.close();
}, 1);
};
</script>
</body>

If you want to print what's in the window you opened from, i suggest you use
window.opener.print();
in the popup.

I wanted to create a printer friendly version of a page that then automatically printed, this is what I came up with, seems to work great for me!
function printPage(){
var w = window.open();
var headers = $("#headers").html();
var field= $("#field1").html();
var field2= $("#field2").html();
var html = "<!DOCTYPE HTML>";
html += '<html lang="en-us">';
html += '<head><style></style></head>';
html += "<body>";
//check to see if they are null so "undefined" doesnt print on the page. <br>s optional, just to give space
//This allows you to reuse this on lots of pages with the same template
if(headers != null) html += headers + "<br/><br/>";
if(field != null) html += field + "<br/><br/>";
if(field2 != null) html += field2 + "<br/><br/>";
html += "</body>";
w.document.write(html);
w.window.print();
w.document.close();
};

Related

My angular App freezes when the print window is open

I am making an angular app that requires to create a document, open it in a new tab and print a section. I have already achieved this.
The problem is my client want to continue interacting with the app while the print window is still open.
But I have noticed that when this print window is open, the app like it freezes, all click events no longer work until you close this window.
I have tried a few solutions provided here on Stack Overflow but none really works. In one case I tried setTimeout().
Here is my html code:
<!-- Print button-->
<div class="footer-share" (click)="print()">
<button class="btn btn-back"><span class="mdi mdi-printer"></span><span> Drucken</span></button>
</div>
And here is the funtion in my ts file:
print() {
let printContents, popupWin;
printContents = document.getElementById('print-section').innerHTML;
popupWin = window.open('', 'top=0,left=0,height=100%,width=auto');
popupWin.document.open();
popupWin.document.write(`
<html>
<head>
<title>XYZ Records</title>
<style type="text/css" media="print">
#page { size: landscape; }
</style>
<style>${printStyles}</style>
</head>
<body onload="window.print();window.close()">${printContents}
<h2>This is the end!
</h2>
<img src="/assets/images/tempton-logo.png" style="width:60%;padding-top:0%;" alt="homepage" class="dark-logo" />
</body>
</html>`
);
popupWin.document.close();
}
What can I change to make it possible for the user to continue interacting with the app when the print tab is still open?
Remove the html property and value for onload in .write() method. Then, remove the close method directly after the write method use this instead:
popupWin.focus();
popupWin.print();
popupWin.close();
Try to do what was suggested in this other question, it worked for me.
https://stackoverflow.com/a/62808575/7912859
According to the documentation: (https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Window_features) window.open() currently supports features. Hence we can pass noreferrer or noopener as shown below, which does not freeze or block the parent window.
window.open(hostUrl, '_blank', 'noreferrer')

innerDocument.getElementById(<elment ID>).click(); doesn't work in Firefox/chrome, in IE it works

I am working with Iframes for controlling the elements of iframe by automating it from the parent html file.
I was trying to to click the link defined in iframe.html file from the test.html file using function click() on javascript while loading test.html :
Test.html file :
function handleMainOnload(){
alert("main frame loaded");
var innerFrame = document.getElementById("frame1");
alert("hi-1" + innerFrame.ownerDocument.title);
var innerDocument = frame1.document;
alert("hi" + innerDocument.title);
innerDocument.getElementById("input1").value = "Dynamically Inserted Text";
innerDocument.getElementById("a1").click();
}
<body onload="handleMainOnload();">
<iframe id="frame1" src="iframe.html"/>
iframe.html file :
<a id="a1" href="http://www.google.co.in"> Google.. click</a>
This achor id = a1 automatically get clicked onload of test.html in IE but doesn't work on any browser apart from IE. Please help.
From Javascriptkit.com:
click() - Executes a click on a element as if the user manually clicked on it. In most browsers, click() only works on form INPUT elements that's non "submit" or "reset". It can't be used to simulate a click on a link or form submit button.
I have verified that this is the reason why it's not working for you. Also, I had to change the following line:
var innerDocument = frame1.document;
to
var innerDocument = window.frames["frame1"].document;
Will update with a way to do this in jQuery.
EDIT:
Here's how you do it in jQuery. Essentially you bind a click event and then call click() on the element. This simulates the action since there is no standard way of executing clicks on hyperlinks.
$(document).ready(function() {
$("#frame1").ready(function () { //The function below executes once the iframe has finished loading
alert("iframe loaded");
$('#frame1').contents().find('#a1').click(function() {
alert("Hello");
$('#frame1').attr('src', $('#frame1').contents().find('#a1').attr("href"));
$('#frame1').load();
});
$('#frame1').contents().find('#a1').click();
});
});
Create the event, initialize it and dispatch it on the node.
See https://developer.mozilla.org/en/DOM/element.dispatchEvent for example.
Just remember to call createEvent on the document that has the node you're going to dispatch on.
You can do this without jQuery and without click event handlers on the anchor tags. (Confirmed with IE 9, FF 15, Chrome 23)
The reason it wasn't working (and for JackWilson's edit) is that [in IE at least] innerFrame.document == innerFrame.ownerDocument, so you were not actually looking for the anchor in the iFrame's content document. Use innerFrame.contentDocument instead.
(I haven't confirmed JackWilson's solution for using window.frames[] in browsers other than IE but some browsers may require referencing window.frames[] by index instead of its id. Anybody know for sure?)
Main page: "aclicktest.html":
<!DOCTYPE html>
<html>
<head><title>A click test</title></head>
<body onload="clickIframe();">
<a id="alocal" href="http://stackoverflow.com" target=_blank>Local link</a>
<iframe id='frame1' src="iframeaclicktest.html"></iframe>
<input type='button' value='click local' onclick='clickLocal();'/>
<input type='button' value='click iframe' onclick='clickIframe();'/>
<script type="text/javascript">
function clickLocal(){document.getElementById("alocal").click();}
function clickIframe(){document.getElementById("frame1").contentDocument.getElementById("aiframe").click();}
</script>
</body>
</html>
Iframe page: "iframeaclicktest.html":
<!DOCTYPE html>
<html>
<head><title>A click test IFRAME</title></head>
<body>
<a id="aiframe" href="http://stackoverflow.com" target=_blank>IFRAME link</a>
</body>
</html>
That's interesting that your old code was working in IE. What version? And did you define doctype? It may have been quirks mode behavior.

Document.links empty after calling document.close

When you execute following example using Firefox 3:
<html>
<head>
<script language="javascript" type="text/javascript">
<!--
function openWindow(){
var w = window.open('', 'otherWin', 'width=600,height=600');
w.document.write(document.getElementsByTagName("html")[0].innerHTML);
w.document.close();
reportLinks(w.document.links);
}
function reportLinks(links){
var report = 'links: '+links.length;
for (var i=0;i<links.length;i++){
report += '\n (link='+links[i].href+')';
}
alert(report);
}
//-->
</script>
</head>
<body>
<p>Open Same Content and Show Links Report</p>
<p>Show Links Report</p>
</body>
</html>
You will see that both the number of links shown when clicking on 'Show Links Report' as when clicking on 'Open Same Content and Show Links Report' will be 2. However when having an external JavaScript file reference from this page the behavior seems different (just make an empty file some.js if you want). When clicking 'Open Same Content and Show Links Report' the number of links will be 0.
<html>
<head>
<script language="javascript" type="text/javascript" src="some.js"></script>
<script language="javascript" type="text/javascript">
<!--
function openWindow(){
var w = window.open('', 'otherWin', 'width=600,height=600');
w.document.write(document.getElementsByTagName("html")[0].innerHTML);
w.document.close();
reportLinks(w.document.links);
}
function reportLinks(links){
var report = 'links: '+links.length;
for (var i=0;i<links.length;i++){
report += '\n (link='+links[i].href+')';
}
alert(report);
}
//-->
</script>
</head>
<body>
<p>Open Same Content and Show Links Report</p>
<p>Show Links Report</p>
</body>
</html>
It is probably a matter of loading the page and the moment that reportLinks executed exactly. I assume that the external some.js is added that the document is not completely build up. Is there a way that I can register this reportLinks call for onload event so that I can be sure that document.links is complete?
By the way the example works fine in both cases with Google Chrome.
(added after answer1)
As suggested by Marcel K. I rewrote the example, added also the code the way I really would like to have the thing going. And now testing it, and this simple example seems to work with Firefox and with Chrome.
<html>
<head>
<script type="text/javascript" src="some.js"></script>
<script type="text/javascript">
<!--
function openWindow(){
var w = window.open('', 'otherWin', 'width=600,height=600');
w.document.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n'+
document.getElementsByTagName("html")[0].innerHTML+'\n</html>');
w.onload=function(){
reportLinks(w.document.links);
};
w.document.close();
}
function reportLinks(links){
var report = 'links: '+links.length;
for (var i=0;i<links.length;i++){
report += '\n (link='+links[i].href+')';
}
alert(report);
}
//-->
</script>
</head>
<body>
<p>Open Same Content and Show Links Report</p>
<p>Show Links Report</p>
</body>
</html>
I had hoped with this simple example to show a simple case of the actual code I am writing. A print preview screen of complicated html in which I want to disable all hrefs once opened. But in that one the onload handler is never called... How can I register an onload handler in this case in the most robust way?
Many thanks,
Marcel
As I said in a comment, this is a very strange issue. But I think it happens because the inclusion of an external script causes a delay in page rendering (of the new page) and its DOM might not be ready to inspect.
My suspicion is supported by the fact that adding the (new) defer attribute seems to solve this issue:
This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed.
The defer attribute can be set on the original page, as you want an exact copy of it. You can set it if it doesn't matter where a script is being included (e.g., when using document.write in your included file it does matter at which place you include it).
As defer is a Boolean attribute, it is activated when it is simply present (defer) or (when using XHTML) set to itself (defer="defer"). In your case, the script inclusion would read:
<script type="text/javascript" src="some.js" defer></script>
Update regarding your update: you should still insert a Doctype in the main page (consider using the HTML 5 one).
And I think the way you attached your onload event is the best you can do.
But considering the goal you want to achieve (a print preview without hyperlinks): you can also use the "print" media attribute and style hyperlinks like text; that's way more easy than the thing you are doing and it works when JavaScript is disabled.
The only way I could make the example above work portable over Firefox, Chrome and IE is by registering the onload listener through inlined JavaScript in the HTML loaded in the popup window. Following example code shows how.
<html>
<head>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<p>Open Same Content and Show Links Report</p>
<p>Show Links Report</p>
</body>
</html>
This page uses a script in script.js file. Following shows the content of that file.
function openWindow(){
var w = window.open('', 'otherWin', 'width=600,height=600');
w.document.write(
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html>\n'+
document.getElementsByTagName("html")[0].innerHTML+
'\n <script type="text/javascript">\n'+
' function addOnloadListener(listener){\n'+
' if (window.addEventListener) {\n'+
' window.addEventListener("load", listener, false);\n'+
' } else {\n'+
' window.attachEvent("onload",listener);\n'+
' }\n'+
' }\n'+
' addOnloadListener(function(){reportLinks(document.links);});\n'+
' </script>\n'+
'</html>');
w.document.close();
}
function reportLinks(links){
var report = 'links: '+links.length;
for (var i=0;i<links.length;i++){
report += '\n (link='+links[i].href+')';
}
alert(report);
}
When putting the function addOnloadListener directly in the JavaScript file (not inlined in the page) it doesn't work in IE6 because, I believe, it cannot handle the order of script entries correctly. When addOnloadListener was not inlined the inlined call to addOnloadListener didn't work, it simply couldn't find the function in the earlier:
<script type="text/javascript" src="script.js"></script>
The code is only a simple example that doesn't really do a lot. I used it for disabling all links in a print preview popup page.
A simpler way to register an onload listener for a popup window portable over browser is always welcome.
Thanks,
Marcel

Why does using document.write to create an iframe "cancel out" all remaining Javascript?

This happens in all browsers, so there must be a reason.
Example:
<html>
<body>
<script>var a="support/";
var aa='<iframe src="http://google.com/' + a + '" />';
document.write(aa)</script>
<script>alert('test')</script>
</body>
</html>
The code after the iframe write (in this case alert('test')) doesn't execute. Why?
Because you're writing broken HTML into the document -- there's no > on the iframe tag.
Your HTML that you write into the document is invalid and causes the browser to fail interpreting the rest of the document, including the remaining <script> tags.
You are writing <iframe src="http://google.com/support/. Add "></iframe> and it's ok.
However, a cleaner approach would be not to use document.write at all (assuming you have some HTML element with id="container" to hold the iframe):
var iframe = document.createElement('iframe');
iframe.setAttribute("src", "http://google.com/support/");
document.getElementById("container").appendChild(iframe);
You need to close your quotes and iframe. This works:
<html>
<body>
<script>var a="support/";
var aa='<iframe src="http://google.com/' + a + '" />';
document.write(aa)</script>
<script>alert('test')</script>
</body>
</html>
This code is Ok and working fine. You can check it on JSFiddle Live DEMO. Rest you can edit it with your data..
<script type="text/javascript">
var write_variable="p/about.html";
var write_iframe='<iframe src="http://www.exeideas.com/' + write_variable + '" />';
document.write(write_iframe);
</script>
Or you can check it online via HTML Editor And Previewer

JQuery - Write to opener window

I have an HTML page that opens another page via JavaScript. When a user clicks a button in the other page, I want to post a message in a DIV of the opening page via JQuery. I cannot put my finger on it, but I cannot seem to get this to work. Here is my opener page
<html>
<head>
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
</head>
<body>
<input type="button" onclick="window.open('dialog.html', '_blank', 'height=200, width=300');" value="launch!" />
<div id="testDiv"></div>
</body>
</html>
When the user clicks the "launch!" button, a dialog will appear. The code for the dialog looks like this:
<html>
<head>
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
</head>
<body>
<input type="button" onclick="updateOpener()" value="Update Opener" />
<script type="text/javascript">
function updateOpener()
{
var testDiv = window.opener.jQuery("#testDiv");
if (testDiv != null) {
alert("here");
testDiv.html("Updated!");
}
}
</script>
</body>
</html>
Surprisingly, the alert box appears. However, I cannot seem to update the HTML of the DIV in my opening page. Does anyone know how to do this?
You're referencing "confirmDiv". Where is that DIV?
You can't do that if the parent page (the opener) resides on another domain. Otherwise, your code works perfectly.
Also, your != null check is probably not doing what you think it is doing, as the jQuery function never returns null. If you are checking for the existence of an element, you need to do it this way...
var el = $("#myElementId");
if(el.length == 0)
alert('Not found!');
Ummm, it works for me in Firefox 3.0.11, IE8 and Chrome 2... (I.e. the dialog.html button updates the HTML in the opener page to say 'Updated!'.)
Oddly, your example works fine for me in Chrome, IE 8 and FireFox. Do you have any other details?

Categories