Scripting Support for Web Page Printing

 

Andrew Nosenko
Mead & Company Limited

Updated March 28, 2000

Contents

Introduction
Printing and Internet Explorer 5: What's New?
The Internet Explorer 4.x way: WebBrowser Control
Printing-Related Commands
Example
It's in the Frame
Printing Hidden Content
Print Setup Options

Introduction

In this article, we will talk about ways in which you can implement printing support for your HTML pages viewed using Internet Explorer version 4.0 and later. We will examine Internet Explorer 5's new printing functions, and provide a ready-built JScript™ file that you can include in your pages to provide "backwards compatibility" with those functions in earlier 4.x browsers. We'll also show you some samples that use our print.js file, briefly describe our code (non-techies can skip this bit), and mention some ActiveX control-based ways to customize your page printing settings even further.

Internet Explorer 4.0 introduced a bunch of new and very exciting capabilities for Web application development. Unfortunately, one very important feature was overlooked: printing. There is no Dynamic HTML (DHTML) DOM method available to print a page or modify page settings in Internet Explorer 4.x. With the release of Internet Explorer 5, we see the introduction of some new printing features, so this seems like a good time to demonstrate how to use Internet Explorer 5's native printing support and investigate the possibility of near-100 percent emulation for 4.x browsers.

**Note   **The information and code presented in this article are specific to Internet Explorer running on the Microsoft Windows® platform. The procedures outlined in this article may not work properly on other platforms.

Printing and Internet Explorer 5: What's New?

Let's start with a brief description of Internet Explorer 5's new printing functions:

window.print()

This method will behave as if the user has chosen the File | Print... menu. It will not be possible for a normal HTML page to start printing without the user interface (UI). This method is Netscape Navigator 4. x compatible, so it does not take any parameters.

window.onbeforeprint

This event cannot be canceled and will not bubble. It will fire only after the document has been fully loaded and the onload events have returned. Printing will not occur until onbeforeprint handlers have been executed.

window.onafterprint

