Prince Documentation
  • Documentation
  • Help
  • Release Notes

›User Guide

Installation Guide

  • Getting Started
  • Your First Document
  • Help

User Guide

  • Convert HTML to PDF
  • Styling
  • Paged Media
  • Generated Content
  • Scripting
  • Graphics
  • Prince Tips and Tricks
  • Help
  • Prince Input
  • Prince Output
  • Prince Networking
  • Server Integration
  • Prince for Books

Reference Guide

    CSS Support

    • Length & Angle Units
    • CSS Properties
    • CSS Selectors
    • CSS Media Queries
    • CSS Functional Expressions
    • CSS At-rules
    • Color Names
    • Supported CSS Specifications
  • JavaScript Support
  • Command-line Options
  • Miscellaneous

    • Page Size Keywords
    • Character Entities
  • Acknowledgments

Scripting

JavaScript can be used to transform documents by generating tables of contents and indices, sorting tables, rendering charts and graphs, and other tasks that go beyond the scope of CSS.

Scripts can access and modify the input document using the W3C standard DOM (Document Object Model). Prince also supports some additional properties and methods described below.

Prince is not running JavaScript by default - it needs to be explicitly enabled. See Applying JavaScript in Prince.

JavaScript in Printed Media

Prince is a user agent producing primarily documents meant to be printed, and as such, some limitations are in place that set it apart from most other user agents that support JavaScript.

The most notable difference is the fact that a printed page cannot be interactive, being static in nature: in principle a document cannot be modified after it is deemed to be ready for print. JavaScript can basically be run twice: the first time it is run before layout, where it interacts with and modifies the layout (and the DOM structure). Once layout is finished, JavaScript can be run a second time from the complete event handler (see Event Handling) to inspect the layout, without modifying the DOM.

However, Prince also offers to register the function Prince.registerPostLayoutFunc(func), which is called after layout finished, similar to the current oncomplete event. If this function modifies the DOM, Prince will perform layout again on the updated document. For more details see Multi-Pass formatting and The "Multi-Pass" Solution.

Please also note that a consequence of the non-interactive nature of printed media is that any interactive events, such as e.g. onClick, do not make sense, and will never fire.

JavaScript in Prince

Prince supports most of ECMAScript 5th edition (ES5), with the exception of strict mode. ES6 is not fully supported yet, and later editions of ECMAScript are not supported.

Document JavaScript is not run by default - it needs to be explicitly enabled. See Applying JavaScript in Prince for details.

In addition to normal JavaScript run in the document, Prince allows also for scripts to be passed directly to the PDF, to be executed when the PDF file is opened (by means of the CSS property -prince-pdf-script), or triggered by specific events (with the CSS property -prince-pdf-event-scripts). See Script Functions and PDF Actions for more details.

These PDF scripts, known as "Document Action" scripts, will always be run. Note, however, that these scripts are dependent on the PDF viewer, and in many cases might only work in Adobe Acrobat products.

A full list of all supported JavaScript objects, methods and properties can be found in the References section, in JavaScript Support. Here we shall just illustrate a few highlights from Prince's JavaScript support.

Logging

The Prince log can be accessed from JavaScript via the Log object (also available as Prince.Log), which has the following methods:

    Log.debug("message")
    Log.info("message")
    Log.warning("message")
    Log.error("message")
    Log.data("name", "value")

Log.debug() is only available when the --debug command-line option has been specified, while Log.info() is only available when the --verbose command-line option has been specified.

Console Access

When running Prince from the command-line, the console object can be used to write messages directly to the terminal:

    console.log("Hello, world!")

Console access is only supported when running Prince directly from the command-line, and should not be used when calling Prince through a server wrapper or graphical user interface.

Event Handling

When the document has been fully parsed and is ready for processing, Prince will fire the DOMContentLoaded and load events on the window object.

These load events can be captured by setting the onload attribute on the body element in HTML documents, or by setting the window.onload property or calling window.addEventListener.

When document conversion has finished, Prince will fire the complete event on the Prince object. This event can be captured by calling Prince.addEventListener, or by setting the Prince.oncomplete property, and is useful for logging document statistics.

Prince also offers the possibility to register the function Prince.registerPostLayoutFunc(func) after layout has finished for possibly triggering a new layout - see Multi-Pass formatting for more details.

When multiple documents are processed into one PDF, the complete event will only fire once, on the first document.

User interface events such as onclick are not supported by Prince.

The Prince Object

