UNPKG

ngx-extended-pdf-viewer

Version:

Embedding PDF files in your Angular application. Highly configurable viewer including the toolbar, sidebar, and all the features you're used to.

1,428 lines (1,419 loc) 578 kB
window.ngxZone.runOutsideAngular(() => { /** * @licstart The following is the entire license notice for the * JavaScript code in this page * * Copyright 2023 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @licend The above is the entire license notice for the * JavaScript code in this page */ /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ([ /* 0 */, /* 1 */ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.GenericCom = void 0; var _app = __webpack_require__(2); var _preferences = __webpack_require__(47); var _download_manager = __webpack_require__(48); var _genericl10n = __webpack_require__(49); var _generic_scripting = __webpack_require__(51); ; const GenericCom = {}; exports.GenericCom = GenericCom; class GenericPreferences extends _preferences.BasePreferences { async _writeToStorage(prefObj) { try { localStorage.setItem("pdfjs.preferences", JSON.stringify(prefObj)); } catch (safariSecurityException) {} } async _readFromStorage(prefObj) { try { return JSON.parse(localStorage.getItem("pdfjs.preferences")); } catch (safariSecurityException) { return {}; } } } class GenericExternalServices extends _app.DefaultExternalServices { static createDownloadManager() { return new _download_manager.DownloadManager(); } static createPreferences() { return new GenericPreferences(); } static createL10n({ locale = "en-US" }) { return new _genericl10n.GenericL10n(locale); } static createScripting({ sandboxBundleSrc }) { return new _generic_scripting.GenericScripting(sandboxBundleSrc); } } _app.PDFViewerApplication.externalServices = GenericExternalServices; /***/ }), /* 2 */ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.PDFViewerApplication = exports.PDFPrintServiceFactory = exports.DefaultExternalServices = void 0; var _ui_utils = __webpack_require__(3); var _pdfjsLib = __webpack_require__(4); var _app_options = __webpack_require__(5); var _event_utils = __webpack_require__(6); var _pdf_link_service = __webpack_require__(7); var _webAnnotation_editor_params = __webpack_require__(8); var _overlay_manager = __webpack_require__(9); var _password_prompt = __webpack_require__(10); var _webPdf_attachment_viewer = __webpack_require__(11); var _webPdf_cursor_tools = __webpack_require__(13); var _webPdf_document_properties = __webpack_require__(15); var _webPdf_find_bar = __webpack_require__(16); var _pdf_find_controller = __webpack_require__(17); var _pdf_history = __webpack_require__(21); var _webPdf_layer_viewer = __webpack_require__(22); var _webPdf_outline_viewer = __webpack_require__(23); var _webPdf_presentation_mode = __webpack_require__(24); var _pdf_rendering_queue = __webpack_require__(25); var _pdf_scripting_manager = __webpack_require__(26); var _webPdf_sidebar = __webpack_require__(27); var _webPdf_sidebar_resizer = __webpack_require__(28); var _webPdf_thumbnail_viewer = __webpack_require__(29); var _pdf_viewer = __webpack_require__(31); var _webSecondary_toolbar = __webpack_require__(44); var _webToolbar = __webpack_require__(45); var _view_history = __webpack_require__(46); const FORCE_PAGES_LOADED_TIMEOUT = 10; const WHEEL_ZOOM_DISABLED_TIMEOUT = 1000; const ViewOnLoad = { UNKNOWN: -1, PREVIOUS: 0, INITIAL: 1 }; const ViewerCssTheme = { AUTOMATIC: 0, LIGHT: 1, DARK: 2 }; class DefaultExternalServices { constructor() { throw new Error("Cannot initialize DefaultExternalServices."); } static updateFindControlState(data) {} static updateFindMatchesCount(data) {} static initPassiveLoading(callbacks) {} static reportTelemetry(data) {} static createDownloadManager() { throw new Error("Not implemented: createDownloadManager"); } static createPreferences() { throw new Error("Not implemented: createPreferences"); } static createL10n(options) { throw new Error("Not implemented: createL10n"); } static createScripting(options) { throw new Error("Not implemented: createScripting"); } static get supportsPinchToZoom() { return (0, _pdfjsLib.shadow)(this, "supportsPinchToZoom", true); } static get supportsIntegratedFind() { return (0, _pdfjsLib.shadow)(this, "supportsIntegratedFind", false); } static get supportsDocumentFonts() { return (0, _pdfjsLib.shadow)(this, "supportsDocumentFonts", true); } static get supportedMouseWheelZoomModifierKeys() { return (0, _pdfjsLib.shadow)(this, "supportedMouseWheelZoomModifierKeys", { ctrlKey: true, metaKey: true }); } static get isInAutomation() { return (0, _pdfjsLib.shadow)(this, "isInAutomation", false); } static updateEditorStates(data) { throw new Error("Not implemented: updateEditorStates"); } } exports.DefaultExternalServices = DefaultExternalServices; const PDFViewerApplication = { initialBookmark: document.location.hash.substring(1), _initializedCapability: (0, _pdfjsLib.createPromiseCapability)(), appConfig: null, pdfDocument: null, pdfLoadingTask: null, printService: null, pdfViewer: null, pdfThumbnailViewer: null, pdfRenderingQueue: null, pdfPresentationMode: null, pdfDocumentProperties: null, pdfLinkService: null, pdfHistory: null, pdfSidebar: null, pdfSidebarResizer: null, pdfOutlineViewer: null, pdfAttachmentViewer: null, pdfLayerViewer: null, pdfCursorTools: null, pdfScriptingManager: null, store: null, downloadManager: null, overlayManager: null, preferences: null, toolbar: null, secondaryToolbar: null, eventBus: null, l10n: null, annotationEditorParams: null, isInitialViewSet: false, downloadComplete: false, isViewerEmbedded: window.parent !== window, url: "", baseUrl: "", _downloadUrl: "", externalServices: DefaultExternalServices, _boundEvents: Object.create(null), documentInfo: null, metadata: null, _contentDispositionFilename: null, _contentLength: null, _saveInProgress: false, _wheelUnusedTicks: 0, _wheelUnusedFactor: 1, _touchUnusedTicks: 0, _touchUnusedFactor: 1, _PDFBug: null, _hasAnnotationEditors: false, _title: document.title, _printAnnotationStoragePromise: null, _touchInfo: null, _isCtrlKeyDown: false, async initialize(appConfig) { this.preferences = this.externalServices.createPreferences(); this.appConfig = appConfig; await this._initializeOptions(); this._forceCssTheme(); await this._initializeL10n(); if (this.isViewerEmbedded && _app_options.AppOptions.get("externalLinkTarget") === _pdf_link_service.LinkTarget.NONE) { _app_options.AppOptions.set("externalLinkTarget", _pdf_link_service.LinkTarget.TOP); } await this._initializeViewerComponents(); this.bindEvents(); this.bindWindowEvents(); const appContainer = appConfig.appContainer || document.documentElement; this.l10n.translate(appContainer).then(() => { this.eventBus.dispatch("localized", { source: this }); }); this._initializedCapability.resolve(); this.initializeLoadingBar(); }, async _initializeOptions() { if (_app_options.AppOptions.get("disablePreferences")) { if (_app_options.AppOptions.get("pdfBugEnabled")) { await this._parseHashParams(); } return; } if (_app_options.AppOptions._hasUserOptions()) { Window['ngxConsole'].warn("_initializeOptions: The Preferences may override manually set AppOptions; " + 'please use the "disablePreferences"-option in order to prevent that.'); } try { _app_options.AppOptions.setAll(await this.preferences.getAll()); } catch (reason) { Window['ngxConsole'].error(`_initializeOptions: "${reason?.message}".`); } if (_app_options.AppOptions.get("pdfBugEnabled")) { await this._parseHashParams(); } }, async _parseHashParams() { const hash = document.location.hash.substring(1); if (!hash) { return; } const { mainContainer, viewerContainer } = this.appConfig, params = (0, _ui_utils.parseQueryString)(hash); if (params.get("disableworker") === "true") { try { await loadFakeWorker(); } catch (ex) { console.error(`_parseHashParams: "${ex.message}".`); } } if (params.has("disablerange")) { _app_options.AppOptions.set("disableRange", params.get("disablerange") === "true"); } if (params.has("disablestream")) { _app_options.AppOptions.set("disableStream", params.get("disablestream") === "true"); } if (params.has("disableautofetch")) { _app_options.AppOptions.set("disableAutoFetch", params.get("disableautofetch") === "true"); } if (params.has("disablefontface")) { _app_options.AppOptions.set("disableFontFace", params.get("disablefontface") === "true"); } if (params.has("disablehistory")) { _app_options.AppOptions.set("disableHistory", params.get("disablehistory") === "true"); } if (params.has("verbosity")) { _app_options.AppOptions.set("verbosity", params.get("verbosity") | 0); } if (params.has("textlayer")) { switch (params.get("textlayer")) { case "off": _app_options.AppOptions.set("textLayerMode", _ui_utils.TextLayerMode.DISABLE); break; case "visible": case "shadow": case "hover": viewerContainer.classList.add(`textLayer-${params.get("textlayer")}`); try { await loadPDFBug(this); this._PDFBug.loadCSS(); } catch (ex) { console.error(`_parseHashParams: "${ex.message}".`); } break; } } if (params.has("pdfbug")) { _app_options.AppOptions.set("pdfBug", true); _app_options.AppOptions.set("fontExtraProperties", true); const enabled = params.get("pdfbug").split(","); try { await loadPDFBug(this); this._PDFBug.init({ OPS: _pdfjsLib.OPS }, mainContainer, enabled); } catch (ex) { console.error(`_parseHashParams: "${ex.message}".`); } } if (params.has("locale")) { _app_options.AppOptions.set("locale", params.get("locale")); } }, async _initializeL10n() { this.l10n = this.externalServices.createL10n({ locale: _app_options.AppOptions.get("locale") }); const dir = await this.l10n.getDirection(); document.getElementsByTagName("html")[0].dir = dir; }, _forceCssTheme() { const cssTheme = _app_options.AppOptions.get("viewerCssTheme"); if (cssTheme === ViewerCssTheme.AUTOMATIC || !Object.values(ViewerCssTheme).includes(cssTheme)) { return; } try { const styleSheet = document.styleSheets[0]; const cssRules = styleSheet?.cssRules || []; for (let i = 0, ii = cssRules.length; i < ii; i++) { const rule = cssRules[i]; if (rule instanceof CSSMediaRule && rule.media?.[0] === "(prefers-color-scheme: dark)") { if (cssTheme === ViewerCssTheme.LIGHT) { styleSheet.deleteRule(i); return; } const darkRules = /^@media \(prefers-color-scheme: dark\) {\n\s*([\w\s-.,:;/\\{}()]+)\n}$/.exec(rule.cssText); if (darkRules?.[1]) { styleSheet.deleteRule(i); styleSheet.insertRule(darkRules[1], i); } return; } } } catch (reason) { Window['ngxConsole'].error(`_forceCssTheme: "${reason?.message}".`); } }, async _initializeViewerComponents() { const { appConfig, externalServices } = this; const eventBus = externalServices.isInAutomation ? new _event_utils.AutomationEventBus() : new _event_utils.EventBus(); this.eventBus = eventBus; this.overlayManager = new _overlay_manager.OverlayManager(); const pdfRenderingQueue = new _pdf_rendering_queue.PDFRenderingQueue(); pdfRenderingQueue.onIdle = this._cleanup.bind(this); this.pdfRenderingQueue = pdfRenderingQueue; const pdfLinkService = new _pdf_link_service.PDFLinkService({ eventBus, externalLinkTarget: _app_options.AppOptions.get("externalLinkTarget"), externalLinkRel: _app_options.AppOptions.get("externalLinkRel"), ignoreDestinationZoom: _app_options.AppOptions.get("ignoreDestinationZoom") }); this.pdfLinkService = pdfLinkService; const downloadManager = externalServices.createDownloadManager(); this.downloadManager = downloadManager; const findController = new _pdf_find_controller.PDFFindController({ linkService: pdfLinkService, eventBus, pageViewMode: _app_options.AppOptions.get("pageViewMode"), updateMatchesCountOnProgress: true }); this.findController = findController; const pdfScriptingManager = new _pdf_scripting_manager.PDFScriptingManager({ eventBus, sandboxBundleSrc: _app_options.AppOptions.get("sandboxBundleSrc"), scriptingFactory: externalServices, docPropertiesLookup: this._scriptingDocProperties.bind(this) }); this.pdfScriptingManager = pdfScriptingManager; const container = appConfig.mainContainer, viewer = appConfig.viewerContainer; const annotationEditorMode = _app_options.AppOptions.get("annotationEditorMode"); const pageColors = _app_options.AppOptions.get("forcePageColors") || window.matchMedia("(forced-colors: active)").matches ? { background: _app_options.AppOptions.get("pageColorsBackground"), foreground: _app_options.AppOptions.get("pageColorsForeground") } : null; this.pdfViewer = new _pdf_viewer.PDFViewer({ container, viewer, eventBus, renderingQueue: pdfRenderingQueue, linkService: pdfLinkService, downloadManager, findController, scriptingManager: _app_options.AppOptions.get("enableScripting") && pdfScriptingManager, renderer: _app_options.AppOptions.get("renderer"), l10n: this.l10n, textLayerMode: _app_options.AppOptions.get("textLayerMode"), annotationMode: _app_options.AppOptions.get("annotationMode"), annotationEditorMode, imageResourcesPath: _app_options.AppOptions.get("imageResourcesPath"), removePageBorders: _app_options.AppOptions.get("removePageBorders"), enablePrintAutoRotate: _app_options.AppOptions.get("enablePrintAutoRotate"), useOnlyCssZoom: _app_options.AppOptions.get("useOnlyCssZoom"), isOffscreenCanvasSupported: _app_options.AppOptions.get("isOffscreenCanvasSupported"), maxCanvasPixels: _app_options.AppOptions.get("maxCanvasPixels"), pageViewMode: _app_options.AppOptions.get("pageViewMode"), enablePermissions: _app_options.AppOptions.get("enablePermissions"), pageColors }); pdfRenderingQueue.setViewer(this.pdfViewer); pdfLinkService.setViewer(this.pdfViewer); pdfScriptingManager.setViewer(this.pdfViewer); if (appConfig.sidebar?.thumbnailView) { this.pdfThumbnailViewer = new _webPdf_thumbnail_viewer.PDFThumbnailViewer({ container: appConfig.sidebar.thumbnailView, renderingQueue: pdfRenderingQueue, linkService: pdfLinkService, l10n: this.l10n, pageColors }); pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer); } if (!this.isViewerEmbedded && !_app_options.AppOptions.get("disableHistory")) { this.pdfHistory = new _pdf_history.PDFHistory({ linkService: pdfLinkService, eventBus }); pdfLinkService.setHistory(this.pdfHistory); } if (!this.supportsIntegratedFind && appConfig.findBar) { this.findBar = new _webPdf_find_bar.PDFFindBar(appConfig.findBar, eventBus, this.l10n); } if (appConfig.annotationEditorParams) { if (annotationEditorMode !== _pdfjsLib.AnnotationEditorType.DISABLE) { this.annotationEditorParams = new _webAnnotation_editor_params.AnnotationEditorParams(appConfig.annotationEditorParams, eventBus); } else { for (const id of ["editorModeButtons", "editorModeSeparator"]) { document.getElementById(id)?.classList.add("hidden"); } } } if (appConfig.documentProperties) { this.pdfDocumentProperties = new _webPdf_document_properties.PDFDocumentProperties(appConfig.documentProperties, this.overlayManager, eventBus, this.l10n, () => { return this._docFilename; }); } if (appConfig.secondaryToolbar?.cursorHandToolButton) { this.pdfCursorTools = new _webPdf_cursor_tools.PDFCursorTools({ container, eventBus, cursorToolOnLoad: _app_options.AppOptions.get("cursorToolOnLoad") }); } if (appConfig.toolbar) { this.toolbar = new _webToolbar.Toolbar(appConfig.toolbar, eventBus, this.l10n); } if (appConfig.secondaryToolbar) { this.secondaryToolbar = new _webSecondary_toolbar.SecondaryToolbar(appConfig.secondaryToolbar, eventBus, this.externalServices); } if (this.supportsFullscreen && appConfig.secondaryToolbar?.presentationModeButton) { this.pdfPresentationMode = new _webPdf_presentation_mode.PDFPresentationMode({ container, pdfViewer: this.pdfViewer, eventBus }); } let prompt = _app_options.AppOptions.get("passwordPrompt"); if (!prompt) { if (appConfig.passwordOverlay) { prompt = new _password_prompt.PasswordPrompt(appConfig.passwordOverlay, this.overlayManager, this.l10n, this.isViewerEmbedded); } } this.passwordPrompt = prompt; if (appConfig.sidebar?.outlineView) { this.pdfOutlineViewer = new _webPdf_outline_viewer.PDFOutlineViewer({ container: appConfig.sidebar.outlineView, eventBus, linkService: pdfLinkService, downloadManager }); } if (appConfig.sidebar?.attachmentsView) { this.pdfAttachmentViewer = new _webPdf_attachment_viewer.PDFAttachmentViewer({ container: appConfig.sidebar.attachmentsView, eventBus, downloadManager }); } if (appConfig.sidebar?.layersView) { this.pdfLayerViewer = new _webPdf_layer_viewer.PDFLayerViewer({ container: appConfig.sidebar.layersView, eventBus, l10n: this.l10n }); } if (appConfig.sidebar) { this.pdfSidebar = new _webPdf_sidebar.PDFSidebar({ elements: appConfig.sidebar, pdfViewer: this.pdfViewer, pdfThumbnailViewer: this.pdfThumbnailViewer, eventBus, l10n: this.l10n }); this.pdfSidebar.onToggled = this.forceRendering.bind(this); this.pdfSidebarResizer = new _webPdf_sidebar_resizer.PDFSidebarResizer(appConfig.sidebarResizer, eventBus, this.l10n); } }, run(config) { this.initialize(config).then(webViewerInitialized); }, get initialized() { return this._initializedCapability.settled; }, get initializedPromise() { return this._initializedCapability.promise; }, zoomIn(steps, scaleFactor) { if (this.pdfViewer.isInPresentationMode) { return; } this.pdfViewer.increaseScale({ drawingDelay: _app_options.AppOptions.get("defaultZoomDelay"), steps, scaleFactor }); }, zoomOut(steps, scaleFactor) { if (this.pdfViewer.isInPresentationMode) { return; } this.pdfViewer.decreaseScale({ drawingDelay: _app_options.AppOptions.get("defaultZoomDelay"), steps, scaleFactor }); }, zoomReset() { if (this.pdfViewer.isInPresentationMode) { return; } this.pdfViewer.currentScaleValue = _ui_utils.DEFAULT_SCALE_VALUE; }, get pagesCount() { return this.pdfDocument ? this.pdfDocument.numPages : 0; }, get page() { return this.pdfViewer.currentPageNumber; }, set page(val) { this.pdfViewer.currentPageNumber = val; }, get supportsPrinting() { return PDFPrintServiceFactory.instance.supportsPrinting; }, get supportsFullscreen() { return (0, _pdfjsLib.shadow)(this, "supportsFullscreen", document.fullscreenEnabled); }, get supportsPinchToZoom() { return this.externalServices.supportsPinchToZoom; }, get supportsIntegratedFind() { return this.externalServices.supportsIntegratedFind; }, get supportsDocumentFonts() { return this.externalServices.supportsDocumentFonts; }, initializeLoadingBar() { const barElement = document.getElementById("loadingBar"); const bar = barElement ? new _ui_utils.ProgressBar(barElement) : null; bar?.hide(); return (0, _pdfjsLib.shadow)(this, "loadingBar", bar); }, get supportedMouseWheelZoomModifierKeys() { return this.externalServices.supportedMouseWheelZoomModifierKeys; }, initPassiveLoading() { throw new Error("Not implemented: initPassiveLoading"); }, setTitleUsingUrl(url = "", downloadUrl = null) {}, setTitle(title = this._title) { this._title = title; if (this.isViewerEmbedded) { return; } const editorIndicator = this._hasAnnotationEditors && !this.pdfRenderingQueue.printing; document.title = `${editorIndicator ? "* " : ""}${title}`; }, get _docFilename() { return this._contentDispositionFilename || (0, _pdfjsLib.getPdfFilenameFromUrl)(this.url); }, _hideViewBookmark() { const { secondaryToolbar } = this.appConfig; secondaryToolbar?.viewBookmarkButton.classList.add("hidden"); if (secondaryToolbar?.presentationModeButton.classList.contains("hidden")) { document.getElementById("viewBookmarkSeparator")?.classList.add("hidden"); } }, async close() { this._unblockDocumentLoadEvent(); this._hideViewBookmark(); if (!this.pdfLoadingTask) { return; } if (this.pdfDocument?.annotationStorage.size > 0 && this._annotationStorageModified) { try { await this.save(); } catch (reason) {} } const promises = []; promises.push(this.pdfLoadingTask.destroy()); this.pdfLoadingTask = null; if (this.pdfDocument) { this.pdfDocument = null; this.pdfThumbnailViewer?.setDocument(null); this.pdfViewer.setDocument(null); this.pdfLinkService.setDocument(null); this.pdfDocumentProperties?.setDocument(null); } this.pdfLinkService.externalLinkEnabled = true; this.store = null; this.isInitialViewSet = false; this.downloadComplete = false; this.url = ""; this.baseUrl = ""; this._downloadUrl = ""; this.documentInfo = null; this.metadata = null; this._contentDispositionFilename = null; this._contentLength = null; this._saveInProgress = false; this._hasAnnotationEditors = false; promises.push(this.pdfScriptingManager.destroyPromise); this.setTitle(); this.pdfSidebar?.reset(); this.pdfOutlineViewer?.reset(); this.pdfAttachmentViewer?.reset(); this.pdfLayerViewer?.reset(); this.pdfHistory?.reset(); this.findBar?.reset(); this.toolbar?.reset(); this.secondaryToolbar?.reset(); this._PDFBug?.cleanup(); await Promise.all(promises); }, async open(args) { window.adjacentPagesLoader = undefined; window.ngxZone.runOutsideAngular(async () => { let deprecatedArgs = false; if (typeof args === "string") { args = { url: args }; deprecatedArgs = true; } else if (args?.byteLength) { args = { data: args }; deprecatedArgs = true; } if (deprecatedArgs) { console.error("The `PDFViewerApplication.open` signature was updated, please use an object instead."); } if (this.pdfLoadingTask) { await this.close(); } const workerParams = _app_options.AppOptions.getAll(_app_options.OptionKind.WORKER); Object.assign(_pdfjsLib.GlobalWorkerOptions, workerParams); if (args.url) { this.setTitleUsingUrl(args.originalUrl || args.url, args.url); } const apiParams = _app_options.AppOptions.getAll(_app_options.OptionKind.API); const params = { ...apiParams, ...args }; const loadingTask = (0, _pdfjsLib.getDocument)(params); this.pdfLoadingTask = loadingTask; loadingTask.onPassword = (updateCallback, reason) => { if (this.isViewerEmbedded) { this._unblockDocumentLoadEvent(); } this.pdfLinkService.externalLinkEnabled = false; this.passwordPrompt.setUpdateCallback(updateCallback, reason); this.passwordPrompt.open(); }; loadingTask.onProgress = ({ loaded, total }) => { this.progress(loaded / total); this.eventBus?.dispatch("progress", { source: this, type: "load", total, loaded, percent: 100 * loaded / total }); }; return loadingTask.promise.then(pdfDocument => { this.load(pdfDocument); }, reason => { if (loadingTask !== this.pdfLoadingTask) { return undefined; } let key = "loading_error"; if (reason instanceof _pdfjsLib.InvalidPDFException) { key = "invalid_file_error"; } else if (reason instanceof _pdfjsLib.MissingPDFException) { key = "missing_file_error"; } else if (reason instanceof _pdfjsLib.UnexpectedResponseException) { key = "unexpected_response_error"; } if (PDFViewerApplication.onError) { PDFViewerApplication.onError(reason); } return this.l10n.get(key).then(msg => { this._documentError(msg, { message: reason?.message }); throw reason; }); }); }); }, _ensureDownloadComplete() { if (this.pdfDocument && this.downloadComplete) { return; } throw new Error("PDF document not downloaded."); }, async download() { const url = this._downloadUrl, filename = this._docFilename; try { this._ensureDownloadComplete(); const data = await this.pdfDocument.getData(); const blob = new Blob([data], { type: "application/pdf" }); await this.downloadManager.download(blob, url, filename); } catch (reason) { await this.downloadManager.downloadUrl(url, filename); } }, async save() { if (this._saveInProgress) { return; } this._saveInProgress = true; await this.pdfScriptingManager.dispatchWillSave(); const url = this._downloadUrl, filename = this._docFilename; try { this._ensureDownloadComplete(); const data = await this.pdfDocument.saveDocument(); const blob = new Blob([data], { type: "application/pdf" }); await this.downloadManager.download(blob, url, filename); } catch (reason) { Window["ngxConsole"].error(`Error when saving the document: ${reason.message}`); await this.download(); } finally { await this.pdfScriptingManager.dispatchDidSave(); this._saveInProgress = false; } if (this._hasAnnotationEditors) { this.externalServices.reportTelemetry({ type: "editing", data: { type: "save" } }); } }, downloadOrSave() { if (this.pdfDocument?.annotationStorage.size > 0) { this.save(); } else { this.download(); } }, _documentError(message, moreInfo = null) { this._unblockDocumentLoadEvent(); this._otherError(message, moreInfo); this.eventBus.dispatch("documenterror", { source: this, message, reason: moreInfo?.message ?? null }); }, _otherError(message, moreInfo = null) { const moreInfoText = [`PDF.js v${_pdfjsLib.version || "?"} (build: ${_pdfjsLib.build || "?"})`]; if (moreInfo) { moreInfoText.push(`Message: ${moreInfo.message}`); if (moreInfo.stack) { moreInfoText.push(`Stack: ${moreInfo.stack}`); } else { if (moreInfo.filename) { moreInfoText.push(`File: ${moreInfo.filename}`); } if (moreInfo.lineNumber) { moreInfoText.push(`Line: ${moreInfo.lineNumber}`); } } } console.error(`${message}\n\n${moreInfoText.join("\n")}`); }, progress(level) { if (!this.loadingBar || this.downloadComplete) { return; } const percent = Math.round(level * 100); if (percent <= this.loadingBar.percent) { return; } this.loadingBar.percent = percent; if (this.pdfDocument?.loadingParams.disableAutoFetch ?? _app_options.AppOptions.get("disableAutoFetch")) { this.loadingBar.setDisableAutoFetch(); } }, load(pdfDocument) { this.pdfDocument = pdfDocument; pdfDocument.getDownloadInfo().then(({ length }) => { this._contentLength = length; this.downloadComplete = true; this.loadingBar?.hide(); firstPagePromise.then(() => { this.eventBus?.dispatch("documentloaded", { source: this }); }); }); const pageLayoutPromise = pdfDocument.getPageLayout().catch(function () {}); const pageModePromise = pdfDocument.getPageMode().catch(function () {}); const openActionPromise = pdfDocument.getOpenAction().catch(function () {}); this.toolbar?.setPagesCount(pdfDocument.numPages, false); this.secondaryToolbar?.setPagesCount(pdfDocument.numPages); let baseDocumentUrl; baseDocumentUrl = null; if (baseDocumentUrl && (0, _pdfjsLib.isDataScheme)(baseDocumentUrl)) { baseDocumentUrl = null; } this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl); this.pdfDocumentProperties?.setDocument(pdfDocument); const pdfViewer = this.pdfViewer; pdfViewer.setDocument(pdfDocument); const { firstPagePromise, onePageRendered, pagesPromise } = pdfViewer; this.pdfThumbnailViewer?.setDocument(pdfDocument); const storedPromise = (this.store = new _view_history.ViewHistory(pdfDocument.fingerprints[0])).getMultiple({ page: null, zoom: _ui_utils.DEFAULT_SCALE_VALUE, scrollLeft: "0", scrollTop: "0", rotation: null, sidebarView: _ui_utils.SidebarView.UNKNOWN, scrollMode: _ui_utils.ScrollMode.UNKNOWN, spreadMode: _ui_utils.SpreadMode.UNKNOWN }).catch(() => { return Object.create(null); }); firstPagePromise.then(pdfPage => { this.loadingBar?.setWidth(this.appConfig.viewerContainer); this._initializeAnnotationStorageCallbacks(pdfDocument); Promise.all([_ui_utils.animationStarted, storedPromise, pageLayoutPromise, pageModePromise, openActionPromise]).then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => { const viewOnLoad = _app_options.AppOptions.get("viewOnLoad"); this._initializePdfHistory({ fingerprint: pdfDocument.fingerprints[0], viewOnLoad, initialDest: openAction?.dest }); const initialBookmark = this.initialBookmark; const zoom = _app_options.AppOptions.get("defaultZoomValue"); let hash = zoom ? `zoom=${zoom}` : null; let rotation = null; let sidebarView = _app_options.AppOptions.get("sidebarViewOnLoad"); let scrollMode = _app_options.AppOptions.get("scrollModeOnLoad"); let spreadMode = _app_options.AppOptions.get("spreadModeOnLoad"); if (stored.page && viewOnLoad !== ViewOnLoad.INITIAL) { hash = `page=${stored.page}&zoom=${zoom || stored.zoom},` + `${stored.scrollLeft},${stored.scrollTop}`; rotation = parseInt(stored.rotation, 10); if (sidebarView === _ui_utils.SidebarView.UNKNOWN) { sidebarView = stored.sidebarView | 0; } if (scrollMode === _ui_utils.ScrollMode.UNKNOWN) { scrollMode = stored.scrollMode | 0; } if (spreadMode === _ui_utils.SpreadMode.UNKNOWN) { spreadMode = stored.spreadMode | 0; } } if (pageMode && sidebarView === _ui_utils.SidebarView.UNKNOWN) { sidebarView = (0, _ui_utils.apiPageModeToSidebarView)(pageMode); } if (pageLayout && scrollMode === _ui_utils.ScrollMode.UNKNOWN && spreadMode === _ui_utils.SpreadMode.UNKNOWN) { const modes = (0, _ui_utils.apiPageLayoutToViewerModes)(pageLayout); spreadMode = modes.spreadMode; } this.setInitialView(hash, { rotation, sidebarView, scrollMode, spreadMode }); this.eventBus.dispatch("documentinit", { source: this }); if (!this.isViewerEmbedded) { pdfViewer.focus(); } await Promise.race([pagesPromise, new Promise(resolve => { setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT); })]); if (!initialBookmark && !hash) { return; } if (pdfViewer.hasEqualPageSizes) { return; } this.initialBookmark = initialBookmark; pdfViewer.currentScaleValue = pdfViewer.currentScaleValue; this.setInitialView(hash); }).catch(() => { this.setInitialView(); }).then(function () { pdfViewer.update(); }); }); pagesPromise.then(() => { this._unblockDocumentLoadEvent(); this._initializeAutoPrint(pdfDocument, openActionPromise); }, reason => { if (PDFViewerApplication.onError) { PDFViewerApplication.onError(reason); } this.l10n.get("loading_error").then(msg => { this._documentError(msg, { message: reason?.message }); }); }); onePageRendered.then(data => { this.externalServices.reportTelemetry({ type: "pageInfo", timestamp: data.timestamp }); if (this.pdfOutlineViewer) { pdfDocument.getOutline().then(outline => { if (pdfDocument !== this.pdfDocument) { return; } this.pdfOutlineViewer.render({ outline, pdfDocument }); }); } if (this.pdfAttachmentViewer) { pdfDocument.getAttachments().then(attachments => { if (pdfDocument !== this.pdfDocument) { return; } this.pdfAttachmentViewer.render({ attachments }); }); } if (this.pdfLayerViewer) { pdfViewer.optionalContentConfigPromise.then(optionalContentConfig => { if (pdfDocument !== this.pdfDocument) { return; } this.pdfLayerViewer.render({ optionalContentConfig, pdfDocument }); }); } }); this._initializePageLabels(pdfDocument); this._initializeMetadata(pdfDocument); }, async _scriptingDocProperties(pdfDocument) { if (!this.documentInfo) { await new Promise(resolve => { this.eventBus._on("metadataloaded", resolve, { once: true }); }); if (pdfDocument !== this.pdfDocument) { return null; } } if (!this._contentLength) { await new Promise(resolve => { this.eventBus._on("documentloaded", resolve, { once: true }); }); if (pdfDocument !== this.pdfDocument) { return null; } } return { ...this.documentInfo, baseURL: this.baseUrl, filesize: this._contentLength, filename: this._docFilename, metadata: this.metadata?.getRaw(), authors: this.metadata?.get("dc:creator"), numPages: this.pagesCount, URL: this.url }; }, async _initializeAutoPrint(pdfDocument, openActionPromise) { const [openAction, javaScript] = await Promise.all([openActionPromise, !this.pdfViewer.enableScripting ? pdfDocument.getJavaScript() : null]); if (pdfDocument !== this.pdfDocument) { return; } let triggerAutoPrint = false; if (openAction?.action === "Print") { triggerAutoPrint = true; } if (javaScript) { javaScript.some(js => { if (!js) { return false; } Window['ngxConsole'].warn("Warning: JavaScript support is not enabled"); return true; }); if (!triggerAutoPrint) { for (const js of javaScript) { if (js && _ui_utils.AutoPrintRegExp.test(js)) { triggerAutoPrint = true; break; } } } } if (triggerAutoPrint) { this.triggerPrinting(); } }, async _initializeMetadata(pdfDocument) { const { info, metadata, contentDispositionFilename, contentLength } = await pdfDocument.getMetadata(); if (pdfDocument !== this.pdfDocument) { return; } this.documentInfo = info; this.metadata = metadata; this._contentDispositionFilename ??= contentDispositionFilename; this._contentLength ??= contentLength; console.log(`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` + `${(info.Producer || "-").trim()} / ${(info.Creator || "-").trim()}] ` + `(PDF.js: ${_pdfjsLib.version || "?"} [${_pdfjsLib.build || "?"}]) modified by ngx-extended-pdf-viewer`); let pdfTitle = info.Title; const metadataTitle = metadata?.get("dc:title"); if (metadataTitle) { if (metadataTitle !== "Untitled" && !/[\uFFF0-\uFFFF]/g.test(metadataTitle)) { pdfTitle = metadataTitle; } } if (pdfTitle) { this.setTitle(`${pdfTitle} - ${this._contentDispositionFilename || this._title}`); } else if (this._contentDispositionFilename) { this.setTitle(this._contentDispositionFilename); } if (info.IsXFAPresent && !info.IsAcroFormPresent && !pdfDocument.isPureXfa) { if (pdfDocument.loadingParams.enableXfa) { Window['ngxConsole'].warn("Warning: XFA Foreground documents are not supported"); } else { Window['ngxConsole'].warn("Warning: XFA support is not enabled"); } } else if ((info.IsAcroFormPresent || info.IsXFAPresent) && !this.pdfViewer.renderForms) { console.warn("Warning: Interactive form support is not enabled"); } if (info.IsSignaturesPresent) { console.warn("Warning: Digital signatures validation is not supported"); } this.eventBus.dispatch("metadataloaded", { source: this }); }, async _initializePageLabels(pdfDocument) { const labels = await pdfDocument.getPageLabels(); if (pdfDocument !== this.pdfDocument) { return; } if (!labels || _app_options.AppOptions.get("disablePageLabels")) { return; } const numLabels = labels.length; let standardLabels = 0, emptyLabels = 0; for (let i = 0; i < numLabels; i++) { const label = labels[i]; if (label === (i + 1).toString()) { standardLabels++; } else if (label === "") { emptyLabels++; } else { break; } } if (standardLabels >= numLabels || emptyLabels >= numLabels) { return; } const { pdfViewer, pdfThumbnailViewer, toolbar } = this; pdfViewer.setPageLabels(labels); pdfThumbnailViewer?.setPageLabels(labels); toolbar?.setPagesCount(numLabels, true); toolbar?.setPageNumber(pdfViewer.currentPageNumber, pdfViewer.currentPageLabel); }, _initializePdfHistory({ fingerprint, viewOnLoad, initialDest = null }) { if (!this.pdfHistory) { return; } this.pdfHistory.initialize({ fingerprint, resetHistory: viewOnLoad === ViewOnLoad.INITIAL, updateUrl: _app_options.AppOptions.get("historyUpdateUrl") }); if (this.pdfHistory.initialBookmark) { this.initialBookmark = this.pdfHistory.initialBookmark; this.initialRotation = this.pdfHistory.initialRotation; } if (initialDest && !this.initialBookmark && viewOnLoad === ViewOnLoad.UNKNOWN) { this.initialBookmark = JSON.stringify(initialDest); this.pdfHistory.push({ explicitDest: initialDest, pageNumber: null }); } }, _initializeAnnotationStorageCallbacks(pdfDocument) { if (pdfDocument !== this.pdfDocument) { return; } const { annotationStorage } = pdfDocument; annotationStorage.onSetModified = () => { window.addEventListener("beforeunload", beforeUnload); this._annotationStorageModified = true; }; annotationStorage.onResetModified = () => { window.removeEventListener("beforeunload", beforeUnload); delete this._annotationStorageModified; }; annotationStorage.onAnnotationEditor = typeStr => { this._hasAnnotationEditors = !!typeStr; this.setTitle(); if (typeStr) { this.externalServices.reportTelemetry({ type: "editing", data: { type: typeStr } }); } }; }, setInitialView(storedHash, { rotation, sidebarView, scrollMode, spreadMode } = {}) { const setRotation = angle => { if ((0, _ui_utils.isValidRotation)(angle)) { this.pdfViewer.pagesRotation = angle; } }; const setViewerModes = (scroll, spread) => { if ((0, _ui_utils.isValidScrollMode)(scroll)) { this.pdfViewer.scrollMode = scroll; } if ((0, _ui_utils.isValidSpreadMode)(spread)) { this.pdfViewer.spreadMode = spread; } }; this.isInitialViewSet = true; this.pdfSidebar?.setInitialView(sidebarView); setViewerModes(scrollMode, spreadMode); if (this.initialBookmark) { setRotation(this.initialRotation); delete this.initialRotation; this.pdfLinkService.setHash(this.initialBookmark); this.initialBookmark = null; } else if (storedHash) { setRotation(rotation); this.pdfLinkService.setHash(storedHash); } this.toolbar?.setPageNumber(this.pdfViewer.currentPageNumber, this.pdfViewer.currentPageLabel); this.secondaryToolbar?.setPageNumber(this.pdfViewer.currentPageNumber); if (!this.pdfViewer.currentScaleValue) { const defaultZoomOption = PDFViewerApplicationOptions.get('defaultZoomValue'); if (defaultZoomOption) { this.pdfViewer.currentScaleValue = defaultZoomOption; } } }, _cleanup() { if (!this.pdfDocument) { return; } this.pdfViewer.cleanup(); this.pdfThumbnailViewer?.cleanup(); this.pdfDocument.cleanup(this.pdfViewer.renderer === _ui_utils.RendererType.SVG); }, forceRendering() { this.pdfRenderingQueue.printing = !!this.printService; this.pdfRenderingQueue.isThumbnailViewEnabled = this.pdfSidebar?.visibleView === _ui_utils.SidebarView.THUMBS; this.pdfRenderingQueue.renderHighestPriority(); }, beforePrint() { this._printAnnotationStoragePromise = this.pdfScriptingManager.dispatchWillPrint().catch(() => {}).then(() => { return this.pdfDocument?.annotationStorage.print; }); if (this.printService) { return; } if (!this.supportsPrinting) { this.l10n.get("printing_not_supported").then(msg => { this._otherError(msg); }); return; } if (!this.pdfViewer.pageViewsReady) { this.l10n.get("printing_not_ready").then(msg => { window.alert(msg); }); return; } const pagesOverview = this.pdfViewer.getPagesOverview(); const printContainer = this.appConfig.printContainer; const printResolution = _app_options.AppOptions.get("printResolution"); const optionalContentConfigPromise = this.pdfViewer.optionalContentConfigPromise; const printService = PDFPrintServiceFactory.instance.createPrintService(this.pdfDocument, pagesOverview, printContainer, printResolution, optionalContentConfigPromise, this._printAnnotationStoragePromise, this.l10n, this.pdfViewer.eventBus); this.printService = printService; this.forceRendering(); this.setTitle(); printService.layout(); if (this._hasAnnotationEditors) { this.externalServices.reportTelemetry({ type: "editing", data: { type: "print" } }); } }, afterPrint() { if (this._printAnnotationStoragePromise) { this._printAnnotationStoragePromise.then(() => { this.pdfScriptingManager.dispatchDidPrint(); }); this._printAnnotationStoragePromise = null; } if (this.printService) { this.printService.destroy(); this.printService = null; this.pdfDocument?.annotationStorage.resetModified(); } this.forceRendering(); this.setTitle(); }, rotatePages(delta) { this.pdfViewer.pagesRotation += delta; }, requestPresentationMode() { this.pdfPresentationMode?.request(); }, triggerPrinting() { if (!this.supportsPrinting) { return; } window.printPDF(); }, bindEvents() { const { eventBus, _boundEvents } = this; _boundEvents.beforePrint = this.beforePrint.bind(this); _boundEvents.afterPrint = this.afterPrint.bind(this); eventBus._on("resize", webViewerResize); eventBus._on("hashchange", webViewerHashchange); eventBus._on("beforeprint", _boundEvents.beforePrint); eventBus._on("afterprint", _boundEvents.afterPrint); eventBus._on("pagerender", webViewerPageRender); eventBus._on("pagerendered", webViewerPageRendered); eventBus._on("updateviewarea", webViewerUpdateViewarea); eventBus._on("pagechanging", webViewerPageChanging); eventBus._on("scalechanging", webViewerScaleChanging); eventBus._on("rotationchanging", webViewerRotationChanging); eventBus._on("sidebarviewchanged", webViewerSidebarViewChanged); eventBus._on("pagemode", webViewerPageMode); eventBus._on("namedaction", webViewerNamedAction); eventBus._on("presentationmodechanged", webViewerPresentationModeChanged); eventBus._on("presentationmode", webViewerPresentationMode); eventBus._on("switchannotationeditormode", webViewerSwitchAnnotationEditorMode); eventBus._on("switchannotationeditorparams", webViewerSwitchAnnotationEditorParams); eventBus._on("print", webViewerPrint); eventBus._on("download", webViewerDownload); eventBus._on("firstpage", webViewerFirstPage); eventBus._on("lastpage", webViewerLastPage); eventBus._on("nextpage", webViewerNextPage); eventBus._on("previouspage", webViewerPreviousPage); eventBus._on("zoomin", webViewerZoomIn); eventBus._on("zoomout", webViewerZoomOut); eventBus._on("zoomreset", webViewerZoomReset); eventBus._on("pagenumberchanged", webViewerPageNumberChanged); eventBus._on("scalechanged", webViewerScaleChanged); eventBus._on("rotatecw", webViewerRotateCw); eventBus._on("rotateccw", webViewerRotateCcw); eventBus._on("optionalcontentconfig", webViewerOptionalContentConfig); eventBus._on("switchscrollmode", webViewerSwitchScrollMode); eventBus._on("scrollmodechanged", webViewerScrollModeChanged); eventBus._on("switchspreadmode", webViewerSwitchSpreadMode); eventBus._on("spreadmodechanged", webViewerSpreadModeChanged); eventBus._on("documentproperties", webViewerDocumentProperties); eventBus._on("findfromurlhash", webViewerFindFromUrlHash); eventBus._on("updatefindmatchescount", webViewerUpdateFindMatchesCount); eventBus._on("updatefindcontrolstate", webViewerUpdateFindControlState); if (_app_options.AppOptions.get("pdfBug")) { _boundEvents.reportPageStatsPDFBug = reportPageStatsPDFBug; eventBus._on("pagerendered", _boundEvents.reportPageStatsPDFBug); eventBus._on("pagechanging", _boundEvents.reportPageStatsPDFBug); } eventBus._on("fileinputchange", webViewerFileInputChange); eventBus._on("openfile", webViewerOpenFile); }, bindWindowEvents() { const { eventBus, _boundEvents } = this; function addWindowResolutionChange(evt = null) { if (evt) { webViewerResolutionChange(evt); } const mediaQueryList = window.matchMedia(`(resolution: ${window.devicePixelRatio || 1}dppx)`); mediaQueryList.addEventListener("change", addWindowResolutionChange, { once: true }); _boundEvents.removeWindowResolutionChange ||= function () { mediaQueryList.removeEventListener("change", addWindowResolutionChange); _boundEvents.removeWindowResolutionChange = null; }; } addWindowResolutionChange(); _boundEvents.windowResize = () => { eventBus.dispatch("resize", { source: window }); }; _boundEvents.windowHashChange = () => { eventBus.dispatch("hashchange", { source: window, hash: document.location.hash.substring(1) }); }; _boundEvents.windowBeforePrint = () => { eventBus.dispatch("beforeprint", { source: window }); }; _boundEvents.windowAfterPrint = () => { eventBus.dispatch("afterprint", { source: window }); }; _boundEvents.windowUpdateFromSandbox = event => { eventBus.dispatch("updatefromsandbox", { source: window, detail: event.detail }); }; window.addEventListener("visibilitychange", webViewerVisibilityChange); window.addEventListener("wheel", webViewerWheel, { passive: false }); window.addEventListener("touchstart", webViewerTouchStart, { passive: false