PDF Tools

An userscript that enhances the pdf.js window in Firefox.

  1. // ==UserScript==
  2. // @name PDF Tools
  3. // @id PDF_Tools@https://github.com/jerone/UserScripts
  4. // @description An userscript that enhances the pdf.js window in Firefox.
  5. // @version 1.0
  6. // @namespace https://github.com/jerone/UserScripts
  7. // @author jerone
  8. // @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
  9. // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  10. // @supportURL https://github.com/jerone/UserScripts/issues
  11. // @contributionURL https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VCYMHWQ7ZMBKW
  12. // @include *.pdf
  13. // @include *.pdf?*
  14. // @include *.pdf#*
  15. // @run-at document-end
  16. // ==/UserScript==
  17.  
  18. // cSpell:ignore PDF
  19. /* eslint security/detect-object-injection: "off" */
  20.  
  21. (function () {
  22. //console.log(PDFJS.version); // "1.0.277"
  23.  
  24. var mimetype = "png";
  25.  
  26. var SecondaryToolbar = {
  27. opened: false,
  28. initialize: function secondaryToolbarInitialize() {
  29. this.toolbar = document.createElement("div");
  30. this.toolbar.classList.add(
  31. "secondaryToolbar",
  32. "doorHangerRight",
  33. "hidden",
  34. );
  35. this.toolbar.style.right = "180px";
  36. document.getElementById("mainContainer").appendChild(this.toolbar);
  37.  
  38. this.buttonContainer = document.createElement("div");
  39. this.buttonContainer.classList.add(
  40. "secondaryToolbarButtonContainer",
  41. );
  42. this.toolbar.appendChild(this.buttonContainer);
  43.  
  44. this.attachEvents();
  45. },
  46.  
  47. attachEvents: function () {
  48. /// https://github.com/mozilla/pdf.js/blob/2f5c6d6c3a75f9f44826c776dd356e2f786f35de/web/viewer.js#L2248
  49. window.addEventListener(
  50. "click",
  51. function click(evt) {
  52. if (
  53. SecondaryToolbar.opened &&
  54. unsafeWindow.PDFView.container.contains(evt.target)
  55. ) {
  56. SecondaryToolbar.close();
  57. }
  58. },
  59. false,
  60. );
  61. /// https://github.com/mozilla/pdf.js/blob/2f5c6d6c3a75f9f44826c776dd356e2f786f35de/web/viewer.js#L2381
  62. window.addEventListener("keydown", function keydown(evt) {
  63. if (SecondaryToolbar.opened && evt.keyCode === 27) {
  64. // esc;
  65. SecondaryToolbar.close();
  66. }
  67. });
  68. },
  69.  
  70. render: function () {
  71. console.log(unsafeWindow.PDFView.pages);
  72. console.log(unsafeWindow.PDFView.pages[0].draw);
  73.  
  74. var pages = unsafeWindow.PDFView.pages;
  75.  
  76. for (var i = 0, ii = pages.length; i < ii; i++) {
  77. var page = pages[i];
  78. console.log(page, page.draw);
  79. var img = document.createElement("a");
  80. img.classList.add("secondaryToolbarButton", "download");
  81. img.dataset.pageIndex = i;
  82. img.setAttribute("download", "page" + page.id + "." + mimetype);
  83. img.setAttribute(
  84. "title",
  85. "Download 'page" + page.id + "." + mimetype + "'",
  86. );
  87. img.style.display = "inline-block";
  88. img.style.boxSizing = "border-box";
  89. img.appendChild(document.createTextNode("Page " + page.id));
  90. img.addEventListener("click", function () {
  91. var page = pages[this.dataset.pageIndex];
  92. if (!page.canvas) {
  93. page.draw();
  94. }
  95. this.href = page.canvas.toDataURL("image/" + mimetype);
  96. //window.open( page.canvas.toDataURL("image/" + mimetype));
  97. });
  98. //this.buttonContainer.appendChild(img);
  99.  
  100. console.log(page.canvas, img, arguments);
  101.  
  102. //if (!page.canvas) { page.draw(); }
  103. var img2 = document.createElement("img");
  104. //img2.style.width = "16px";
  105. img2.style.height = "16px";
  106. img2.style.border = "1px solid red";
  107. //img2.src = page.canvas.toDataURL("image/" + mimetype);
  108. img2.src =
  109. (page.canvas &&
  110. page.canvas.toDataURL("image/" + mimetype)) ||
  111. "";
  112. this.buttonContainer.appendChild(img2);
  113. }
  114.  
  115. /*
  116. unsafeWindow.PDFView.pages.forEach(function(page) {
  117. console.log(page, page.draw);
  118. if (page.draw) page.draw();
  119.  
  120. var img = document.createElement("button");
  121. img.classList.add("secondaryToolbarButton", "download");
  122. img.dataset.canvasURL = page.canvas.toDataURL("image/" + mimetype);
  123. img.setAttribute("download", page.canvas.id + "." + mimetype);
  124. img.setAttribute("title", "Download " + page.canvas.id + "." + mimetype);
  125. img.style.display = "inline-block";
  126. img.appendChild(document.createTextNode(page.canvas.id));
  127. img.addEventListener("click", function() {
  128. this.href = this.dataset.canvasURL;
  129. });
  130. this.buttonContainer.appendChild(img);
  131. console.log(page.canvas, img, arguments);
  132. });
  133. /*
  134. var canvases = document.querySelectorAll("canvas:not(.thumbnailImage)");
  135. console.log("test", canvases);
  136. Array.prototype.forEach.call(canvases, function(canvas) {
  137. var img = document.createElement("button");
  138. img.classList.add("secondaryToolbarButton", "download");
  139. img.dataset.canvasURL = canvas.toDataURL("image/" + mimetype);
  140. img.setAttribute("download", canvas.id + "." + mimetype);
  141. img.setAttribute("title", "Download " + canvas.id + "." + mimetype);
  142. img.style.display = "inline-block";
  143. img.appendChild(document.createTextNode(canvas.id));
  144. img.addEventListener("click", function() {
  145. this.href = this.dataset.canvasURL;
  146. });
  147. this.buttonContainer.appendChild(img);
  148. console.log(canvas, img, arguments);
  149. });*/
  150. },
  151.  
  152. empty: function () {
  153. while (this.buttonContainer.hasChildNodes()) {
  154. this.buttonContainer.removeChild(
  155. this.buttonContainer.lastChild,
  156. );
  157. }
  158. },
  159.  
  160. open: function secondaryToolbarOpen() {
  161. if (this.opened) {
  162. return;
  163. }
  164. this.opened = true;
  165. this.toolbar.classList.remove("hidden");
  166. this.render();
  167. },
  168.  
  169. close: function secondaryToolbarClose(target) {
  170. if (!this.opened) {
  171. return;
  172. } else if (target && !this.toolbar.contains(target)) {
  173. return;
  174. }
  175. this.opened = false;
  176. this.toolbar.classList.add("hidden");
  177. this.empty();
  178. },
  179.  
  180. toggle: function secondaryToolbarToggle() {
  181. if (this.opened) {
  182. this.close();
  183. } else {
  184. this.open();
  185. }
  186. },
  187. };
  188.  
  189. SecondaryToolbar.initialize();
  190.  
  191. var toolbar = document.getElementById("toolbarViewerRight");
  192. var btn = document.createElement("button");
  193. btn.classList.add("toolbarButton", "zoomIn");
  194. toolbar.insertBefore(btn, toolbar.firstChild);
  195. btn.addEventListener("click", function () {
  196. SecondaryToolbar.toggle();
  197. });
  198. })();