The Prince object can be used to control various scripting aspects in Prince.

    Prince.addEventListener(type, ...callback, optional extra options)
    Prince.oncomplete
    Prince.addScriptFunc(name, func)
    Prince.trackBoxes = (boolean)
    Prince.convertToFile(JSON, OutputFileName, ...optional extra job resources)
    Prince.convertToBuffer(JSON, ...optional extra job resources)
    Prince.failStatus
    Prince.pageCount
    Prince.registerPostLayoutFunc(func)

Event tracking

The Prince.addEventListener method or the Prince.oncomplete property can be called to listen to the complete event on the Prince object, which is fired when all layout is finished (and after the last repeated layout, if this was requested), just before the PDF is generated, so that it can cancel the PDF output by triggering a fail-safe if necessary, or log information about the PDF like the page count.

Script functions

The Prince.addScriptFunc method exposes an arbitrary JavaScript function to CSS. It takes two arguments: the string name that will be exposed to CSS, and the function itself. See Script Functions for an example.

Box tracking

Prince.trackBoxes is a bool that will enable the box tracking API if set to true, so that it can be used later in the complete event. See The Box Tracking API.

Prince jobs

The Prince.convertToFile and Prince.convertToBuffer methods allow you to start new Prince jobs:

    convertToFile(JSON, OutputFileName, ...optional extra job resources)
  • returns bool indicating success;
    convertToBuffer(JSON, ...optional extra job resources)
  • returns ArrayBuffer if successful, null if not;

whereby JSON is a job description as specified in the Job description JSON, while the optional extra job resource arguments are ArrayBuffers or strings that can be referenced from the JSON using the job-resource: URLs. See Prince Control Protocol.

The Prince jobs methods are only accessible in Prince shell mode.

Failure status

The property Prince.failStatus is a boolean which can be set to trigger an explicit failure status through JavaScript, based on custom criteria. See also Fail-Safe Options.

It can be set to true by a script that runs after layout in the oncomplete handler (see Event Handling) and checks for complex conditions, like overlapping content (see The Box Tracking API and the Detecting Overflow sample) or some other user-defined issue that you want to trigger the fail-safe.

For example, perhaps there should be only one page: you check the page count (see Document Statistics), and if it's greater than one, you log a warning and trigger the fail-safe to ensure that no PDF is generated.

Document Statistics

The Prince.pageCount property can be accessed after document conversion has finished, then logged as data for the calling process to access:

    function logPageCount()
    {
        Log.data("total-page-count", Prince.pageCount);
    }

    Prince.addEventListener("complete", logPageCount, false);

Multi-Pass formatting

Prince also offers the possibility to register the function Prince.registerPostLayoutFunc(func), which is called after layout finished, similar to the current oncomplete event. If this function modifies the DOM, Prince will perform layout again on the updated document once the function returns, and before generating the PDF.

JavaScript

    Prince.registerPostLayoutFunc(function() {
        var str = '@prince-color Color1 { alternate-color: cmyk(1,0,0,0) }';
        var add = document.getElementById('add');
        add.appendChild(document.createTextNode(str));
    });

HTML

    <style id='add'></style>
    <p style='color: prince-color(Color1)'>This was black, becomes cyan</p>

A post layout function may register itself, or another post layout function, in order to repeat this process multiple times! By default the number of passes is not limited, but in order to prevent endless layout loops you can set a limit by using the --max-passes=N command-line option. For more details see The "Multi-Pass" Solution.

The PDF Object

The PDF object can be used to specify PDF properties and settings, including attaching extra files to the generated PDF, similar to the --attach command-line argument:

    PDF.attachFile(url, description?)

    PDF.attachFile("data.xls", "Latest sales figures.");

Other PDF properties, which are set by assignment, include:

    PDF.embedFonts = (boolean)
    PDF.subsetFonts = (boolean)
    PDF.artificialFonts = (boolean)

    PDF.compress = (boolean)

    PDF.encrypt = (boolean)
    PDF.userPassword, PDF.ownerPassword = (string, can be null)
    PDF.allowPrint, PDF.allowModify, PDF.allowCopy, PDF.allowAnnotate = (boolean)
    PDF.keyBits = "40" | "128"

    PDF.script = (string, can be null)
    PDF.openAction = (eg. "print")
    PDF.pageLayout = "single-page" | "one-column" | "two-column[-left/right]"
    PDF.pageMode = "auto" | "show-bookmarks" | "fullscreen" | "show-attachments"
    PDF.printScaling = "auto" | "none"
    PDF.duplex = "auto" | "simplex" | "duplex-flip-short-edge" | "duplex-flip-long-edge"

    PDF.profile = (string, can be null)
    PDF.outputIntent = (URL string, can be null)

    PDF.objectStreams = (boolean)

    PDF.title
    PDF.subject
    PDF.author
    PDF.keywords
    PDF.creator

    PDF.lang

