1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719 |
- import { getDocument, GlobalWorkerOptions, InvalidPDFException, MissingPDFException, UnexpectedResponseException, getPdfFilenameFromUrl } from 'pdfjs-dist/legacy/build/pdf'
- import CryptoJS from 'crypto-js'
- import printJS from 'print-js'
- import { saveAs } from 'file-saver'
- import { PDFLinkService } from "./pdf_link_service"
- import { PasswordPrompt } from "./password_prompt.js";
- import { PDFViewer } from './pdf_viewer'
- import { PDFThumbnailViewer } from './pdf_thumbnail_viewer'
- import { PDFRenderingQueue } from "./pdf_rendering_queue";
- import { PDFSidebar } from "./pdf_sidebar.js";
- import { GenericExternalServices } from "./genericcom.js";
- import { PDFCursorTools } from "./pdf_cursor_tools.js";
- import { EventBus, isValidRotation, isValidScrollMode, shadow, isValidSpreadMode, toDateObject, findIndex, scrollIntoView, DEFAULT_SCALE_VALUE, SidebarView, parseAnnotationFromXml, PromiseExt, parseAdobePDFTimestamp, round } from './ui_utils'
- import { AnnotationTypeString } from "../constants";
- import { PDFPresentationMode } from "./pdf_presentation_mode.js";
- import annotationStore from "./annotation_store"
- import { InkSign } from "./ink_sign"
- import MessageHandler from "./message_handler"
- import JSZip from 'jszip'
- import Outline from './Outline'
- GlobalWorkerOptions.workerSrc = './lib/pdf.worker.min.js'
- const CMAP_URL = './cmaps/'
- class ComPDFKitViewer {
- #pwd = ''
- #oldPwd = ''
- #textSearch = null
- #activeSearchIndex = 0
- #fonFile = null
- constructor(options) {
- this.config = options
- this.viewerContainer = null
- this.pdfLoadingTask = null
- this.printService = null
- this.pdfSidebar = null
- this.pdfOutlineViewer = null
- this.outlines = []
- this.pdfLayerViewer = null
- this.pdfDocument = null
- this.downloadComplete = false
- this.isInitialViewSet = false
- this.pdfLinkService = null
- this.externalServices = GenericExternalServices
- this.percent = 0
- this.pageChangedCallback = null
- this.scaleChangedCallback = null
- this.annotationsNumChangedCallback = null
- this.distanceChangedCallback = null
- this._license = ''
- this._token = null
- this._pdfId = null
- this.annotations = null
- this.annotationHistory = []
- this._annotationMode = 0
- this._boundEvents = Object.create(null)
- this._title = document.title
- this.activeTool = ''
- this.color = 'color'
- this.pagesPtr = []
- this.saveAction = null
- this.optionUrl = {
- baseUrl: 'https://test-compdf.kdan.cn',
- // baseUrl: 'https://wms.compdf.com',
- verifyUrl: '/api/license/verify',
- webviewBaseUrl: 'https://test-pdf-pro.kdan.cn:3032',
- // webviewBaseUrl: 'https://web-viewer-backend.compdf.com',
- uploadUrl: '/web-viewer/annotate/openPdfToAnnotate',
- editUrl: '/web-viewer/annotate/edit',
- saveUrl: '/web-viewer/annotate/save',
- flattenUrl: '/web-viewer/annotate/saveAndFlatten',
- uploadAnnotationsUrl: '/web-viewer/annotate/importAnnotateToPdf',
- downloadAnnotation: '/web-viewer/annotate/exportAnnotate',
- compareUrl: '/web-viewer/annotate/pdfCompare'
- }
- this.eventBus = new EventBus();
- this.toolMode = ''
- this.$t = options.$t
- this.fontFileInited = false
- this.contentEditAnnotationsManager = {}
- }
- get pagesCount() {
- return this.doc ? this._pagesCount : 0;
- }
- get annotationsCount() {
- return this.pdfViewer.annotationStorage ? this.pdfViewer.annotationStorage.size : 0;
- }
- get page() {
- return this.pdfViewer.currentPageNumber;
- }
- set page(val) {
- this.pdfViewer.currentPageNumber = val;
- }
- get currentPageNumber() {
- return this.pdfViewer.currentPageNumber
- }
- get scale() {
- return this.pdfViewer.currentScale;
- }
- async init() {
- await new Promise((resolve, reject) => {
- const worker = new PDFWorker()
- this.worker = worker
- const messageHandler = worker.messageHandler
- this.messageHandler = messageHandler
- messageHandler.on('initDoc', ({ doc }) => {
- this.doc = doc
- resolve(true)
- })
- })
- }
- async initConfig(options) {
- if (!options.license) return false
- this._license = options.license
- const data = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- license: this._license
- })
- }
- if (options.webviewerServer === 'Server') {
- this.webviewerServer = true
- }
- // this.webviewerServer = true
- const verified = await fetch(this.optionUrl.baseUrl + this.optionUrl.verifyUrl, data)
- .then((res) => {
- return res.json()
- })
- .then((resp) => {
- if (resp.code === 200) {
- const verified = this._decrypt(resp.data)
- return verified
- } else {
- alert(resp.message)
- return false
- }
- })
- .catch((error) => {
- alert('Network Error')
- console.log({ error: true, message: error.message })
- return false
- });
- if (verified) {
- if (!this.webviewerServer) {
- const response = await fetch('./lib/DroidSansFallbackFull.ttf')
- const blob = await response.blob()
- this.#fonFile = new File([blob], 'DroidSansFallbackFull.ttf', { type: blob.type })
- }
- await this.init()
- }
- return verified
- }
- _decrypt(data) {
- const decrypt = CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse('T2EKWNOflrd6ICU5'), {
- iv: CryptoJS.enc.Utf8.parse('GM3Faw9kX7CBmojt')
- })
- const decrypted = JSON.parse(decrypt.toString(CryptoJS.enc.Utf8))
- const hostname = window.location.hostname
- const reg = new RegExp(`^.*${decrypted.domain}$`);
- if (reg.test(hostname) || data.app_type === 2) {
- this._token = decrypted.token
- return true
- }
- return false
- }
- initializeViewer({
- container,
- viewer,
- thumbnailView,
- annotationView,
- findbarView,
- toggleButton,
- }) {
- this._initializeViewerComponents({
- container,
- viewer,
- thumbnailView,
- annotationView,
- findbarView,
- toggleButton,
- })
- this.initBindEvents()
- if (thumbnailView && annotationView) {
- this.bindEvents();
- this.bindWindowEvents();
- }
- }
- setTool({
- tool,
- color
- }) {
- this.activeTool = tool
- this.color = color
- this.eventBus.dispatch("toolChanged", { tool, color });
- }
- initAnnotations(annotations, render = false) {
- for (let index = 0; index < annotations.length; index++) {
- this.handleAnnotations(annotations[index], true)
- render && this.pdfViewer.renderAnnotation(annotations[index])
- }
- this.eventBus.dispatch('annotationChanged', { annotations: this.annotations })
- }
- async handleAnnotations(annotation, init = false) {
- if (!this.annotations) {
- this.annotations = {}
- }
- if (init) {
- this.initAddAnnotations(annotation)
- } else {
- if (Number(annotation.pageIndex) + 1 > this.pagesCount) return
- this.pushAnnotations(annotation)
- if (!this.webviewerServer || annotation.type === 'stamp') {
- const pagePtr = this.pagesPtr[annotation.pageIndex].pagePtr
- const annotPtr = await this.messageHandler.sendWithPromise('CreateAnnotation', {
- doc: this.doc,
- pagePtr,
- annotation
- })
- annotation.pagePtr = pagePtr
- annotation.annotPtr = annotPtr
- if (!annotation.rect && this.webviewerServer) {
- const getRect = await this.messageHandler.sendWithPromise('GetAnnotRect', {
- pagePtr: pagePtr,
- annotPtr: annotPtr
- })
- let pageView = this.pdfViewer.getPageView(annotation.pageIndex)
- const pageWidth = pageView.viewport.viewBox[2]
- const pageHeight = pageView.viewport.viewBox[3]
- const imgWidth = getRect.right - getRect.left
- const imgHeight = getRect.bottom - getRect.top
-
- const left = (pageWidth - imgWidth) / 2
- const top = (pageHeight - imgHeight) / 2
- const right = (pageWidth + imgWidth) / 2
- const bottom = (pageHeight + imgHeight) / 2
-
- const rect = {
- left,
- top,
- right,
- bottom,
- }
- annotation.rect = rect
- }
- }
- }
- }
- initAddAnnotations(annotation) {
- const pageIndex = annotation.pageIndex
- const annotations = this.annotations
- if (!annotations[pageIndex]) {
- annotations[pageIndex] = []
- }
- console.log(typeof annotation.index)
- if (typeof annotation.index !== 'undefined') {
- annotations[pageIndex][annotation.index] = annotation
- } else {
- annotations[pageIndex].push(annotation)
- }
- if (!annotationStore.annotationsAll) {
- annotationStore.annotationsAll = annotations
- }
- }
- pushAnnotations(annotation) {
- const pageIndex = annotation.pageIndex
- const annotations = this.annotations
- if (!annotations[pageIndex]) {
- annotations[pageIndex] = []
- this.pdfViewer._pages[pageIndex].annotations = annotations[pageIndex]
- }
- if (!annotationStore.annotationsAll) {
- annotationStore.annotationsAll = annotations
- }
- annotations[pageIndex].push(annotation)
- }
- addAnnotations(annotation) {
- this.handleAnnotationChange({
- type: 'add',
- annotation: [annotation]
- })
- }
- delAnnotations(annotation) {
- this.handleAnnotationChange({
- type: 'delete',
- annotation: [annotation]
- })
- }
- addEvent(eventName, fn) {
- this.eventBus._on(eventName, fn);
- }
- removeEvent(eventName, fn) {
- this.eventBus._off(eventName, fn);
- }
- async loadDocument(file, options = {}) {
- if (this.pdfLoadingTask) {
- await this.close()
- }
- if (options.annotations) {
- parseAnnotationFromXml(options.annotations)
- }
- this.info = options.info || null
- this.pageChangedCallback = options.pageChangedCallback || this.pageChangedCallback
- this.scaleChangedCallback = options.scaleChangedCallback || this.scaleChangedCallback
- this.annotationsNumChangedCallback = options.annotationsNumChangedCallback || this.annotationsNumChangedCallback
- this.distanceChangedCallback = options.distanceChangedCallback || this.distanceChangedCallback
- annotationStore.annotationsAll = null
- annotationStore.selectedName = null
- this.fontFileInited = false
- const parameters = {
- cMapUrl: CMAP_URL,
- cMapPacked: true,
- enableXfa: true
- };
- if (typeof file === "string") {
- // URL
- parameters.url = file
- } else if (file && "byteLength" in file) {
- // ArrayBuffer
- parameters.data = file;
- } else if (file.url && file.originalUrl) {
- parameters.url = file.url;
- }
- // 获取pdf信息,返回promise
- const loadingTask = getDocument(parameters)
- this.pdfLoadingTask = loadingTask
- this._docName = options.filename || getPdfFilenameFromUrl(parameters.url)
- const getPwd = (pwd) => this.#pwd = pwd
- const handlePassword = (updateCallback, reason) => {
- if (this.#oldPwd && options.notUpdatePwd) {
- getPwd(this.#oldPwd);
- updateCallback(this.#oldPwd);
- loadingTask.onPassword = null;
- } else if (options.pwd) {
- getPwd(options.pwd);
- updateCallback(options.pwd);
- loadingTask.onPassword = null;
- } else {
- this.passwordPrompt.setUpdateCallback(updateCallback, reason, getPwd);
- this.passwordPrompt.open();
- }
- };
- loadingTask.onPassword = handlePassword;
- loadingTask.onProgress = ({ loaded, total }) => {
- const progress = options.progress || this.progress
- progress.call(this, loaded / total)
- }
- // notUploadPdf -> 仅预览 不上传到服务器
- // if (options.notUploadPdf) {
- // const pdfDocument = await loadingTask.promise;
- // await this.load(pdfDocument);
- // return this.#pwd
- // }
- // 处理传入的PDF
- return await loadingTask.promise.then(
- async pdfDocument => {
- // 上传pdf
- await pdfDocument.getData().then(async (binaryData) => {
- this.pdfDocument = pdfDocument
- if (!options.notUpdatePwd) {
- this.#oldPwd = this.#pwd
- }
- let buffer = new Uint8Array(binaryData)
- await this.messageHandler.sendWithPromise('LoadFile', {
- buffer,
- fontFile: this.#fonFile,
- fontName: 'DroidSansFallbackFull'
- })
- const loadRes = await this.messageHandler.sendWithPromise('LoadDocumentByStream', {
- doc: this.doc,
- fileId: 0,
- length: buffer.length,
- password: this.#pwd
- })
- this.contentEditAnnotationsManager.addTextEditor = (data) => {
- const pageNumber = data.pageNumber
- if (pageNumber > this.pagesCount || pageNumber < 1) {
- throw new Error({
- message: 'Invalid pageNumber'
- })
- }
- if (this.toolMode !== 'editor') {
- this.setToolMode('editor')
- }
- if (this.currentPageNumber !== pageNumber) {
- this.pdfViewer.scrollPageIntoView({ pageNumber: pageNumber })
- }
- const pageIndex = pageNumber - 1
- const pageView = this.pdfViewer._pages[pageIndex]
- if (pageView) {
- pageView.addTextEditor(data)
- }
- }
- this.contentEditAnnotationsManager.getEditAnnotation = async (pageNumber) => {
- if (pageNumber > this.pagesCount || pageNumber < 1) {
- throw new Error({
- message: 'Invalid pageNumber'
- })
- }
- if (this.toolMode !== 'editor') {
- this.setToolMode('editor')
- }
- if (this.currentPageNumber !== pageNumber) {
- this.pdfViewer.scrollPageIntoView({ pageNumber: pageNumber })
- }
- const pageIndex = pageNumber - 1
- const pageView = this.pdfViewer._pages[pageIndex]
- if (pageView) {
- const editAnnotation = await pageView.getEditAnnotation()
- return editAnnotation
- }
- }
- let annotations = null
- console.log(this.webviewerServer)
- await this.initPage()
- if (this.webviewerServer) {
- const formData = new FormData();
- formData.append('file', new Blob([binaryData], { type: 'application/pdf' }), this._docName);
- formData.append('password', this.#pwd);
- const data = {
- method: 'POST',
- headers: {
- 'Authorization': this._token
- },
- body: formData
- }
- await fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.uploadUrl, data)
- .then((res) => {
- return res.json()
- })
- .then((resp) => {
- if (resp.code === "200") {
- const data = resp.data
- this._pdfId = data.pdfId
- // const rawAnnotations = data.annotateJson && JSON.parse(data.annotateJson)
- const rawAnnotations = data.annotateJson && data.annotateJson
- console.log(rawAnnotations)
- annotations = this.convertAnnotation(rawAnnotations)
- } else if (resp.code === "319") {
-
- }
- })
- .catch((error) => {
- console.log(error)
- return { error: true, message: error.message }
- });
- } else {
- annotations = await this.getAnnotations()
- }
- console.log(annotations)
- annotations && this.initAnnotations(annotations)
- console.log(this.annotations)
- })
- await this.load(pdfDocument);
- return { pwd: !!this.#pwd };
- },
- reason => {
- if (loadingTask !== this.pdfLoadingTask) {
- return undefined; // Ignore errors for previously opened PDF files.
- }
- let key = "loading_error";
- if (reason instanceof InvalidPDFException) {
- key = "invalid_file_error";
- console.warn('Invalid or corrupted PDF file.')
- return new Promise(function (resolve, reject) {
- reject('invalid_file_error')
- });
- } else if (reason instanceof MissingPDFException) {
- key = "missing_file_error";
- console.warn('Missing PDF file.')
- } else if (reason instanceof UnexpectedResponseException) {
- key = "unexpected_response_error";
- console.warn('Unexpected server response.')
- } else if (reason) {
- if (reason.message === 'No password given') {
- key = "no_password_given";
- console.warn('No password given.')
- return new Promise(function (resolve, reject) {
- reject('no_password_given')
- });
- } else if (reason.message === 'Incorrect Password') {
- return new Promise(function (resolve, reject) {
- reject('incorrect_password')
- });
- }
- }
- throw new Error(key)
- }
- )
- }
- getSelectedText(pageNumber) {
- if (pageNumber) {
- const page = this.pdfViewer._pages[pageNumber - 1]
- if (page) {
- return page.selectedText
- }
- }
- return this.pdfViewer._pages.map(function(page) {
- return page.selectedText
- }).filter(function(text) {
- return text !== null
- }).join('\n')
- }
- convertAnnotation(rawAnnotations) {
- const annotations = []
- for (const type in rawAnnotations) {
- let annotationData = rawAnnotations[type]
- if (!Array.isArray(annotationData)) {
- annotationData = [annotationData]
- }
- for (let i = 0; i < annotationData.length; i++) {
- annotationData[i].type = type
- const annotation = this.#formatAnnotation(annotationData[i])
- annotations.push(annotation)
- }
- }
- return annotations
- }
- #formatRect(annotation) {
- const pageIndex = annotation.page
- const { height } = this.pagesPtr[pageIndex]
- const rect = annotation.rect.split(',')
- const left = round(rect[0], 2)
- const bottom = round((height - Number(rect[1])), 2)
- const right = round(rect[2], 2)
- const top = round((height - Number(rect[3])), 2)
- return {
- left,
- bottom,
- right,
- top
- }
- }
- #formatCoords(annotation) {
- const formattedCoords = []
- const pageIndex = annotation.page
- const { height } = this.pagesPtr[pageIndex]
- const coords = annotation.coords.split(',')
- for (let i = 0; (i + 7) < coords.length; i += 8) {
- formattedCoords.push({
- PointX: round(coords[i + 4], 2),
- PointY: round((height - Number(coords[i + 5])), 2)
- })
- formattedCoords.push({
- PointX: round(coords[i + 6], 2),
- PointY: round((height - Number(coords[i + 7])), 2)
- })
- formattedCoords.push({
- PointX: round(coords[i], 2),
- PointY: round((height - Number(coords[i + 1])), 2)
- })
- formattedCoords.push({
- PointX: round(coords[i + 2], 2),
- PointY: round((height - Number(coords[i + 3])), 2)
- })
- }
- return formattedCoords
- }
- #formatLinePoints(annotation) {
- const pageIndex = annotation.page
- const { height } = this.pagesPtr[pageIndex]
- const linePoints = []
- const start = annotation.start.split(',')
- const end = annotation.end.split(',')
- linePoints.push(round(start[0], 2))
- linePoints.push(round((height - Number(start[1])), 2))
- linePoints.push(round(end[0], 2))
- linePoints.push(round((height - Number(end[1])), 2))
- return linePoints
- }
- #formatInkPointes(annotation) {
- const pageIndex = annotation.page
- const { height } = this.pagesPtr[pageIndex]
- const inklist = []
- let inklistData = annotation.inklist.gesture
- if (!Array.isArray(inklistData)) {
- inklistData = [inklistData]
- }
- for (let i = 0; i < inklistData.length; i++) {
- if (inklistData[i][inklistData[i].length - 1] === ';') {
- inklistData[i] = inklistData[i].slice(0, inklistData[i].length - 1)
- }
- const points = inklistData[i].split(';').map((rawPoint) => {
- const point = rawPoint.split(',')
- return {
- PointX: round(point[0], 2),
- PointY: round((height - Number(point[1])), 2)
- }
- })
- inklist.push(points)
- }
- return inklist
- }
- #formatAnnotation(rawAnnotation) {
- const annotation = {}
- annotation.type = rawAnnotation.type
- rawAnnotation.rect && (annotation.rect = this.#formatRect(rawAnnotation))
- annotation.date = parseAdobePDFTimestamp(rawAnnotation.creationdate)
- annotation.pageIndex = Number(rawAnnotation.page)
- annotation.index = Number(rawAnnotation.index)
- annotation.content = rawAnnotation.contents || ''
- annotation.transparency = round(rawAnnotation.opacity, 2) || 1
- switch (rawAnnotation.type) {
- case 'freetext':
- let fontName = rawAnnotation.textStyle.fontName
- fontName = fontName[0].toUpperCase() + fontName.slice(1)
- annotation.fontName = fontName
- annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
- annotation.color = rawAnnotation.textStyle.fontColor
- annotation.textAlignment = rawAnnotation.textStyle.alignment
- annotation.content = rawAnnotation['contents-richtext'] || rawAnnotation.content
- if (rawAnnotation['contents-richtext']) {
- const parser = new DOMParser()
- const xmlDoc = parser.parseFromString(rawAnnotation['contents-richtext'], 'text/xml');
- const error = xmlDoc.getElementsByTagName("parsererror")
- if (error.length > 0) {
- annotation.content = rawAnnotation['contents-richtext']
- } else {
- annotation.content = xmlDoc.firstElementChild.innerText
- }
- }
- break
- case 'text':
- annotation.textColor = rawAnnotation.color
- break
- case 'highlight':
- case 'underline':
- case 'strikeout':
- case 'squiggly':
- annotation.color = rawAnnotation.color
- annotation.quadPoints = this.#formatCoords(rawAnnotation)
- break
- case 'line':
- annotation.linePoints = this.#formatLinePoints(rawAnnotation)
- annotation.tail = rawAnnotation.tail
- annotation.head = rawAnnotation.head
- annotation.borderColor = rawAnnotation.color
- annotation.lineWidth = round(rawAnnotation.width, 2)
- break
- case 'square':
- case 'circle':
- annotation.borderColor = rawAnnotation.color
- annotation.lineWidth = round(rawAnnotation.width, 2)
- rawAnnotation['interior-opacity'] && (annotation.fillTransparency = round(rawAnnotation['interior-opacity'], 2))
- rawAnnotation['interior-color'] && (annotation.fillColor = rawAnnotation['interior-color'])
- break
- case 'ink':
- annotation.color = rawAnnotation.color
- annotation.lineWidth = round(rawAnnotation.width, 2)
- annotation.inkPointes = this.#formatInkPointes(rawAnnotation)
- break
- case 'link':
- const linkAction = pushbuttonAction && pushbuttonAction.Action
- if (linkAction && linkAction.Dest && linkAction.Dest.XYZ) {
- annotation.destPage = Number(linkAction.Dest.XYZ.Page) + 1
- annotation.url = ''
- } else if (linkAction && linkAction.URI) {
- annotation.url = linkAction.URI.URI
- annotation.destPage = ''
- }
- break
- case 'stamp':
- annotation.content = rawAnnotation.icon
- rawAnnotation.image && (annotation.image = rawAnnotation.image)
- annotation.stampType = rawAnnotation['stamp-type']
- break
- case 'textfield':
- rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
- annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
- annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
- rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
- let textfieldFontName = rawAnnotation.textStyle.fontName
- textfieldFontName = textfieldFontName[0].toUpperCase() + textfieldFontName.slice(1)
- annotation.fontName = textfieldFontName
- annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
- annotation.color = rawAnnotation.textStyle.fontColor
- annotation.textAlignment = rawAnnotation.textStyle.alignment
- annotation.content = rawAnnotation.value
- annotation.fieldName = rawAnnotation.fieldname
- annotation.isBold = rawAnnotation.textStyle.blod === 'true'
- annotation.isItalic = rawAnnotation.textStyle.italic === 'true'
- annotation.isMultiLine = rawAnnotation.textStyle.multiLine === 'true' ? 1 : 0
- annotation.isHidden = (!rawAnnotation.flags || rawAnnotation.flags === 'invisible') ? 1 : 0
- break
- case 'checkbox':
- case 'radiobutton':
- rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
- annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
- annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
- rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
- annotation.fieldName = rawAnnotation.fieldname
- annotation.isHidden = (!rawAnnotation.flags || rawAnnotation.flags === 'invisible') ? 1 : 0
- annotation.isChecked = rawAnnotation.value === 'Yes' ? 1 : 0
- annotation.checkStyle = Number(rawAnnotation.styleCA)
- break
- case 'combobox':
- case 'listbox':
- rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
- annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
- annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
- rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
- annotation.fieldName = rawAnnotation.fieldname
- let comboboxFontName = rawAnnotation.textStyle.fontName
- comboboxFontName = comboboxFontName[0].toUpperCase() + comboboxFontName.slice(1)
- annotation.fontName = comboboxFontName
- annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
- annotation.color = rawAnnotation.textStyle.fontColor
- annotation.isBold = rawAnnotation.textStyle.blod === 'true'
- annotation.isItalic = rawAnnotation.textStyle.italic === 'true'
- annotation.isMultiLine = rawAnnotation.textStyle.multiLine === 'true' ? 1 : 0
- annotation.isHidden = !rawAnnotation.flags && rawAnnotation.flags === 'invisible' ? 1 : 0
- annotation.items = this.#getItems(rawAnnotation)
- annotation.selected = round(rawAnnotation.select, 0)
- break
- case 'pushbutton':
- const pushbuttonAction = rawAnnotation.OnActivation && rawAnnotation.OnActivation.Action
- if (pushbuttonAction && pushbuttonAction.URI) {
- annotation.url = pushbuttonAction.URI.URI
- annotation.destPage = ''
- annotation.actionType = 6
- } else if (pushbuttonAction && pushbuttonAction.Dest && pushbuttonAction.Dest.XYZ) {
- annotation.destPage = Number(pushbuttonAction.Dest.XYZ.Page) + 1
- annotation.url = ''
- annotation.actionType = 1
- }
- rawAnnotation['background-color'] && (annotation.backgroundColor = rawAnnotation['background-color'])
- annotation.borderStyle = rawAnnotation.borderStyle || 'solid'
- annotation.borderWidth = (rawAnnotation.width && round(rawAnnotation.width, 2)) || 1
- rawAnnotation['border-color'] && (annotation.borderColor = rawAnnotation['border-color'])
- annotation.fieldName = rawAnnotation.fieldname
- if (rawAnnotation.textStyle.fontName) {
- let pushbuttonFontName = rawAnnotation.textStyle.fontName
- pushbuttonFontName = pushbuttonFontName[0].toUpperCase() + pushbuttonFontName.slice(1)
- annotation.fontName = pushbuttonFontName
- } else {
- annotation.fontName = 'Helvetica'
- }
- annotation.fontSize = round(rawAnnotation.textStyle.fontSize, 0)
- annotation.color = rawAnnotation.textStyle.fontColor
- annotation.isBold = rawAnnotation.textStyle.blod === 'true'
- annotation.isItalic = rawAnnotation.textStyle.italic === 'true'
- annotation.title = rawAnnotation.styleCA
- annotation.isHidden = !rawAnnotation.flags && rawAnnotation.flags === 'invisible' ? 1 : 0
- break
- }
- return annotation
- }
- #getItems(rawAnnotation) {
- const items = []
- const opt = rawAnnotation.opt
- for (let i = 0; i < opt.length; i++) {
- items.push({
- Value: opt[i].value,
- String: opt[i].key
- })
- }
- return items
- }
- getOutlines() {
- if (this.outlines) {
- return this.outlines
- }
- }
- scrollPageIntoView({
- pageNumber,
- }) {
- // if (this.currentPage)
- }
- async search(value) {
- const searchResults = await this.messageHandler.sendWithPromise('Search', {
- pagesPtr: this.pagesPtr,
- value
- })
- this.searchResults = searchResults
- this.eventBus.dispatch('search', searchResults)
- if (!searchResults.length) {
- this.clearSearchResults()
- this.#activeSearchIndex = 0
- } else {
- this.setActiveSearchResult()
- }
- return searchResults
- }
- setActiveSearchResult(result = null, activeSearchIndex = 0) {
- if (!this.searchResults) return
- const activeResult = result ? result : this.searchResults[0]
- const quad = activeResult.quads[0]
- const left = quad.left * this.scale
- const top = quad.top * this.scale
- const pageView = this.pdfViewer._pages[activeResult.pageNum - 1]
- this.pdfViewer.currentPageNumber = activeResult.pageNum
- scrollIntoView(pageView.div, {
- left,
- top
- })
- if (result) {
- const preActiveSearchResult = this.searchResults[this.#activeSearchIndex]
- this.pdfViewer._pages[preActiveSearchResult.pageNum - 1].clearActiveSearchResult(preActiveSearchResult)
- pageView.setActiveSearchResult(result)
- this.#activeSearchIndex = activeSearchIndex
- } else {
- pageView.setActiveSearchResult(activeResult)
- this.#activeSearchIndex = 0
- }
- }
- clearSearchResults() {
- for (let i = 0; i < this.pdfViewer._pages.length; i++) {
- const _page = this.pdfViewer._pages[i]
- _page.clearSearchResults()
- }
- this.searchResults = null
- }
- async initPage() {
- const pagesCount = await this.messageHandler.sendWithPromise("GetPageCount", {
- doc: this.doc,
- })
- this._pagesCount = pagesCount
- this.pagesPtr = []
- for (let pageIndex = 0; pageIndex < pagesCount; pageIndex++) {
- const page = await this.messageHandler.sendWithPromise("GetPageSize", {
- doc: this.doc,
- pageIndex
- })
- const textPtr = await this.messageHandler.sendWithPromise('InitText', {
- pagePtr: page.pagePtr
- })
- this.pagesPtr.push({
- doc: this.doc,
- pagePtr: page.pagePtr,
- textPtr,
- width: page.width,
- height: page.height
- })
- }
- }
- async getAnnotations() {
- const annotations = []
- const pagesPtr = this.pagesPtr
- for (let pageIndex = 0; pageIndex < this.pagesCount; pageIndex++) {
- const page = pagesPtr[pageIndex]
- const data = await this.messageHandler.sendWithPromise('InitAnnot', {
- pageIndex,
- pagePtr: page.pagePtr
- })
- for (let annotCountNum = 0; annotCountNum < data.annotCount; annotCountNum++) {
- const annotation = data.annotations[annotCountNum]
- const typeInt = annotation.type
- const type = AnnotationTypeString[typeInt]
- annotation.pageIndex = pageIndex
- annotation.type = type
- let attr = null
- if (type === 'widget') {
- attr = await this.messageHandler.sendWithPromise('GetWidgetAnnotation', {
- doc: this.doc,
- annotPtr: annotation.annotPtr,
- pagePtr: annotation.pagePtr,
- typeInt
- })
- } else {
- attr = await this.messageHandler.sendWithPromise('GetAnnotation', {
- doc: this.doc,
- annotPtr: annotation.annotPtr,
- pagePtr: annotation.pagePtr,
- typeInt,
- scale: this.scale
- })
- }
- Object.assign(annotation, attr)
- annotations.push(annotation)
- }
- }
- this.pdfViewer.pagesPtr = this.pagesPtr
- return annotations
- }
- async reRenderAnnotations() {
- this.annotations = null
- const annotations = []
- const pagesPtr = this.pagesPtr
- for (let pageIndex = 0; pageIndex < pagesPtr.length; pageIndex++) {
- const pagePtr = pagesPtr[pageIndex]
- const data = await this.messageHandler.sendWithPromise('InitAnnot', {
- pageIndex,
- pagePtr: pagePtr.pagePtr
- })
- for (let annotCountNum = 0; annotCountNum < data.annotCount; annotCountNum++) {
- const annotation = data.annotations[annotCountNum]
- const typeInt = annotation.type
- const type = AnnotationTypeString[typeInt]
- annotation.pageIndex = pageIndex
- annotation.type = type
- let attr = null
- if (type === 'widget') {
- attr = await this.messageHandler.sendWithPromise('GetWidgetAnnotation', {
- doc: this.doc,
- annotPtr: annotation.annotPtr,
- pagePtr: annotation.pagePtr,
- typeInt
- })
- } else {
- attr = await this.messageHandler.sendWithPromise('GetAnnotation', {
- doc: this.doc,
- annotPtr: annotation.annotPtr,
- pagePtr: annotation.pagePtr,
- typeInt,
- scale: this.scale
- })
- }
- Object.assign(annotation, attr)
- annotations.push(annotation)
- }
- }
- for (let index = 0; index < annotations.length; index++) {
- if (!this.annotations) {
- this.annotations = {}
- }
- this.pushAnnotations(annotations[index])
- this.pdfViewer.renderAnnotation(annotations[index])
- }
- this.eventBus.dispatch('annotationChanged', { annotations: this.annotations })
- }
- get supportsFullscreen() {
- const fullscreenEnabled = document.webkitFullscreenEnabled || document.mozFullscreenEnabled || document.fullscreenEnabled
- return shadow(this, "supportsFullscreen", fullscreenEnabled);
- }
- removeAllAnnotations() {
- if (this.pdfViewer.annotationStorage) {
- this.pdfViewer.annotationStorage.cleanup()
- }
- }
- async importAnnotations(data) {
- const source = await new Promise((resolve) => {
- const reader = new FileReader();
- reader.onload = (event) => {
- const contents = event.target.result
- resolve(contents)
- };
- if (this.webviewerServer) {
- reader.readAsText(data);
- } else {
- reader.readAsArrayBuffer(data);
- }
- });
- if (this.webviewerServer) {
- const annotationsXml = parseAnnotationFromXml(source)
- if (!annotationsXml.length) return
- this.handleAnnotationChange({
- type: 'add',
- annotation: annotationsXml
- })
- } else {
- const xfdfBuffer = new Uint8Array(source)
- await this.messageHandler.sendWithPromise('XFDFImportAnnotations', {
- doc: this.doc,
- xfdfBuffer
- })
- }
- this.emptyAnnotations()
- this.reRenderAnnotations()
- // for (let i = 0; i < len; i++) {
- // const item = annotationsXml[i]
- // const data = {
- // annotationType: 3,
- // fontSize: 10,
- // value: item.obj_attr.content,
- // rotation: 0,
- // position: item.obj_attr.position,
- // type: 'custom'
- // }
- // this.pdfViewer._pages[annotationsXml[i].obj_attr.page].pdfAnnotationLayer.deserialize(data)
- // }
- }
- saveAnnotations() {
- if (!this.pdfDocument || !this.info) return
- let append_objects = []
- for (let [key, value] of this.pdfViewer.annotationStorage._storage) {
- append_objects.push(value.annotationObj);
- }
- this.uploadAnnotations({
- append_objects,
- tid: this.info.tid
- })
- }
- initApiUrl(urls) {
- this.optionUrl = urls
- }
- setPassword(value) {
- if (this.webviewerServer) {
- const options = {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- 'Authorization': this._token
- },
- body: JSON.stringify({
- pdfId: this._pdfId,
- annotateHandles: [{
- operate: 'set-password',
- userPassword: value
- }]
- }),
- }
- return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.editUrl, options)
- .then((res) => {
- return res.json()
- })
- .then((data) => {
- if (data.code === "200") {
- return true
- } else {
- return false
- }
- })
- .catch((error) => {
- console.log(error)
- return false
- });
- } else {
- // 设置密码标志
- this.saveAction = 'set'
- this.#pwd = value
- return true
- }
- }
- removePassword() {
- if (this.webviewerServer) {
- const options = {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- 'Authorization': this._token
- },
- body: JSON.stringify({
- pdfId: this._pdfId,
- annotateHandles: [{
- operate: 'remove-password'
- }]
- }),
- }
- return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.editUrl, options)
- .then((res) => {
- return res.json()
- })
- .then((data) => {
- if (data.code === "200") {
- return true
- } else {
- return false
- }
- })
- .catch((error) => {
- console.log(error)
- return false
- });
- } else {
- if (this.#pwd) {
- // 移除密码标志
- this.saveAction = 'remove'
- this.#pwd = ''
- }
- return true
- }
- }
- getOptionUrl() {
- return this.optionUrl
- }
- uploadAnnotations(data) {
- const options = {
- method: 'POST',
- headers: {
- Accept: 'application/json',
- 'Content-type': 'application/json',
- },
- }
- if (!data.append_objects.length) return
- options.body = JSON.stringify(data)
- fetch(this.optionUrl.baseUrl + this.optionUrl.saveAnnotations + '?f=' + this.info.token, options)
- .then((res) => {
- alert('Save Success')
- return res.json()
- })
- .then((resp) => resp)
- .catch((error) => ({ error: true, message: error.message }));
- }
- toggleSidebar() {
- this.pdfSidebar.toggle()
- }
- // 渲染PDF
- async load(pdfDocument) {
- this.pdfLinkService.setDocument(pdfDocument);
- const pdfViewer = this.pdfViewer;
- pdfViewer.setDocument(pdfDocument, this.annotations, this.pagesPtr);
- const { firstPagePromise, onePageRendered, pagesPromise } = pdfViewer;
-
- pdfDocument.getDownloadInfo().then(({ length }) => {
- this._contentLength = length; // Ensure that the correct length is used.
- this.downloadComplete = true;
- firstPagePromise.then(() => {
- this.eventBus.dispatch("documentloaded", { source: this });
- });
- })
- if (this.pdfThumbnailViewer) {
- const pdfThumbnailViewer = this.pdfThumbnailViewer;
- pdfThumbnailViewer.setDocument(pdfDocument);
- }
- const doc = this.doc
- const messageHandler = this.messageHandler
- const outlines = await messageHandler.sendWithPromise('GetOutlines', {
- doc
- })
- const generateOutline = (outline, index, parent) => {
- const outlineItem = new Outline({
- outline,
- index,
- doc,
- messageHandler,
- parent
- })
- outline.children.forEach(function (outline, index) {
- outlineItem.children.push(generateOutline(outline, index, outlineItem))
- })
- return outlineItem
- }
- outlines.forEach((outline, index) => {
- const outlineItem = generateOutline(outline, index, null)
- this.outlines.push(outlineItem)
- })
- firstPagePromise.then(pdfPage => {
- let hash = null;
- let rotation = null;
- let sidebarView = 0
- let scrollMode = -1
- let spreadMode = -1
- this.setInitialView(hash, {
- rotation,
- sidebarView,
- scrollMode,
- spreadMode,
- });
- })
- this.eventBus.dispatch("documentinit", { source: this });
- }
- initBindEvents() {
- const { eventBus, _boundEvents } = this;
- eventBus._on("scalechanging", this.webViewerScaleChanging.bind(this));
- }
- // 绑定自定义事件
- bindEvents() {
- const { eventBus, _boundEvents } = this;
- eventBus._on("resize", this.webViewerResize.bind(this));
- eventBus._on("pagerendered", this.webViewerPageRendered.bind(this));
- eventBus._on("updateviewarea", this.webViewerUpdateViewarea.bind(this));
- eventBus._on("pagechanging", this.webViewerPageChanging.bind(this));
- eventBus._on("rotationchanging", this.webViewerRotationChanging.bind(this));
- eventBus._on("sidebarviewchanged", this.webViewerSidebarViewChanged.bind(this));
- eventBus._on("presentationmodechanged", this.webViewerPresentationModeChanged.bind(this));
- eventBus._on("presentationmode", this.webViewerPresentationMode.bind(this));
- eventBus._on("nextpage", this.webViewerNextPage.bind(this));
- eventBus._on("previouspage", this.webViewerPreviousPage.bind(this));
- eventBus._on("zoomin", this.webViewerZoomIn.bind(this));
- eventBus._on("zoomout", this.webViewerZoomOut.bind(this));
- eventBus._on("pagenumberchanged", this.webViewerPageNumberChanged.bind(this));
- eventBus._on("scalechanged", this.webViewerScaleChanged.bind(this));
- eventBus._on("rotatecw", this.webViewerRotateCw.bind(this));
- eventBus._on("rotateccw", this.webViewerRotateCcw.bind(this));
- eventBus._on("switchscrollmode", this.webViewerSwitchScrollMode.bind(this));
- eventBus._on("scrollmodechanged", this.webViewerScrollModeChanged.bind(this));
- eventBus._on("switchspreadmode", this.webViewerSwitchSpreadMode.bind(this));
- eventBus._on("spreadmodechanged", this.webViewerSpreadModeChanged.bind(this));
- eventBus._on("findfromurlhash", this.webViewerFindFromUrlHash.bind(this));
- eventBus._on("updatefindmatchescount", this.webViewerUpdateFindMatchesCount.bind(this));
- eventBus._on("updatefindcontrolstate", this.webViewerUpdateFindControlState.bind(this));
- eventBus._on("fileinputchange", this.webViewerFileInputChange.bind(this));
- eventBus._on("openfile", this.webViewerOpenFile.bind(this));
- eventBus._on("switchannotationeditormode", this.webViewerSwitchAnnotationEditorMode.bind(this));
- eventBus._on("annotationsCountChanged", this.webViewerAnnotationsCountChanged.bind(this))
- eventBus._on("distanceChanged", this.webViewerDistanceChanged.bind(this));
- eventBus._on("annotationChange", this.handleAnnotationChange.bind(this));
- eventBus._on("createSignature", this.handleCreateSignature.bind(this));
- eventBus._on("handleField", this.handleField.bind(this));
- eventBus._on("pageNumberChanged", this.pageNumberChanged.bind(this));
- }
- bindWindowEvents() {
- const { eventBus, _boundEvents } = this;
- _boundEvents.windowResize = () => {
- eventBus.dispatch("resize", { source: window });
- };
- _boundEvents.windowHashChange = () => {
- eventBus.dispatch("hashchange", {
- source: window,
- hash: document.location.hash.substring(1),
- });
- };
- _boundEvents.windowUpdateFromSandbox = event => {
- eventBus.dispatch("updatefromsandbox", {
- source: window,
- detail: event.detail,
- });
- };
- window.addEventListener("resize", _boundEvents.windowResize);
- window.addEventListener("hashchange", _boundEvents.windowHashChange);
- window.addEventListener(
- "updatefromsandbox",
- _boundEvents.windowUpdateFromSandbox
- );
- }
- async close() {
- if (!this.pdfLoadingTask) {
- return
- }
- 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.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;
- this.pdfSidebar?.reset();
- this.pdfOutlineViewer?.reset();
- this.pdfAttachmentViewer?.reset();
- this.outlines = []
- this.#pwd = ''
- this._pdfId = null
- this.annotations = null
- await Promise.all(promises);
- }
- handleInk(annotation) {
- let rawAnnotation = JSON.parse(JSON.stringify(annotation))
- let inklist = ''
- let inkArray = []
- if (Array.isArray(rawAnnotation.inklist)) {
- inkArray = rawAnnotation.inklist
- }
- else {
- inkArray.push(rawAnnotation.inklist)
- }
- for (let i = 0; i < inkArray.length; i++) {
- inklist = inklist + inkArray[i].replaceAll(';', ',') + '//'
- }
- rawAnnotation.inklist = inklist// rawAnnotation.inklist.replaceAll(';', ',') + '//'
- return rawAnnotation
- }
- async handleAnnotationChange(data) {
- let annotation = data.annotation
- this.annotationHistory.push(annotation)
- let annotateHandles = []
- const formTypes = ['textfield', 'checkbox', 'radiobutton', 'listbox', 'combobox', 'pushbutton']
- if (data.type === 'add') {
- if (!Array.isArray(annotation)) {
- annotation = [annotation]
- }
- const length = annotation.length
- for (let i = 0; i < length; i++) {
- if (Number(annotation[i].pageIndex) + 1 > this.pagesCount) continue
- if (formTypes.includes(annotation[i].type)) {
- annotation[i].operate = "add-form"
- } else {
- annotation[i].operate = "add-annot"
- }
- await this.handleAnnotations(annotation[i])
- if (this.pdfViewer) {
- this.pdfViewer.renderAnnotation(annotation[i], !!data.show)
- }
- annotation[i].targetPage = annotation[i].pageIndex * 1 + 1
- let currentAnnotation = JSON.parse(JSON.stringify(annotation[i]))
- if (currentAnnotation.inklist) {
- currentAnnotation = this.handleInk(currentAnnotation)
- }
- annotateHandles.push(currentAnnotation)
- }
- } else {
- const annotations = this.annotations[annotation.pageIndex]
- if (!annotations) return
- const index = findIndex(annotation.name, annotations)
- if (this.webviewerServer) {
- annotation.index = index + 1
- }
- if (data.type === 'delete') {
- annotations.splice(index, 1)
- if (!annotations.length) {
- delete this.annotations[annotation.pageIndex]
- }
- if (!this.webviewerServer) {
- this.messageHandler.sendWithPromise('RemoveAnnot', {
- annotPtr: annotation.annotPtr
- })
- }
- } else if (data.type === 'empty') {
- annotations.splice(index, 1)
- if (!annotations.length) {
- delete this.annotations[annotation.pageIndex]
- }
- return
- } else {
- if (!this.webviewerServer) {
- annotation.doc = this.doc
- this.messageHandler.sendWithPromise('EditAnnotation', {
- annotation
- })
- }
- const rawAnnotation = annotations[index]
- annotations[index] = {
- ...rawAnnotation,
- ...annotation
- }
- }
- annotation.targetPage = annotation.pageIndex + 1
- let currentAnnotation = annotation
- if (currentAnnotation.inklist) {
- currentAnnotation = this.handleInk(currentAnnotation)
- }
- annotateHandles.push(currentAnnotation)
- }
- this.eventBus.dispatch('annotationChanged', { annotations: this.annotations })
- if (this.webviewerServer) {
- this.#convertAnnotationsForBackend(annotateHandles)
- const options = {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- 'Authorization': this._token
- },
- body: JSON.stringify({
- pdfId: this._pdfId,
- annotateHandles
- }),
- }
- return await fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.editUrl, options)
- .then((res) => {
- return res.json()
- })
- .then((data) => {
- if (data.code === "200") {
- return true
- } else {
- return false
- }
- })
- .catch((error) => (console.log(error)));
- }
- return true
- }
- #convertAnnotationsForBackend(annotations) {
- console.log(annotations)
- for (let i =0; i < annotations.length; i++) {
- const annotation = annotations[i]
- switch (annotation.type) {
- case 'freetext':
- annotation.fillColor = annotation.bgColor
- delete annotation.bgColor
- break
- }
- for (let key in annotation) {
- switch (key) {
- case 'rect':
- annotation.rect = this.#formatRectForBackend(annotation.rect, annotation.pageIndex)
- break
- case 'linePoints':
- annotation.linePoints = this.#formatLinePointsForBackend(annotation.linePoints, annotation.pageIndex)
- break
- case 'borderWidth':
- annotation.lineWidth = annotation.borderWidth
- break
- case 'textAlignment':
- annotation.alignment = annotation.textAlignment
- delete annotation.textAlignment
- break
- case 'stampType':
- if (annotation.stampType === 'standard') {
- annotation.standardStampType = annotation.content
- } else if (annotation.stampType === 'text') {
- annotation.textStampFirststring = annotation.content
- annotation.textStampSecondstring = annotation.time
- annotation.textStampColor = annotation.stampColor
- annotation.textStampShape = annotation.stampShape
- delete annotation.time
- delete annotation.stampColor
- delete annotation.stampShape
- } else if (annotation.stampType === 'image') {
- annotation.type = 'image'
- delete annotation.annotPtr
- delete annotation.imageData
- delete annotation.pagePtr
- }
- delete annotation.content
- break
- case 'inkPointes':
- const { height } = this.pagesPtr[annotation.pageIndex]
- const inkPointes = annotation.inkPointes
- let points = ''
- for (let i = 0; i < inkPointes.length; i++) {
- const inkPoint = inkPointes[i]
- for (let j = 0; j + 1 < inkPoint.length; j+=2) {
- if (j === 0) {
- points+=inkPoint[j].PointX
- }
- points+=`,${height - inkPoint[j + 1].PointY}`
- }
- points+='//'
- }
- delete annotation.inkPointes
- annotation.inklist = points
- break
- }
- }
- }
- }
- #formatRectForBackend(rect, pageIndex) {
- const { height } = this.pagesPtr[pageIndex]
- const { left, top: rawTop, right, bottom: rawBottom } = rect
- const top = height - rawTop
- const bottom = height - rawBottom
- return `${left},${bottom},${right},${top}`
- }
- #formatLinePointsForBackend(linePoints, pageIndex) {
- const { height } = this.pagesPtr[pageIndex]
- const top = height - linePoints[1]
- const bottom = height - linePoints[3]
- return `${linePoints[0]},${top},${linePoints[2]},${bottom}`
- }
- emptyAnnotations() {
- const annotations = this.annotations
- if (this.annotations) {
- for (let pageIndex in annotations) {
- this.pdfViewer._pages[pageIndex].emptyAnnotations()
- }
- }
- }
- handleCreateSignature(data) {
- this.addAnnotations(data)
- }
- webViewerDistanceChanged(evt) {
- this.distanceChangedCallback(evt.distance)
- }
- progress(level) {
- if (this.downloadComplete) {
- // Don't accidentally show the loading bar again when the entire file has
- // already been fetched (only an issue when disableAutoFetch is enabled).
- return
- }
- const percent = Math.round(level * 100);
- // When we transition from full request to range requests, it's possible
- // that we discard some of the loaded data. This can cause the loading
- // bar to move backwards. So prevent this by only updating the bar if it
- // increases.
- if (percent <= this.percent) {
- return
- }
- this.percent = percent;
- }
- async flattenPdfDownload() {
- if (this._token && this._pdfId) {
- const data = {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- 'Authorization': this._token
- },
- body: JSON.stringify({
- pdfId: this._pdfId
- })
- }
- return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.flattenUrl, data)
- .then(async (res) => {
- const type = res.headers.get("content-type")
- if (type.startsWith("application/json")) {
- const errorObj = await res.json();
- return Promise.reject(errorObj);
- } else {
- return res.blob()
- }
- })
- .then((data) => {
- saveAs(data, this._docName)
- return true
- })
- .catch((error) => {
- console.log(error)
- return false
- });
- } else {
- let saveType = 2
- if (!this.saveAction || this.saveAction === 'set') {
- saveType = 2
- } else if (this.saveAction === 'remove') {
- saveType = 3
- }
- const blobData = await this.messageHandler.sendWithPromise('FlattenPage', {
- doc: this.doc,
- pagesPtr: this.pagesPtr,
- saveType,
- password: this.#pwd,
- oldPassword: this.#oldPwd
- })
- saveAs(blobData, this._docName)
- return true
- }
- }
- async download(download = false, data, type) {
- if (data) {
- data.forEach(file => {
- saveAs(file.url, file.fileName)
- })
- } else if (this._token && this._pdfId) {
- const data = {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- 'Authorization': this._token
- },
- body: JSON.stringify({
- pdfId: this._pdfId
- })
- }
- return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.saveUrl, data)
- .then(async (res) => {
- const type = res.headers.get("content-type")
- if (type.startsWith("application/json")) {
- const errorObj = await res.json();
- return Promise.reject(errorObj);
- } else {
- return res.blob()
- }
- })
- .then((data) => {
- if (download) {
- saveAs(data, this._docName)
- }
- return data
- })
- .catch((error) => {
- console.log(error)
- return false
- });
- } else {
- let saveType = 2
- if (!this.saveAction || this.saveAction === 'set') {
- saveType = 2
- } else if (this.saveAction === 'remove') {
- saveType = 3
- }
- const blobData = await this.messageHandler.sendWithPromise('SaveDocumentByStream', {
- doc: this.doc,
- saveType: type || saveType,
- password: this.#pwd,
- oldPassword: this.#oldPwd
- })
- if (download) {
- saveAs(blobData, this._docName)
- }
- return blobData
- }
- }
- async exportXfdf(download = true) {
- const xfdf = await this.messageHandler.sendWithPromise('XFDFExportAnnotations', {
- doc: this.doc
- })
- const blob = new Blob([xfdf], { type: 'application/vnd.adobe.xfdf' })
- if (download) {
- const name = this._docName.replace(/\.pdf$/, '.xfdf')
- saveAs(blob, name)
- }
- return blob
- return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.downloadAnnotation + "?pdfId=" + this._pdfId, {
- method: 'GET',
- headers: {
- "Content-Type": "application/json",
- 'Authorization': this._token
- }
- })
- .then(async (res) => {
- const type = res.headers.get("content-type")
- if (type.startsWith("application/json")) {
- const errorObj = await res.json();
- return Promise.reject(errorObj);
- } else {
- return res.blob()
- }
- })
- .then((data) => {
- const name = this._docName.replace(/\.pdf$/, '.xfdf')
- saveAs(data, name)
- return true
- })
- .catch((error) => {
- console.log(error)
- return false
- });
- }
- _initializeViewerComponents({
- container,
- viewer,
- thumbnailView,
- annotationView,
- findbarView,
- toggleButton,
- }) {
- this.viewerContainer = viewer
- const pdfRenderingQueue = new PDFRenderingQueue();
- pdfRenderingQueue.onIdle = this._cleanup.bind(this);
- this.pdfRenderingQueue = pdfRenderingQueue;
- const pdfLinkService = new PDFLinkService();
- this.pdfLinkService = pdfLinkService;
- this.pdfViewer = new PDFViewer({
- container,
- viewer,
- messageHandler: this.messageHandler,
- annotationStore,
- tool: {
- tool: this.activeTool,
- color: this.color
- },
- annotationView,
- renderingQueue: pdfRenderingQueue,
- linkService: pdfLinkService,
- renderer: 'canvas',
- textLayerMode: 1,
- enablePrintAutoRotate: true,
- eventBus: this.eventBus,
- $t: this.$t,
- doc: this.doc,
- messageHandler: this.messageHandler
- });
- pdfRenderingQueue.setViewer(this.pdfViewer);
- pdfLinkService.setViewer(this.pdfViewer);
- if (thumbnailView) {
- this.pdfThumbnailViewer = new PDFThumbnailViewer({
- container: thumbnailView,
- renderingQueue: pdfRenderingQueue,
- linkService: pdfLinkService
- });
- pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
- }
- this.pdfCursorTools = new PDFCursorTools({
- container,
- eventBus: this.eventBus,
- cursorToolOnLoad: 0,
- });
- if (this.supportsFullscreen) {
- this.pdfPresentationMode = new PDFPresentationMode({
- container,
- pdfViewer: this.pdfViewer,
- eventBus: this.eventBus,
- });
- }
- this.passwordPrompt = new PasswordPrompt(
- {
- dialog: document.getElementById("passwordDialog"),
- label: document.getElementById("passwordText"),
- input: document.getElementById("password"),
- submitButton: document.getElementById("passwordSubmit"),
- cancelButton: document.getElementById("passwordCancel"),
- $t: this.$t
- }
- );
- if (toggleButton) {
- this.pdfSidebar = new PDFSidebar({
- elements: {
- toggleButton
- },
- pdfViewer: this.pdfViewer,
- pdfThumbnailViewer: this.pdfThumbnailViewer,
- eventBus: this.eventBus
- });
- this.pdfSidebar.onToggled = this.forceRendering.bind(this);
- }
- }
- setInitialView(
- storedHash,
- { rotation, sidebarView, scrollMode, spreadMode } = {}
- ) {
- const setRotation = angle => {
- if (isValidRotation(angle)) {
- this.pdfViewer.pagesRotation = angle;
- }
- };
- const setViewerModes = (scroll, spread) => {
- if (isValidScrollMode(scroll)) {
- this.pdfViewer.scrollMode = scroll;
- }
- if (isValidSpreadMode(spread)) {
- this.pdfViewer.spreadMode = spread;
- }
- };
- this.isInitialViewSet = true;
- // this.pdfSidebar.setInitialView(sidebarView);
- setViewerModes(scrollMode, spreadMode);
- if (!this.pdfViewer.currentScaleValue) {
- // Scale was not initialized: invalid bookmark or scale was not specified.
- // Setting the default one.
- this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
- }
- this.pdfViewer.forceRendering()
- }
- requestFullScreenMode() {
- this.pdfPresentationMode?.request();
- }
- /**
- * @private
- */
- _cleanup() {
- if (!this.pdfDocument) {
- return; // run cleanup when document is loaded
- }
- this.pdfViewer.cleanup();
- this.pdfThumbnailViewer?.cleanup();
- // We don't want to remove fonts used by active page SVGs.
- this.pdfDocument.cleanup(
- /* keepLoadedFonts = */ this.pdfViewer.renderer === 'svg'
- );
- }
- cleanup() {
- this._cleanup()
- }
- zoomIn(steps) {
- if (this.pdfViewer.isInPresentationMode) {
- return;
- }
- this.pdfViewer.increaseScale({
- drawingDelay: 400
- });
- }
- zoomOut(steps) {
- if (this.pdfViewer.isInPresentationMode) {
- return;
- }
- this.pdfViewer.decreaseScale({
- drawingDelay: 400
- });
- }
- nextPage() {
- return this.pdfViewer.nextPage()
- }
- previousPage() {
- return this.pdfViewer.previousPage()
- }
- pageNumberChanged(value) {
- // Note that for `<input type="number">` HTML elements, an empty string will
- // be returned for non-number inputs; hence we simply do nothing in that case.
- if (value !== "") {
- this.pdfLinkService.goToPage(value);
- }
- // Ensure that the page number input displays the correct value, even if the
- // value entered by the user was invalid (e.g. a floating point number).
- if (
- value !== this.pdfViewer.currentPageNumber.toString() &&
- value !== this.pdfViewer.currentPageLabel
- ) {
- this.toolbar && this.toolbar.setPageNumber(
- pdfViewer.currentPageNumber,
- pdfViewer.currentPageLabel
- );
- }
- }
- scrollTo({
- left,
- top
- }) {
- scrollIntoView(this.viewerContainer, {
- left,
- top
- })
- }
- webViewerAnnotationsCountChanged(evt) {
- this.annotationsNumChangedCallback(evt.annotationsCount);
- }
- forceRendering() {
- this.pdfRenderingQueue.printing = !!this.printService;
- this.pdfRenderingQueue.isThumbnailViewEnabled =
- this.pdfSidebar.visibleView === SidebarView.THUMBS;
- this.pdfRenderingQueue.renderHighestPriority();
- }
- webViewerResize() {
- const { pdfDocument, pdfViewer, pdfRenderingQueue } = this;
- if (pdfRenderingQueue.printing && window.matchMedia("print").matches) {
- // Work-around issue 15324 by ignoring "resize" events during printing.
- return;
- }
- if (!pdfDocument) {
- return;
- }
- console.log('resize')
- const currentScaleValue = pdfViewer.currentScaleValue;
- if (
- currentScaleValue === "auto" ||
- currentScaleValue === "page-fit" ||
- currentScaleValue === "page-width"
- ) {
- // Note: the scale is constant for 'page-actual'.
- pdfViewer.resize(currentScaleValue)
- }
- // pdfViewer.update();
- }
- webViewerPageRendered({ pageNumber, error }) {
- // If the page is still visible when it has finished rendering,
- // ensure that the page number input loading indicator is hidden.
- /** if (pageNumber === this.page) {
- this.toolbar.updateLoadingIndicatorState(false);
- } */
- // Use the rendered page to set the corresponding thumbnail image.
- if (this.pdfSidebar?.visibleView === SidebarView.THUMBS) {
- const pageView = this.pdfViewer.getPageView(
- /* index = */ pageNumber - 1
- );
- const thumbnailView = this.pdfThumbnailViewer.getThumbnail(
- /* index = */ pageNumber - 1
- );
- if (pageView && thumbnailView) {
- thumbnailView.setImage(pageView);
- }
- }
- }
- get annotationMode() {
- return this._annotationMode
- }
- set annotationMode(mode) {
- this._annotationMode = mode;
- }
- webViewerSwitchAnnotationEditorMode(evt) {
- this.pdfViewer.annotationEditorMode = evt.mode;
- }
- switchTool(mode) {
- this.pdfCursorTools.switchTool(mode);
- }
- webViewerUpdateViewarea({ location }) {
- if (this.isInitialViewSet) {
- // Only update the storage when the document has been loaded *and* rendered.
- this.store
- ?.setMultiple({
- page: location.pageNumber,
- zoom: location.scale,
- scrollLeft: location.left,
- scrollTop: location.top,
- rotation: location.rotation,
- })
- .catch(() => {
- // Unable to write to storage.
- });
- }
- if (this.#textSearch) {
- this.#textSearch.updateMatch()
- }
- }
- webViewerScrollModeChanged(evt) {
- if (
- this.isInitialViewSet &&
- !this.pdfViewer.isInPresentationMode
- ) {
- // Only update the storage when the document has been loaded *and* rendered.
- this.store?.set("scrollMode", evt.mode).catch(() => {
- // Unable to write to storage.
- });
- }
- }
- webViewerScaleChanging(evt) {
- // this.toolbar.setPageScale(evt.presetValue, evt.scale);
- // this.pdfViewer.update();
- this.scaleChangedCallback && this.scaleChangedCallback(evt.scale)
- }
- webViewerRotationChanging(evt) {
- this.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
- this.forceRendering();
- // Ensure that the active page doesn't change during rotation.
- this.pdfViewer.currentPageNumber = evt.pageNumber;
- }
- webViewerPageChanging({ pageNumber, pageLabel }) {
- // this.toolbar.setPageNumber(pageNumber, pageLabel);
- // this.secondaryToolbar.setPageNumber(pageNumber);
- if (this.pdfSidebar?.visibleView === SidebarView.THUMBS) {
- this.pdfThumbnailViewer.scrollThumbnailIntoView(pageNumber);
- }
- this.pageChangedCallback(this.page)
- }
- webViewerSidebarViewChanged({ view }) {
- this.pdfRenderingQueue.isThumbnailViewEnabled =
- view === SidebarView.THUMBS;
- if (this.isInitialViewSet) {
- // Only update the storage when the document has been loaded *and* rendered.
- this.store?.set("sidebarView", view).catch(() => {
- // Unable to write to storage.
- });
- }
- }
- webViewerPageMode({ mode }) {
- // Handle the 'pagemode' hash parameter, see also `PDFLinkService_setHash`.
- let view;
- switch (mode) {
- case "thumbs":
- view = SidebarView.THUMBS;
- break;
- case "bookmarks":
- case "outline": // non-standard
- view = SidebarView.OUTLINE;
- break;
- case "attachments": // non-standard
- view = SidebarView.ATTACHMENTS;
- break;
- case "layers": // non-standard
- view = SidebarView.LAYERS;
- break;
- case "none":
- view = SidebarView.NONE;
- break;
- default:
- console.error('Invalid "pagemode" hash parameter: ' + mode);
- return;
- }
- this.pdfSidebar.switchView(view, /* forceOpen = */ true);
- }
- async webViewerNamedAction(evt) {
- // Processing a couple of named actions that might be useful, see also
- // `PDFLinkService.executeNamedAction`.
- switch (evt.action) {
- case "GoToPage":
- this.appConfig.toolbar.pageNumber.select();
- break;
- case "Print":
- const url = await this.download(false, null, 3)
- this.triggerPrinting(url);
- return url
- break;
- case "SaveAs":
- this.downloadOrSave();
- break;
- }
- }
- triggerPrinting(data) {
- let url = data instanceof Blob ? URL.createObjectURL(data) : data
- url = decodeURIComponent(url)
- printJS({
- url,
- printable: url,
- type: 'pdf',
- showModal: false
- });
- }
- webViewerPresentationModeChanged(evt) {
- this.pdfViewer.presentationModeState = evt.state;
- }
- webViewerPresentationMode() {
- this.requestPresentationMode();
- }
- webViewerNextPage() {
- this.pdfViewer.nextPage();
- }
- webViewerPreviousPage() {
- this.pdfViewer.previousPage();
- }
- webViewerZoomIn() {
- this.zoomIn();
- }
- webViewerZoomOut() {
- this.zoomOut();
- }
- webViewerPageNumberChanged(evt) {
- const pdfViewer = this.pdfViewer;
- // Note that for `<input type="number">` HTML elements, an empty string will
- // be returned for non-number inputs; hence we simply do nothing in that case.
- if (evt.value !== "") {
- this.pdfLinkService.goToPage(evt.value);
- }
- // Ensure that the page number input displays the correct value, even if the
- // value entered by the user was invalid (e.g. a floating point number).
- if (
- evt.value !== pdfViewer.currentPageNumber.toString() &&
- evt.value !== pdfViewer.currentPageLabel
- ) {
- this.toolbar.setPageNumber(
- pdfViewer.currentPageNumber,
- pdfViewer.currentPageLabel
- );
- }
- }
- webViewerScaleChanged(value) {
- this.pdfViewer.currentScaleValue = value;
- }
- webViewerRotateCw() {
- this.rotatePages(90);
- }
- webViewerRotateCcw() {
- this.rotatePages(-90);
- }
- webViewerSwitchScrollMode(mode) {
- this.pdfViewer.scrollMode = mode;
- }
- webViewerSwitchSpreadMode(mode) {
- this.pdfViewer.spreadMode = mode;
- }
- rotatePages(delta) {
- this.pdfViewer.pagesRotation += delta;
- // Note that the thumbnail viewer is updated, and rendering is triggered,
- // in the 'rotationchanging' event handler.
- }
- webViewerSpreadModeChanged(evt) {
- if (
- this.isInitialViewSet &&
- !this.pdfViewer.isInPresentationMode
- ) {
- // Only update the storage when the document has been loaded *and* rendered.
- this.store?.set("spreadMode", evt.mode).catch(() => {
- // Unable to write to storage.
- });
- }
- }
- webViewerFindFromUrlHash(evt) {
- this.eventBus.dispatch("find", {
- source: evt.source,
- type: "",
- query: evt.query,
- phraseSearch: evt.phraseSearch,
- caseSensitive: false,
- entireWord: false,
- highlightAll: true,
- findPrevious: false,
- matchDiacritics: true,
- });
- }
- webViewerUpdateFindMatchesCount({ matchesCount }) {
- if (this.supportsIntegratedFind) {
- this.externalServices.updateFindMatchesCount(matchesCount);
- } else {
- this.findBar.updateResultsCount(matchesCount);
- }
- }
- webViewerUpdateFindControlState({
- state,
- previous,
- matchesCount,
- rawQuery,
- }) {
- if (this.supportsIntegratedFind) {
- this.externalServices.updateFindControlState({
- result: state,
- findPrevious: previous,
- matchesCount,
- rawQuery,
- });
- } else {
- this.findBar.updateUIState(state, previous, matchesCount);
- }
- }
- webViewerFileInputChange(evt) {
- if (this.pdfViewer?.isInPresentationMode) {
- return; // Opening a new PDF file isn't supported in Presentation Mode.
- }
- const file = evt.fileInput.files[0];
- let url = URL.createObjectURL(file);
- if (file.name) {
- url = { url, originalUrl: file.name };
- }
- this.open(url);
- };
- // eslint-disable-next-line no-var
- webViewerOpenFile(evt) {
- const fileInput = this.appConfig.openFileInput;
- fileInput.click();
- }
- async setToolMode(mode) {
- const oldMode = this.toolMode;
- this.toolMode = mode;
- if (mode === 'editor' && !this.fontFileInited) {
- await this.initFontFile()
- }
- this.eventBus.dispatch("toolModeChanged", mode);
- if (oldMode === 'editor' && this.toolMode !== 'editor') {
- await this.updateTextPtr();
- }
- for (let page in this.annotations) {
- for (let i = 0; i < this.annotations[page].length; i++) {
- const annot = this.annotations[page][i]
- const element = document.getElementById(annot['name'])
- if (element) {
- if (this.toolMode !== 'form') {
- if (annot.isHidden == 1) {
- element.style.display = 'none';
- element.style.pointerEvents = 'none';
- } else if (annot.isHidden == 0) {
- element.style.display = 'block';
- element.style.pointerEvents = 'auto';
- }
- } else {
- element.style.display = 'block';
- element.style.pointerEvents = 'auto';
- }
- }
- }
- }
- }
- async updateTextPtr() {
- await this.messageHandler.sendWithPromise('ClearPage', {
- doc: this.doc
- })
- for (let pageIndex = 0; pageIndex < this.pagesCount; pageIndex++) {
- await this.messageHandler.sendWithPromise('ClearText', {
- textPtr: this.pagesPtr[pageIndex].textPtr
- })
- const pageSize = await this.messageHandler.sendWithPromise("GetPageSize", {
- doc: this.doc,
- pageIndex
- })
- const textPtr = await this.messageHandler.sendWithPromise('InitText', {
- pagePtr: pageSize.pagePtr
- })
- this.pagesPtr[pageIndex].textPtr = textPtr
- this.pagesPtr[pageIndex].pagePtr = pageSize.pagePtr
- }
- this.pdfViewer.pagesPtr = this.pagesPtr
- this.pdfViewer._pages.forEach(page => {
- page.pagesPtr = this.pagesPtr
- });
- this.pdfViewer.refresh()
- }
- setPropertyPanel(props) {
- this.eventBus.dispatch("propertyPanelChanged", props);
- }
- setTextProperty(props) {
- this.eventBus.dispatch("textPropertyChanged", props);
- }
- setInitProperty() {
- if (this.activeTool === 'textfield') {
- this.eventBus.dispatch("initTextfieldName");
- } else if (this.activeTool === 'checkbox') {
- this.eventBus.dispatch("initCheckboxName");
- } else if (this.activeTool === 'radiobutton') {
- this.eventBus.dispatch("initRadioButtonName");
- } else if (this.activeTool === 'pushbutton') {
- this.eventBus.dispatch("initPushButtonName");
- }
- }
- handleField(prop) {
- const id = prop.id
- const key = prop.key
- const value = prop.value
- if (!id) return
- let annotationsAll = Object.values(annotationStore.annotationsAll).reduce(function (acc, curr) {
- return acc.concat(curr);
- }, []);
- let targetObj = annotationsAll.find(obj => obj.name === id)
- if (key && (value || value === 0)) {
- let props = {
- name: id
- }
- props[key] = value
- this.eventBus.dispatch("setProperty", props)
- }
- return targetObj
- }
- handleSign(flag, param) {
- if (flag === 'create' && !this.InkSign) {
- this.InkSign = new InkSign({
- pdfViewer: this.pdfViewer,
- eventBus: this.eventBus,
- })
- }
- if (!this.InkSign) return;
- if (flag === 'clear' || flag === 'create') {
- this.InkSign.clear()
- }
- if (flag === 'save') {
- this.InkSign.toImage(param)
- }
- if (flag === 'reset') {
- this.InkSign.reset()
- this.InkSign = null
- }
- if (flag === "update") {
- this.InkSign.update(param)
- }
- }
- handleStamp(data) {
- if (!data) return
- let imgUi = data.stampContainer
- let pageNum = data.page
- let pageView = this.pdfViewer.getPageView(pageNum - 1)
- let rect = null
- let annotData = null
- if (pageView && imgUi) {
- let pageWidth = pageView.viewport.viewBox[2]
- let pageHeight = pageView.viewport.viewBox[3]
- let imgWidth = imgUi.width
- let imgHeight = imgUi.height
- let left = (pageWidth - imgWidth) / 2
- let top = (pageHeight - imgHeight) / 2
- let right = (pageWidth + imgWidth) / 2
- let bottom = (pageHeight + imgHeight) / 2
- rect = {
- left,
- top,
- right,
- bottom,
- }
- }
- if (data.stampType === 'standard') {
- annotData = {
- operate: 'add-annot',
- type: 'stamp',
- pageIndex: pageNum - 1,
- rect,
- stampColor: 'white',
- date: new Date(),
- stampType: 'standard',
- content: imgUi.alt
- }
- }
- if (data.stampType === 'dynamic') {
- annotData = {
- operate: 'add-annot',
- type: 'stamp',
- date: new Date(),
- pageIndex: pageNum - 1,
- // rect,
- content: data.text,
- time: data.time,
- stampColor: data.color,
- stampType: 'text'
- }
- }
- annotData.stampShape = 0
- this.addAnnotations(annotData)
- }
- async compare(data) {
- if (this.webviewerServer) {
- const formData = new FormData()
- for (let key in data) {
- formData.append(key, data[key])
- }
- const options = {
- method: 'POST',
- headers: {
- 'Authorization': this._token
- },
- body: formData
- }
- return fetch(this.optionUrl.webviewBaseUrl + this.optionUrl.compareUrl, options)
- .then(async (res) => {
- const type = res.headers.get("content-type")
- if (type.startsWith("application/json")) {
- const errorObj = await res.json();
- return Promise.reject(errorObj);
- } else {
- const filename = res.headers.get("Content-Disposition").split("filename=")[1];
- return { filename, blobData: res.blob(), type };
- }
- })
- .then(async ({ filename, blobData, type }) => {
- if (type === 'application/zip') {
- return await unzipAndReadFiles(blobData)
- } else {
- // return blobData.then(blob => {
- // const reader = new FileReader();
- // reader.onload = function(event) {
- // const content = event.target.result;
- // console.log(content); // 打印blobData的内容
- // };
- // reader.readAsDataURL(blob);
- // return { filename, url: URL.createObjectURL(blob) };
- // })
- return blobData.then(blob => ({
- filename,
- url: URL.createObjectURL(blob)
- }));
- }
- })
- .then((resp) => resp)
- .catch((error) => ({ error: true, message: error.message }));
- } else {
- const res = await this.messageHandler.sendWithPromise('CompareDocument', {
- data
- })
- if (data.type === 1) {
- return [{
- filename: data.leftFile.name.replace(/(\.pdf)/, `_${this.$t('compare.byComPDFKit')}.pdf`),
- url: URL.createObjectURL(res[0])
- }, {
- filename: data.rightFile.name.replace(/(\.pdf)/, `_${this.$t('compare.byComPDFKit')}.pdf`),
- url: URL.createObjectURL(res[1])
- }, {
- filename: this.$t('compare.byComPDFKit') + '.pdf',
- url: URL.createObjectURL(res[2])
- }
- ]
- } else if (data.type === 2) {
- return {
- filename: this._docName,
- url: URL.createObjectURL(res)
- }
- }
- // const { oldData, newData } = res
- // let oldBlobData = new Blob(oldData, { type: "application/pdf" })
- // saveAs(oldBlobData, 'old' + this._docName)
- // let newBlobData = new Blob(newData, { type: "application/pdf" })
- // saveAs(newBlobData, 'new' + this._docName)
- }
- }
- async checkPassword(file) {
- const parameters = {
- cMapUrl: CMAP_URL,
- cMapPacked: true,
- enableXfa: true
- };
- if (typeof file === "string") {
- // URL
- parameters.url = file
- } else if (file && "byteLength" in file) {
- // ArrayBuffer
- parameters.data = file;
- } else if (file.url && file.originalUrl) {
- parameters.url = file.url;
- }
- const loadingTask = getDocument(parameters)
- this.pdfLoadingTask = loadingTask
- this.#pwd = ''
- const getPwd = (pwd) => this.#pwd = pwd
- loadingTask.onPassword = (updateCallback, reason) => {
- this.passwordPrompt.setUpdateCallback(updateCallback, reason, getPwd);
- this.passwordPrompt.open();
- };
- return await loadingTask.promise.then(() => {
- if (this.#pwd) return this.#pwd
- return ''
- }).catch((error) => {
- return false
- })
- }
- handleCreateStatus({
- bool,
- fileData
- }) {
- annotationStore.creating = bool
- annotationStore.fileData = fileData
- }
- async initFontFile() {
- try {
- this.pdfViewer.setFontFile(this.#fonFile)
- this.fontFileInited = true
- } catch (error) {
- console.log(error)
- }
- }
- }
- class PDFWorker {
- destroyed = false
- constructor() {
- this._promiseCapability = new PromiseExt()
- this._messageHandler = null
- this._webWorker = null
- this._initialize()
- }
- _initialize() {
- try {
- const workerSrc = "./lib/PDFWorker.js"
- const worker = new Worker(workerSrc)
- const messageHandler = new MessageHandler('main', 'worker', worker)
- this._messageHandler = messageHandler
- const terminateEarly = () => {
- worker.removeEventListener("error", onWorkerError)
- messageHandler.destroy()
- worker.terminate()
- if (this.destroyed) {
- this._promiseCapability.reject(new Error("Worker was destroyed"))
- } else {
- console.error("The worker has been disabled.")
- }
- }
- const onWorkerError = () => {
- if (!this._webWorker) {
- // Worker failed to initialize due to an error. Clean up and fall
- // back to the fake worker.
- terminateEarly();
- }
- }
- worker.addEventListener("error", onWorkerError)
- messageHandler.on("test", (data) => {
- worker.removeEventListener("error", onWorkerError)
- if (this.destroyed) {
- terminateEarly();
- return; // worker was destroyed
- }
- if (data) {
- this._messageHandler = messageHandler
- this._webWorker = worker
- this._promiseCapability.resolve(true);
- }
- })
- messageHandler.on("ready", data => {
- worker.removeEventListener("error", onWorkerError);
- if (this.destroyed) {
- terminateEarly();
- return; // worker was destroyed
- }
- try {
- sendTest();
- messageHandler.send("Ready", true)
- } catch {
- console.error("The worker has been disabled.")
- }
- })
- const sendTest = () => {
- const testObj = new Uint8Array();
- // Ensure that we can use `postMessage` transfers.
- messageHandler.send("test", testObj);
- }
- sendTest()
- } catch (error) {
- console.log(error)
- console.log("The worker has been disabled.")
- }
- }
- get promise() {
- return this._promiseCapability.promise;
- }
- get messageHandler() {
- return this._messageHandler;
- }
- destroy() {
- this.destroyed = true
- if (this._webWorker) {
- // We need to terminate only web worker created resource.
- this._webWorker.terminate()
- this._webWorker = null
- }
- if (this._messageHandler) {
- this._messageHandler.destroy()
- this._messageHandler = null
- }
- }
- }
- // 解压缩zip文件
- function unzipAndReadFiles(zipBlob) {
- return new Promise((resolve, reject) => {
- const jzip = new JSZip();
- jzip.loadAsync(zipBlob)
- .then((zipFiles) => {
- const filePromises = Object.keys(zipFiles.files).map(fileName => {
- return zipFiles.file(fileName).async("uint8array").then(fileData => {
- const blob = new Blob([fileData], { type: 'application/octet-stream' });
- const url = URL.createObjectURL(blob);
- return { fileName, url };
- });
- });
- Promise.all(filePromises)
- .then(resolve)
- .catch(reject);
- })
- .catch((error) => {
- reject(error);
- });
- });
- }
- export default ComPDFKitViewer
|