- WordPress core y plugins - Tema Twenty Twenty-Four configurado - Plugin allow-unfiltered-html.php simplificado - .gitignore configurado para excluir wp-config.php y uploads 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2019 lines
55 KiB
JavaScript
Executable File
2019 lines
55 KiB
JavaScript
Executable File
const pdfjsLib = require('pdfjs-dist');
|
|
import {
|
|
animationStarted,
|
|
apiPageLayoutToViewerModes,
|
|
AutoPrintRegExp,
|
|
DEFAULT_SCALE_VALUE,
|
|
getActiveOrFocusedElement,
|
|
isValidRotation,
|
|
isValidScrollMode,
|
|
isValidSpreadMode,
|
|
noContextMenuHandler,
|
|
normalizeWheelEventDirection,
|
|
parseQueryString,
|
|
ProgressBar,
|
|
RendererType,
|
|
RenderingStates,
|
|
ScrollMode,
|
|
SpreadMode,
|
|
TextLayerMode,
|
|
} from './ui_utils.js';
|
|
import { Toolbar } from './toolbar.js';
|
|
import { PDFFindController } from './pdf_find_controller.js';
|
|
import { PDFFindBar } from './pdf_find_bar.js';
|
|
import { OverlayManager } from './overlay_manager.js';
|
|
import { AppOptions, OptionKind } from './app_options.js';
|
|
|
|
import { CursorTool, PDFCursorTools } from './pdf_cursor_tools.js';
|
|
|
|
const pdfjsViewer = require('pdfjs-dist/web/pdf_viewer.js');
|
|
|
|
const DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000; // ms
|
|
const FORCE_PAGES_LOADED_TIMEOUT = 10000; // ms
|
|
const WHEEL_ZOOM_DISABLED_TIMEOUT = 1000; // ms
|
|
|
|
const ViewOnLoad = {
|
|
UNKNOWN: -1,
|
|
PREVIOUS: 0, // Default value.
|
|
INITIAL: 1,
|
|
};
|
|
|
|
const ViewerCssTheme = {
|
|
AUTOMATIC: 0, // Default value.
|
|
LIGHT: 1,
|
|
DARK: 2,
|
|
};
|
|
|
|
// Keep these in sync with mozilla-central's Histograms.json.
|
|
const KNOWN_VERSIONS = [
|
|
'1.0',
|
|
'1.1',
|
|
'1.2',
|
|
'1.3',
|
|
'1.4',
|
|
'1.5',
|
|
'1.6',
|
|
'1.7',
|
|
'1.8',
|
|
'1.9',
|
|
'2.0',
|
|
'2.1',
|
|
'2.2',
|
|
'2.3',
|
|
];
|
|
// Keep these in sync with mozilla-central's Histograms.json.
|
|
const KNOWN_GENERATORS = [
|
|
'acrobat distiller',
|
|
'acrobat pdfwriter',
|
|
'adobe livecycle',
|
|
'adobe pdf library',
|
|
'adobe photoshop',
|
|
'ghostscript',
|
|
'tcpdf',
|
|
'cairo',
|
|
'dvipdfm',
|
|
'dvips',
|
|
'pdftex',
|
|
'pdfkit',
|
|
'itext',
|
|
'prince',
|
|
'quarkxpress',
|
|
'mac os x',
|
|
'microsoft',
|
|
'openoffice',
|
|
'oracle',
|
|
'luradocument',
|
|
'pdf-xchange',
|
|
'antenna house',
|
|
'aspose.cells',
|
|
'fpdf',
|
|
];
|
|
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfemb_trans.worker_src;
|
|
const USE_ONLY_CSS_ZOOM = true;
|
|
|
|
const DEFAULT_SCALE_DELTA = 1.1;
|
|
const MIN_SCALE = 0.25;
|
|
const MAX_SCALE = 10.0;
|
|
|
|
class DefaultExternalServices {
|
|
constructor() {
|
|
throw new Error('Cannot initialize DefaultExternalServices.');
|
|
}
|
|
|
|
static updateFindControlState(data) {}
|
|
|
|
static updateFindMatchesCount(data) {}
|
|
|
|
static initPassiveLoading(callbacks) {}
|
|
|
|
static reportTelemetry(data) {}
|
|
|
|
static createDownloadManager(options) {
|
|
throw new Error('Not implemented: createDownloadManager');
|
|
}
|
|
|
|
static createPreferences() {
|
|
throw new Error('Not implemented: createPreferences');
|
|
}
|
|
|
|
static createL10n(options) {
|
|
throw new Error('Not implemented: createL10n');
|
|
}
|
|
|
|
static createScripting(options) {
|
|
throw new Error('Not implemented: createScripting');
|
|
}
|
|
|
|
static get supportsIntegratedFind() {
|
|
return shadow(this, 'supportsIntegratedFind', false);
|
|
}
|
|
|
|
static get supportsDocumentFonts() {
|
|
return shadow(this, 'supportsDocumentFonts', true);
|
|
}
|
|
|
|
static get supportedMouseWheelZoomModifierKeys() {
|
|
return shadow(this, 'supportedMouseWheelZoomModifierKeys', {
|
|
ctrlKey: true,
|
|
metaKey: true,
|
|
});
|
|
}
|
|
|
|
static get isInAutomation() {
|
|
return shadow(this, 'isInAutomation', false);
|
|
}
|
|
|
|
static updateEditorStates(data) {
|
|
throw new Error('Not implemented: updateEditorStates');
|
|
}
|
|
}
|
|
const PDFViewerApplication = {
|
|
initialBookmark: document.location.hash.substring(1),
|
|
appConfig: null,
|
|
pdfLoadingTask: null,
|
|
pdfDocument: null,
|
|
pdfViewer: null,
|
|
pdfHistory: null,
|
|
pdfLinkService: null,
|
|
eventBus: null,
|
|
downloadManager: null,
|
|
store: null,
|
|
/** @type {Toolbar} */
|
|
toolbar: null,
|
|
_boundEvents: Object.create(null),
|
|
/** @type {SecondaryToolbar} */
|
|
secondaryToolbar: null,
|
|
url: '',
|
|
baseUrl: '',
|
|
_downloadUrl: '',
|
|
externalServices: DefaultExternalServices,
|
|
isInitialViewSet: false,
|
|
downloadComplete: false,
|
|
async initalize(appConfig) {
|
|
this.appConfig = appConfig;
|
|
await this.intializeWebView();
|
|
|
|
this.bindEvents();
|
|
this.bindWindowEvents();
|
|
},
|
|
async intializeWebView() {
|
|
const { appConfig } = this;
|
|
let self = this;
|
|
const eventBus = new pdfjsViewer.EventBus();
|
|
this.eventBus = eventBus;
|
|
|
|
this.overlayManager = new OverlayManager();
|
|
|
|
const linkService = new pdfjsViewer.PDFLinkService({
|
|
eventBus,
|
|
externalLinkTarget: AppOptions.get('externalLinkTarget'),
|
|
externalLinkRel: AppOptions.get('externalLinkRel'),
|
|
ignoreDestinationZoom: AppOptions.get('ignoreDestinationZoom'),
|
|
});
|
|
this.pdfLinkService = linkService;
|
|
|
|
const findController = new PDFFindController({
|
|
linkService: linkService,
|
|
eventBus,
|
|
});
|
|
this.findController = findController;
|
|
this.l10n = pdfjsViewer.NullL10n;
|
|
|
|
const container = document.getElementById('viewerContainer');
|
|
const pdfViewer = new pdfjsViewer.PDFViewer({
|
|
container,
|
|
eventBus,
|
|
linkService,
|
|
findController,
|
|
l10n: this.l10n,
|
|
useOnlyCssZoom: USE_ONLY_CSS_ZOOM,
|
|
textLayerMode: AppOptions.get('textLayerMode'),
|
|
_currentScaleValue: 'page-fit',
|
|
});
|
|
|
|
this.pdfViewer = pdfViewer;
|
|
|
|
linkService.setViewer(pdfViewer);
|
|
|
|
this.pdfHistory = new pdfjsViewer.PDFHistory({
|
|
eventBus,
|
|
linkService,
|
|
});
|
|
linkService.setHistory(this.pdfHistory);
|
|
|
|
if (!this.supportsIntegratedFind) {
|
|
this.findBar = new PDFFindBar(
|
|
appConfig.findBar,
|
|
eventBus,
|
|
this.l10n,
|
|
);
|
|
}
|
|
|
|
this.pdfCursorTools = new PDFCursorTools({
|
|
container,
|
|
eventBus,
|
|
cursorToolOnLoad: CursorTool.HAND,
|
|
});
|
|
|
|
this.toolbar = new Toolbar(appConfig.toolbar, eventBus, false);
|
|
|
|
//Set the user settings.
|
|
eventBus.on('pagesinit', function () {
|
|
let toolbarBottom = document.getElementById('toolbar-bottom');
|
|
|
|
//Set the PDF SCALE
|
|
self.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
|
|
self.pdfViewer.scrollMode = pdfemb_trans.continousscroll
|
|
? ScrollMode.VERTICAL
|
|
: ScrollMode.PAGE;
|
|
//Number of pages
|
|
document.getElementById('numPages').innerHTML = self.pagesCount;
|
|
if (typeof toolbarBottom != 'undefined' && toolbarBottom != null) {
|
|
document.getElementById('numPages-bottom').innerHTML =
|
|
self.pagesCount;
|
|
}
|
|
});
|
|
eventBus.on(
|
|
'pagechanging',
|
|
function (evt) {
|
|
const page = evt.pageNumber;
|
|
const numPages = self.pagesCount;
|
|
let toolbarBottom = document.getElementById('toolbar-bottom');
|
|
document.getElementById('pageNumber').value = page;
|
|
document.getElementById('numPages').innerHTML = numPages;
|
|
document.getElementById('previous').disabled = page <= 1;
|
|
document.getElementById('next').disabled = page >= numPages;
|
|
|
|
page >= numPages;
|
|
|
|
document.getElementById('previous').disabled = page <= 1;
|
|
document.getElementById('next').disabled = page >= numPages;
|
|
|
|
if (
|
|
typeof toolbarBottom != 'undefined' &&
|
|
toolbarBottom != null
|
|
) {
|
|
document.getElementById('previous-bottom').disabled =
|
|
page <= 1;
|
|
document.getElementById('next-bottom').disabled =
|
|
document.getElementById('pageNumber-bottom').value =
|
|
page;
|
|
document.getElementById('numPages-bottom').innerHTML =
|
|
numPages;
|
|
document.getElementById('previous-bottom').disabled =
|
|
page <= 1;
|
|
document.getElementById('next-bottom').disabled =
|
|
page >= numPages;
|
|
}
|
|
},
|
|
true,
|
|
);
|
|
},
|
|
/**
|
|
* @private
|
|
*/
|
|
async _initializeMetadata(pdfDocument) {
|
|
const { info, metadata, contentDispositionFilename, contentLength } =
|
|
await pdfDocument.getMetadata();
|
|
|
|
if (pdfDocument !== this.pdfDocument) {
|
|
return; // The document was closed while the metadata resolved.
|
|
}
|
|
this.documentInfo = info;
|
|
this.metadata = metadata;
|
|
this._contentDispositionFilename ??= contentDispositionFilename;
|
|
this._contentLength ??= contentLength; // See `getDownloadInfo`-call above.
|
|
|
|
// Provides some basic debug information
|
|
console.log(
|
|
`PDF ${pdfDocument.fingerprints[0]} [${info.PDFFormatVersion} ` +
|
|
`${(info.Producer || '-').trim()} / ${(
|
|
info.Creator || '-'
|
|
).trim()}] ` +
|
|
`(PDF.js: ${version || '-'})`,
|
|
);
|
|
let pdfTitle = info.Title;
|
|
|
|
const metadataTitle = metadata?.get('dc:title');
|
|
if (metadataTitle) {
|
|
// Ghostscript can produce invalid 'dc:title' Metadata entries:
|
|
// - The title may be "Untitled" (fixes bug 1031612).
|
|
// - The title may contain incorrectly encoded characters, which thus
|
|
// looks broken, hence we ignore the Metadata entry when it contains
|
|
// characters from the Specials Unicode block (fixes bug 1605526).
|
|
if (
|
|
metadataTitle !== 'Untitled' &&
|
|
!/[\uFFF0-\uFFFF]/g.test(metadataTitle)
|
|
) {
|
|
pdfTitle = metadataTitle;
|
|
}
|
|
}
|
|
if (pdfTitle) {
|
|
this.setTitle(
|
|
`${pdfTitle} - ${
|
|
this._contentDispositionFilename || this._title
|
|
}`,
|
|
);
|
|
} else if (this._contentDispositionFilename) {
|
|
this.setTitle(this._contentDispositionFilename);
|
|
}
|
|
|
|
if (
|
|
info.IsXFAPresent &&
|
|
!info.IsAcroFormPresent &&
|
|
!pdfDocument.isPureXfa
|
|
) {
|
|
if (pdfDocument.loadingParams.enableXfa) {
|
|
console.warn(
|
|
'Warning: XFA Foreground documents are not supported',
|
|
);
|
|
} else {
|
|
console.warn('Warning: XFA support is not enabled');
|
|
}
|
|
this.fallback(UNSUPPORTED_FEATURES.forms);
|
|
} else if (
|
|
(info.IsAcroFormPresent || info.IsXFAPresent) &&
|
|
!this.pdfViewer.renderForms
|
|
) {
|
|
console.warn('Warning: Interactive form support is not enabled');
|
|
this.fallback(UNSUPPORTED_FEATURES.forms);
|
|
}
|
|
|
|
if (info.IsSignaturesPresent) {
|
|
console.warn(
|
|
'Warning: Digital signatures validation is not supported',
|
|
);
|
|
this.fallback(UNSUPPORTED_FEATURES.signatures);
|
|
}
|
|
|
|
// Telemetry labels must be C++ variable friendly.
|
|
let versionId = 'other';
|
|
if (KNOWN_VERSIONS.includes(info.PDFFormatVersion)) {
|
|
versionId = `v${info.PDFFormatVersion.replace('.', '_')}`;
|
|
}
|
|
let generatorId = 'other';
|
|
if (info.Producer) {
|
|
const producer = info.Producer.toLowerCase();
|
|
KNOWN_GENERATORS.some(function (generator) {
|
|
if (!producer.includes(generator)) {
|
|
return false;
|
|
}
|
|
generatorId = generator.replace(/[ .-]/g, '_');
|
|
return true;
|
|
});
|
|
}
|
|
let formType = null;
|
|
if (info.IsXFAPresent) {
|
|
formType = 'xfa';
|
|
} else if (info.IsAcroFormPresent) {
|
|
formType = 'acroform';
|
|
}
|
|
this.externalServices.reportTelemetry({
|
|
type: 'documentInfo',
|
|
version: versionId,
|
|
generator: generatorId,
|
|
formType,
|
|
});
|
|
|
|
this.eventBus.dispatch('metadataloaded', { source: this });
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
async _initializePageLabels(pdfDocument) {
|
|
const labels = await pdfDocument.getPageLabels();
|
|
|
|
if (pdfDocument !== this.pdfDocument) {
|
|
return; // The document was closed while the page labels resolved.
|
|
}
|
|
if (!labels || AppOptions.get('disablePageLabels')) {
|
|
return;
|
|
}
|
|
const numLabels = labels.length;
|
|
// Ignore page labels that correspond to standard page numbering,
|
|
// or page labels that are all empty.
|
|
let standardLabels = 0,
|
|
emptyLabels = 0;
|
|
for (let i = 0; i < numLabels; i++) {
|
|
const label = labels[i];
|
|
if (label === (i + 1).toString()) {
|
|
standardLabels++;
|
|
} else if (label === '') {
|
|
emptyLabels++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (standardLabels >= numLabels || emptyLabels >= numLabels) {
|
|
return;
|
|
}
|
|
const { pdfViewer, pdfThumbnailViewer, toolbar } = this;
|
|
|
|
pdfViewer.setPageLabels(labels);
|
|
pdfThumbnailViewer.setPageLabels(labels);
|
|
|
|
// Changing toolbar page display to use labels and we need to set
|
|
// the label of the current page.
|
|
toolbar.setPagesCount(numLabels, true);
|
|
toolbar.setPageNumber(
|
|
pdfViewer.currentPageNumber,
|
|
pdfViewer.currentPageLabel,
|
|
);
|
|
},
|
|
|
|
run(config) {
|
|
this.initalize(config).then(WebViewInitialized);
|
|
},
|
|
/**
|
|
* Opens PDF document specified by URL.
|
|
* @returns {Promise} - Returns the promise, which is resolved when document
|
|
* is opened.
|
|
*/
|
|
async open(file, args) {
|
|
const self = this;
|
|
|
|
if (this.pdfLoadingTask) {
|
|
// We need to destroy already opened document.
|
|
await this.close();
|
|
}
|
|
|
|
const parameters = Object.create(null);
|
|
if (typeof file === 'string') {
|
|
// URL
|
|
this.setTitleUsingUrl(file, /* downloadUrl = */ file);
|
|
parameters.url = file;
|
|
} else if (file && 'byteLength' in file) {
|
|
// ArrayBuffer
|
|
parameters.data = file;
|
|
} else if (file.url && file.originalUrl) {
|
|
this.setTitleUsingUrl(
|
|
file.originalUrl,
|
|
/* downloadUrl = */ file.url,
|
|
);
|
|
parameters.url = file.url;
|
|
}
|
|
|
|
// Finally, update the API parameters with the arguments (if they exist).
|
|
if (args) {
|
|
for (const key in args) {
|
|
parameters[key] = args[key];
|
|
}
|
|
}
|
|
let url = parameters.url;
|
|
if (parameters.secure) {
|
|
this._downloadUrl = parameters.download_url;
|
|
} else {
|
|
this._downloadUrl = url;
|
|
}
|
|
this._docFilename = parameters.file;
|
|
parameters.cMapPacked = true;
|
|
parameters.cMapUrl = pdfemb_trans.cmap_url;
|
|
|
|
// Loading document.
|
|
const loadingTask = pdfjsLib.getDocument(parameters);
|
|
|
|
this.pdfLoadingTask = loadingTask;
|
|
loadingTask.onPassword = (updateCallback, reason) => {
|
|
this.pdfLinkService.externalLinkEnabled = false;
|
|
this.passwordPrompt.setUpdateCallback(updateCallback, reason);
|
|
this.passwordPrompt.open();
|
|
};
|
|
loadingTask.onProgress = function (progressData) {
|
|
self.progress(progressData.loaded / progressData.total);
|
|
};
|
|
|
|
return loadingTask.promise.then(
|
|
function (pdfDocument) {
|
|
// Document loaded, specifying document for the viewer.
|
|
self.pdfDocument = pdfDocument;
|
|
self.pdfViewer.setDocument(pdfDocument);
|
|
self.pdfLinkService.setDocument(pdfDocument);
|
|
self.pdfHistory.initialize({
|
|
fingerprint: pdfDocument.fingerprints[0],
|
|
});
|
|
webViewerZoomReset();
|
|
self.loadingBar.hide();
|
|
self.setTitleUsingMetadata(pdfDocument);
|
|
self._initializePageLabels(pdfDocument);
|
|
},
|
|
function (exception) {
|
|
const message = exception && exception.message;
|
|
const l10n = self.l10n;
|
|
let loadingErrorMessage;
|
|
|
|
if (exception instanceof pdfjsLib.InvalidPDFException) {
|
|
// change error message also for other builds
|
|
loadingErrorMessage = l10n.get(
|
|
'invalid_file_error',
|
|
null,
|
|
'Invalid or corrupted PDF file.',
|
|
);
|
|
} else if (exception instanceof pdfjsLib.MissingPDFException) {
|
|
// special message for missing PDFs
|
|
loadingErrorMessage = l10n.get(
|
|
'missing_file_error',
|
|
null,
|
|
'Missing PDF file.',
|
|
);
|
|
} else if (
|
|
exception instanceof pdfjsLib.UnexpectedResponseException
|
|
) {
|
|
loadingErrorMessage = l10n.get(
|
|
'unexpected_response_error',
|
|
null,
|
|
'Unexpected server response.',
|
|
);
|
|
} else {
|
|
loadingErrorMessage = l10n.get(
|
|
'loading_error',
|
|
null,
|
|
'An error occurred while loading the PDF.',
|
|
);
|
|
}
|
|
|
|
loadingErrorMessage.then(function (msg) {
|
|
self.error(msg, { message });
|
|
});
|
|
self.loadingBar.hide();
|
|
},
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Closes opened PDF document.
|
|
* @returns {Promise} - Returns the promise, which is resolved when all
|
|
* destruction is completed.
|
|
*/
|
|
close() {
|
|
const errorWrapper = document.getElementById('errorWrapper');
|
|
errorWrapper.hidden = true;
|
|
|
|
if (!this.pdfLoadingTask) {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
const promise = this.pdfLoadingTask.destroy();
|
|
this.pdfLoadingTask = null;
|
|
|
|
if (this.pdfDocument) {
|
|
this.pdfDocument = null;
|
|
|
|
this.pdfViewer.setDocument(null);
|
|
this.pdfLinkService.setDocument(null, null);
|
|
|
|
if (this.pdfHistory) {
|
|
this.pdfHistory.reset();
|
|
}
|
|
}
|
|
|
|
return promise;
|
|
},
|
|
|
|
get loadingBar() {
|
|
const bar = new pdfjsViewer.ProgressBar('loadingBar');
|
|
|
|
return pdfjsLib.shadow(this, 'loadingBar', bar);
|
|
},
|
|
|
|
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
|
|
this.url = url;
|
|
let title = pdfjsLib.getFilenameFromUrl(url) || url;
|
|
try {
|
|
title = decodeURIComponent(title);
|
|
} catch (e) {
|
|
// decodeURIComponent may throw URIError,
|
|
// fall back to using the unprocessed url in that case
|
|
}
|
|
this.setTitle(title);
|
|
},
|
|
|
|
setTitleUsingMetadata(pdfDocument) {
|
|
const self = this;
|
|
pdfDocument.getMetadata().then(function (data) {
|
|
const info = data.info,
|
|
metadata = data.metadata;
|
|
self.documentInfo = info;
|
|
self.metadata = metadata;
|
|
|
|
let pdfTitle;
|
|
if (metadata && metadata.has('dc:title')) {
|
|
const title = metadata.get('dc:title');
|
|
// Ghostscript sometimes returns 'Untitled', so prevent setting the
|
|
// title to 'Untitled.
|
|
if (title !== 'Untitled') {
|
|
pdfTitle = title;
|
|
}
|
|
}
|
|
|
|
if (!pdfTitle && info && info.Title) {
|
|
pdfTitle = info.Title;
|
|
}
|
|
|
|
if (pdfTitle) {
|
|
self.setTitle(pdfTitle + ' - ' + document.title);
|
|
}
|
|
});
|
|
},
|
|
|
|
setTitle: function pdfViewSetTitle(title) {
|
|
document.title = title;
|
|
},
|
|
|
|
error: function pdfViewError(message, moreInfo) {
|
|
const l10n = this.l10n;
|
|
const moreInfoText = [
|
|
l10n.get(
|
|
'error_version_info',
|
|
{
|
|
version: pdfjsLib.version || '?',
|
|
build: pdfjsLib.build || '?',
|
|
},
|
|
'PDF.js v{{version}} (build: {{build}})',
|
|
),
|
|
];
|
|
|
|
if (moreInfo) {
|
|
moreInfoText.push(
|
|
l10n.get(
|
|
'error_message',
|
|
{ message: moreInfo.message },
|
|
'Message: {{message}}',
|
|
),
|
|
);
|
|
if (moreInfo.stack) {
|
|
moreInfoText.push(
|
|
l10n.get(
|
|
'error_stack',
|
|
{ stack: moreInfo.stack },
|
|
'Stack: {{stack}}',
|
|
),
|
|
);
|
|
} else {
|
|
if (moreInfo.filename) {
|
|
moreInfoText.push(
|
|
l10n.get(
|
|
'error_file',
|
|
{ file: moreInfo.filename },
|
|
'File: {{file}}',
|
|
),
|
|
);
|
|
}
|
|
if (moreInfo.lineNumber) {
|
|
moreInfoText.push(
|
|
l10n.get(
|
|
'error_line',
|
|
{ line: moreInfo.lineNumber },
|
|
'Line: {{line}}',
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
const errorWrapper = document.getElementById('errorWrapper');
|
|
errorWrapper.hidden = false;
|
|
|
|
const errorMessage = document.getElementById('errorMessage');
|
|
errorMessage.textContent = message;
|
|
|
|
const closeButton = document.getElementById('errorClose');
|
|
closeButton.onclick = function () {
|
|
errorWrapper.hidden = true;
|
|
};
|
|
|
|
const errorMoreInfo = document.getElementById('errorMoreInfo');
|
|
const moreInfoButton = document.getElementById('errorShowMore');
|
|
const lessInfoButton = document.getElementById('errorShowLess');
|
|
moreInfoButton.onclick = function () {
|
|
errorMoreInfo.hidden = false;
|
|
moreInfoButton.hidden = true;
|
|
lessInfoButton.hidden = false;
|
|
errorMoreInfo.style.height = errorMoreInfo.scrollHeight + 'px';
|
|
};
|
|
lessInfoButton.onclick = function () {
|
|
errorMoreInfo.hidden = true;
|
|
moreInfoButton.hidden = false;
|
|
lessInfoButton.hidden = true;
|
|
};
|
|
moreInfoButton.hidden = false;
|
|
lessInfoButton.hidden = true;
|
|
Promise.all(moreInfoText).then(function (parts) {
|
|
errorMoreInfo.value = parts.join('\n');
|
|
});
|
|
},
|
|
progress: function pdfViewProgress(level) {
|
|
const percent = Math.round(level * 100);
|
|
// Updating the bar if value increases.
|
|
if (percent > this.loadingBar.percent || isNaN(percent)) {
|
|
this.loadingBar.percent = percent;
|
|
}
|
|
},
|
|
|
|
get pagesCount() {
|
|
return this.pdfDocument.numPages;
|
|
},
|
|
|
|
get page() {
|
|
return this.pdfViewer.currentPageNumber;
|
|
},
|
|
|
|
set page(val) {
|
|
this.pdfViewer.currentPageNumber = val;
|
|
},
|
|
|
|
bindEvents() {
|
|
const { eventBus, _boundEvents } = this;
|
|
|
|
_boundEvents.beforePrint = this.beforePrint.bind(this);
|
|
_boundEvents.afterPrint = this.afterPrint.bind(this);
|
|
eventBus._on('resize', webViewerResize);
|
|
eventBus._on('hashchange', webViewerHashchange);
|
|
eventBus._on('beforeprint', _boundEvents.beforePrint);
|
|
eventBus._on('afterprint', _boundEvents.afterPrint);
|
|
eventBus._on('pagerendered', webViewerPageRendered);
|
|
eventBus._on('updateviewarea', webViewerUpdateViewarea);
|
|
eventBus._on('pagechanging', webViewerPageChanging);
|
|
eventBus._on('scalechanging', webViewerScaleChanging);
|
|
eventBus._on('rotationchanging', webViewerRotationChanging);
|
|
eventBus._on('namedaction', webViewerNamedAction);
|
|
eventBus._on(
|
|
'presentationmodechanged',
|
|
webViewerPresentationModeChanged,
|
|
);
|
|
eventBus._on('presentationmode', webViewerPresentationMode);
|
|
eventBus._on(
|
|
'switchannotationeditormode',
|
|
webViewerSwitchAnnotationEditorMode,
|
|
);
|
|
eventBus._on(
|
|
'switchannotationeditorparams',
|
|
webViewerSwitchAnnotationEditorParams,
|
|
);
|
|
eventBus._on('print', webViewerPrint);
|
|
eventBus._on('download', webViewerDownload);
|
|
eventBus._on('fullscreen', webViewerFullscreen);
|
|
eventBus._on('firstpage', webViewerFirstPage);
|
|
eventBus._on('lastpage', webViewerLastPage);
|
|
eventBus._on('nextpage', webViewerNextPage);
|
|
eventBus._on('previouspage', webViewerPreviousPage);
|
|
eventBus._on('zoomin', webViewerZoomIn);
|
|
eventBus._on('zoomout', webViewerZoomOut);
|
|
eventBus._on('zoomreset', webViewerZoomReset);
|
|
eventBus._on('pagenumberchanged', webViewerPageNumberChanged);
|
|
eventBus._on('scalechanged', webViewerScaleChanged);
|
|
eventBus._on('rotatecw', webViewerRotateCw);
|
|
eventBus._on('rotateccw', webViewerRotateCcw);
|
|
eventBus._on('optionalcontentconfig', webViewerOptionalContentConfig);
|
|
eventBus._on('switchscrollmode', webViewerSwitchScrollMode);
|
|
eventBus._on('scrollmodechanged', webViewerScrollModeChanged);
|
|
eventBus._on('spreadmodechanged', webViewerSpreadModeChanged);
|
|
eventBus._on('documentproperties', webViewerDocumentProperties);
|
|
eventBus._on('findfromurlhash', webViewerFindFromUrlHash);
|
|
eventBus._on('updatefindmatchescount', webViewerUpdateFindMatchesCount);
|
|
eventBus._on('updatefindcontrolstate', webViewerUpdateFindControlState);
|
|
},
|
|
bindWindowEvents() {
|
|
const { eventBus, _boundEvents } = this;
|
|
|
|
function addWindowResolutionChange(evt = null) {
|
|
if (evt) {
|
|
webViewerResolutionChange(evt);
|
|
}
|
|
const mediaQueryList = window.matchMedia(
|
|
`(resolution: ${window.devicePixelRatio || 1}dppx)`,
|
|
);
|
|
mediaQueryList.addEventListener(
|
|
'change',
|
|
addWindowResolutionChange,
|
|
{
|
|
once: true,
|
|
},
|
|
);
|
|
|
|
if (
|
|
typeof PDFJSDev !== 'undefined' &&
|
|
PDFJSDev.test('MOZCENTRAL')
|
|
) {
|
|
return;
|
|
}
|
|
_boundEvents.removeWindowResolutionChange ||= function () {
|
|
mediaQueryList.removeEventListener(
|
|
'change',
|
|
addWindowResolutionChange,
|
|
);
|
|
_boundEvents.removeWindowResolutionChange = null;
|
|
};
|
|
}
|
|
addWindowResolutionChange();
|
|
|
|
_boundEvents.windowResize = () => {
|
|
eventBus.dispatch('resize', { source: window });
|
|
};
|
|
_boundEvents.windowHashChange = () => {
|
|
eventBus.dispatch('hashchange', {
|
|
source: window,
|
|
hash: document.location.hash.substring(1),
|
|
});
|
|
};
|
|
_boundEvents.windowBeforePrint = () => {
|
|
eventBus.dispatch('beforeprint', { source: window });
|
|
};
|
|
_boundEvents.windowAfterPrint = () => {
|
|
eventBus.dispatch('afterprint', { source: window });
|
|
};
|
|
_boundEvents.windowUpdateFromSandbox = (event) => {
|
|
eventBus.dispatch('updatefromsandbox', {
|
|
source: window,
|
|
detail: event.detail,
|
|
});
|
|
};
|
|
|
|
window.addEventListener('visibilitychange', webViewerVisibilityChange);
|
|
window.addEventListener('wheel', webViewerWheel, { passive: false });
|
|
window.addEventListener('touchstart', webViewerTouchStart, {
|
|
passive: false,
|
|
});
|
|
window.addEventListener('keydown', webViewerKeyDown);
|
|
window.addEventListener('resize', _boundEvents.windowResize);
|
|
window.addEventListener('hashchange', _boundEvents.windowHashChange);
|
|
window.addEventListener('beforeprint', _boundEvents.windowBeforePrint);
|
|
window.addEventListener('afterprint', _boundEvents.windowAfterPrint);
|
|
window.addEventListener(
|
|
'updatefromsandbox',
|
|
_boundEvents.windowUpdateFromSandbox,
|
|
);
|
|
},
|
|
unbindEvents() {
|
|
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('MOZCENTRAL')) {
|
|
throw new Error('Not implemented: unbindEvents');
|
|
}
|
|
const { eventBus, _boundEvents } = this;
|
|
|
|
eventBus._off('resize', webViewerResize);
|
|
eventBus._off('hashchange', webViewerHashchange);
|
|
eventBus._off('beforeprint', _boundEvents.beforePrint);
|
|
eventBus._off('afterprint', _boundEvents.afterPrint);
|
|
eventBus._off('pagerendered', webViewerPageRendered);
|
|
eventBus._off('updateviewarea', webViewerUpdateViewarea);
|
|
eventBus._off('pagechanging', webViewerPageChanging);
|
|
eventBus._off('scalechanging', webViewerScaleChanging);
|
|
eventBus._off('rotationchanging', webViewerRotationChanging);
|
|
eventBus._off('namedaction', webViewerNamedAction);
|
|
eventBus._off(
|
|
'presentationmodechanged',
|
|
webViewerPresentationModeChanged,
|
|
);
|
|
eventBus._off('presentationmode', webViewerPresentationMode);
|
|
eventBus._off('print', webViewerPrint);
|
|
eventBus._off('download', webViewerDownload);
|
|
eventBus._off('fullscreen', webViewerFullscreen);
|
|
eventBus._off('firstpage', webViewerFirstPage);
|
|
eventBus._off('lastpage', webViewerLastPage);
|
|
eventBus._off('nextpage', webViewerNextPage);
|
|
eventBus._off('previouspage', webViewerPreviousPage);
|
|
eventBus._off('zoomin', webViewerZoomIn);
|
|
eventBus._off('zoomout', webViewerZoomOut);
|
|
eventBus._off('zoomreset', webViewerZoomReset);
|
|
eventBus._off('pagenumberchanged', webViewerPageNumberChanged);
|
|
eventBus._off('scalechanged', webViewerScaleChanged);
|
|
eventBus._off('rotatecw', webViewerRotateCw);
|
|
eventBus._off('rotateccw', webViewerRotateCcw);
|
|
eventBus._off('optionalcontentconfig', webViewerOptionalContentConfig);
|
|
eventBus._off('switchscrollmode', webViewerSwitchScrollMode);
|
|
eventBus._off('scrollmodechanged', webViewerScrollModeChanged);
|
|
eventBus._off('switchspreadmode', webViewerSwitchSpreadMode);
|
|
eventBus._off('spreadmodechanged', webViewerSpreadModeChanged);
|
|
eventBus._off('documentproperties', webViewerDocumentProperties);
|
|
eventBus._off('findfromurlhash', webViewerFindFromUrlHash);
|
|
eventBus._off(
|
|
'updatefindmatchescount',
|
|
webViewerUpdateFindMatchesCount,
|
|
);
|
|
eventBus._off(
|
|
'updatefindcontrolstate',
|
|
webViewerUpdateFindControlState,
|
|
);
|
|
|
|
if (_boundEvents.reportPageStatsPDFBug) {
|
|
eventBus._off('pagerendered', _boundEvents.reportPageStatsPDFBug);
|
|
eventBus._off('pagechanging', _boundEvents.reportPageStatsPDFBug);
|
|
|
|
_boundEvents.reportPageStatsPDFBug = null;
|
|
}
|
|
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
|
eventBus._off('fileinputchange', webViewerFileInputChange);
|
|
eventBus._off('openfile', webViewerOpenFile);
|
|
}
|
|
|
|
_boundEvents.beforePrint = null;
|
|
_boundEvents.afterPrint = null;
|
|
},
|
|
unbindWindowEvents() {
|
|
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('MOZCENTRAL')) {
|
|
throw new Error('Not implemented: unbindWindowEvents');
|
|
}
|
|
const { _boundEvents } = this;
|
|
|
|
window.removeEventListener(
|
|
'visibilitychange',
|
|
webViewerVisibilityChange,
|
|
);
|
|
window.removeEventListener('wheel', webViewerWheel, { passive: false });
|
|
window.removeEventListener('touchstart', webViewerTouchStart, {
|
|
passive: false,
|
|
});
|
|
window.removeEventListener('keydown', webViewerKeyDown);
|
|
window.removeEventListener('resize', _boundEvents.windowResize);
|
|
window.removeEventListener('hashchange', _boundEvents.windowHashChange);
|
|
window.removeEventListener(
|
|
'beforeprint',
|
|
_boundEvents.windowBeforePrint,
|
|
);
|
|
window.removeEventListener('afterprint', _boundEvents.windowAfterPrint);
|
|
window.removeEventListener(
|
|
'updatefromsandbox',
|
|
_boundEvents.windowUpdateFromSandbox,
|
|
);
|
|
|
|
_boundEvents.removeWindowResolutionChange?.();
|
|
_boundEvents.windowResize = null;
|
|
_boundEvents.windowHashChange = null;
|
|
_boundEvents.windowBeforePrint = null;
|
|
_boundEvents.windowAfterPrint = null;
|
|
_boundEvents.windowUpdateFromSandbox = null;
|
|
},
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
_reportDocumentStatsTelemetry() {
|
|
const { stats } = this.pdfDocument;
|
|
if (stats !== this._docStats) {
|
|
this._docStats = stats;
|
|
|
|
this.externalServices.reportTelemetry({
|
|
type: 'documentStats',
|
|
stats,
|
|
});
|
|
}
|
|
},
|
|
beforePrint() {
|
|
this._printAnnotationStoragePromise = this.pdfScriptingManager
|
|
.dispatchWillPrint()
|
|
.catch(() => {
|
|
/* Avoid breaking printing; ignoring errors. */
|
|
})
|
|
.then(() => {
|
|
return this.pdfDocument?.annotationStorage.print;
|
|
});
|
|
|
|
if (this.printService) {
|
|
// There is no way to suppress beforePrint/afterPrint events,
|
|
// but PDFPrintService may generate double events -- this will ignore
|
|
// the second event that will be coming from native window.print().
|
|
return;
|
|
}
|
|
|
|
if (!this.supportsPrinting) {
|
|
this.l10n.get('printing_not_supported').then((msg) => {
|
|
this._otherError(msg);
|
|
});
|
|
return;
|
|
}
|
|
|
|
// The beforePrint is a sync method and we need to know layout before
|
|
// returning from this method. Ensure that we can get sizes of the pages.
|
|
if (!this.pdfViewer.pageViewsReady) {
|
|
this.l10n.get('printing_not_ready').then((msg) => {
|
|
// eslint-disable-next-line no-alert
|
|
window.alert(msg);
|
|
});
|
|
return;
|
|
}
|
|
|
|
const pagesOverview = this.pdfViewer.getPagesOverview();
|
|
const printContainer = this.appConfig.printContainer;
|
|
const printResolution = AppOptions.get('printResolution');
|
|
const optionalContentConfigPromise =
|
|
this.pdfViewer.optionalContentConfigPromise;
|
|
|
|
const printService = PDFPrintServiceFactory.instance.createPrintService(
|
|
this.pdfDocument,
|
|
pagesOverview,
|
|
printContainer,
|
|
printResolution,
|
|
optionalContentConfigPromise,
|
|
this._printAnnotationStoragePromise,
|
|
this.l10n,
|
|
);
|
|
this.printService = printService;
|
|
this.forceRendering();
|
|
|
|
printService.layout();
|
|
|
|
this.externalServices.reportTelemetry({
|
|
type: 'print',
|
|
});
|
|
|
|
if (this.pdfDocument?.annotationStorage.hasAnnotationEditors) {
|
|
this.externalServices.reportTelemetry({
|
|
type: 'editing',
|
|
data: {
|
|
type: 'print',
|
|
},
|
|
});
|
|
}
|
|
},
|
|
/**
|
|
* @private
|
|
*/
|
|
_ensureDownloadComplete() {
|
|
if (this.pdfDocument && this.downloadComplete) {
|
|
return;
|
|
}
|
|
throw new Error('PDF document not downloaded.');
|
|
},
|
|
goFullscreen() {},
|
|
async download() {
|
|
const url = this._downloadUrl,
|
|
filename = new URL(url).pathname.split('/').pop();
|
|
|
|
let link = document.createElement('a');
|
|
link.href = url;
|
|
link.download = filename;
|
|
link.dispatchEvent(new MouseEvent('click'));
|
|
},
|
|
|
|
afterPrint() {
|
|
if (this._printAnnotationStoragePromise) {
|
|
this._printAnnotationStoragePromise.then(() => {
|
|
this.pdfScriptingManager.dispatchDidPrint();
|
|
});
|
|
this._printAnnotationStoragePromise = null;
|
|
}
|
|
|
|
if (this.printService) {
|
|
this.printService.destroy();
|
|
this.printService = null;
|
|
|
|
this.pdfDocument?.annotationStorage.resetModified();
|
|
}
|
|
this.forceRendering();
|
|
},
|
|
|
|
zoomIn: function pdfViewZoomIn(ticks) {
|
|
let newScale = this.pdfViewer.currentScale;
|
|
do {
|
|
newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2);
|
|
newScale = Math.ceil(newScale * 10) / 10;
|
|
newScale = Math.min(MAX_SCALE, newScale);
|
|
} while (--ticks && newScale < MAX_SCALE);
|
|
this.pdfViewer.currentScaleValue = newScale;
|
|
},
|
|
|
|
zoomOut: function pdfViewZoomOut(ticks) {
|
|
let newScale = this.pdfViewer.currentScale;
|
|
do {
|
|
newScale = (newScale / DEFAULT_SCALE_DELTA).toFixed(2);
|
|
newScale = Math.floor(newScale * 10) / 10;
|
|
newScale = Math.max(MIN_SCALE, newScale);
|
|
} while (--ticks && newScale > MIN_SCALE);
|
|
this.pdfViewer.currentScaleValue = newScale;
|
|
},
|
|
zoomReset() {
|
|
if (this.pdfViewer.isInPresentationMode) {
|
|
return;
|
|
}
|
|
this.pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
|
|
},
|
|
get pagesCount() {
|
|
return this.pdfDocument ? this.pdfDocument.numPages : 0;
|
|
},
|
|
|
|
get page() {
|
|
return this.pdfViewer.currentPageNumber;
|
|
},
|
|
|
|
set page(val) {
|
|
this.pdfViewer.currentPageNumber = val;
|
|
},
|
|
|
|
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;
|
|
error_log(ScrollMode.PAGE);
|
|
setViewerModes(ScrollMode.PAGE, spreadMode);
|
|
|
|
if (this.initialBookmark) {
|
|
setRotation(this.initialRotation);
|
|
delete this.initialRotation;
|
|
|
|
this.pdfLinkService.setHash(this.initialBookmark);
|
|
this.initialBookmark = null;
|
|
} else if (storedHash) {
|
|
setRotation(rotation);
|
|
|
|
this.pdfLinkService.setHash(storedHash);
|
|
}
|
|
|
|
// Ensure that the correct page number is displayed in the UI,
|
|
// even if the active page didn't change during document load.
|
|
this.toolbar.setPageNumber(
|
|
this.pdfViewer.currentPageNumber,
|
|
this.pdfViewer.currentPageLabel,
|
|
);
|
|
|
|
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;
|
|
}
|
|
},
|
|
};
|
|
function webViewerHashchange(evt) {
|
|
const hash = evt.hash;
|
|
if (!hash) {
|
|
return;
|
|
}
|
|
if (!PDFViewerApplication.isInitialViewSet) {
|
|
PDFViewerApplication.initialBookmark = hash;
|
|
} else if (!PDFViewerApplication.pdfHistory?.popStateInProgress) {
|
|
PDFViewerApplication.pdfLinkService.setHash(hash);
|
|
}
|
|
}
|
|
function 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 === PDFViewerApplication.page) {
|
|
PDFViewerApplication.toolbar.updateLoadingIndicatorState(false);
|
|
}
|
|
|
|
if (error) {
|
|
PDFViewerApplication.l10n.get('rendering_error').then((msg) => {
|
|
PDFViewerApplication._otherError(msg, error);
|
|
});
|
|
}
|
|
|
|
// It is a good time to report stream and font types.
|
|
PDFViewerApplication._reportDocumentStatsTelemetry();
|
|
}
|
|
function webViewerUpdateViewarea({ location }) {
|
|
if (PDFViewerApplication.isInitialViewSet) {
|
|
// Only update the storage when the document has been loaded *and* rendered.
|
|
PDFViewerApplication.store
|
|
?.setMultiple({
|
|
page: location.pageNumber,
|
|
zoom: location.scale,
|
|
scrollLeft: location.left,
|
|
scrollTop: location.top,
|
|
rotation: location.rotation,
|
|
})
|
|
.catch(() => {
|
|
// Unable to write to storage.
|
|
});
|
|
}
|
|
|
|
// Show/hide the loading indicator in the page number input element.
|
|
const currentPage = PDFViewerApplication.pdfViewer.getPageView(
|
|
/* index = */ PDFViewerApplication.page - 1,
|
|
);
|
|
const loading = currentPage?.renderingState !== RenderingStates.FINISHED;
|
|
PDFViewerApplication.toolbar.updateLoadingIndicatorState(loading);
|
|
}
|
|
|
|
function webViewerResize() {
|
|
const { pdfDocument, pdfViewer } = PDFViewerApplication;
|
|
|
|
pdfViewer.updateContainerHeightCss();
|
|
|
|
if (!pdfDocument) {
|
|
return;
|
|
}
|
|
const currentScaleValue = pdfViewer.currentScaleValue;
|
|
if (
|
|
currentScaleValue === 'auto' ||
|
|
currentScaleValue === 'page-fit' ||
|
|
currentScaleValue === 'page-width'
|
|
) {
|
|
// Note: the scale is constant for 'page-actual'.
|
|
pdfViewer.currentScaleValue = currentScaleValue;
|
|
}
|
|
pdfViewer.update();
|
|
}
|
|
const WebViewInitialized = () => {
|
|
const { appConfig, eventBus } = PDFViewerApplication;
|
|
let file;
|
|
const queryString = document.location.search.substring(1);
|
|
const params = parseQueryString(queryString);
|
|
file = params.get('url') ?? AppOptions.get('defaultUrl');
|
|
|
|
if (file.search('/?pdfemb-serveurl=') == -1) {
|
|
PDFViewerApplication.open(file);
|
|
} else {
|
|
document.oncontextmenu = function () {
|
|
return false;
|
|
};
|
|
pdfembGetPDF(file);
|
|
}
|
|
};
|
|
|
|
function webViewerScaleChanging(evt) {
|
|
PDFViewerApplication.toolbar.setPageScale(evt.presetValue, evt.scale);
|
|
|
|
PDFViewerApplication.pdfViewer.update();
|
|
}
|
|
|
|
function webViewerRotationChanging(evt) {
|
|
PDFViewerApplication.pdfThumbnailViewer.pagesRotation = evt.pagesRotation;
|
|
|
|
PDFViewerApplication.forceRendering();
|
|
// Ensure that the active page doesn't change during rotation.
|
|
PDFViewerApplication.pdfViewer.currentPageNumber = evt.pageNumber;
|
|
}
|
|
|
|
function webViewerPageChanging({ pageNumber, pageLabel }) {
|
|
PDFViewerApplication.toolbar.setPageNumber(pageNumber, pageLabel);
|
|
}
|
|
|
|
function webViewerResolutionChange(evt) {
|
|
PDFViewerApplication.pdfViewer.refresh();
|
|
}
|
|
function webViewerPresentationModeChanged(evt) {
|
|
PDFViewerApplication.pdfViewer.presentationModeState = evt.state;
|
|
}
|
|
function webViewerSwitchAnnotationEditorMode(evt) {
|
|
PDFViewerApplication.pdfViewer.annotationEditorMode = evt.mode;
|
|
}
|
|
function webViewerPrint() {
|
|
PDFViewerApplication.triggerPrinting();
|
|
}
|
|
function webViewerFullscreen() {
|
|
PDFViewerApplication.goFullscreen();
|
|
}
|
|
function webViewerDownload() {
|
|
PDFViewerApplication.download();
|
|
}
|
|
function webViewerFirstPage() {
|
|
if (PDFViewerApplication.pdfDocument) {
|
|
PDFViewerApplication.page = 1;
|
|
}
|
|
}
|
|
function webViewerLastPage() {
|
|
if (PDFViewerApplication.pdfDocument) {
|
|
PDFViewerApplication.page = PDFViewerApplication.pagesCount;
|
|
}
|
|
}
|
|
function webViewerSwitchAnnotationEditorParams(evt) {
|
|
PDFViewerApplication.pdfViewer.annotationEditorParams = evt;
|
|
}
|
|
function webViewerNextPage() {
|
|
PDFViewerApplication.pdfViewer.nextPage();
|
|
}
|
|
function webViewerPreviousPage() {
|
|
PDFViewerApplication.pdfViewer.previousPage();
|
|
}
|
|
function webViewerZoomIn() {
|
|
PDFViewerApplication.zoomIn();
|
|
}
|
|
function webViewerZoomOut() {
|
|
PDFViewerApplication.zoomOut();
|
|
}
|
|
function webViewerZoomReset() {
|
|
PDFViewerApplication.zoomReset();
|
|
}
|
|
function webViewerNamedAction(evt) {
|
|
// Processing a couple of named actions that might be useful, see also
|
|
// `PDFLinkService.executeNamedAction`.
|
|
switch (evt.action) {
|
|
case 'GoToPage':
|
|
PDFViewerApplication.appConfig.toolbar.pageNumber.select();
|
|
break;
|
|
|
|
case 'Find':
|
|
if (!PDFViewerApplication.supportsIntegratedFind) {
|
|
PDFViewerApplication.findBar.toggle();
|
|
}
|
|
break;
|
|
|
|
case 'Print':
|
|
PDFViewerApplication.triggerPrinting();
|
|
break;
|
|
|
|
case 'SaveAs':
|
|
PDFViewerApplication.downloadOrSave();
|
|
break;
|
|
}
|
|
}
|
|
function webViewerPresentationMode() {
|
|
PDFViewerApplication.requestPresentationMode();
|
|
}
|
|
|
|
let zoomDisabledTimeout = null;
|
|
function setZoomDisabledTimeout() {
|
|
if (zoomDisabledTimeout) {
|
|
clearTimeout(zoomDisabledTimeout);
|
|
}
|
|
zoomDisabledTimeout = setTimeout(function () {
|
|
zoomDisabledTimeout = null;
|
|
}, WHEEL_ZOOM_DISABLED_TIMEOUT);
|
|
}
|
|
|
|
function webViewerPageNumberChanged(evt) {
|
|
const pdfViewer = PDFViewerApplication.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 !== '') {
|
|
PDFViewerApplication.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
|
|
) {
|
|
PDFViewerApplication.toolbar.setPageNumber(
|
|
pdfViewer.currentPageNumber,
|
|
pdfViewer.currentPageLabel,
|
|
);
|
|
}
|
|
}
|
|
function webViewerScrollModeChanged(evt) {
|
|
if (PDFViewerApplication.isInitialViewSet) {
|
|
// Only update the storage when the document has been loaded *and* rendered.
|
|
PDFViewerApplication.store?.set('scrollMode', evt.mode).catch(() => {
|
|
// Unable to write to storage.
|
|
});
|
|
}
|
|
}
|
|
function webViewerUpdateFindMatchesCount({ matchesCount }) {
|
|
if (PDFViewerApplication.supportsIntegratedFind) {
|
|
PDFViewerApplication.externalServices.updateFindMatchesCount(
|
|
matchesCount,
|
|
);
|
|
} else {
|
|
PDFViewerApplication.findBar.updateResultsCount(matchesCount);
|
|
}
|
|
}
|
|
|
|
function webViewerWheel(evt) {
|
|
const { pdfViewer, supportedMouseWheelZoomModifierKeys } =
|
|
PDFViewerApplication;
|
|
|
|
if (pdfViewer.isInPresentationMode) {
|
|
return;
|
|
}
|
|
|
|
if (
|
|
(evt.ctrlKey && supportedMouseWheelZoomModifierKeys.ctrlKey) ||
|
|
(evt.metaKey && supportedMouseWheelZoomModifierKeys.metaKey)
|
|
) {
|
|
// Only zoom the pages, not the entire viewer.
|
|
evt.preventDefault();
|
|
// NOTE: this check must be placed *after* preventDefault.
|
|
if (zoomDisabledTimeout || document.visibilityState === 'hidden') {
|
|
return;
|
|
}
|
|
|
|
// It is important that we query deltaMode before delta{X,Y}, so that
|
|
// Firefox doesn't switch to DOM_DELTA_PIXEL mode for compat with other
|
|
// browsers, see https://bugzilla.mozilla.org/show_bug.cgi?id=1392460.
|
|
const deltaMode = evt.deltaMode;
|
|
const delta = normalizeWheelEventDirection(evt);
|
|
const previousScale = pdfViewer.currentScale;
|
|
|
|
let ticks = 0;
|
|
if (
|
|
deltaMode === WheelEvent.DOM_DELTA_LINE ||
|
|
deltaMode === WheelEvent.DOM_DELTA_PAGE
|
|
) {
|
|
// For line-based devices, use one tick per event, because different
|
|
// OSs have different defaults for the number lines. But we generally
|
|
// want one "clicky" roll of the wheel (which produces one event) to
|
|
// adjust the zoom by one step.
|
|
if (Math.abs(delta) >= 1) {
|
|
ticks = Math.sign(delta);
|
|
} else {
|
|
// If we're getting fractional lines (I can't think of a scenario
|
|
// this might actually happen), be safe and use the accumulator.
|
|
ticks = PDFViewerApplication.accumulateWheelTicks(delta);
|
|
}
|
|
} else {
|
|
// pixel-based devices
|
|
const PIXELS_PER_LINE_SCALE = 30;
|
|
ticks = PDFViewerApplication.accumulateWheelTicks(
|
|
delta / PIXELS_PER_LINE_SCALE,
|
|
);
|
|
}
|
|
|
|
if (ticks < 0) {
|
|
PDFViewerApplication.zoomOut(-ticks);
|
|
} else if (ticks > 0) {
|
|
PDFViewerApplication.zoomIn(ticks);
|
|
}
|
|
|
|
const currentScale = pdfViewer.currentScale;
|
|
if (previousScale !== currentScale) {
|
|
// After scaling the page via zoomIn/zoomOut, the position of the upper-
|
|
// left corner is restored. When the mouse wheel is used, the position
|
|
// under the cursor should be restored instead.
|
|
const scaleCorrectionFactor = currentScale / previousScale - 1;
|
|
const rect = pdfViewer.container.getBoundingClientRect();
|
|
const dx = evt.clientX - rect.left;
|
|
const dy = evt.clientY - rect.top;
|
|
pdfViewer.container.scrollLeft += dx * scaleCorrectionFactor;
|
|
pdfViewer.container.scrollTop += dy * scaleCorrectionFactor;
|
|
}
|
|
} else {
|
|
setZoomDisabledTimeout();
|
|
}
|
|
}
|
|
|
|
function webViewerTouchStart(evt) {
|
|
if (evt.touches.length > 1) {
|
|
// Disable touch-based zooming, because the entire UI bits gets zoomed and
|
|
// that doesn't look great. If we do want to have a good touch-based
|
|
// zooming experience, we need to implement smooth zoom capability (probably
|
|
// using a CSS transform for faster visual response, followed by async
|
|
// re-rendering at the final zoom level) and do gesture detection on the
|
|
// touchmove events to drive it. Or if we want to settle for a less good
|
|
// experience we can make the touchmove events drive the existing step-zoom
|
|
// behaviour that the ctrl+mousewheel path takes.
|
|
evt.preventDefault();
|
|
}
|
|
}
|
|
|
|
function webViewerKeyDown(evt) {
|
|
if (PDFViewerApplication.overlayManager.active) {
|
|
return;
|
|
}
|
|
const { eventBus, pdfViewer } = PDFViewerApplication;
|
|
const isViewerInPresentationMode = pdfViewer.isInPresentationMode;
|
|
|
|
let handled = false,
|
|
ensureViewerFocused = false;
|
|
const cmd =
|
|
(evt.ctrlKey ? 1 : 0) |
|
|
(evt.altKey ? 2 : 0) |
|
|
(evt.shiftKey ? 4 : 0) |
|
|
(evt.metaKey ? 8 : 0);
|
|
|
|
// First, handle the key bindings that are independent whether an input
|
|
// control is selected or not.
|
|
if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
|
|
// either CTRL or META key with optional SHIFT.
|
|
switch (evt.keyCode) {
|
|
case 70: // f
|
|
if (
|
|
!PDFViewerApplication.supportsIntegratedFind &&
|
|
!evt.shiftKey
|
|
) {
|
|
PDFViewerApplication.findBar.open();
|
|
handled = true;
|
|
}
|
|
break;
|
|
case 71: // g
|
|
if (!PDFViewerApplication.supportsIntegratedFind) {
|
|
const { state } = PDFViewerApplication.findController;
|
|
if (state) {
|
|
const eventState = Object.assign(
|
|
Object.create(null),
|
|
state,
|
|
{
|
|
source: window,
|
|
type: 'again',
|
|
findPrevious: cmd === 5 || cmd === 12,
|
|
},
|
|
);
|
|
eventBus.dispatch('find', eventState);
|
|
}
|
|
handled = true;
|
|
}
|
|
break;
|
|
case 61: // FF/Mac '='
|
|
case 107: // FF '+' and '='
|
|
case 187: // Chrome '+'
|
|
case 171: // FF with German keyboard
|
|
if (!isViewerInPresentationMode) {
|
|
PDFViewerApplication.zoomIn();
|
|
}
|
|
handled = true;
|
|
break;
|
|
case 173: // FF/Mac '-'
|
|
case 109: // FF '-'
|
|
case 189: // Chrome '-'
|
|
if (!isViewerInPresentationMode) {
|
|
PDFViewerApplication.zoomOut();
|
|
}
|
|
handled = true;
|
|
break;
|
|
case 48: // '0'
|
|
case 96: // '0' on Numpad of Swedish keyboard
|
|
if (!isViewerInPresentationMode) {
|
|
// keeping it unhandled (to restore page zoom to 100%)
|
|
setTimeout(function () {
|
|
// ... and resetting the scale after browser adjusts its scale
|
|
PDFViewerApplication.zoomReset();
|
|
});
|
|
handled = false;
|
|
}
|
|
break;
|
|
|
|
case 38: // up arrow
|
|
if (
|
|
isViewerInPresentationMode ||
|
|
PDFViewerApplication.page > 1
|
|
) {
|
|
PDFViewerApplication.page = 1;
|
|
handled = true;
|
|
ensureViewerFocused = true;
|
|
}
|
|
break;
|
|
case 40: // down arrow
|
|
if (
|
|
isViewerInPresentationMode ||
|
|
PDFViewerApplication.page < PDFViewerApplication.pagesCount
|
|
) {
|
|
PDFViewerApplication.page = PDFViewerApplication.pagesCount;
|
|
handled = true;
|
|
ensureViewerFocused = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC || CHROME')) {
|
|
// CTRL or META without shift
|
|
if (cmd === 1 || cmd === 8) {
|
|
switch (evt.keyCode) {
|
|
case 83: // s
|
|
eventBus.dispatch('download', { source: window });
|
|
handled = true;
|
|
break;
|
|
|
|
case 79: // o
|
|
if (
|
|
typeof PDFJSDev === 'undefined' ||
|
|
PDFJSDev.test('GENERIC')
|
|
) {
|
|
eventBus.dispatch('openfile', { source: window });
|
|
handled = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// CTRL+ALT or Option+Command
|
|
if (cmd === 3 || cmd === 10) {
|
|
switch (evt.keyCode) {
|
|
case 80: // p
|
|
PDFViewerApplication.requestPresentationMode();
|
|
handled = true;
|
|
break;
|
|
case 71: // g
|
|
// focuses input#pageNumber field
|
|
PDFViewerApplication.appConfig.toolbar.pageNumber.select();
|
|
handled = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (handled) {
|
|
if (ensureViewerFocused && !isViewerInPresentationMode) {
|
|
pdfViewer.focus();
|
|
}
|
|
evt.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// Some shortcuts should not get handled if a control/input element
|
|
// is selected.
|
|
const curElement = getActiveOrFocusedElement();
|
|
const curElementTagName = curElement?.tagName.toUpperCase();
|
|
if (
|
|
curElementTagName === 'INPUT' ||
|
|
curElementTagName === 'TEXTAREA' ||
|
|
curElementTagName === 'SELECT' ||
|
|
curElement?.isContentEditable
|
|
) {
|
|
// Make sure that the secondary toolbar is closed when Escape is pressed.
|
|
if (evt.keyCode !== /* Esc = */ 27) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// No control key pressed at all.
|
|
if (cmd === 0) {
|
|
let turnPage = 0,
|
|
turnOnlyIfPageFit = false;
|
|
switch (evt.keyCode) {
|
|
case 38: // up arrow
|
|
case 33: // pg up
|
|
// vertical scrolling using arrow/pg keys
|
|
if (pdfViewer.isVerticalScrollbarEnabled) {
|
|
turnOnlyIfPageFit = true;
|
|
}
|
|
turnPage = -1;
|
|
break;
|
|
case 8: // backspace
|
|
if (!isViewerInPresentationMode) {
|
|
turnOnlyIfPageFit = true;
|
|
}
|
|
turnPage = -1;
|
|
break;
|
|
case 37: // left arrow
|
|
// horizontal scrolling using arrow keys
|
|
if (pdfViewer.isHorizontalScrollbarEnabled) {
|
|
turnOnlyIfPageFit = true;
|
|
}
|
|
/* falls through */
|
|
case 75: // 'k'
|
|
case 80: // 'p'
|
|
turnPage = -1;
|
|
break;
|
|
case 27: // esc key
|
|
if (
|
|
!PDFViewerApplication.supportsIntegratedFind &&
|
|
PDFViewerApplication.findBar.opened
|
|
) {
|
|
PDFViewerApplication.findBar.close();
|
|
handled = true;
|
|
}
|
|
break;
|
|
case 40: // down arrow
|
|
case 34: // pg down
|
|
// vertical scrolling using arrow/pg keys
|
|
if (pdfViewer.isVerticalScrollbarEnabled) {
|
|
turnOnlyIfPageFit = true;
|
|
}
|
|
turnPage = 1;
|
|
break;
|
|
case 13: // enter key
|
|
case 32: // spacebar
|
|
if (!isViewerInPresentationMode) {
|
|
turnOnlyIfPageFit = true;
|
|
}
|
|
turnPage = 1;
|
|
break;
|
|
case 39: // right arrow
|
|
// horizontal scrolling using arrow keys
|
|
if (pdfViewer.isHorizontalScrollbarEnabled) {
|
|
turnOnlyIfPageFit = true;
|
|
}
|
|
/* falls through */
|
|
case 74: // 'j'
|
|
case 78: // 'n'
|
|
turnPage = 1;
|
|
break;
|
|
|
|
case 36: // home
|
|
if (
|
|
isViewerInPresentationMode ||
|
|
PDFViewerApplication.page > 1
|
|
) {
|
|
PDFViewerApplication.page = 1;
|
|
handled = true;
|
|
ensureViewerFocused = true;
|
|
}
|
|
break;
|
|
case 35: // end
|
|
if (
|
|
isViewerInPresentationMode ||
|
|
PDFViewerApplication.page < PDFViewerApplication.pagesCount
|
|
) {
|
|
PDFViewerApplication.page = PDFViewerApplication.pagesCount;
|
|
handled = true;
|
|
ensureViewerFocused = true;
|
|
}
|
|
break;
|
|
|
|
case 83: // 's'
|
|
PDFViewerApplication.pdfCursorTools.switchTool(
|
|
CursorTool.SELECT,
|
|
);
|
|
break;
|
|
case 72: // 'h'
|
|
PDFViewerApplication.pdfCursorTools.switchTool(CursorTool.HAND);
|
|
break;
|
|
|
|
case 82: // 'r'
|
|
PDFViewerApplication.rotatePages(90);
|
|
break;
|
|
}
|
|
|
|
if (
|
|
turnPage !== 0 &&
|
|
(!turnOnlyIfPageFit || pdfViewer.currentScaleValue === 'page-fit')
|
|
) {
|
|
if (turnPage > 0) {
|
|
pdfViewer.nextPage();
|
|
} else {
|
|
pdfViewer.previousPage();
|
|
}
|
|
handled = true;
|
|
}
|
|
}
|
|
|
|
// shift-key
|
|
if (cmd === 4) {
|
|
switch (evt.keyCode) {
|
|
case 13: // enter key
|
|
case 32: // spacebar
|
|
if (
|
|
!isViewerInPresentationMode &&
|
|
pdfViewer.currentScaleValue !== 'page-fit'
|
|
) {
|
|
break;
|
|
}
|
|
pdfViewer.previousPage();
|
|
|
|
handled = true;
|
|
break;
|
|
|
|
case 82: // 'r'
|
|
PDFViewerApplication.rotatePages(-90);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!handled && !isViewerInPresentationMode) {
|
|
// 33=Page Up 34=Page Down 35=End 36=Home
|
|
// 37=Left 38=Up 39=Right 40=Down
|
|
// 32=Spacebar
|
|
if (
|
|
(evt.keyCode >= 33 && evt.keyCode <= 40) ||
|
|
(evt.keyCode === 32 && curElementTagName !== 'BUTTON')
|
|
) {
|
|
ensureViewerFocused = true;
|
|
}
|
|
}
|
|
|
|
if (ensureViewerFocused && !pdfViewer.containsElement(curElement)) {
|
|
// The page container is not focused, but a page navigation key has been
|
|
// pressed. Change the focus to the viewer container to make sure that
|
|
// navigation by keyboard works as expected.
|
|
pdfViewer.focus();
|
|
}
|
|
|
|
if (handled) {
|
|
evt.preventDefault();
|
|
}
|
|
}
|
|
|
|
function webViewerUpdateFindControlState({
|
|
state,
|
|
previous,
|
|
matchesCount,
|
|
rawQuery,
|
|
}) {
|
|
if (PDFViewerApplication.supportsIntegratedFind) {
|
|
PDFViewerApplication.externalServices.updateFindControlState({
|
|
result: state,
|
|
findPrevious: previous,
|
|
matchesCount,
|
|
rawQuery,
|
|
});
|
|
} else {
|
|
PDFViewerApplication.findBar.updateUIState(
|
|
state,
|
|
previous,
|
|
matchesCount,
|
|
);
|
|
}
|
|
}
|
|
|
|
function webViewerFindFromUrlHash(evt) {
|
|
PDFViewerApplication.eventBus.dispatch('find', {
|
|
source: evt.source,
|
|
type: '',
|
|
query: evt.query,
|
|
phraseSearch: evt.phraseSearch,
|
|
caseSensitive: false,
|
|
entireWord: false,
|
|
highlightAll: true,
|
|
findPrevious: false,
|
|
matchDiacritics: true,
|
|
});
|
|
}
|
|
function webViewerSpreadModeChanged(evt) {
|
|
if (PDFViewerApplication.isInitialViewSet) {
|
|
// Only update the storage when the document has been loaded *and* rendered.
|
|
PDFViewerApplication.store?.set('spreadMode', evt.mode).catch(() => {
|
|
// Unable to write to storage.
|
|
});
|
|
}
|
|
}
|
|
function webViewerScaleChanged(evt) {
|
|
PDFViewerApplication.pdfViewer.currentScaleValue = evt.value;
|
|
}
|
|
function webViewerRotateCw() {
|
|
PDFViewerApplication.rotatePages(90);
|
|
}
|
|
function webViewerRotateCcw() {
|
|
PDFViewerApplication.rotatePages(-90);
|
|
}
|
|
function webViewerOptionalContentConfig(evt) {
|
|
PDFViewerApplication.pdfViewer.optionalContentConfigPromise = evt.promise;
|
|
}
|
|
function webViewerSwitchScrollMode(evt) {
|
|
PDFViewerApplication.pdfViewer.scrollMode = evt.mode;
|
|
}
|
|
function webViewerSwitchSpreadMode(evt) {
|
|
PDFViewerApplication.pdfViewer.spreadMode = evt.mode;
|
|
}
|
|
function webViewerDocumentProperties() {
|
|
PDFViewerApplication.pdfDocumentProperties.open();
|
|
}
|
|
function webViewerVisibilityChange(evt) {
|
|
if (document.visibilityState === 'visible') {
|
|
// Ignore mouse wheel zooming during tab switches (bug 1503412).
|
|
setZoomDisabledTimeout();
|
|
}
|
|
}
|
|
window.PDFViewerApplication = PDFViewerApplication;
|
|
|
|
function pdfembGetPDF(url, callback) {
|
|
// Get PDF directly
|
|
if (url.search('/?pdfemb-serveurl=') == -1) {
|
|
return false;
|
|
}
|
|
let download_url = url;
|
|
pdfembAddAjaxBufferTransport();
|
|
jQuery
|
|
.ajax({
|
|
dataType: 'arraybuffer',
|
|
type: 'POST',
|
|
url: url,
|
|
})
|
|
.done(function (blob) {
|
|
let uia = new Uint8Array(blob);
|
|
|
|
let args = {
|
|
secure: true,
|
|
download_url: window.location.origin + download_url,
|
|
};
|
|
PDFViewerApplication.open(uia, args);
|
|
})
|
|
.fail(function (jqXHR, textStatus, errorThrown) {
|
|
return false;
|
|
});
|
|
}
|
|
|
|
function pdfembAddAjaxBufferTransport() {
|
|
let pdfembAddAjaxBufferTransport_added = false;
|
|
|
|
if (pdfembAddAjaxBufferTransport_added) {
|
|
return;
|
|
}
|
|
pdfembAddAjaxBufferTransport_added = true;
|
|
|
|
// http://www.artandlogic.com/blog/2013/11/jquery-ajax-blobs-and-array-buffers/
|
|
/**
|
|
* Register ajax transports for blob send/recieve and array buffer send/receive via XMLHttpRequest Level 2
|
|
* within the comfortable framework of the jquery ajax request, with full support for promises.
|
|
*
|
|
* Notice the +* in the dataType string? The + indicates we want this transport to be prepended to the list
|
|
* of potential transports (so it gets first dibs if the request passes the conditions within to provide the
|
|
* ajax transport, preventing the standard transport from hogging the request), and the * indicates that
|
|
* potentially any request with any dataType might want to use the transports provided herein.
|
|
*
|
|
* Remember to specify 'processData:false' in the ajax options when attempting to send a blob or arraybuffer -
|
|
* otherwise jquery will try (and fail) to convert the blob or buffer into a query string.
|
|
*/
|
|
jQuery.ajaxTransport('+*', function (options, originalOptions, jqXHR) {
|
|
// Test for the conditions that mean we can/want to send/receive blobs or arraybuffers - we need XMLHttpRequest
|
|
// level 2 (so feature-detect against window.FormData), feature detect against window.Blob or window.ArrayBuffer,
|
|
// and then check to see if the dataType is blob/arraybuffer or the data itself is a Blob/ArrayBuffer
|
|
if (
|
|
window.FormData &&
|
|
((options.dataType &&
|
|
(options.dataType == 'blob' ||
|
|
options.dataType == 'arraybuffer')) ||
|
|
(options.data &&
|
|
((window.Blob && options.data instanceof Blob) ||
|
|
(window.ArrayBuffer &&
|
|
options.data instanceof ArrayBuffer))))
|
|
) {
|
|
return {
|
|
/**
|
|
* Return a transport capable of sending and/or receiving blobs - in this case, we instantiate
|
|
* a new XMLHttpRequest and use it to actually perform the request, and funnel the result back
|
|
* into the jquery complete callback (such as the success function, done blocks, etc.)
|
|
*
|
|
* @param headers
|
|
* @param completeCallback
|
|
*/
|
|
send: function (headers, completeCallback) {
|
|
var xhr = new XMLHttpRequest(),
|
|
url = options.url || window.location.href,
|
|
type = options.type || 'GET',
|
|
dataType = options.dataType || 'text',
|
|
data = options.data || null,
|
|
async = options.async || true;
|
|
|
|
xhr.addEventListener('load', function () {
|
|
var res = {};
|
|
|
|
res[dataType] = xhr.response;
|
|
completeCallback(
|
|
xhr.status,
|
|
xhr.statusText,
|
|
res,
|
|
xhr.getAllResponseHeaders(),
|
|
);
|
|
});
|
|
|
|
xhr.open(type, url, async);
|
|
xhr.responseType = dataType;
|
|
xhr.send(data);
|
|
},
|
|
abort: function () {
|
|
jqXHR.abort();
|
|
},
|
|
};
|
|
}
|
|
});
|
|
}
|
|
|
|
function pdfemb_rc4ab(key, ab) {
|
|
var s = [],
|
|
j = 0,
|
|
x,
|
|
res = '',
|
|
input,
|
|
output;
|
|
var dv = new DataView(ab);
|
|
|
|
// Check for Unicode BOM and skip it
|
|
var starty = 0;
|
|
if (
|
|
dv.getUint8(0) == 0xef &&
|
|
dv.getUint8(1) == 0xbb &&
|
|
dv.getUint8(2) == 0xbf
|
|
) {
|
|
starty = 3;
|
|
}
|
|
|
|
// Decrypt
|
|
for (var i = 0; i < 256; i++) {
|
|
s[i] = i;
|
|
}
|
|
for (i = 0; i < 256; i++) {
|
|
j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
|
|
x = s[i];
|
|
s[i] = s[j];
|
|
s[j] = x;
|
|
}
|
|
i = 0;
|
|
j = 0;
|
|
for (var y = starty; y < ab.byteLength; y++) {
|
|
i = (i + 1) % 256;
|
|
j = (j + s[i]) % 256;
|
|
x = s[i];
|
|
s[i] = s[j];
|
|
s[j] = x;
|
|
input = dv.getUint8(y);
|
|
output = input ^ s[(s[i] + s[j]) % 256];
|
|
dv.setUint8(y, output);
|
|
}
|
|
}
|
|
|
|
export { PDFViewerApplication };
|