There is one more PDF object not mentioned so far: the PDF.pages object is different from all preceding PDF objects - the latter ones are set before document conversion begins, while the former becomes available only after the complete event (see Event Handling) and returns a list of boxes - see The Box Tracking API.

The Box Tracking API

The box tracking API must be enabled with Prince.trackBoxes before formatting starts.

    Prince.trackBoxes = true;

It then becomes available in the complete event (see Event Handling), when you can call the getPrinceBoxes() method while iterating through the required DOM elements, to return a list of boxes.

    Prince.addEventListener("complete", function() {
      var xs = document.getElementsByTagName("ins");
      for (var i = 0; i < xs.length; ++i)
        {
          var ins = xs[i];
          var boxes = ins.getPrinceBoxes();
        }
    }, false);

The PDF.pages array mentioned earlier (see The PDF Object) also is available only after the complete event and also returns a list of boxes (see Page regions).

    function printbox(str,box) {
      console.log("");
      for (var i in box) {
        console.log(str+i+": "+box[i]);
      }
      for (var i=0; i<box.children.length; i++) {
        printbox(str+"  ",box.children[i]);
      }
    }

    Prince.addEventListener("complete", function() {
      var pages = PDF.pages;
      for (var i = 0; i<pages.length; ++i)
        {
          console.log("PAGE "+(i+1)+" HAS THESE BOXES");
          printbox("  ",pages[i]);
        }
    }, false);

Boxes are JavaScript objects with some or all of the following properties:

type =          "BODY" |
                "COLUMN" |
                "FLEXLINE" |
                "FOOTNOTES" |
                "FLOATS" |
                "BOX" |
                "LINE" |
                "SPAN" |
                "TEXT" |
                "SVG" |
                "IMAGE"
pageNum =       the page of the current box
x =             x-coordinate, in pt
y =             y-coordinate, in pt (set to zero on some boxes)
w =             width, in pt
h =             height, in pt (set to zero on some boxes)
baseline =      the y-coordinate of the baseline of the box,
                ie. the line that the text rests on, in pt -
                applies only to inline boxes
marginTop
marginRight
marginBottom
marginLeft =    the used values for margins
floatPosition = "TOP" | "BOTTOM"
children =      array of child boxes
parent =        parent box
element =       DOM element for box (may be null)
pseudo =        pseudo-element name or null
text =          string
src =           URL string for images
style =         CSS style object for box

The x, y, w, h and baseline measures, defining respectively the x- and y-coordinates and the width and height of the box, use the same coordinate system as the PDF, i.e. the box tracking units are measured in points (pt) and the origin is the lower left corner of the page.

The box with the value BODY represents the page area returned by PDF.pages (and thus is not necessarily equivalent with the body element); the content of the page-margin boxes is not included in the tree (see Page regions for the definition of page area and page-margin boxes).

The properties of a box can be queried with the BoxInfo() method.

The marginTop, marginRight, marginBottom and marginLeft properties return the used values for margins. This can be useful in cases of elements that are being floated to the top or to the bottom of a column, to determine whether the alternative margin will be applied (see Margins of Page and Column Floats).

When elements are snapped to the nearest column or page end (see Page and Column Floats), the floatPosition property tells us whether the element snapped to the top, or to the bottom - please note that it needs to be checked not on the element itself, but on the anonymous (non-element) parent box that gets created to contain all the floats at the top or bottom of a page or column (in just the same fashion as the footnotes area contains all the footnotes).

See also our nifty script to return the position and dimension of the margin box, the border box, the padding box and the content box of an element.

Two further sample applications of the box tracking API can be seen in the Changebars example, and in Detecting Overflow.

Unsupported DOM Methods

The following DOM methods are not supported in Prince:

    document.write
    window.setInterval
← Generated ContentGraphics →
  • JavaScript in Printed Media
  • JavaScript in Prince
    • Logging
    • Console Access
    • Event Handling
    • The Prince Object
    • The PDF Object
    • The Box Tracking API
    • Unsupported DOM Methods
About us | Privacy Policy | Contact
Copyright © 2023 YesLogic Pty. Ltd.