This event cannot be canceled and will not bubble. UI control will not return to the user until the event handler is executed. The event will be called after all the drawing operations have been completed (in other words, after the software's job is done and the printing hardware has taken over).

Setting Event Handlers Without Code

The onbeforeprint and onafterprint event handlers are defined in much the same way as those for the existing onload and onunload events*.* They can be set using the following attributes:

For <BODY>:

<body
onbeforeprint="beforeprint()"
onafterprint="afterprint()">

For <FRAMESET>:

<frameset onbeforeprint="beforeprint()"
onafterprint="afterprint()">

Or you may assign them at run time:

window.document.onbeforeprint=beforeprint;
window.document.onafterprint=afterprint;
window.onbeforeprint=beforeprint;
window.onafterprint=afterprint;

Code sample

// This example shows a page that modifies its title before printing
// and then resets it to its original value after printing.
var originalTitle;

<script for=window event=onbeforeprint>
  originalTitle = document.title;
  document.title = document.title + " - by Captain"
</script>

<script for=window event=onafterprint>
  document.title = originalTitle;
</script>

In summary, we can now print from script, we can choose to do something just before we print, and we can make something happen once printing has started. All in all, it's a very welcome development for users of Internet Explorer 5 and later. But how can we generalize printing tasks for both Internet Explorer 4.x and Internet Explorer 5? From here on, we provide the script that uses native printing support if available, and closely emulates it if not.

The Internet Explorer 4.x way: WebBrowser Control

Developers who create custom browsing applications know about the WebBrowser control. This is the underlying engine that hosts Active Documents (as MSHTML documents) and handles navigation from one document to another. Each page and nested frame has a corresponding WebBrowser object.

Is It Safe?

The WebBrowser control exposes a set of Automation properties that is potentially unsafe, but at first sight that doesn't matter, because there is apparently no reason to place a WebBrowser object onto an HTML page, and anyway the Internet Explorer 4.0 team has done its best to make such a pastime fairly useless. However, some clever person—possibly Steve Gore, although we don't really know who did this first—came up with the idea of using WebBrowser's ExecWB method to initiate the printing of a page.

Where There's a Method...

In fact, ExecWB is partially documented for those who do custom WebBrowser hosting. As it turns out, a stand-alone, non-navigated WebBrowser object can be placed on an HTML page—in which case it will forward all ExecWB calls to its parent document.

WebBrowser is known to support OLECMDID_PRINT(6,1) and OLECMDID_PAGESETUP(8) printing related commands.

Doing the Basics

The trick is to create a temporary WebBrowser object with DHTML and invoke *ExecWB(6, 1)*on it to print the page, as shown:

document.body.insertAdjacentHTML("beforeEnd",
    "<object id=\"idWBPrint\" width=0 height=0 \

classid=\"clsid:8856F961-340A-11D0-A96B-00C04FD705A2\">
    </object>");
  idWBPrint.ExecWB(6, 1);
  idWBPrint.outerHTML = "";

In real life, we've added error handling to the above code, because ExecWB(6, 1) could fail if a user selected the Cancel button on the print dialog.

Example

**Note   **To check out these samples, you must be using Internet Explorer 4.x or Internet Explorer 5.

You can check out the first sample or read on for more details. The JScript printing method is printFrame(frameToPrint). You can also review a description of the code in the print.js file. It uses the new native print support for Internet Explorer 5 and provides emulation for the print() method and the onbeforeprint/onafterprint events in Internet Explorer 4. x. To use this, simply include our print.js file on your own pages:

<script defer
src="print.js"></script>

Now you can have a single HTML page source for both Internet Explorer 4.x and Internet Explorer 5:

<head>
<title>Simple Printing</title>
<script defer language=JScript
src="print.js"></script>
</head>

<body onbeforeprint="beforeprint()"
onafterprint="afterprint()"
  bgcolor="infobackground">
<p><input disabled name="idPrint" type="button"
  value="Print this page"
onclick="print()"> </p>
</body>

<script defer>
function window.onload() {
  idPrint.disabled = false;
}

var originalTitle;
function beforeprint() {
  idPrint.disabled = true;
  originalTitle = document.title;
  document.title = originalTitle + " - by Captain";
}

function afterprint() {
  document.title = originalTitle;
  idPrint.disabled = false;
}
</script>

**Note   **We have Internet Explorer 4.x support only for <BODY> inline assigned event handlers. Not perfect, but we think this is probably enough to maintain the same code for both Internet Explorer 4.x and Internet Explorer 5. Notice how, in the sample code above, we are updating the title of the document at print time.

It's in the Frame

We also want to be able to print a specific frame, probably from another frame. Or we might need to print a window's content from inside a frame. Luckily, WebBrowser prints the frame that has the focus by default; we just need to set the focus to the required frame (or to the window itself). This is required for Internet Explorer 4.x only. With Internet Explorer 5, we just call frame.print() on a specific frame.

Caution 1 (Internet Explorer 4.0)

Unfortunately there is no way in Internet Explorer 4.0 to set the focus on to a specific frame because frame.focus() simply has no effect. This is fixed with Internet Explorer 4.01, but users of Internet Explorer 4.0 will be able to print only the frame/window that has a focus.

Caution 2 (Internet Explorer 4.01)

If we use frame.focus() followed by idWBPrint.ExecWB, WebBrowser doesn't take the focus change immediately and ends up printing the whole window. We can work around this with a setTimeout() call to retain the idWBPrint.ExecWB command (technically, until the next message loop pump). Try the sample of frame printing we've provided.

Caution 3 (Internet Explorer 4.x)

Some unpleasant issues can also arise when we call printFrame from inside a frame. If the user cancels, the printing dialog will "bubble" for each frame nesting level up to the top window. This behavior is undesirable, but help is at hand. If you really need such functionality, you can use the Scripting Factory ActiveX control.

Printing Hidden Content

Another interesting kind of functionality is the printing of hidden HTML documents. For example, an author may want to print an HTML-generated database report. Have a look at the sample and check out the code description if you are interested in the details. The main method, printHidden(url), can be found in the shared include file printHid.js.

<head>
<title>Hidden Document Printing</title>
</head>

<body bgcolor="infobackground">

<p>This is a main page</p>
<script defer language=JScript
src="print.js"></script>
<script defer src="printHid.js"></script>

<p><input disabled name="idPrint" type="button"
  value="Print this page" onclick="print()">
<input disabled name="idPrintFrame" type="button"
  value="Print the frame below"
onclick="printFrame(idFrame)"> </p>
<IFRAME style="visibility: visible" name="idFrame"
  width="50%" height="30%" src="frame.htm">
</IFRAME>

<p><input disabled name="idPrintHidden" type="button"
  value="Print hidden page"
onclick="printURL()"></p>

<script defer>
function window.onload() {
  idPrintHidden.disabled = false;
  idPrint.disabled = false;
  idPrintFrame.disabled = false;
}

function printURL() {
  idPrintHidden.disabled = true;
  // set to handle completition
  window.onprintcomplete = function() {
    idPrintHidden.disabled = false;
  }
  // print the content
  printHidden("report.htm");
}
</script>

</body>
</html>

The samples we give above work without any custom controls or extensions. However, there is often a need to adjust page settings such as headers/footers, portrait/landscape orientation, margins and so forth from script—and we provide support for this as part of the 'basic' functionality of our freely-distributable ScriptX ActiveX control. ScriptX 'advanced' printing functionality (accessible by license) is comprehensive and very powerful. Check out the ScriptX documentation and associated printing samples.

ScriptX is part of the free MeadCo Scripting Factorydeveloped for use with any scripting host: Internet Explorer 4.0 or later HTML, ASP, WSH, or Customwhich itself forms part of the company's evolving Web applications tool kit. Established in 1988 and based in Cambridge UK, MeadCo builds and maintains online information systems for corporate and institutional clients around the world.