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.

749 lines 112 kB
import { effect, Injectable } from '@angular/core'; import { AnnotationEditorParamsType, AnnotationMode } from './options/editor-annotations'; import * as i0 from "@angular/core"; import * as i1 from "./pdf-notification-service"; export class NgxExtendedPdfViewerService { rendererFactory; ngxExtendedPdfViewerInitialized = false; secondaryMenuIsEmpty = false; renderer; PDFViewerApplication; constructor(rendererFactory, notificationService) { this.rendererFactory = rendererFactory; this.renderer = this.rendererFactory.createRenderer(null, null); effect(() => { this.PDFViewerApplication = notificationService.onPDFJSInitSignal(); }); } find(text, options = {}) { if (!this.ngxExtendedPdfViewerInitialized) { // tslint:disable-next-line:quotemark console.error("The PDF viewer hasn't finished initializing. Please call find() later."); return undefined; } else { if (!options.useSecondaryFindcontroller) { const highlightAllCheckbox = document.getElementById('findHighlightAll'); if (highlightAllCheckbox) { highlightAllCheckbox.checked = options.highlightAll ?? false; } const matchCaseCheckbox = document.getElementById('findMatchCase'); if (matchCaseCheckbox) { matchCaseCheckbox.checked = options.matchCase ?? false; } const findMultipleCheckbox = document.getElementById('findMultiple'); if (findMultipleCheckbox) { findMultipleCheckbox.checked = options.findMultiple ?? false; } const entireWordCheckbox = document.getElementById('findEntireWord'); if (entireWordCheckbox) { entireWordCheckbox.checked = options.wholeWords ?? false; } const matchDiacriticsCheckbox = document.getElementById('findMatchDiacritics'); if (matchDiacriticsCheckbox) { matchDiacriticsCheckbox.checked = options.matchDiacritics ?? false; } const matchRegExpCheckbox = document.getElementById('matchRegExp'); if (matchRegExpCheckbox) { matchRegExpCheckbox.checked = options.regexp ?? false; if (matchRegExpCheckbox.checked) { if (findMultipleCheckbox) { findMultipleCheckbox.checked = false; } if (entireWordCheckbox) { entireWordCheckbox.checked = false; } if (matchDiacriticsCheckbox) { matchDiacriticsCheckbox.checked = false; } } if (findMultipleCheckbox) { findMultipleCheckbox.disabled = matchRegExpCheckbox.checked; } if (entireWordCheckbox) { entireWordCheckbox.disabled = matchRegExpCheckbox.checked; } if (matchDiacriticsCheckbox) { matchDiacriticsCheckbox.disabled = matchRegExpCheckbox.checked; } } const inputField = document.getElementById('findInput'); if (inputField && typeof text === 'string') { inputField.value = text; } } const findParameters = { caseSensitive: options.matchCase ?? false, entireWord: options.wholeWords ?? false, highlightAll: options.highlightAll ?? false, matchDiacritics: options.matchDiacritics ?? false, findMultiple: options.findMultiple, matchRegExp: options.regexp ?? false, findPrevious: false, query: text, source: null, type: 'find', dontScrollIntoView: options.dontScrollIntoView ?? false, }; const findController = options.useSecondaryFindcontroller ? this.PDFViewerApplication?.customFindController : this.PDFViewerApplication?.findController; const result = findController?.ngxFind(findParameters); return result; } } findNext(useSecondaryFindcontroller = false) { if (!this.ngxExtendedPdfViewerInitialized) { // tslint:disable-next-line:quotemark console.error("The PDF viewer hasn't finished initializing. Please call findNext() later."); return false; } else { const findController = useSecondaryFindcontroller ? this.PDFViewerApplication?.customFindController : this.PDFViewerApplication?.findController; findController?.ngxFindNext(); return true; } } findPrevious(useSecondaryFindcontroller = false) { if (!this.ngxExtendedPdfViewerInitialized) { // tslint:disable-next-line:quotemark console.error("The PDF viewer hasn't finished initializing. Please call findPrevious() later."); return false; } else { const findController = useSecondaryFindcontroller ? this.PDFViewerApplication?.customFindController : this.PDFViewerApplication?.findController; findController?.ngxFindPrevious(); return true; } } print(printRange) { if (this.PDFViewerApplication) { const alreadyPrinting = this.PDFViewerApplication?.PDFPrintServiceFactory?.isInPDFPrintRange !== undefined; if (!alreadyPrinting) { // slow down hurried users clicking the print button multiple times if (!printRange) { printRange = {}; } this.setPrintRange(printRange); this.PDFViewerApplication?.printPdf(); this.PDFViewerApplication?.eventBus.on('afterprint', this.removePrintRange.bind(this), { once: true }); } } } removePrintRange() { if (this.PDFViewerApplication?.PDFPrintServiceFactory) { delete this.PDFViewerApplication.PDFPrintServiceFactory.isInPDFPrintRange; delete this.PDFViewerApplication.PDFPrintServiceFactory.filteredPageCount; } } setPrintRange(printRange) { if (!this.PDFViewerApplication?.PDFPrintServiceFactory) { console.error("The print service hasn't been initialized yet."); return; } this.PDFViewerApplication.PDFPrintServiceFactory.isInPDFPrintRange = (page) => this.isInPDFPrintRange(page, printRange); this.PDFViewerApplication.PDFPrintServiceFactory.filteredPageCount = this.filteredPageCount(this.PDFViewerApplication?.pagesCount, printRange); } filteredPageCount(pageCount, range) { let result = 0; for (let page = 0; page < pageCount; page++) { if (this.isInPDFPrintRange(page, range)) { result++; } } return result; } isInPDFPrintRange(pageIndex, printRange) { const page = pageIndex + 1; if (printRange.from) { if (page < printRange.from) { return false; } } if (printRange.to) { if (page > printRange.to) { return false; } } if (printRange.excluded) { if (printRange.excluded.some((p) => p === page)) { return false; } } if (printRange.included) { if (!printRange.included.some((p) => p === page)) { return false; } } return true; } async getPageAsLines(pageNumber) { if (this.PDFViewerApplication) { const pdfDocument = this.PDFViewerApplication?.pdfDocument; const page = await pdfDocument.getPage(pageNumber); const textSnippets = (await page.getTextContent()).items // .filter((info) => !info['type']); // ignore the TextMarkedContent items const snippets = textSnippets; let minX = Number.MAX_SAFE_INTEGER; let minY = Number.MAX_SAFE_INTEGER; let maxX = Number.MIN_SAFE_INTEGER; let maxY = Number.MIN_SAFE_INTEGER; let countLTR = 0; let countRTL = 0; let text = ''; let lines = new Array(); for (let i = 0; i < snippets.length; i++) { const currentSnippet = snippets[i]; // #3065 modified by ngx-extended-pdf-viewer // Always process the current snippet's text and bounds, regardless of hasEOL const x = currentSnippet.transform[4]; const y = -currentSnippet.transform[5]; const width = currentSnippet.width; const height = currentSnippet.height; minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x + width); maxY = Math.max(maxY, y + height); text += currentSnippet.str; if (currentSnippet.dir === 'rtl') { countRTL++; } if (currentSnippet.dir === 'ltr') { countLTR++; } // #3065 end of modification by ngx-extended-pdf-viewer let addIt = i === snippets.length - 1 || currentSnippet.hasEOL; if (addIt) { let direction = undefined; if (countLTR > 0 && countRTL > 0) { direction = 'both'; } else if (countLTR > 0) { direction = 'ltr'; } else if (countRTL > 0) { direction = 'rtl'; } const line = { direction, x: minX, y: minY, width: maxX - minX, height: maxY - minY, text: text.trim(), }; lines.push(line); minX = Number.MAX_SAFE_INTEGER; minY = Number.MAX_SAFE_INTEGER; maxX = Number.MIN_SAFE_INTEGER; maxY = Number.MIN_SAFE_INTEGER; countLTR = 0; countRTL = 0; text = ''; } } return lines; } return []; } async getPageAsText(pageNumber) { if (!this.PDFViewerApplication) { return ''; } const pdfDocument = this.PDFViewerApplication?.pdfDocument; const page = await pdfDocument.getPage(pageNumber); const textSnippets = (await page.getTextContent()).items; return this.convertTextInfoToText(textSnippets); } convertTextInfoToText(textInfoItems) { if (!textInfoItems) { return ''; } return textInfoItems .filter((info) => !info['type']) .map((info) => (info.hasEOL ? info.str + '\n' : info.str)) .join(''); } async getPageAsCanvas(pageNumber, scale, background, backgroundColorToReplace = '#FFFFFF', annotationMode = AnnotationMode.ENABLE) { if (!this.PDFViewerApplication) { return Promise.resolve(undefined); } const pdfDocument = this.PDFViewerApplication.pdfDocument; const pdfPage = await pdfDocument.getPage(pageNumber); return this.draw(pdfPage, scale, background, backgroundColorToReplace, annotationMode); } async getPageAsImage(pageNumber, scale, background, backgroundColorToReplace = '#FFFFFF', annotationMode = AnnotationMode.ENABLE) { const canvas = await this.getPageAsCanvas(pageNumber, scale, background, backgroundColorToReplace, annotationMode); return canvas?.toDataURL(); } async draw(pdfPage, scale, background, backgroundColorToReplace = '#FFFFFF', annotationMode = AnnotationMode.ENABLE) { let zoomFactor = 1; if (scale.scale) { zoomFactor = scale.scale; } else if (scale.width) { zoomFactor = scale.width / pdfPage.getViewport({ scale: 1 }).width; } else if (scale.height) { zoomFactor = scale.height / pdfPage.getViewport({ scale: 1 }).height; } const viewport = pdfPage.getViewport({ scale: zoomFactor, }); const { ctx, canvas } = this.getPageDrawContext(viewport.width, viewport.height); const drawViewport = viewport.clone(); const renderContext = { canvasContext: ctx, viewport: drawViewport, background, backgroundColorToReplace, annotationMode, }; const renderTask = pdfPage.render(renderContext); const dataUrlPromise = () => Promise.resolve(canvas); return renderTask.promise.then(dataUrlPromise); } getPageDrawContext(width, height) { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d', { alpha: true }); if (!ctx) { // tslint:disable-next-line: quotemark throw new Error("Couldn't create the 2d context"); } canvas.width = width; canvas.height = height; this.renderer.setStyle(canvas, 'width', `${width}px`); this.renderer.setStyle(canvas, 'height', `${height}px`); return { ctx, canvas }; } async getCurrentDocumentAsBlob() { return (await this.PDFViewerApplication?.export()) || undefined; } async getFormData(currentFormValues = true) { if (!this.PDFViewerApplication) { return []; } const pdf = this.PDFViewerApplication?.pdfDocument; // screen DPI / PDF DPI const dpiRatio = 96 / 72; const result = []; for (let i = 1; i <= pdf?.numPages; i++) { // track the current page const currentPage /* : PDFPageProxy */ = await pdf.getPage(i); const annotations = await currentPage.getAnnotations(); annotations .filter((a) => a.subtype === 'Widget') // get the form field annotations only .map((a) => ({ ...a })) // only expose copies of the annotations to avoid side-effects .forEach((a) => { // get the rectangle that represent the single field // and resize it according to the current DPI const fieldRect = currentPage.getViewport({ scale: dpiRatio }).convertToViewportRectangle(a.rect); // add the corresponding input if (currentFormValues && a.fieldName) { try { if (a.exportValue) { const currentValue = this.PDFViewerApplication?.pdfDocument.annotationStorage.getValue(a.id, a.fieldName + '/' + a.exportValue, ''); a.value = currentValue?.value; } else if (a.radioButton) { const currentValue = this.PDFViewerApplication?.pdfDocument.annotationStorage.getValue(a.id, a.fieldName + '/' + a.fieldValue, ''); a.value = currentValue?.value; } else { const currentValue = this.PDFViewerApplication?.pdfDocument.annotationStorage.getValue(a.id, a.fieldName, ''); a.value = currentValue?.value; } } catch (exception) { // just ignore it } } result.push({ fieldAnnotation: a, fieldRect, pageNumber: i }); }); } return result; } /** * Adds a page to the rendering queue * @param {number} pageIndex Index of the page to render * @returns {boolean} false, if the page has already been rendered, * if it's out of range or if the viewer hasn't been initialized yet */ addPageToRenderQueue(pageIndex) { return this.PDFViewerApplication?.pdfViewer.addPageToRenderQueue(pageIndex) ?? false; } isRenderQueueEmpty() { const scrolledDown = true; const renderExtra = false; if (this.PDFViewerApplication) { const nextPage = this.PDFViewerApplication.pdfViewer.renderingQueue.getHighestPriority(this.PDFViewerApplication?.pdfViewer._getVisiblePages(), this.PDFViewerApplication?.pdfViewer._pages, scrolledDown, renderExtra); return !nextPage; } return true; } hasPageBeenRendered(pageIndex) { if (!this.PDFViewerApplication) { return false; } const pages = this.PDFViewerApplication?.pdfViewer._pages; if (pages.length > pageIndex && pageIndex >= 0) { const pageView = pages[pageIndex]; const hasBeenRendered = pageView.renderingState === 3; return hasBeenRendered; } return false; } sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async renderPage(pageIndex) { if (!this.hasPageBeenRendered(pageIndex)) { await this.addPageToRenderQueue(pageIndex); while (!this.hasPageBeenRendered(pageIndex)) { await this.sleep(7); } } } currentlyRenderedPages() { if (!this.PDFViewerApplication) { return []; } const pages = this.PDFViewerApplication?.pdfViewer._pages; return pages.filter((page) => page.renderingState === 3).map((page) => page.id); } numberOfPages() { if (!this.PDFViewerApplication) { return 0; } const pages = this.PDFViewerApplication?.pdfViewer._pages; return pages.length; } getCurrentlyVisiblePageNumbers() { const app = this.PDFViewerApplication; if (!app) { return []; } const pages = app.pdfViewer._getVisiblePages().views; return pages?.map((page) => page.id); } async listLayers() { if (!this.PDFViewerApplication) { return []; } const optionalContentConfig = await this.PDFViewerApplication?.pdfViewer.optionalContentConfigPromise; if (optionalContentConfig) { const levelData = optionalContentConfig.getOrder(); const layerIds = levelData.filter((groupId) => typeof groupId !== 'object'); return layerIds.map((layerId) => { const config = optionalContentConfig.getGroup(layerId); return { layerId: layerId, name: config.name, visible: config.visible, }; }); } return undefined; } async toggleLayer(layerId) { if (!this.PDFViewerApplication) { return; } const optionalContentConfig = await this.PDFViewerApplication?.pdfViewer.optionalContentConfigPromise; if (optionalContentConfig) { let isVisible = optionalContentConfig.getGroup(layerId).visible; const checkbox = document.querySelector(`input[id='${layerId}']`); if (checkbox) { isVisible = checkbox.checked; checkbox.checked = !isVisible; } optionalContentConfig.setVisibility(layerId, !isVisible); this.PDFViewerApplication?.eventBus.dispatch('optionalcontentconfig', { source: this, promise: Promise.resolve(optionalContentConfig), }); } } scrollPageIntoView(pageNumber, pageSpot) { const viewer = this.PDFViewerApplication?.pdfViewer; viewer?.scrollPagePosIntoView(pageNumber, pageSpot); } getSerializedAnnotations() { return this.PDFViewerApplication?.pdfViewer.getSerializedAnnotations(); } async addEditorAnnotation(serializedAnnotation) { // #3061 When the editor mode is NONE, PDF.js internally switches to FREETEXT mode temporarily, // which causes the FreeText popup to flash. Prevent this by hiding the popup during the operation. const currentMode = this.PDFViewerApplication?.pdfViewer.annotationEditorMode; const popup = document.getElementById('editorFreeTextParamsToolbar'); const wasHidden = popup?.classList.contains('hidden') ?? true; // If mode is NONE and popup was hidden, keep it hidden during the temporary mode switch if (currentMode === 0 && wasHidden && popup) { this.renderer.addClass(popup, 'ngx-keep-hidden'); } await this.PDFViewerApplication?.pdfViewer.addEditorAnnotation(serializedAnnotation); // #3061 Remove the temporary hiding class after the operation if (currentMode === 0 && wasHidden && popup) { this.renderer.removeClass(popup, 'ngx-keep-hidden'); } } removeEditorAnnotations(filter) { this.PDFViewerApplication?.pdfViewer.removeEditorAnnotations(filter); } async loadImageAsDataURL(imageUrl) { if (imageUrl.startsWith('data:')) { return imageUrl; } const response = await fetch(imageUrl); if (!response.ok) { throw new Error(`Failed to fetch the image from ${imageUrl}: ${response.statusText}`); } const imageBlob = await response.blob(); return imageBlob; } async addImageToAnnotationLayer({ urlOrDataUrl, page, left, bottom, right, top, rotation }) { if (!this.PDFViewerApplication) { console.error('The PDF viewer has not been initialized yet.'); return; } let pageToModify; if (page !== undefined) { if (page !== this.currentPageIndex()) { await this.renderPage(page); } pageToModify = page; } else { pageToModify = this.currentPageIndex() ?? 0; } const previousAnnotationEditorMode = this.PDFViewerApplication.pdfViewer.annotationEditorMode; // #3061 Check if the stamp popup is currently hidden to prevent flashing const popup = document.getElementById('editorStampParamsToolbar'); const wasHidden = popup?.classList.contains('hidden') ?? true; // If the popup was hidden, add a CSS class to keep it hidden during mode switch if (wasHidden && popup) { this.renderer.addClass(popup, 'ngx-keep-hidden'); } this.switchAnnotationEdtorMode(13); const dataUrl = await this.loadImageAsDataURL(urlOrDataUrl); const pageSize = this.PDFViewerApplication.pdfViewer._pages[pageToModify].pdfPage.view; const leftDim = pageSize[0]; const bottomDim = pageSize[1]; const rightDim = pageSize[2]; const topDim = pageSize[3]; const width = rightDim - leftDim; const height = topDim - bottomDim; const imageWidth = this.PDFViewerApplication?.pdfViewer._pages[pageToModify].div.clientWidth; const imageHeight = this.PDFViewerApplication?.pdfViewer._pages[pageToModify].div.clientHeight; const leftPdf = this.convertToPDFCoordinates(left, width, 0, imageWidth); const bottomPdf = this.convertToPDFCoordinates(bottom, height, 0, imageHeight); const rightPdf = this.convertToPDFCoordinates(right, width, width, imageWidth); const topPdf = this.convertToPDFCoordinates(top, height, height, imageHeight); const stampAnnotation = { annotationType: 13, pageIndex: pageToModify, bitmapUrl: dataUrl, rect: [leftPdf, bottomPdf, rightPdf, topPdf], rotation: rotation ?? 0, isCopy: true, }; this.addEditorAnnotation(stampAnnotation); await this.sleep(10); this.switchAnnotationEdtorMode(previousAnnotationEditorMode); // #3061 Remove the temporary hiding class after switching back if (wasHidden && popup) { this.renderer.removeClass(popup, 'ngx-keep-hidden'); } } async addHighlightToAnnotationLayer(color, page, left, bottom, right, top, thickness = 12, rotation = 0, opacity = 0.5) { if (!this.PDFViewerApplication) { console.error('The PDF viewer has not been initialized yet.'); return; } let pageToModify; if (page !== undefined) { if (page !== this.currentPageIndex()) { await this.renderPage(page); } pageToModify = page; } else { pageToModify = this.currentPageIndex() ?? 0; } const previousAnnotationEditorMode = this.PDFViewerApplication.pdfViewer.annotationEditorMode; // #3061 Check if the popup is currently hidden to prevent flashing const popup = document.getElementById('editorHighlightParamsToolbar'); const wasHidden = popup?.classList.contains('hidden') ?? true; // If the popup was hidden, add a CSS class to keep it hidden during mode switch if (wasHidden && popup) { this.renderer.addClass(popup, 'ngx-keep-hidden'); } this.switchAnnotationEdtorMode(9); // AnnotationEditorType.HIGHLIGHT const pageSize = this.PDFViewerApplication.pdfViewer._pages[pageToModify].pdfPage.view; const leftDim = pageSize[0]; const bottomDim = pageSize[1]; const rightDim = pageSize[2]; const topDim = pageSize[3]; const width = rightDim - leftDim; const height = topDim - bottomDim; const pageWidth = this.PDFViewerApplication?.pdfViewer._pages[pageToModify].div.clientWidth; const pageHeight = this.PDFViewerApplication?.pdfViewer._pages[pageToModify].div.clientHeight; const leftPdf = this.convertToPDFCoordinates(left, width, 0, pageWidth); const bottomPdf = this.convertToPDFCoordinates(bottom, height, 0, pageHeight); const rightPdf = this.convertToPDFCoordinates(right, width, width, pageWidth); const topPdf = this.convertToPDFCoordinates(top, height, height, pageHeight); // Create quadPoints object with numeric keys (matching export format) const quadPoints = {}; quadPoints[0] = leftPdf; // x1 - left edge start quadPoints[1] = topPdf; // y1 - top edge start quadPoints[2] = rightPdf; // x2 - right edge end quadPoints[3] = topPdf; // y2 - top edge end quadPoints[4] = leftPdf; // x3 - left edge start (bottom) quadPoints[5] = bottomPdf; // y3 - bottom edge start quadPoints[6] = rightPdf; // x4 - right edge end (bottom) quadPoints[7] = bottomPdf; // y4 - bottom edge end const highlightAnnotation = { annotationType: 9, color: color, opacity: opacity, thickness: thickness, quadPoints: quadPoints, outlines: [ [ // Single outline rectangle leftPdf, bottomPdf, leftPdf, topPdf, rightPdf, topPdf, rightPdf, bottomPdf, // Bottom-right ], ], pageIndex: pageToModify, rect: [leftPdf, bottomPdf, rightPdf, topPdf], rotation: rotation, isCopy: true, }; this.addEditorAnnotation(highlightAnnotation); await this.sleep(10); this.switchAnnotationEdtorMode(previousAnnotationEditorMode); // #3061 Remove the temporary hiding class after switching back if (wasHidden && popup) { this.renderer.removeClass(popup, 'ngx-keep-hidden'); } } currentPageIndex() { const viewer = this.PDFViewerApplication?.pdfViewer; if (viewer) { return viewer.currentPageNumber - 1; } return undefined; } convertToPDFCoordinates(value, maxValue, defaultValue, imageMaxValue) { if (!value) { return defaultValue; } if (typeof value === 'string') { if (value.endsWith('%')) { return (parseInt(value, 10) / 100) * maxValue; } else if (value.endsWith('px')) { return parseInt(value, 10) * (maxValue / imageMaxValue); } else { return parseInt(value, 10); } } else { return value; } } switchAnnotationEdtorMode(mode) { this.PDFViewerApplication?.eventBus.dispatch('switchannotationeditormode', { mode }); } set editorFontSize(size) { this.setEditorProperty(AnnotationEditorParamsType.FREETEXT_SIZE, size); } set editorFontColor(color) { this.setEditorProperty(AnnotationEditorParamsType.FREETEXT_COLOR, color); } set editorInkColor(color) { this.setEditorProperty(AnnotationEditorParamsType.INK_COLOR, color); } set editorInkOpacity(opacity) { this.setEditorProperty(AnnotationEditorParamsType.INK_OPACITY, opacity); } set editorInkThickness(thickness) { this.setEditorProperty(AnnotationEditorParamsType.INK_THICKNESS, thickness); } set editorHighlightColor(color) { this.setEditorProperty(AnnotationEditorParamsType.HIGHLIGHT_COLOR, color); } set editorHighlightDefaultColor(color) { this.setEditorProperty(AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR, color); } set editorHighlightShowAll(showAll) { this.setEditorProperty(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, showAll); } set editorHighlightThickness(thickness) { this.setEditorProperty(AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, thickness); } setEditorProperty(editorPropertyType, value) { this.PDFViewerApplication?.eventBus.dispatch('switchannotationeditorparams', { type: editorPropertyType, value }); this.PDFViewerApplication?.eventBus.dispatch('annotationeditorparamschanged', { details: [[editorPropertyType, value]] }); } getCurrentPage() { if (!this.PDFViewerApplication) { return 1; } return this.PDFViewerApplication.page ?? 1; } getPageCount() { if (!this.PDFViewerApplication) { return 0; } return this.PDFViewerApplication.pagesCount ?? 0; } movePage(fromIndex, toIndex) { if (!this.PDFViewerApplication) { console.error('PDF viewer not initialized'); return; } // Check if page reordering is enabled const enablePageReordering = globalThis.pdfDefaultOptions?.enablePageReordering; if (!enablePageReordering) { console.error('Page reordering is not enabled. Set pdfDefaultOptions.enablePageReordering = true'); return; } // Validate indices (1-based) const pageCount = this.getPageCount(); if (fromIndex < 1 || fromIndex > pageCount || toIndex < 1 || toIndex > pageCount) { console.error(`Invalid page indices. fromIndex: ${fromIndex}, toIndex: ${toIndex}, pageCount: ${pageCount}`); return; } if (fromIndex === toIndex) { return; // No movement needed } try { // Call the movePage function from app.js if (this.PDFViewerApplication.movePage) { this.PDFViewerApplication.movePage(fromIndex, toIndex); } else { console.error('movePage function not available in PDF viewer application'); } } catch (error) { console.error('Error moving page:', error); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgxExtendedPdfViewerService, deps: [{ token: i0.RendererFactory2 }, { token: i1.PDFNotificationService }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgxExtendedPdfViewerService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgxExtendedPdfViewerService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [{ type: i0.RendererFactory2 }, { type: i1.PDFNotificationService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1leHRlbmRlZC1wZGYtdmlld2VyL3NyYy9saWIvbmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBK0IsTUFBTSxlQUFlLENBQUM7QUFDaEYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLGNBQWMsRUFBc0UsTUFBTSw4QkFBOEIsQ0FBQzs7O0FBNkQ5SixNQUFNLE9BQU8sMkJBQTJCO0lBU25CO0lBUlosK0JBQStCLEdBQUcsS0FBSyxDQUFDO0lBRXhDLG9CQUFvQixHQUFHLEtBQUssQ0FBQztJQUVuQixRQUFRLENBQVk7SUFDN0Isb0JBQW9CLENBQXlCO0lBRXJELFlBQ21CLGVBQWlDLEVBQ2xELG1CQUEyQztRQUQxQixvQkFBZSxHQUFmLGVBQWUsQ0FBa0I7UUFHbEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDaEUsTUFBTSxDQUFDLEdBQUcsRUFBRTtZQUNWLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxtQkFBbUIsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3RFLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLElBQUksQ0FBQyxJQUFnQyxFQUFFLFVBQXVCLEVBQUU7UUFDckUsSUFBSSxDQUFDLElBQUksQ0FBQywrQkFBK0IsRUFBRTtZQUN6QyxxQ0FBcUM7WUFDckMsT0FBTyxDQUFDLEtBQUssQ0FBQyx3RUFBd0UsQ0FBQyxDQUFDO1lBQ3hGLE9BQU8sU0FBUyxDQUFDO1NBQ2xCO2FBQU07WUFDTCxJQUFJLENBQUMsT0FBTyxDQUFDLDBCQUEwQixFQUFFO2dCQUN2QyxNQUFNLG9CQUFvQixH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