pdf_attachment_viewer.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2020 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.PDFAttachmentViewer = void 0;
  27. var _pdf = require("../pdf");
  28. var _base_tree_viewer = require("./base_tree_viewer.js");
  29. var _viewer_compatibility = require("./viewer_compatibility.js");
  30. const PdfFileRegExp = /\.pdf$/i;
  31. class PDFAttachmentViewer extends _base_tree_viewer.BaseTreeViewer {
  32. constructor(options) {
  33. super(options);
  34. this.downloadManager = options.downloadManager;
  35. this.eventBus._on("fileattachmentannotation", this._appendAttachment.bind(this));
  36. }
  37. reset(keepRenderedCapability = false) {
  38. super.reset();
  39. this._attachments = null;
  40. if (!keepRenderedCapability) {
  41. this._renderedCapability = (0, _pdf.createPromiseCapability)();
  42. }
  43. if (this._pendingDispatchEvent) {
  44. clearTimeout(this._pendingDispatchEvent);
  45. }
  46. this._pendingDispatchEvent = null;
  47. }
  48. _dispatchEvent(attachmentsCount) {
  49. this._renderedCapability.resolve();
  50. if (this._pendingDispatchEvent) {
  51. clearTimeout(this._pendingDispatchEvent);
  52. this._pendingDispatchEvent = null;
  53. }
  54. if (attachmentsCount === 0) {
  55. this._pendingDispatchEvent = setTimeout(() => {
  56. this.eventBus.dispatch("attachmentsloaded", {
  57. source: this,
  58. attachmentsCount: 0
  59. });
  60. this._pendingDispatchEvent = null;
  61. });
  62. return;
  63. }
  64. this.eventBus.dispatch("attachmentsloaded", {
  65. source: this,
  66. attachmentsCount
  67. });
  68. }
  69. _bindPdfLink(element, {
  70. content,
  71. filename
  72. }) {
  73. let blobUrl;
  74. element.onclick = () => {
  75. if (!blobUrl) {
  76. blobUrl = URL.createObjectURL(new Blob([content], {
  77. type: "application/pdf"
  78. }));
  79. }
  80. let viewerUrl;
  81. viewerUrl = "?file=" + encodeURIComponent(blobUrl + "#" + filename);
  82. try {
  83. window.open(viewerUrl);
  84. } catch (ex) {
  85. console.error(`_bindPdfLink: ${ex}`);
  86. URL.revokeObjectURL(blobUrl);
  87. blobUrl = null;
  88. this.downloadManager.downloadData(content, filename, "application/pdf");
  89. }
  90. return false;
  91. };
  92. }
  93. _bindLink(element, {
  94. content,
  95. filename
  96. }) {
  97. element.onclick = () => {
  98. const contentType = PdfFileRegExp.test(filename) ? "application/pdf" : "";
  99. this.downloadManager.downloadData(content, filename, contentType);
  100. return false;
  101. };
  102. }
  103. render({
  104. attachments,
  105. keepRenderedCapability = false
  106. }) {
  107. if (this._attachments) {
  108. this.reset(keepRenderedCapability);
  109. }
  110. this._attachments = attachments || null;
  111. if (!attachments) {
  112. this._dispatchEvent(0);
  113. return;
  114. }
  115. const names = Object.keys(attachments).sort(function (a, b) {
  116. return a.toLowerCase().localeCompare(b.toLowerCase());
  117. });
  118. const fragment = document.createDocumentFragment();
  119. let attachmentsCount = 0;
  120. for (const name of names) {
  121. const item = attachments[name];
  122. const filename = (0, _pdf.getFilenameFromUrl)(item.filename);
  123. const div = document.createElement("div");
  124. div.className = "treeItem";
  125. const element = document.createElement("a");
  126. if (PdfFileRegExp.test(filename) && !_viewer_compatibility.viewerCompatibilityParams.disableCreateObjectURL) {
  127. this._bindPdfLink(element, {
  128. content: item.content,
  129. filename
  130. });
  131. } else {
  132. this._bindLink(element, {
  133. content: item.content,
  134. filename
  135. });
  136. }
  137. element.textContent = this._normalizeTextContent(filename);
  138. div.appendChild(element);
  139. fragment.appendChild(div);
  140. attachmentsCount++;
  141. }
  142. this.container.appendChild(fragment);
  143. this._dispatchEvent(attachmentsCount);
  144. }
  145. _appendAttachment({
  146. id,
  147. filename,
  148. content
  149. }) {
  150. const renderedPromise = this._renderedCapability.promise;
  151. renderedPromise.then(() => {
  152. if (renderedPromise !== this._renderedCapability.promise) {
  153. return;
  154. }
  155. let attachments = this._attachments;
  156. if (!attachments) {
  157. attachments = Object.create(null);
  158. } else {
  159. for (const name in attachments) {
  160. if (id === name) {
  161. return;
  162. }
  163. }
  164. }
  165. attachments[id] = {
  166. filename,
  167. content
  168. };
  169. this.render({
  170. attachments,
  171. keepRenderedCapability: true
  172. });
  173. });
  174. }
  175. }
  176. exports.PDFAttachmentViewer = PDFAttachmentViewer;