Source

meadco-scriptxfactory.js

  1. /**
  2. * MeadCo ScriptX 'window.factory' shim (support for modern browsers) JS client library.<br/>
  3. *
  4. * The ScriptX Add-on for Internet Explorer is included on a html document with an &lt;object /&gt; element with a de-facto standard id of 'factory': &lt;object id='factory' /&gt;.
  5. *
  6. * The object is referenced with the property window.factory which exposes properties and methods to define print setting and perform operations such as printing a document or frame.
  7. *
  8. * The object has three further properties:
  9. * - object
  10. * - js
  11. * - rawPrinting
  12. * - printing
  13. * - printerControl
  14. * - enhancedFormatting
  15. *
  16. * This javascript 'module' provides partial emulation of window.factory, window.factory.object and window.factory.object.js
  17. *
  18. * Full emulation (and almost complete implementation) is provided for window.factory.printing, window.factory.printing.printerControl, window.factory.printing.enhancedFormatting. The most notable absent implementation is an implementation of print preview.
  19. *
  20. * Full emulation is provided for window.factory.rawPrinting. Please note that the implementation is synchronous and browsers will issue a warning to the console.
  21. *
  22. * ScriptX Add-on for Internet Explorer intercepts the browser UI for printing. For obvious reasons this is not possible with javascript, however ::
  23. *
  24. * <strong>PLEASE NOTE:</strong> This library replaces window.print().
  25. *
  26. * Full documentation on the properties/methods is provided by the {@link https://www.meadroid.com/Developers/KnowledgeBank/TechnicalReference/ScriptXAddOn|technical reference documentation} for the ScriptX Add-on for Internet Explorer. That documentation is not reproduced here.
  27. *
  28. * If the startup script determines that the ScriptX Add.on for IE is already active then it will quietly give priority to the object. In other words, the Add-on has precedence on Internet Explorer.
  29. *
  30. * This enables the same experience (almost) to be delivered to any browser on any device with the same html/javascript code.
  31. *
  32. * It is strongly recommended that the [MeadCoScriptJS library]{@link https://github.com/MeadCo/MeadCoScriptXJS} is used in conjunction with this library as it provides code (Promises) to assist
  33. * with working with the significant difference between the synchronous nature of the functions of ScriptX.Add-on (which hide the underlying asynchrony) and the asynchronous nature of javascript AJAX processing.
  34. *
  35. * Requires:
  36. * - MeadCo.Core
  37. * - MeadCo.ScriptX.Print
  38. * - MeadCo.ScriptX.Print.HTML
  39. *
  40. * - MeadCo.ScriptX.Print.Licensing when using ScritpX.Services for Windows PC
  41. *
  42. * MeadCo.ScriptX.Print.HTML.connect[Async]() or MeadCo.ScriptX.Print.connect[Async]() *MUST* be called before using the apis in this library.
  43. *
  44. * See [ScriptX Samples]{@link https://scriptxprintsamples.meadroid.com} for a lot of samples on using this code.
  45. *
  46. * Some Add-on APIs lead to system provided dialogs (e.g. printer and paper setup) - support for implementing the dialogs in javascript as simple plug-ins is provided, along with an example implementation using bootstrap/jQuery (see jQuery-MeadCo.ScriptX.Print.UI.js)
  47. *
  48. * @example
  49. * MeadCo.ScriptX.Print.UI = {
  50. * PageSetup: function(fnDialgCompleteCallBack) { ... dialog code ...},
  51. * PrinterSettings: function(fnDialgCompleteCallBack) { ... dialog code ...}
  52. * }
  53. *
  54. * @namespace factory
  55. */
  56. // we anti-polyfill &lt;object id="factory" /&gt;
  57. // enabling old code to run in modern browsers
  58. //
  59. // static singleton instances.
  60. //
  61. ; (function (name, definition, undefined) {
  62. if (this[name] !== undefined || document.getElementById(name) !== null) {
  63. MeadCo.log("ScriptX.Services ScriptX.factory emulation believes it may not be requred.");
  64. if (this[name] !== undefined) {
  65. MeadCo.log("this[" + name + "] is defined");
  66. }
  67. if (document.getElementById(name) !== null) {
  68. MeadCo.log("document.getElementById(" + name + ") is defined");
  69. }
  70. if (this[name].object !== undefined) {
  71. MeadCo.log("this[" + name + "].object is defined -- not required!!!");
  72. return;
  73. } else {
  74. MeadCo.log("this[" + name + "].object is *not* defined");
  75. }
  76. }
  77. MeadCo.log("ScriptX.Services ScriptX.factory emulation believes it is requred.");
  78. var theModule = definition();
  79. // Assign to the global object (window)
  80. (this)[name] = theModule;
  81. })('factory', function () {
  82. // If this is executing, we believe we are needed.
  83. // protected API
  84. const moduleversion = "1.16.0.0";
  85. const emulatedVersion = "8.3.0.0";
  86. let servicesVersion = "";
  87. const printApi = MeadCo.ScriptX.Print;
  88. const logApi = MeadCo; // could be console
  89. let outerScope = this;
  90. function log(str) {
  91. logApi.log("factory emulation :: " + str);
  92. }
  93. log("'factory' loaded " + moduleversion);
  94. // public API.
  95. return {
  96. log: log,
  97. // 'factory' functions
  98. /* GetComponentVersion is no longer documented . It is implemented as MeadCoScriptJS relies on it.
  99. *
  100. * We support ScriptX ProgIds and progid style names for scriptx services.
  101. */
  102. GetComponentVersion: function (sComponent, a, b, c, d) {
  103. log("factory.object.getcomponentversion: " + sComponent);
  104. var v = moduleversion;
  105. switch (sComponent.toLowerCase()) {
  106. case "scriptx.factory":
  107. v = emulatedVersion;
  108. break;
  109. case "scriptx.factory.services":
  110. v = moduleversion;
  111. break;
  112. case "scriptx.services":
  113. if (servicesVersion === "") {
  114. if (typeof printApi !== "undefined") {
  115. var ea = printApi.onErrorAction;
  116. printApi.onErrorAction = printApi.ErrorAction.THROW;
  117. try {
  118. var sd = printApi.serviceDescription();
  119. if (sd !== null) {
  120. if (typeof sd.serviceVersion === "string") {
  121. servicesVersion = sd.serviceVersion;
  122. }
  123. else {
  124. var sv = sd.serviceVersion;
  125. servicesVersion = sv.major + "." + sv.minor + "." + sv.build + "." + sv.revision;
  126. }
  127. }
  128. } catch (e) { servicesVersion = moduleversion; }
  129. printApi.onErrorAction = ea;
  130. }
  131. }
  132. v = servicesVersion;
  133. break;
  134. case "meadco.secmgr":
  135. try {
  136. v = outerScope.secmgr.version;
  137. } catch (e) { v = "0.0.0.0"; }
  138. break;
  139. case "meadco.triprint":
  140. try {
  141. v = MeadCo.ScriptX.Print.HTML.version;
  142. } catch (e) { v = "0.0.0.0"; }
  143. break;
  144. }
  145. v = v.split(".");
  146. a[0] = v[0];
  147. b[0] = v[1];
  148. c[0] = v[2];
  149. d[0] = v[3];
  150. },
  151. /*
  152. * Only ScriptX related ProgIds are supported.
  153. *
  154. */
  155. ComponentVersionString: function (sProgId) {
  156. var a = new Object();
  157. var b = new Object();
  158. var c = new Object();
  159. var d = new Object();
  160. outerScope.factory.GetComponentVersion(sProgId, a, b, c, d);
  161. return a[0] + "." + b[0] + "." + c[0] + "." + d[0];
  162. },
  163. get ScriptXVersion() { return emulatedVersion; },
  164. get SecurityManagerVersion() { return emulatedVersion; },
  165. /*
  166. * Unique IDs are not suported in services
  167. */
  168. IsUniqueIDAvailable: function (bForMachine) { return false; },
  169. UniqueID: function (bForMachine) { return 0; },
  170. ResetUniqueID: function (bForMachine) { return 0; },
  171. baseURL: function (sUrl) {
  172. var link = document.createElement("a");
  173. link.href = sUrl;
  174. return link.href;
  175. },
  176. relativeURL: function (sUrl) {
  177. throw "MeadCo.ScriptX.Print :: relativeUrl is not implemented.\n\nPlease see https://github.com/medialize/URI.js for an alternative.";
  178. },
  179. OnDocumentComplete: function (frameOrWindow, callback) {
  180. // other windows is an anachronism we dont support, this window is, by
  181. // definition, complete
  182. if (typeof frameOrWindow.contentWindow === "undefined") {
  183. callback();
  184. }
  185. else {
  186. // a frame .. listen for load
  187. frameOrWindow.addEventListener("load", function (e) {
  188. callback();
  189. }, { once: true });
  190. }
  191. },
  192. get rawPrinting() {
  193. var sPrinterName = "";
  194. var printApi = MeadCo.ScriptX.Print;
  195. function printDirect(eContentType, sContent) {
  196. var bPrinted = false;
  197. if (typeof printApi !== "undefined") {
  198. var p = factory.printing.printer;
  199. factory.printing.printer = sPrinterName;
  200. if (eContentType === printApi.ContentType.URL) {
  201. sContent = outerScope.factory.baseURL(sContent);
  202. }
  203. bPrinted = printApi.printDirect(eContentType, sContent);
  204. factory.printing.printer = p;
  205. }
  206. return bPrinted;
  207. }
  208. return {
  209. get printer() { return sPrinterName; },
  210. set printer(printerName) {
  211. var p = factory.printing.printer;
  212. factory.printing.printer = printerName;
  213. if (factory.printing.printer !== printerName) {
  214. throw "Unknown printer";
  215. }
  216. factory.printing.printer = p;
  217. sPrinterName = printerName;
  218. },
  219. printString: function (s) {
  220. return typeof printApi !== "undefined" ? printDirect(printApi.ContentType.STRING, s) : false;
  221. },
  222. printDocument: function (sUrl) {
  223. return typeof printApi !== "undefined" ? printDirect(printApi.ContentType.URL, sUrl) : false;
  224. }
  225. };
  226. },
  227. /*
  228. * A no op for services
  229. */
  230. Shutdown: function () {
  231. return null;
  232. },
  233. // extend the namespace
  234. extendFactoryNamespace: function (name, definition) {
  235. var theModule = definition();
  236. log("MeadCo factory extending namespace: " + name);
  237. // walk/build the namespace part by part and assign the module to the leaf
  238. var namespaces = name.split(".");
  239. var scope = outerScope;
  240. for (var i = 0; i < namespaces.length; i++) {
  241. var packageName = namespaces[i];
  242. if (i === namespaces.length - 1) {
  243. if (typeof scope[packageName] === "undefined") {
  244. log("installing implementation at: " + packageName);
  245. scope[packageName] = theModule;
  246. } else {
  247. log("Warning - not overwriting package: " + packageName);
  248. }
  249. } else if (typeof scope[packageName] === "undefined") {
  250. log("initialising new: " + packageName);
  251. scope[packageName] = {};
  252. } else {
  253. log("using existing package: " + packageName);
  254. }
  255. scope = scope[packageName];
  256. }
  257. },
  258. // a Ctrl-P handler function
  259. keyPressCtrlP: function (e) {
  260. if (e.ctrlKey && e.keyCode == 80 && !e.shiftKey) {
  261. e.preventDefault();
  262. log("ctrl-p being handled.");
  263. outerScope.print();
  264. }
  265. },
  266. };
  267. });
  268. ; (function (name, definition) {
  269. if (typeof factory.extendFactoryNamespace === "function") {
  270. factory.extendFactoryNamespace(name, definition);
  271. }
  272. })('factory.printing', function () {
  273. // protected API
  274. const printHtml = MeadCo.ScriptX.Print.HTML;
  275. const printPdf = MeadCo.ScriptX.Print.PDF;
  276. const settings = printHtml.settings;
  277. const printApi = MeadCo.ScriptX.Print;
  278. const htmlPrefixes = ["html://", "html4://", "html5://"];
  279. let outerScope = this;
  280. let unloadMsg = "";
  281. outerScope.factory.log("factory.Printing loaded.");
  282. function promptAndPrint(bPrompt, fnPrint, fnNotifyStarted) {
  283. if (typeof (bPrompt) === 'undefined') bPrompt = true;
  284. const lock = printApi.ensureSpoolingStatus();
  285. let bStarted = false;
  286. let err = null;
  287. if (bPrompt) {
  288. if (MeadCo.ScriptX.Print.UI) {
  289. MeadCo.ScriptX.Print.UI.PrinterSettings(function (dlgAccepted) {
  290. if (dlgAccepted) {
  291. MeadCo.log("promptAndPrint requesting print ...");
  292. try {
  293. bStarted = fnPrint();
  294. fnNotifyStarted(bStarted);
  295. }
  296. catch (e) {
  297. err = e;
  298. MeadCo.error(e.message)
  299. fnNotifyStarted(false);
  300. }
  301. }
  302. else
  303. fnNotifyStarted(false);
  304. printApi.freeSpoolStatus(lock);
  305. });
  306. MeadCo.log("promptAndPrint exits ...");
  307. if (err != null) { // not great but a breaking change to remove this behaviour
  308. throw err;
  309. }
  310. return bStarted;
  311. }
  312. MeadCo.warn("prompted print requested but no UI library loaded. See: https://www.meadroid.com/Developers/KnowledgeBank/Articles/Dialogs");
  313. }
  314. try {
  315. bStarted = fnPrint();
  316. fnNotifyStarted(bStarted);
  317. }
  318. catch (e) {
  319. err = e;
  320. MeadCo.error(e.message)
  321. fnNotifyStarted(false);
  322. }
  323. finally {
  324. printApi.freeSpoolStatus(lock);
  325. }
  326. if (err !== null)
  327. throw err;
  328. return bStarted;
  329. }
  330. function isSnippet(sContent) {
  331. var foundPrefix = htmlPrefixes.find(function (sPrefix) {
  332. return sContent.indexOf(sPrefix) === 0;
  333. });
  334. if (typeof foundPrefix === "string") {
  335. return sContent.substring(foundPrefix.length);
  336. }
  337. return "";
  338. }
  339. function printHtmlContent(sUrl, bPrompt, fnNotifyStarted, fnCallback, data) {
  340. var sHtml = isSnippet(sUrl);
  341. // if requesting snippet then trim to just the html
  342. if (sHtml.length > 0) {
  343. var docType = "<!doctype";
  344. // add-on scripters might also add doctype but the server handles this
  345. if (sHtml.substr(0, docType.length).toLowerCase() === docType) {
  346. sHtml = sHtml.substring(sHtml.indexOf(">") + 1);
  347. }
  348. } else {
  349. // if a relative URL supplied then add the base URL of this website
  350. sUrl = outerScope.factory.baseURL(sUrl);
  351. }
  352. return promptAndPrint(bPrompt,
  353. function () {
  354. MeadCo.log("printHtmlContent requesting print ...");
  355. return sHtml.length > 0 ? printHtml.printHtml(sHtml, null, fnCallback, data) : printHtml.printFromUrl(sUrl, null, fnCallback, data);
  356. }, fnNotifyStarted);
  357. }
  358. function printPdfContent(sUrl, bPrompt, fnNotifyStarted, fnCallback, data) {
  359. // if a relative URL supplied then add the base URL of this website
  360. if (typeof printPdf !== "undefined") {
  361. sUrl = outerScope.factory.baseURL(sUrl);
  362. return promptAndPrint(bPrompt,
  363. function () {
  364. MeadCo.log("printPdfContent requesting print ...");
  365. return printPdf.print(sUrl, null, fnCallback, data);
  366. },
  367. fnNotifyStarted);
  368. }
  369. MeadCo.error("MeadCo.ScriptX.Print.PDF is not available to ScriptX.Services factory emulation.");
  370. fnNotifyStarted(false);
  371. return false;
  372. }
  373. var iEnhancedFormatting = {
  374. get allPagesHeader() {
  375. return settings.extraHeadersAndFooters.allPagesHeader;
  376. },
  377. set allPagesHeader(v) {
  378. settings.extraHeadersAndFooters.allPagesHeader = v;
  379. },
  380. get allPagesFooter() {
  381. return settings.extraHeadersAndFooters.allPagesFooter;
  382. },
  383. set allPagesFooter(v) {
  384. settings.extraHeadersAndFooters.allPagesFooter = v;
  385. },
  386. get firstPageHeader() {
  387. return settings.extraHeadersAndFooters.firstPageHeader;
  388. },
  389. set firstPageHeader(v) {
  390. settings.extraHeadersAndFooters.firstPageHeader = v;
  391. },
  392. get firstPageFooter() {
  393. return settings.extraHeadersAndFooters.firstPageFooter;
  394. },
  395. set firstPageFooter(v) {
  396. settings.extraHeadersAndFooters.firstPageFooter = v;
  397. },
  398. get extraFirstPageFooter() {
  399. return settings.extraHeadersAndFooters.extraFirstPageFooter;
  400. },
  401. set extraFirstPageFooter(v) {
  402. settings.extraHeadersAndFooters.extraFirstPageFooter = v;
  403. },
  404. get allHeaderHeight() {
  405. return settings.extraHeadersAndFooters.allHeaderHeight;
  406. },
  407. set allHeaderHeight(v) {
  408. if (typeof v !== "number") {
  409. throw "Invalid argument";
  410. }
  411. settings.extraHeadersAndFooters.allHeaderHeight = v;
  412. },
  413. get allFooterHeight() {
  414. return settings.extraHeadersAndFooters.allFooterHeight;
  415. },
  416. set allFooterHeight(v) {
  417. if (typeof v !== "number") {
  418. throw "Invalid argument";
  419. }
  420. settings.extraHeadersAndFooters.allFooterHeight = v;
  421. },
  422. get firstHeaderHeight() {
  423. return settings.extraHeadersAndFooters.firstHeaderHeight;
  424. },
  425. set firstHeaderHeight(v) {
  426. if (typeof v !== "number") {
  427. throw "Invalid argument";
  428. }
  429. settings.extraHeadersAndFooters.firstHeaderHeight = v;
  430. },
  431. get firstFooterHeight() {
  432. return settings.extraHeadersAndFooters.firstFooterHeight;
  433. },
  434. set firstFooterHeight(v) {
  435. if (typeof v !== "number") {
  436. throw "Invalid argument";
  437. }
  438. settings.extraHeadersAndFooters.firstFooterHeight = v;
  439. },
  440. get extraFirstFooterHeight() {
  441. return settings.extraHeadersAndFooters.extraFirstFooterHeight;
  442. },
  443. set extraFirstFooterHeight(v) {
  444. if (typeof v !== "number") {
  445. throw "Invalid argument";
  446. }
  447. settings.extraHeadersAndFooters.extraFirstFooterHeight = v;
  448. },
  449. get pageRange() {
  450. return settings.pageRange;
  451. },
  452. set pageRange(v) {
  453. settings.pageRange = v;
  454. if (typeof printPdf !== "undefined") {
  455. printPdf.settings.pageRange = v;
  456. }
  457. },
  458. get printingPass() {
  459. var v = "";
  460. switch (settings.printingPass) {
  461. case printHtml.PrintingPasses.DEFAULT:
  462. case printHtml.PrintingPasses.ALL:
  463. v = "all";
  464. break;
  465. case printHtml.PrintingPasses.ODD:
  466. v = "odd";
  467. break;
  468. case printHtml.PrintingPasses.EVEN:
  469. v = "even";
  470. break;
  471. }
  472. return v;
  473. },
  474. set printingPass(v) {
  475. var x = printHtml.PrintingPasses.ALL;
  476. if (typeof v === "string") {
  477. switch (v.toLowerCase()) {
  478. case "odd":
  479. x = printHtml.PrintingPasses.ODD;
  480. break;
  481. case "even":
  482. x = printHtml.PrintingPasses.EVEN;
  483. break;
  484. case "odd&even":
  485. case "all":
  486. x = printHtml.PrintingPasses.ALL;
  487. break;
  488. }
  489. }
  490. settings.printingPass = x;
  491. },
  492. get pdfPrintMode() {
  493. return typeof printPdf !== "undefined" ? printPdf.settings.printQuality : 0;
  494. },
  495. set pdfPrintMode(v) {
  496. if (typeof printPdf !== "undefined") {
  497. printPdf.settings.printQuality = v;
  498. }
  499. }
  500. };
  501. if (typeof printApi !== "undefined") {
  502. printApi.useAttributes();
  503. if (typeof outerScope.print === "function") {
  504. outerScope.factory.log("overwriting outerScope.print");
  505. outerScope.print = function () {
  506. outerScope.factory.log("window.print() called and being handled.");
  507. promptAndPrint(
  508. true,
  509. function () {
  510. return printHtml.printDocument();
  511. },
  512. function () { });
  513. };
  514. }
  515. // ScriptX.Addon printing intercepts Ctrl-p ...
  516. // listen for Ctrl-P and override ...
  517. var doNotEnable = document.querySelector("[data-meadco-ctrlp='false']") != null;
  518. if (!doNotEnable) {
  519. outerScope.factory.log("using addEventListener('keydown',factory.keyPressCtrlP) for Ctrl-P");
  520. document.addEventListener("keydown", factory.keyPressCtrlP);
  521. }
  522. }
  523. else {
  524. MeadCo.error("MeadCo.ScriptX.Print is not available to ScriptX.Services factory emulation.");
  525. }
  526. // public API
  527. return {
  528. // basic properties
  529. //
  530. set header(str) {
  531. outerScope.factory.log("set factory.printing.header: " + str);
  532. settings.header = str;
  533. },
  534. get header() {
  535. return settings.header;
  536. },
  537. set footer(str) {
  538. settings.footer = str;
  539. },
  540. get footer() {
  541. return settings.footer;
  542. },
  543. set headerFooterFont(str) {
  544. settings.headerFooterFont = str;
  545. },
  546. get headerFooterFont() {
  547. return settings.headerFooterFont;
  548. },
  549. set orientation(sOrientation) {
  550. switch (sOrientation.toLowerCase()) {
  551. case "landscape":
  552. settings.page.orientation = printHtml.PageOrientation.LANDSCAPE;
  553. break;
  554. case "portrait":
  555. settings.page.orientation = printHtml.PageOrientation.PORTRAIT;
  556. break;
  557. }
  558. },
  559. get orientation() {
  560. return settings.page.orientation === printHtml.PageOrientation.PORTRAIT ? "portrait" : "landscape";
  561. },
  562. set portrait(bPortrait) {
  563. settings.page.orientation = bPortrait ? printHtml.PageOrientation.PORTRAIT : printHtml.PageOrientation.LANDSCAPE;
  564. },
  565. get portrait() {
  566. return settings.page.orientation === printHtml.PageOrientation.PORTRAIT;
  567. },
  568. set leftMargin(n) {
  569. settings.page.margins.left = n;
  570. },
  571. get leftMargin() {
  572. return settings.page.margins.left;
  573. },
  574. set topMargin(n) {
  575. settings.page.margins.top = n;
  576. },
  577. get topMargin() {
  578. return settings.page.margins.top;
  579. },
  580. set bottomMargin(n) {
  581. settings.page.margins.bottom = n;
  582. },
  583. get bottomMargin() {
  584. return settings.page.margins.bottom;
  585. },
  586. set rightMargin(n) {
  587. settings.page.margins.right = n;
  588. },
  589. get rightMargin() {
  590. return settings.page.margins.right;
  591. },
  592. // templateURL is a no-op at this time. In the future may
  593. // enable alternative server behaviour. Doing something
  594. // is required by the minimiser or it optimises to bad code
  595. set templateURL(sUrl) {
  596. var x = sUrl;
  597. },
  598. get templateURL() {
  599. return "MeadCo://default";
  600. },
  601. // basic functions
  602. //
  603. // No longer relevant, has returned true since IE 6 and was
  604. // a proxy for testing if the browser was IE5.5 or later!
  605. IsTemplateSupported: function () {
  606. return true;
  607. },
  608. PageSetup: function (fnNotify) {
  609. if (typeof fnNotify !== "function") {
  610. MeadCo.warn("PageSetup API in ScriptX.Print Service is not synchronous, there is no return value.");
  611. fnNotify = function (bDlgOK) { MeadCo.log("PageSetupDlg: " + bDlgOK); };
  612. }
  613. if (MeadCo.ScriptX.Print.UI) {
  614. MeadCo.ScriptX.Print.UI.PageSetup(fnNotify);
  615. } else {
  616. MeadCo.error("PageSetup dialog in ScriptX.Services needs a dialog implementation. See: https://www.meadroid.com/Developers/KnowledgeBank/Articles/Dialogs");
  617. fnNotify(false);
  618. }
  619. },
  620. PrintSetup: function (fnNotify) {
  621. if (typeof fnNotify !== "function") {
  622. MeadCo.warn("PrintSetup API in ScriptX.Print Service is not synchronous, there is no return value.");
  623. fnNotify = function (bDlgOK) { MeadCo.log("PrintSetupDlg: " + bDlgOK); }
  624. }
  625. if (MeadCo.ScriptX.Print.UI) {
  626. MeadCo.ScriptX.Print.UI.PrinterSettings(fnNotify);
  627. } else {
  628. MeadCo.error("PrintSettings dialog in ScriptX.Services needs a dialog implementation. See: https://www.meadroid.com/Developers/KnowledgeBank/Articles/Dialogs");
  629. fnNotify(false);
  630. }
  631. },
  632. Preview: function (sOrOFrame) {
  633. if (!sOrOFrame) {
  634. sOrOFrame = null;
  635. }
  636. else {
  637. // passing in window, or window.self etc will not have an id .. don't barf on that code
  638. if (typeof (sOrOFrame) === 'object' && !sOrOFrame.id) {
  639. sOrOFrame = null;
  640. }
  641. }
  642. if (sOrOFrame !== null) {
  643. var sFrame = typeof (sOrOFrame) === 'string' ? sOrOFrame : sOrOFrame.id;
  644. return printHtml.previewFrame(sFrame);
  645. }
  646. printHtml.previewDocument();
  647. },
  648. Print: function (bPrompt, sOrOFrame, fnNotifyStarted) { // needs and wants update to ES2015 (for default values)
  649. if (!fnNotifyStarted) {
  650. fnNotifyStarted = function (bStarted) { MeadCo.log("A print has started: " + bStarted); };
  651. }
  652. if (!sOrOFrame) {
  653. sOrOFrame = null;
  654. }
  655. else {
  656. // passing in window, or window.self etc will not have an id .. don't barf on that code
  657. if (typeof (sOrOFrame) === 'object' && !sOrOFrame.id) {
  658. sOrOFrame = null;
  659. }
  660. }
  661. return promptAndPrint(bPrompt,
  662. function () {
  663. if (sOrOFrame !== null) {
  664. var sFrame = typeof (sOrOFrame) === 'string' ? sOrOFrame : sOrOFrame.id;
  665. return printHtml.printFrame(sFrame);
  666. }
  667. return printHtml.printDocument();
  668. },
  669. fnNotifyStarted);
  670. },
  671. PrintHTML: function (sUrl, bPrompt, fnNotifyStarted) {
  672. if (typeof fnNotifyStarted === "undefined") {
  673. fnNotifyStarted = function (bStarted) { };
  674. }
  675. return printHtmlContent(sUrl, bPrompt, fnNotifyStarted);
  676. },
  677. PrintHTMLEx: function (sUrl, bPrompt, fnCallback, data, fnNotifyStarted) {
  678. if (typeof fnNotifyStarted === "undefined") {
  679. fnNotifyStarted = function (bStarted) { };
  680. }
  681. return printHtmlContent(sUrl, bPrompt, fnNotifyStarted, fnCallback, data);
  682. },
  683. PrintPDF: function (options, bPrompt, bShrinkToFit, iPageFrom, iPageTo, fnNotifyStarted) {
  684. if (typeof fnNotifyStarted === "undefined") {
  685. fnNotifyStarted = function (bStarted) { };
  686. }
  687. if (typeof printPdf !== "undefined") {
  688. printPdf.resetSettings();
  689. if (typeof options.pagescaling !== "undefined") {
  690. printPdf.settings.pageScaling = options.pagescaling;
  691. } else {
  692. printPdf.settings.pageScaling = bShrinkToFit
  693. ? printPdf.PdfPageScaling.SHRINKLARGEPAGES
  694. : printPdf.PdfPageScaling.UNDEFINED;
  695. }
  696. if (typeof options.autorotatecenter !== "undefined") {
  697. printPdf.settings.autoRotateCenter = options.autorotatecenter
  698. ? printPdf.BooleanOption.TRUE
  699. : printPdf.BooleanOption.FALSE;
  700. } else
  701. printPdf.settings.autoRotateCenter = printPdf.BooleanOption.DEFAULT;
  702. if (typeof options.orientation !== "undefined") {
  703. printPdf.settings.orientation = options.orientation === 1
  704. ? printPdf.PageOrientation.PORTRAIT
  705. : printPdf.PageOrientation.LANDSCAPE;
  706. } else
  707. printPdf.settings.orientation = this.portrait
  708. ? printPdf.PageOrientation.PORTRAIT
  709. : printPdf.PageOrientation.LANDSCAPE;
  710. if (typeof options.pages !== "undefined") {
  711. printPdf.settings.pageRange = options.pages;
  712. } else {
  713. if (typeof iPageFrom !== "undefined" &&
  714. typeof iPageTo !== "undefined" &&
  715. iPageFrom !== -1 &&
  716. iPageTo !== -1) {
  717. printPdf.settings.pageRange = iPageFrom + "-" + iPageTo;
  718. } else {
  719. printPdf.settings.pageRange = "";
  720. }
  721. }
  722. if (typeof options.monochrome !== "undefined") {
  723. printPdf.settings.monochrome = options.monochrome
  724. ? printPdf.BooleanOption.TRUE
  725. : printPdf.BooleanOption.FALSE;
  726. } else
  727. printPdf.settings.monochrome = printPdf.BooleanOption.DEFAULT;
  728. if (typeof options.normalise !== "undefined" || typeof options.normalize !== "undefined") {
  729. printPdf.settings.normalise = options.normalise || options.normalize
  730. ? printPdf.BooleanOption.TRUE
  731. : printPdf.BooleanOption.FALSE;
  732. } else
  733. printPdf.settings.normalise = printPdf.BooleanOption.DEFAULT;
  734. if (typeof options.printMode !== "undefined") {
  735. printPdf.settings.printQuality = options.printMode;
  736. } else {
  737. if (typeof options.printQuality !== "undefined") {
  738. printPdf.settings.printQuality = options.printQuality;
  739. }
  740. }
  741. if (typeof options.jobname !== "undefined") {
  742. printPdf.settings.jobDescription = options.jobname;
  743. }
  744. if (typeof options.jobName !== "undefined") {
  745. printPdf.settings.jobDescription = options.jobName;
  746. }
  747. return printPdfContent(options.url, bPrompt, fnNotifyStarted);
  748. }
  749. MeadCo.error("MeadCo.ScriptX.Print.PDF is not available to ScriptX.Services factory emulation.");
  750. fnNotifyStarted(false);
  751. return false;
  752. },
  753. BatchPrintPDF: function (sUrl, fnNotifyStarted) {
  754. this.BatchPrintPDFEx(sUrl, function () {
  755. }, "BatchPrintPDF", fnNotifyStarted);
  756. },
  757. BatchPrintPDFEx: function (sUrl, fnCallback, data, fnNotifyStarted) {
  758. if (typeof fnNotifyStarted === "undefined") {
  759. fnNotifyStarted = function (bStarted) { };
  760. }
  761. if (typeof printPdf !== "undefined") {
  762. printPdf.resetSettings();
  763. printPdf.settings.pageRange = iEnhancedFormatting.pageRange;
  764. printPdf.settings.pageScaling = settings.viewScale === -1
  765. ? printPdf.PdfPageScaling.SHRINKLARGEPAGES
  766. : printPdf.PdfPageScaling.UNDEFINED;
  767. printPdf.settings.orientation = this.portrait
  768. ? printPdf.PageOrientation.PORTRAIT
  769. : printPdf.PageOrientation.LANDSCAPE;
  770. printPdf.settings.printQuality = iEnhancedFormatting.pdfPrintMode;
  771. printPdfContent(sUrl, false, fnNotifyStarted, fnCallback, data);
  772. return;
  773. }
  774. MeadCo.error("MeadCo.ScriptX.Print.PDF is not available to ScriptX.Services factory emulation.");
  775. fnNotifyStarted(false);
  776. },
  777. set units(enumUnits) {
  778. this.SetMarginMeasure(enumUnits);
  779. },
  780. get units() {
  781. return this.GetMarginMeasure();
  782. },
  783. set paperSize(sPaperSize) {
  784. printApi.deviceSettings.paperSizeName = sPaperSize;
  785. },
  786. get paperSize() {
  787. return printApi.deviceSettings.paperSizeName;
  788. },
  789. set paperSource(sPaperSource) {
  790. printApi.deviceSettings.paperSourceName = sPaperSource;
  791. },
  792. get paperSource() {
  793. return printApi.deviceSettings.paperSourceName;
  794. },
  795. set paperSource2(sPaperSource) {
  796. printApi.deviceSettings.paperSourceName = sPaperSource;
  797. },
  798. get paperSource2() {
  799. return printApi.deviceSettings.paperSourceName;
  800. },
  801. get pageWidth() {
  802. return printApi.deviceSettings.paperPageSize.width;
  803. },
  804. get pageHeight() {
  805. return printApi.deviceSettings.paperPageSize.height;
  806. },
  807. set copies(nCopies) {
  808. printApi.deviceSettings.copies = nCopies;
  809. },
  810. get copies() {
  811. return printApi.deviceSettings.copies;
  812. },
  813. set collate(bCollate) {
  814. printApi.deviceSettings.collate = (bCollate === true || bCollate === 1) ? printApi.CollateOptions.TRUE : printApi.CollateOptions.FALSE;
  815. },
  816. get collate() {
  817. return printApi.deviceSettings.collate === printApi.CollateOptions.TRUE;
  818. },
  819. set duplex(duplex) {
  820. printApi.deviceSettings.duplex = duplex;
  821. },
  822. get duplex() {
  823. return printApi.deviceSettings.duplex;
  824. },
  825. set duplex2(duplex) {
  826. printApi.deviceSettings.duplex = duplex;
  827. },
  828. get duplex2() {
  829. return printApi.deviceSettings.duplex;
  830. },
  831. set onafterprint(fn) {
  832. printApi.reportFeatureNotImplemented("onafterprint", fn);
  833. },
  834. set onbeforeprint(fn) {
  835. printApi.reportFeatureNotImplemented("onbeforeprint", fn);
  836. },
  837. set onbeforeunload(sMsg) {
  838. unloadMsg = sMsg;
  839. window.addEventListener('beforeunload', async (e) => {
  840. MeadCo.log("beforeunload handler running");
  841. if (!MeadCo.ScriptX.Print.noJobsWaitingDelivery) {
  842. MeadCo.log("jobs are waiting client side, will prompt user (custom text is not supported by modern browsers)");
  843. e.returnValue = sMsg;
  844. e.preventDefault();
  845. }
  846. else {
  847. MeadCo.log("no jobs are waiting client side");
  848. }
  849. });
  850. },
  851. get onbeforeunload() {
  852. return unloadMsg;
  853. },
  854. set onpagesetup(fn) {
  855. printApi.reportFeatureNotImplemented("onpagesetup", fn);
  856. },
  857. set onuserpagesetup(fn) {
  858. printApi.reportFeatureNotImplemented("onuserpagesetup", fn);
  859. },
  860. set onuserprint(fn) {
  861. printApi.reportFeatureNotImplemented("onuserprint", fn);
  862. },
  863. set onuserprintpreview(fn) {
  864. printApi.reportFeatureNotImplemented("onuserprintpreview", fn);
  865. },
  866. DefaultPrinter: function () {
  867. return printApi.deviceSettingsFor("systemdefault").printerName;
  868. },
  869. AddPrinterConnection: function (sShareName) {
  870. printApi.addPrinterConnection(sShareName);
  871. },
  872. RemovePrinterConnection: function (sShareName) {
  873. printApi.removePrinterConnection(sShareName);
  874. },
  875. AddPrinterConnectionAsync: function (sShareName, onSuccess) {
  876. printApi.addPrinterConnectionAsync(sShareName, onSuccess, function (errTxt) {
  877. printApi.reportError(errTxt);
  878. });
  879. },
  880. RemovePrinterConnectionAsync: function (sShareName, onSuccess) {
  881. printApi.removePrinterConnectionAsync(sShareName, onSuccess, function (errTxt) {
  882. printApi.reportError(errTxt);
  883. });
  884. },
  885. // duplicate to cope with COM objects were/are not case sensitive
  886. get CurrentPrinter() {
  887. return printApi.printerName;
  888. },
  889. set CurrentPrinter(sPrinterName) {
  890. this.currentPrinter = sPrinterName;
  891. },
  892. get currentPrinter() {
  893. return printApi.printerName;
  894. },
  895. set currentPrinter(sPrinterName) {
  896. if (typeof sPrinterName === "string") {
  897. var a = printApi.onErrorAction;
  898. printApi.onErrorAction = printApi.ErrorAction.THROW;
  899. try {
  900. printApi.printerName = sPrinterName;
  901. printApi.onErrorAction = a;
  902. } catch (e) {
  903. printApi.onErrorAction = a;
  904. throw e;
  905. }
  906. }
  907. },
  908. get printer() {
  909. return printApi.printerName;
  910. },
  911. set printer(sPrinterName) {
  912. if (typeof sPrinterName === "string") {
  913. var a = printApi.onErrorAction;
  914. printApi.onErrorAction = printApi.ErrorAction.THROW;
  915. // eat all and any errors. finally might be better but
  916. // minifiers dont like empty blocks
  917. try {
  918. printApi.printerName = sPrinterName;
  919. printApi.onErrorAction = a;
  920. }
  921. catch (e) {
  922. printApi.onErrorAction = a;
  923. }
  924. }
  925. },
  926. set printToFileName(sFileName) {
  927. printApi.deviceSettings.printToFileName = sFileName;
  928. },
  929. get printBackground() {
  930. return settings.printBackgroundColorsAndImages;
  931. },
  932. set printBackground(bPrintBackground) {
  933. settings.printBackgroundColorsAndImages = bPrintBackground;
  934. },
  935. get viewScale() {
  936. return settings.viewScale;
  937. },
  938. set viewScale(x) {
  939. settings.viewScale = x;
  940. },
  941. set unprintableLeft(n) {
  942. printApi.deviceSettings.unprintableMargins.left = n;
  943. },
  944. get unprintableLeft() {
  945. return printApi.deviceSettings.unprintableMargins.left;
  946. },
  947. set unprintableRight(n) {
  948. printApi.deviceSettings.unprintableMargins.right = n;
  949. },
  950. get unprintableRight() {
  951. return printApi.deviceSettings.unprintableMargins.right;
  952. },
  953. set unprintableTop(n) {
  954. printApi.deviceSettings.unprintableMargins.top = n;
  955. },
  956. get unprintableTop() {
  957. return printApi.deviceSettings.unprintableMargins.top;
  958. },
  959. set unprintableBottom(n) {
  960. printApi.deviceSettings.unprintableMargins.bottom = n;
  961. },
  962. get unprintableBottom() {
  963. return printApi.deviceSettings.unprintableMargins.bottom;
  964. },
  965. EnumPrinters: function (index) {
  966. var arP = printApi.availablePrinterNames;
  967. if (!arP || arP.length === 0) {
  968. if (index === 0) {
  969. return this.CurrentPrinter;
  970. }
  971. } else {
  972. if (index < arP.length) {
  973. return arP[index];
  974. }
  975. }
  976. return "";
  977. },
  978. EnumJobs: function (sPrinterName, iIndex, jobNameOut) {
  979. var jobs = printApi.queue;
  980. var i;
  981. var plist = new Array();
  982. sPrinterName = sPrinterName.toLowerCase();
  983. for (i = 0; i < jobs.length; i++) {
  984. if (jobs[i].printerName.toLowerCase() === sPrinterName) {
  985. plist.push(jobs[i]);
  986. }
  987. }
  988. if (iIndex < plist.length) {
  989. jobNameOut.name = plist[iIndex].jobName;
  990. return plist[iIndex].status;
  991. }
  992. return 0;
  993. },
  994. GetJobsCount: function (sPrinterName) {
  995. // return printApi.activeJobs;
  996. var jobs = printApi.queue;
  997. var i;
  998. var c = 0;
  999. sPrinterName = sPrinterName.toLowerCase();
  1000. for (i = 0; i < jobs.length; i++) {
  1001. if (jobs[i].printerName.toLowerCase() === sPrinterName)
  1002. c++;
  1003. }
  1004. return c;
  1005. },
  1006. printerControl: function (printerName) {
  1007. return {
  1008. get Forms() {
  1009. return printApi.deviceSettingsFor(printerName).forms;
  1010. },
  1011. get Bins() {
  1012. return printApi.deviceSettingsFor(printerName).bins;
  1013. },
  1014. get forms() {
  1015. return printApi.deviceSettingsFor(printerName).forms;
  1016. },
  1017. get bins() {
  1018. return printApi.deviceSettingsFor(printerName).bins;
  1019. },
  1020. get name() {
  1021. return printerName;
  1022. },
  1023. get status() {
  1024. return printApi.deviceSettingsFor(printerName).port;
  1025. },
  1026. get port() {
  1027. return printApi.deviceSettingsFor(printerName).port;
  1028. },
  1029. get attributes() {
  1030. return printApi.deviceSettingsFor(printerName).attributes;
  1031. },
  1032. get serverName() {
  1033. return printApi.deviceSettingsFor(printerName).serverName;
  1034. },
  1035. get shareName() {
  1036. return printApi.deviceSettingsFor(printerName).shareName;
  1037. },
  1038. get location() {
  1039. return printApi.deviceSettingsFor(printerName).location;
  1040. },
  1041. get isLocal() {
  1042. return printApi.deviceSettingsFor(printerName).isLocal;
  1043. },
  1044. get isNetwork() {
  1045. return printApi.deviceSettingsFor(printerName).isNetwork;
  1046. },
  1047. get isShared() {
  1048. return printApi.deviceSettingsFor(printerName).isShared;
  1049. },
  1050. get Jobs() {
  1051. printApi.reportFeatureNotImplemented("printerControl.Jobs");
  1052. },
  1053. Purge: function () {
  1054. printApi.reportFeatureNotImplemented("printerControl.Purge()");
  1055. },
  1056. Pause: function () {
  1057. printApi.reportFeatureNotImplemented("printerControl.Pause()");
  1058. },
  1059. Resume: function () {
  1060. printApi.reportFeatureNotImplemented("printerControl.Resume()");
  1061. }
  1062. };
  1063. },
  1064. GetMarginMeasure: function () {
  1065. return settings.page.units === printApi.MeasurementUnits.INCHES ? 2 : 1;
  1066. },
  1067. SetMarginMeasure: function (enumUnits) {
  1068. settings.page.units = enumUnits === 2 ? printApi.MeasurementUnits.INCHES : printApi.MeasurementUnits.MM;
  1069. },
  1070. SetPrintScale: function (value) {
  1071. settings.viewScale = value;
  1072. },
  1073. IsSpooling: function () {
  1074. return printApi.isSpooling;
  1075. },
  1076. OwnQueue: function () {
  1077. // NOTE: No-op, no concept of 'out of process' here
  1078. return null;
  1079. },
  1080. SetPageRange: function (bSelectionOnly, iFrom, iTo) {
  1081. if (bSelectionOnly) {
  1082. printApi.reportFeatureNotImplemented("SetPageRange selection only");
  1083. }
  1084. settings.pageRange = "" + iFrom + "-" + iTo;
  1085. },
  1086. SetPreviewZoom: function () {
  1087. printApi.reportFeatureNotImplemented("SetPreviewZoom");
  1088. },
  1089. Sleep: function () {
  1090. // If you need this, please implement your own for the browsers you are deploying to.
  1091. // Contact MeadCo for assistance if required.
  1092. printApi.reportFeatureNotImplemented("Sleep");
  1093. },
  1094. TotalPrintPages: function () {
  1095. printApi.reportFeatureNotImplemented("TotalPrintPages");
  1096. },
  1097. WaitForSpoolingComplete: function (iTimeout, fnComplete) {
  1098. printApi.waitForSpoolingComplete(iTimeout, fnComplete);
  1099. },
  1100. enhancedFormatting: iEnhancedFormatting,
  1101. // helpers for wrapper MeadCoJS
  1102. PolyfillInit: function () {
  1103. if (!MeadCo.ScriptX.Print.isConnected) {
  1104. printHtml.connect("", "", function (e) {
  1105. MeadCo.warn("Services server connection failed: " + e);
  1106. });
  1107. }
  1108. return MeadCo.ScriptX.Print.isConnected;
  1109. },
  1110. PolyfillInitAsync: function (resolve, reject) {
  1111. if (MeadCo.ScriptX.Print.isConnected) {
  1112. resolve(2);
  1113. } else {
  1114. printHtml.connectAsync("", "", resolve, reject);
  1115. }
  1116. },
  1117. get PolyfillAuthorisationCookie() {
  1118. return MeadCo.ScriptX.Print.authorisationCookie;
  1119. },
  1120. set PolyfillAuthorisationCookie(cookie) {
  1121. MeadCo.ScriptX.Print.authorisationCookie = cookie;
  1122. }
  1123. };
  1124. });
  1125. ; (function (name, definition) {
  1126. if (typeof factory.extendFactoryNamespace === "function") {
  1127. factory.extendFactoryNamespace(name, definition);
  1128. }
  1129. })('factory.object', function () {
  1130. // protected API
  1131. var outerScope = this;
  1132. outerScope.factory.log("factory.object loaded.");
  1133. /*
  1134. * This completes the emulation of an &lt;object /&gt; element
  1135. *
  1136. * Compatibility with Add-on to allow inspection of &lt;object /&gt; and this javascript
  1137. * for the underlying object implementing 'factory'.
  1138. *
  1139. * @property {object} factory
  1140. * @memberof factoryobject
  1141. */
  1142. return outerScope.factory;
  1143. });
  1144. ; (function (name, definition) {
  1145. if (typeof factory.extendFactoryNamespace === "function") {
  1146. factory.extendFactoryNamespace(name, definition);
  1147. }
  1148. })('factory.object.js', function () {
  1149. // protected API
  1150. var outerScope = this;
  1151. outerScope.factory.log("factory.object.js loaded.");
  1152. // public API
  1153. return {
  1154. /*
  1155. * Convert object to number -- required for some code compatibility only. Do not use
  1156. *
  1157. * @function FormatNumber
  1158. * @memberof factoryjs
  1159. * @param {any} arg object to convert
  1160. * @returns {Number} arg as a number if it can be converted, else 0
  1161. */
  1162. FormatNumber: function (arg) {
  1163. if (isNaN(arg)) {
  1164. return 0;
  1165. } else {
  1166. if (typeof arg === 'string') {
  1167. return Number(arg);
  1168. } else {
  1169. return arg;
  1170. }
  1171. }
  1172. }
  1173. };
  1174. });