PageSourceSearch

https://www.princexml.com/doc/assets/js/94db6e40.9a18e6cd.js

js princexml.com collected 2026-09-24 08:41:06 UTC 30,892 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkdocusaurus_v_3=self.webpackChunkdocusaurus_v_3||[]).push([["7326"],{6500(e,n,t){t.r(n),t.d(n,{metadata:()=>i,default:()=>h,frontMatter:()=>s,contentTitle:()=>c,toc:()=>d,assets:()=>a});var i=JSON.parse('{"id":"javascript","title":"Scripting","description":"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.","source":"@site/docs/javascript.md","sourceDirName":".","slug":"/javascript","permalink":"/doc/javascript","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"title":"Scripting"},"sidebar":"docs","previous":{"title":"Generated Content","permalink":"/doc/gen-content"},"next":{"title":"Graphics","permalink":"/doc/graphics"}}'),o=t(4848),r=t(8453);let s={title:"Scripting"},c,a={},d=[{value:"JavaScript in Printed Media",id:"javascript-in-printed-media",level:2},{value:"JavaScript in Prince",id:"javascript-in-prince",level:2},{value:"Logging",id:"logging",level:3},{value:"Console Access",id:"console-access",level:3},{value:"Event Handling",id:"event-handling",level:3},{value:"The Prince Object",id:"the-prince-object",level:3},{value:"Event tracking",id:"event-tracking",level:4},{value:"Script functions",id:"script-functions",level:4},{value:"Box tracking",id:"box-tracking",level:4},{value:"Prince jobs",id:"prince-jobs",level:4},{value:"Failure status",id:"failure-status",level:4},{value:"Document Statistics",id:"document-statistics",level:4},{value:"Multi-Pass formatting",id:"multi-pass-formatting",level:4},{value:"The PDF Object",id:"the-pdf-object",level:3},{value:"The Box Tracking API",id:"the-box-tracking-api",level:3},{value:"Compatibility",id:"compatibility",level:3},{value:"Unsupported DOM Methods",id:"unsupported-dom-methods",level:3}];function l(e){let n={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsxs)(n.p,{children:["Prince is not running JavaScript by default - it needs to be explicitly enabled. See ",(0,o.jsx)(n.a,{href:"/doc/prince-input#applying-javascript-in-prince",children:"Applying JavaScript in Prince"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"javascript-in-printed-media",children:"JavaScript in Printed Media"}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsxs)(n.p,{children:["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 ",(0,o.jsx)(n.code,{children:"complete"})," event handler (see ",(0,o.jsx)(n.a,{href:"/doc/javascript#event-handling",children:"Event Handling"}),") to inspect the layout, without modifying the DOM."]}),"\n",(0,o.jsxs)(n.p,{children:["However, Prince also offers to register the function ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.registerPostLayoutFunc",children:(0,o.jsx)(n.code,{children:"Prince.registerPostLayoutFunc(func)"})}),", which is called after layout finished, similar to the current ",(0,o.jsx)(n.code,{children:"oncomplete"})," event. If this function modifies the DOM, Prince will perform layout again on the updated document."]}),"\n",(0,o.jsxs)(n.p,{children:["See also the chapter on ",(0,o.jsx)(n.a,{href:"#multi-pass-formatting",children:"Multi-Pass formatting"}),"."]}),"\n",(0,o.jsx)(n.admonition,{type:"tip",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/cookbook",children:"Prince Cookbook"})," offers an in-depth chapter on ",(0,o.jsx)(n.a,{href:"/doc/cookbook#the-multi-pass-solution",children:'The "Multi-Pass" Solution'}),"."]})}),"\n",(0,o.jsxs)(n.p,{children:["Please also note that a consequence of the non-interactive nature of printed media is that any interactive events, such as e.g. ",(0,o.jsx)(n.code,{children:"onClick"}),", do not make sense, and will never fire."]}),"\n",(0,o.jsx)(n.h2,{id:"javascript-in-prince",children:"JavaScript in Prince"}),"\n",(0,o.jsxs)(n.p,{children:["Prince supports most of ECMAScript 5th edition (ES5). Strict mode is enabled with ",(0,o.jsx)(n.code,{children:'"use strict"'})," declarations."]}),"\n",(0,o.jsx)(n.p,{children:"ECMAScript 6th edition (ES6) is not fully supported yet, and later editions of ECMAScript are not supported."}),"\n",(0,o.jsxs)(n.p,{children:["Author scripts in the HTML documents are not run by default - JavaScript needs to be explicitly enabled. See ",(0,o.jsx)(n.a,{href:"/doc/prince-input#applying-javascript-in-prince",children:"Applying JavaScript in Prince"})," for details."]}),"\n",(0,o.jsxs)(n.p,{children:["In addition to normal JavaScript run in the document, Prince allows also for ",(0,o.jsx)(n.em,{children:"JavaScript for Acrobat"})," to be passed directly to the PDF, to be executed when the PDF file is o
1pened (by means of the CSS property ",(0,o.jsx)(n.a,{href:"/doc/css-props#prop-prince-pdf-script",children:(0,o.jsx)(n.code,{children:"-prince-pdf-script"})}),"), or triggered by specific events (with the CSS property ",(0,o.jsx)(n.a,{href:"/doc/css-props#prop-prince-pdf-event-scripts",children:(0,o.jsx)(n.code,{children:"-prince-pdf-event-scripts"})}),"). See ",(0,o.jsx)(n.a,{href:"/doc/prince-output#pdf-scripts",children:"PDF Scripts"}),' 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.']}),"\n",(0,o.jsxs)(n.p,{children:["It is also possible to pass JavaScript to Prince for CSS generated content - see ",(0,o.jsx)(n.a,{href:"/doc/gen-content#script-functions",children:"Script Functions"})," for details."]}),"\n",(0,o.jsxs)(n.p,{children:["A full list of all supported JavaScript objects, methods and properties can be found in the References section, in ",(0,o.jsx)(n.a,{href:"/doc/js-support",children:"JavaScript Support"}),". Here we shall just illustrate a few highlights from Prince's JavaScript support."]}),"\n",(0,o.jsx)(n.h3,{id:"logging",children:"Logging"}),"\n",(0,o.jsxs)(n.p,{children:["The Prince log can be accessed from JavaScript via the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Log",children:(0,o.jsx)(n.code,{children:"Log"})})," object (also available as ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.Log",children:(0,o.jsx)(n.code,{children:"Prince.Log"})}),"), which has the following methods:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:'    Log.debug("message")\n    Log.info("message")\n    Log.warning("message")\n    Log.error("message")\n    Log.data("name", "value")\n'})}),"\n",(0,o.jsx)(n.admonition,{type:"note",children:(0,o.jsxs)(n.p,{children:[(0,o.jsx)("code",{children:"Log.debug()"})," is only available when the ",(0,o.jsx)("a",{href:"/doc/command-line#cl-debug",children:(0,o.jsx)("code",{children:"--debug"})})," command-line option has been specified, while ",(0,o.jsx)("code",{children:"Log.info()"})," is only available when the ",(0,o.jsx)("a",{href:"/doc/command-line#cl-verbose",children:(0,o.jsx)("code",{children:"--verbose"})})," command-line option has been specified."]})}),"\n",(0,o.jsx)(n.h3,{id:"console-access",children:"Console Access"}),"\n",(0,o.jsxs)(n.p,{children:["When running Prince from the command-line, the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.console",children:(0,o.jsx)(n.code,{children:"console"})})," object can be used to write messages directly to the terminal:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:'    console.log("Hello, world!")\n'})}),"\n",(0,o.jsx)(n.admonition,{type:"note",children:(0,o.jsx)(n.p,{children:"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."})}),"\n",(0,o.jsx)(n.h3,{id:"event-handling",children:"Event Handling"}),"\n",(0,o.jsxs)(n.p,{children:["When the document has been fully parsed and is ready for processing, Prince will fire the ",(0,o.jsx)(n.code,{children:"DOMContentLoaded"})," and ",(0,o.jsx)(n.code,{children:"load"})," events on the ",(0,o.jsx)(n.code,{children:"window"})," object."]}),"\n",(0,o.jsxs)(n.p,{children:["These load events can be captured by setting the ",(0,o.jsx)(n.code,{children:"onload"})," attribute on the ",(0,o.jsx)(n.code,{children:"body"})," element in HTML documents, or by setting the ",(0,o.jsx)(n.code,{children:"window.onload"})," property or calling ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.addEventListener",children:(0,o.jsx)(n.code,{children:"window.addEventListener"})}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["When document conversion has finished, Prince will fire the ",(0,o.jsx)(n.code,{children:"complete"})," event on the ",(0,o.jsx)(n.code,{children:"Prince"})," object. This event can be captured by calling ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.addEventListener",children:(0,o.jsx)(n.code,{children:"Prince.addEventListener"})}),", or by setting the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.oncomplete",children:(0,o.jsx)(n.code,{children:"Prince.oncomplete"})})," property, and is useful for logging document statistics."]}),"\n",(0,o.jsxs)(n.p,{children:["When the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Document.prototype.readyState",children:(0,o.jsx)(n.code,{children:"readyState"})})," attribute of a document changes, the ",(0,o.jsx)(n.code,{children:"readystatechange"})," event is fired."]}),"\n",(0,o.jsxs)(n.p,{children:["Prince also offers the possibility to register the function ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.registerPostLayoutFunc",children:(0,o.jsx)(n.code,{children:"Prince.registerPostLayoutFunc(func)"})})," after layout has finished for possibly triggering a new layout - see ",(0,o.jsx)(n.a,{href:"#multi-pass-formatting",children:"Multi-Pass formatting"})," for more details."]}),"\n",(0,o.jsx)(n.admonition,{type:"note",children:(0,o.jsxs)(n.p,{children:["When multiple documents are processed into one PDF, the ",(0,o.jsx)("code",{children:"complete"})," event will only fire once, on the ",(0,o.jsx)("em",{children:"first"})," document."]})}),"\n",(0,o.jsxs)(n.p,{children:["User interface events such as ",(0,o.jsx)(n.code,{children:"onclick"})," are not supported by Prince."]}),"\n",(0,o.jsx)(n.h3,{id:"the-prince-object",children:"The Prince Object"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince",children:(0,o.jsx)(n.code,{children:"Prince"})})," object can be used to control various scripting aspects in Prince."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:"    Prince.addEventListener(type, ...callback, optional extra options)\n    Prince.oncomplete\n    Prince.addScriptFunc(name, func)\n    Prince.trackBoxes = (boolean)\n    Prince.convertToFile(JSON, OutputFileName, ...optional extra job resources)\n    Prince.convertToBuffer(JSON, ...optional extra job resources)\n    Prince.failStatus\n    Prince.pageCount\n    Prince.registerPostLayoutFunc(func)\n"})}),"\n",(0,o.jsx)(n.h4,{id:"event-tracking",children:"Event tracking"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.addEventListener",children:(0,o.jsx)(n.code,{children:"Prince.addEventListener"})})," method or the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.oncomplete",children:(0,o.jsx)(n.code,{children:"Prince.oncomplete"})})," property can be called to listen to the ",(0,o.jsx)(n.code,{children:"complete"}
1)," 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."]}),"\n",(0,o.jsx)(n.h4,{id:"script-functions",children:"Script functions"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.addScriptFunc",children:(0,o.jsx)(n.code,{children:"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 ",(0,o.jsx)(n.a,{href:"/doc/gen-content#script-functions",children:"Script Functions"})," for an example."]}),"\n",(0,o.jsx)(n.h4,{id:"box-tracking",children:"Box tracking"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.trackBoxes",children:(0,o.jsx)(n.code,{children:"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 ",(0,o.jsx)(n.code,{children:"complete"})," event. See ",(0,o.jsx)(n.a,{href:"/doc/javascript#the-box-tracking-api",children:"The Box Tracking API"}),"."]}),"\n",(0,o.jsx)(n.h4,{id:"prince-jobs",children:"Prince jobs"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.convertToFile",children:(0,o.jsx)(n.code,{children:"Prince.convertToFile"})})," and ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.convertToBuffer",children:(0,o.jsx)(n.code,{children:"Prince.convertToBuffer"})})," methods allow you to start new Prince jobs:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:"    convertToFile(JSON, OutputFileName, ...optional extra job resources)\n"})}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"returns bool indicating success;"}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:"    convertToBuffer(JSON, ...optional extra job resources)\n"})}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"returns ArrayBuffer if successful, null if not;"}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["whereby ",(0,o.jsx)(n.code,{children:"JSON"}
1)," is a job description as specified in the ",(0,o.jsx)(n.a,{href:"/doc/server-integration#job-description-json",children:"Job description JSON"}),", while the optional extra job resource arguments are ArrayBuffers or strings that can be referenced from the JSON using the ",(0,o.jsx)(n.code,{children:"job-resource:"})," URLs. See ",(0,o.jsx)(n.a,{href:"/doc/server-integration#prince-control-protocol",children:"Prince Control Protocol"}),"."]}),"\n",(0,o.jsx)(n.admonition,{type:"note",children:(0,o.jsxs)(n.p,{children:["The Prince jobs methods are only accessible in ",(0,o.jsx)("a",{href:"/doc/command-line/#cl-shell",children:"Prince shell mode"}),"."]})}),"\n",(0,o.jsx)(n.h4,{id:"failure-status",children:"Failure status"}),"\n",(0,o.jsxs)(n.p,{children:["The property ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.failStatus",children:(0,o.jsx)(n.code,{children:"Prince.failStatus"})})," is a boolean which can be set to trigger an explicit failure status through JavaScript, based on custom criteria. See also ",(0,o.jsx)(n.a,{href:"/doc/server-integration#fail-safe-options",children:"Fail-Safe Options"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["It can be set to true by a script that runs after layout in the ",(0,o.jsx)(n.code,{children:"oncomplete"})," handler (see ",(0,o.jsx)(n.a,{href:"/doc/javascript#event-handling",children:"Event Handling"}),") and checks for complex conditions, like overlapping content (see ",(0,o.jsx)(n.a,{href:"/doc/javascript#the-box-tracking-api",children:"The Box Tracking API"})," and the ",(0,o.jsx)(n.a,{href:"https://www.princexml.com/forum/topic/3603/detecting-overflow",children:"Detecting Overflow"})," sample) or some other user-defined issue that you want to trigger the fail-safe."]}),"\n",(0,o.jsxs)(n.p,{children:["For example, perhaps there should be only one page: you check the page count (see ",(0,o.jsx)(n.a,{href:"/doc/javascript#document-statistics",children:"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."]}),"\n",(0,o.jsx)(n.h4,{id:"document-statistics",children:"Document Statistics"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.pageCount",children:(0,o.jsx)(n.code,{children:"Prince.pageCount"})})," property can be accessed after document conversion has finished, then logged as data for the calling process to access:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:'    function logPageCount()\n    {\n        Log.data("total-page-count", Prince.pageCount);\n    }\n\n    Prince.addEventListener("complete", logPageCount, false);\n'})}),"\n",(0,o.jsx)(n.h4,{id:"multi-pass-formatting",children:"Multi-Pass formatting"}),"\n",(0,o.jsxs)(n.p,{children:["Prince also offers the possibility to register the function ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.registerPostLayoutFunc",children:(0,o.jsx)(n.code,{children:"Prince.registerPostLayoutFunc(func)"})}),", which is called after layout finished, similar to the current ",(0,o.jsx)(n.code,{children:"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."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",metastring:'title="JavaScript"',children:"    Prince.registerPostLayoutFunc(function() {\n        var str = '@prince-color Color1 { alternate-color: device-cmyk(1 0 0 0) }';\n        var add = document.getElementById('add');\n        add.appendChild(document.createTextNode(str));\n    });\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-markup",metastring:'title="HTML"',children:"    <style id='add'></style>\n    <p style='color: prince-color(Color1)'>This was black, becomes cyan</p>\n"})}),"\n",(0,o.jsxs)(n.p,{children:["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 y
1ou can set a limit by using the ",(0,o.jsx)(n.a,{href:"/doc/command-line#cl-max-passes",children:(0,o.jsx)(n.code,{children:"--max-passes=N"})})," command-line option."]}),"\n",(0,o.jsx)(n.admonition,{type:"tip",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/cookbook",children:"Prince Cookbook"})," offers an in-depth chapter on ",(0,o.jsx)(n.a,{href:"/doc/cookbook#the-multi-pass-solution",children:'The "Multi-Pass" Solution'}),"."]})}),"\n",(0,o.jsx)(n.h3,{id:"the-pdf-object",children:"The PDF Object"}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsxs)(n.a,{href:"/doc/js-support#window.PDF",children:[(0,o.jsx)(n.code,{children:"PDF"})," object"]})," can be used to specify PDF properties and settings, including attaching extra files to the generated PDF, similar to the ",(0,o.jsx)(n.a,{href:"/doc/command-line#cl-attach",children:(0,o.jsx)(n.code,{children:"--attach"})})," command-line argument:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:'    PDF.attachFile(url, description?)\n\n    PDF.attachFile("data.xls", "Latest sales figures.");\n'})}),"\n",(0,o.jsx)(n.p,{children:"Other PDF properties, which are set by assignment, include:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:'    PDF.embedFonts = (boolean)\n    PDF.subsetFonts = (boolean)\n    PDF.artificialFonts = (boolean)\n\n    PDF.compress = (boolean)\n\n    PDF.encrypt = (boolean)\n    PDF.userPassword, PDF.ownerPassword = (string, can be null)\n    PDF.allowPrint, PDF.allowModify, PDF.allowCopy, PDF.allowAnnotate = (boolean)\n    PDF.keyBits = "40" | "128"\n\n    PDF.script = (string, can be null)\n    PDF.openAction = (eg. "print")\n    PDF.pageLayout = "single-page" | "one-column" | "two-column[-left/right]"\n    PDF.pageMode = "auto" | "show-bookmarks" | "fullscreen" | "show-attachments"\n    PDF.printScaling = "auto" | "none"\n    PDF.duplex = "auto" | "simplex" | "duplex-flip-short-edge" | "duplex-flip-long-edge"\n\n    PDF.profile = (string, can be null)\n    PDF.outputIntent = (URL string, can be null)\n\n    PDF.objectStreams = (boolean)\n\n    PDF.xmp = (URL string)\n    PDF.xmpMetadata = (boolean)\n\n    PDF.title\n    PDF.subject\n    PDF.author\n    PDF.keywords\n    PDF.creator\n\n    PDF.lang\n'})}),"\n",(0,o.jsxs)(n.p,{children:["There is one more PDF object not mentioned so far: the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.PDF.pages",children:(0,o.jsx)(n.code,{children:"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 ",(0,o.jsx)(n.em,{children:"after"})," the ",(0,o.jsx)(n.code,{children:"complete"})," event (see ",(0,o.jsx)(n.a,{href:"/doc/javascript#event-handling",children:"Event Handling"}),") and returns a list of ",(0,o.jsx)(n.em,{children:"boxes"})," - see ",(0,o.jsx)(n.a,{href:"/doc/javascript#the-box-tracking-api",children:"The Box Tracking API"}),"."]}),"\n",(0,o.jsx)(n.h3,{id:"the-box-tracking-api",children:"The Box Tracking API"}),"\n",(0,o.jsxs)(n.p,{children:["The box tracking API must be enabled with ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Prince.trackBoxes",children:(0,o.jsx)(n.code,{children:"Prince.trackBoxes"})})," before formatting starts."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:"    Prince.trackBoxes = true;\n"})}),"\n",(0,o.jsxs)(n.p,{children:["It then becomes available in the ",(0,o.jsx)(n.code,{children:"complete"})," event (see ",(0,o.jsx)(n.a,{href:"/doc/javascript#event-handling",children:"Event Handling"}),"), when you can call the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.Element.prototype.getPrinceBoxes",children:(0,o.jsx)(n.code,{children:"getPrinceBoxes()"})})," method while iterating through the required DOM elements, to return a list of ",(0,o.jsx)(n.em,{children:"boxes"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:'    Prince.addEventListener("complete", function() {\
1n      var xs = document.getElementsByTagName("ins");\n      for (var i = 0; i < xs.length; ++i)\n        {\n          var ins = xs[i];\n          var boxes = ins.getPrinceBoxes();\n        }\n    }, false);\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.PDF.pages",children:(0,o.jsx)(n.code,{children:"PDF.pages"})})," array mentioned earlier (see ",(0,o.jsx)(n.a,{href:"/doc/javascript#the-pdf-object",children:"The PDF Object"}),") also is available only after the ",(0,o.jsx)(n.code,{children:"complete"})," event and also returns a list of ",(0,o.jsx)(n.em,{children:"boxes"})," (see ",(0,o.jsx)(n.a,{href:"/doc/paged#page-regions",children:"Page regions"}),")."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:'    function printbox(str,box) {\n      console.log("");\n      for (var i in box) {\n        console.log(str+i+": "+box[i]);\n      }\n      for (var i=0; i<box.children.length; i++) {\n        printbox(str+"  ",box.children[i]);\n      }\n    }\n\n    Prince.addEventListener("complete", function() {\n      var pages = PDF.pages;\n      for (var i = 0; i<pages.length; ++i)\n        {\n          console.log("PAGE "+(i+1)+" HAS THESE BOXES");\n          printbox("  ",pages[i]);\n        }\n    }, false);\n'})}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.em,{children:"Boxes"})," are JavaScript objects with some or all of the following properties:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:'    type =          "BODY" |\n                    "COLUMN" |\n                    "FLEXLINE" |\n                    "FOOTNOTES" |\n                    "FLOATS" |\n                    "BOX" |\n                    "LINE" |\n                    "SPAN" |\n                    "TEXT" |\n                    "SVG" |\n                    "IMAGE"\n    pageNum =       the page of the current box\n    x =             x-coordinate, in pt\n    y =             y-coordinate, in pt (set to zero on some boxes)\n    w =             width, in pt\n    h =             height, in pt (set to zero on some boxes)\n    baseline =      the y-coordinate of the baseline of the box,\n                    ie. the line that the text rests on, in pt -\n                    applies only to inline boxes\n\n    marginTop\n    marginRight\n    marginBottom\n    marginLeft =    the used values for margins\n    paddingTop\n    paddingRight\n    paddingBottom\n    paddingLeft =   the used values for paddings\n    borderTop\n    borderRight\n    borderBottom\n    borderLeft =    the used values for borders\n\n    floatPosition = "TOP" | "BOTTOM"\n    children =      array of child boxes\n    parent =        parent box\n    element =       DOM element for box (may be null)\n    pseudo =        pseudo-element name or null\n    text =          string\n    src =           URL string for images\n    style =         CSS style object for box\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"x"}),", ",(0,o.jsx)(n.code,{children:"y"}),", ",(0,o.jsx)(n.code,{children:"w"}),", ",(0,o.jsx)(n.code,{children:"h"})," and ",(0,o.jsx)(n.code,{children:"baseline"})," measures, defining respectively the x- and y-coordinates and the width and height of the ",(0,o.jsx)(n.em,{children:"box"}),", use the same coordinate system as the PDF, i.e. the box tracking units are measured in points (",(0,o.jsx)(n.code,{children:"pt"}),") and the origin is the lower left corner of the page."]}),"\n",(0,o.jsxs)(n.p,{children:["The box with the value ",(0,o.jsx)(n.code,{children:"BODY"})," represents the ",(0,o.jsx)(n.em,{children:"page area"})," returned by ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.PDF.pages",children:(0,o.jsx)(n.code,{children:"PDF.pages"})})," (and thus is not necessarily equivalent with the ",(0,o.jsx)(n.code,{children:"body"})," element); the content of the ",(0,o.jsx)(n.em,{children:"page-margin boxes"})," is not included in the tree (see ",(0,o.jsx)(n.a,{href:"/doc/paged#page-regions",children:"Page regions"})," for the definition of ",(0,o.jsx)(n.em,{children:"page area"})," and ",(0,o.jsx)(n.em,{children:"page-margin boxes"}),")."]}),"\n",(0,o.jsxs)(n.p,{children:["The properties of a ",(0,o.jsx)(n.em,{children:"box"})," can be queried with the ",(0,o.jsx)(n.a,{href:"/doc/js-support#window.BoxInfo",children:(0,o.jsx)(n.code,{children:"BoxInfo()"})})," method."]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"marginTop"}),", ",(0,o.jsx)(n.code,{children:"marginRight"}),", ",(0,o.jsx)(n.code,{children:"marginBottom"})," and ",(0,o.jsx)(n.code,{children:"marginLeft"})," properties return the ",(0,o.jsx)(n.em,{children:"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 ",(0,o.jsx)(n.a,{href:"/doc/styling#margins-of-page-and-column-floats",children:"Margins of Page and Column Floats"}),")."]}),"\n",(0,o.jsxs)(n.p,{children:["When elements are snapped to the nearest column or page end (see ",(0,o.jsx)(n.a,{href:"/doc/styling#page-and-column-floats",children:"Page and Column Floats"}),"), the ",(0,o.jsx)(n.code,{children:"floatPosition"})," property tells us whether the element snapped to the top, or to the bottom - please note that it needs to be checked 
1not on the element itself, but on the anonymous (non-element) ",(0,o.jsx)(n.em,{children:"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)."]}),"\n",(0,o.jsx)(n.admonition,{type:"tip",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"/doc/cookbook",children:"Prince Cookbook"})," offers ",(0,o.jsx)(n.a,{href:"/doc/cookbook#how-and-where-is-my-box",children:"a 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."]})}),"\n",(0,o.jsxs)(n.p,{children:["Two further sample applications of the box tracking API can be seen in the ",(0,o.jsx)(n.a,{href:"//www.princexml.com/forum/topic/3516/changebars",children:"Changebars"})," example, and in ",(0,o.jsx)(n.a,{href:"//www.princexml.com/forum/topic/3603/detecting-overflow",children:"Detecting Overflow"}),"."]}),"\n",(0,o.jsx)(n.h3,{id:"compatibility",children:"Compatibility"}),"\n",(0,o.jsx)(n.p,{children:"Unfortunately many JavaScript libraries are not developed with printed media in mind, and occasionally little adjustments need to be done to have them smoothly run in Prince."}),"\n",(0,o.jsxs)(n.p,{children:["Prince maintains a useful library of ",(0,o.jsx)(n.a,{href:"https://github.com/yeslogic/prince-scripts",children:"JavaScript helper scripts"})," to ease the task of running libraries such as ABCjs, Highcharts, or MathJax."]}),"\n",(0,o.jsx)(n.h3,{id:"unsupported-dom-methods",children:"Unsupported DOM Methods"}),"\n",(0,o.jsx)(n.p,{children:"The following DOM methods are not supported in Prince:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-javascript",children:"    document.write\n    window.setInterval\n"})})]})}function h(e={}){let{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453(e,n,t){t.d(n,{R:()=>s,x:()=>c});var i=t(6540);let o={},r=i.createContext(o);function s(e){let n=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.