// fake print() for IE4.x if ( !printIsNativeSupport() ) window.print = printFrame; // main stuff function printFrame(frame, onfinish) { if ( !frame ) frame = window; if ( printIsNativeSupport() ) { /* focus handling for this scope is a temporary IE5Beta workaround, and should be unnecessary for IE5 RTM. */ var focused = document.activeElement; frame.focus(); frame.self.print(); if ( onfinish ) onfinish(); if ( !focused.disabled ) focused.focus(); return; } if ( frame.document.readyState !== "complete" && !confirm("The document to print is not downloaded yet! Continue?") ) { return; } var eventScope = printGetEventScope(frame); var focused = document.activeElement; window.printHelper = function() { execScript("on error resume next: printWB.ExecWB 6, 1", "VBScript"); printFireEvent(frame, eventScope, "onafterprint"); printWB.outerHTML = ""; if ( onfinish ) onfinish(); if ( !focused.disabled ) focused.focus(); window.printHelper = null; } document.body.insertAdjacentHTML("beforeEnd", "<object id=\"printWB\" width=0 height=0 \ classid=\"clsid:8856F961-340A-11D0-A96B-00C04FD705A2\"></object>"); printFireEvent(frame, eventScope, "onbeforeprint"); frame.focus(); window.printHelper = printHelper; setTimeout("window.printHelper()", 0); } // helpers function printIsNativeSupport() { var agent = window.navigator.userAgent; var i = agent.indexOf("MSIE ")+5; return parseInt(agent.substr(i)) >= 5 && agent.indexOf("5.0b1") < 0; } function printFireEvent(frame, obj, name) { var handler = obj[name]; switch ( typeof(handler) ) { case "string": frame.execScript(handler); break; case "function": handler(); } } function printGetEventScope(frame) { var frameset = frame.document.all.tags("FRAMESET"); if ( frameset.length ) return frameset[0]; return frame.document.body; }
Most of the code was developed to properly emulate IE5's sparkling new examples of elegance and brevity - the print() method and the onbeforeprint/onafterprint events - for Internet Explorer 4.x. Thankfully you can now just include print.js as a pre-built 'module' and make the same calls for Internet Explorer 4.x or Internet Explorer 5.
If, however, you'd like to know more about some of the advanced DHTML/JScript techniques we used to get this to work, then read on.
One subtle thing about the JScript language is that a JScript function is actually an object. This is true for a nested function, too, and is extremely useful for callbacks (e.g., our printHelper) as it means that from the nested function we can still reference any local variable owned by its parent function, regardless of the fact that the flow control has already gone out of the scope of the parent! This is how - at the time of printHelper (nested into printFrame) - we can reference the frame, onfinish, focused variables that are local to printFrame, even though printFrame has already returned.
An interesting helper is function printFireEvent(frame, obj, name). It's used to "fire" onbeforeprint/onafterprint events for Internet Explorer 4.x (that doesn't natively support them). Here is a snippet illustrating this for the <BODY> tag:
<body onbeforeprint="beforeprint()" onafterprint="afterprint()"> ... <script> function beforeprint() { ... } function afterprint() { ... } </script> </body>
// this could suit, too document.body.onbeforeprint = function() { ... }
// time to call printFireEvent(window, document.body, "onbeforeprint") ... printFireEvent(window, document.body, "onafterprint")
This features the power of JScript's object capabilities, and the custom attribution of DHTML tags.
function printHidden(url) { document.body.insertAdjacentHTML("beforeEnd", "<iframe name=printHiddenFrame width=0 height=0></iframe>"); var doc = printHiddenFrame.document; doc.open(); doc.write("<body onload=\"parent.onprintHiddenFrame()\">"); doc.write("<iframe name=printMe width=0 height=0 src=\"" + url + "\"></iframe>"); doc.write("</body>"); doc.close(); } function onprintHiddenFrame() { function onfinish() { printHiddenFrame.outerHTML = ""; if ( window.onprintcomplete ) window.onprintcomplete(); } printFrame(printHiddenFrame.printMe, onfinish); }
To do this, we create a hidden inline frame (say, 'A') in much the same way as WebBrowser - with insertAdjacentHTML - then generate another inline frame 'B' inside 'A' and navigate 'B' to our required URL. Lastly we need 'B' to handle the download complete event upon which we do printing. In your calling code you may assign window.onprintcomplete to be notified when a document gets downloaded and sent to the print queue.
... we apologize for anything that's still not clear -- or that makes you go "AAAGGGHHH!!! -- and will be glad to answer any of your in-depth questions. Write us!
© 1999 Microsoft Corporation. All rights reserved. Terms of use.