modules/viewerpreferences.js

  1. /**
  2. * @license
  3. * jsPDF viewerPreferences Plugin
  4. * @author Aras Abbasi (github.com/arasabbasi)
  5. * Licensed under the MIT License.
  6. * http://opensource.org/licenses/mit-license
  7. */
  8. import { jsPDF } from "../jspdf.js";
  9. /**
  10. * Adds the ability to set ViewerPreferences and by thus
  11. * controlling the way the document is to be presented on the
  12. * screen or in print.
  13. * @name viewerpreferences
  14. * @module
  15. */
  16. (function(jsPDFAPI) {
  17. "use strict";
  18. /**
  19. * Set the ViewerPreferences of the generated PDF
  20. *
  21. * @name viewerPreferences
  22. * @function
  23. * @public
  24. * @param {Object} options Array with the ViewerPreferences<br />
  25. * Example: doc.viewerPreferences({"FitWindow":true});<br />
  26. * <br />
  27. * You can set following preferences:<br />
  28. * <br/>
  29. * <b>HideToolbar</b> <i>(boolean)</i><br />
  30. * Default value: false<br />
  31. * <br />
  32. * <b>HideMenubar</b> <i>(boolean)</i><br />
  33. * Default value: false.<br />
  34. * <br />
  35. * <b>HideWindowUI</b> <i>(boolean)</i><br />
  36. * Default value: false.<br />
  37. * <br />
  38. * <b>FitWindow</b> <i>(boolean)</i><br />
  39. * Default value: false.<br />
  40. * <br />
  41. * <b>CenterWindow</b> <i>(boolean)</i><br />
  42. * Default value: false<br />
  43. * <br />
  44. * <b>DisplayDocTitle</b> <i>(boolean)</i><br />
  45. * Default value: false.<br />
  46. * <br />
  47. * <b>NonFullScreenPageMode</b> <i>(string)</i><br />
  48. * Possible values: UseNone, UseOutlines, UseThumbs, UseOC<br />
  49. * Default value: UseNone<br/>
  50. * <br />
  51. * <b>Direction</b> <i>(string)</i><br />
  52. * Possible values: L2R, R2L<br />
  53. * Default value: L2R.<br />
  54. * <br />
  55. * <b>ViewArea</b> <i>(string)</i><br />
  56. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  57. * Default value: CropBox.<br />
  58. * <br />
  59. * <b>ViewClip</b> <i>(string)</i><br />
  60. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  61. * Default value: CropBox<br />
  62. * <br />
  63. * <b>PrintArea</b> <i>(string)</i><br />
  64. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  65. * Default value: CropBox<br />
  66. * <br />
  67. * <b>PrintClip</b> <i>(string)</i><br />
  68. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  69. * Default value: CropBox.<br />
  70. * <br />
  71. * <b>PrintScaling</b> <i>(string)</i><br />
  72. * Possible values: AppDefault, None<br />
  73. * Default value: AppDefault.<br />
  74. * <br />
  75. * <b>Duplex</b> <i>(string)</i><br />
  76. * Possible values: Simplex, DuplexFlipLongEdge, DuplexFlipShortEdge
  77. * Default value: none<br />
  78. * <br />
  79. * <b>PickTrayByPDFSize</b> <i>(boolean)</i><br />
  80. * Default value: false<br />
  81. * <br />
  82. * <b>PrintPageRange</b> <i>(Array)</i><br />
  83. * Example: [[1,5], [7,9]]<br />
  84. * Default value: as defined by PDF viewer application<br />
  85. * <br />
  86. * <b>NumCopies</b> <i>(Number)</i><br />
  87. * Possible values: 1, 2, 3, 4, 5<br />
  88. * Default value: 1<br />
  89. * <br />
  90. * For more information see the PDF Reference, sixth edition on Page 577
  91. * @param {boolean} doReset True to reset the settings
  92. * @function
  93. * @returns jsPDF jsPDF-instance
  94. * @example
  95. * var doc = new jsPDF()
  96. * doc.text('This is a test', 10, 10)
  97. * doc.viewerPreferences({'FitWindow': true}, true)
  98. * doc.save("viewerPreferences.pdf")
  99. *
  100. * // Example printing 10 copies, using cropbox, and hiding UI.
  101. * doc.viewerPreferences({
  102. * 'HideWindowUI': true,
  103. * 'PrintArea': 'CropBox',
  104. * 'NumCopies': 10
  105. * })
  106. */
  107. jsPDFAPI.viewerPreferences = function(options, doReset) {
  108. options = options || {};
  109. doReset = doReset || false;
  110. var configuration;
  111. var configurationTemplate = {
  112. HideToolbar: {
  113. defaultValue: false,
  114. value: false,
  115. type: "boolean",
  116. explicitSet: false,
  117. valueSet: [true, false],
  118. pdfVersion: 1.3
  119. },
  120. HideMenubar: {
  121. defaultValue: false,
  122. value: false,
  123. type: "boolean",
  124. explicitSet: false,
  125. valueSet: [true, false],
  126. pdfVersion: 1.3
  127. },
  128. HideWindowUI: {
  129. defaultValue: false,
  130. value: false,
  131. type: "boolean",
  132. explicitSet: false,
  133. valueSet: [true, false],
  134. pdfVersion: 1.3
  135. },
  136. FitWindow: {
  137. defaultValue: false,
  138. value: false,
  139. type: "boolean",
  140. explicitSet: false,
  141. valueSet: [true, false],
  142. pdfVersion: 1.3
  143. },
  144. CenterWindow: {
  145. defaultValue: false,
  146. value: false,
  147. type: "boolean",
  148. explicitSet: false,
  149. valueSet: [true, false],
  150. pdfVersion: 1.3
  151. },
  152. DisplayDocTitle: {
  153. defaultValue: false,
  154. value: false,
  155. type: "boolean",
  156. explicitSet: false,
  157. valueSet: [true, false],
  158. pdfVersion: 1.4
  159. },
  160. NonFullScreenPageMode: {
  161. defaultValue: "UseNone",
  162. value: "UseNone",
  163. type: "name",
  164. explicitSet: false,
  165. valueSet: ["UseNone", "UseOutlines", "UseThumbs", "UseOC"],
  166. pdfVersion: 1.3
  167. },
  168. Direction: {
  169. defaultValue: "L2R",
  170. value: "L2R",
  171. type: "name",
  172. explicitSet: false,
  173. valueSet: ["L2R", "R2L"],
  174. pdfVersion: 1.3
  175. },
  176. ViewArea: {
  177. defaultValue: "CropBox",
  178. value: "CropBox",
  179. type: "name",
  180. explicitSet: false,
  181. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  182. pdfVersion: 1.4
  183. },
  184. ViewClip: {
  185. defaultValue: "CropBox",
  186. value: "CropBox",
  187. type: "name",
  188. explicitSet: false,
  189. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  190. pdfVersion: 1.4
  191. },
  192. PrintArea: {
  193. defaultValue: "CropBox",
  194. value: "CropBox",
  195. type: "name",
  196. explicitSet: false,
  197. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  198. pdfVersion: 1.4
  199. },
  200. PrintClip: {
  201. defaultValue: "CropBox",
  202. value: "CropBox",
  203. type: "name",
  204. explicitSet: false,
  205. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  206. pdfVersion: 1.4
  207. },
  208. PrintScaling: {
  209. defaultValue: "AppDefault",
  210. value: "AppDefault",
  211. type: "name",
  212. explicitSet: false,
  213. valueSet: ["AppDefault", "None"],
  214. pdfVersion: 1.6
  215. },
  216. Duplex: {
  217. defaultValue: "",
  218. value: "none",
  219. type: "name",
  220. explicitSet: false,
  221. valueSet: [
  222. "Simplex",
  223. "DuplexFlipShortEdge",
  224. "DuplexFlipLongEdge",
  225. "none"
  226. ],
  227. pdfVersion: 1.7
  228. },
  229. PickTrayByPDFSize: {
  230. defaultValue: false,
  231. value: false,
  232. type: "boolean",
  233. explicitSet: false,
  234. valueSet: [true, false],
  235. pdfVersion: 1.7
  236. },
  237. PrintPageRange: {
  238. defaultValue: "",
  239. value: "",
  240. type: "array",
  241. explicitSet: false,
  242. valueSet: null,
  243. pdfVersion: 1.7
  244. },
  245. NumCopies: {
  246. defaultValue: 1,
  247. value: 1,
  248. type: "integer",
  249. explicitSet: false,
  250. valueSet: null,
  251. pdfVersion: 1.7
  252. }
  253. };
  254. var configurationKeys = Object.keys(configurationTemplate);
  255. var rangeArray = [];
  256. var i = 0;
  257. var j = 0;
  258. var k = 0;
  259. var isValid;
  260. var method;
  261. var value;
  262. function arrayContainsElement(array, element) {
  263. var iterator;
  264. var result = false;
  265. for (iterator = 0; iterator < array.length; iterator += 1) {
  266. if (array[iterator] === element) {
  267. result = true;
  268. }
  269. }
  270. return result;
  271. }
  272. if (this.internal.viewerpreferences === undefined) {
  273. this.internal.viewerpreferences = {};
  274. this.internal.viewerpreferences.configuration = JSON.parse(
  275. JSON.stringify(configurationTemplate)
  276. );
  277. this.internal.viewerpreferences.isSubscribed = false;
  278. }
  279. configuration = this.internal.viewerpreferences.configuration;
  280. if (options === "reset" || doReset === true) {
  281. var len = configurationKeys.length;
  282. for (k = 0; k < len; k += 1) {
  283. configuration[configurationKeys[k]].value =
  284. configuration[configurationKeys[k]].defaultValue;
  285. configuration[configurationKeys[k]].explicitSet = false;
  286. }
  287. }
  288. if (typeof options === "object") {
  289. for (method in options) {
  290. value = options[method];
  291. if (
  292. arrayContainsElement(configurationKeys, method) &&
  293. value !== undefined
  294. ) {
  295. if (
  296. configuration[method].type === "boolean" &&
  297. typeof value === "boolean"
  298. ) {
  299. configuration[method].value = value;
  300. } else if (
  301. configuration[method].type === "name" &&
  302. arrayContainsElement(configuration[method].valueSet, value)
  303. ) {
  304. configuration[method].value = value;
  305. } else if (
  306. configuration[method].type === "integer" &&
  307. Number.isInteger(value)
  308. ) {
  309. configuration[method].value = value;
  310. } else if (configuration[method].type === "array") {
  311. for (i = 0; i < value.length; i += 1) {
  312. isValid = true;
  313. if (value[i].length === 1 && typeof value[i][0] === "number") {
  314. rangeArray.push(String(value[i] - 1));
  315. } else if (value[i].length > 1) {
  316. for (j = 0; j < value[i].length; j += 1) {
  317. if (typeof value[i][j] !== "number") {
  318. isValid = false;
  319. }
  320. }
  321. if (isValid === true) {
  322. rangeArray.push([value[i][0] - 1, value[i][1] - 1].join(" "));
  323. }
  324. }
  325. }
  326. configuration[method].value = "[" + rangeArray.join(" ") + "]";
  327. } else {
  328. configuration[method].value = configuration[method].defaultValue;
  329. }
  330. configuration[method].explicitSet = true;
  331. }
  332. }
  333. }
  334. if (this.internal.viewerpreferences.isSubscribed === false) {
  335. this.internal.events.subscribe("putCatalog", function() {
  336. var pdfDict = [];
  337. var vPref;
  338. for (vPref in configuration) {
  339. if (configuration[vPref].explicitSet === true) {
  340. if (configuration[vPref].type === "name") {
  341. pdfDict.push("/" + vPref + " /" + configuration[vPref].value);
  342. } else {
  343. pdfDict.push("/" + vPref + " " + configuration[vPref].value);
  344. }
  345. }
  346. }
  347. if (pdfDict.length !== 0) {
  348. this.internal.write(
  349. "/ViewerPreferences\n<<\n" + pdfDict.join("\n") + "\n>>"
  350. );
  351. }
  352. });
  353. this.internal.viewerpreferences.isSubscribed = true;
  354. }
  355. this.internal.viewerpreferences.configuration = configuration;
  356. return this;
  357. };
  358. })(jsPDF.API);