Merge pull request #10099 from timvandermeij/find-controller
[api-major] Rework the find controller for unit testing
This commit is contained in:
commit
ec10cae5b6
@ -38,24 +38,24 @@ var container = document.getElementById('viewerContainer');
|
|||||||
// (Optionally) enable hyperlinks within PDF files.
|
// (Optionally) enable hyperlinks within PDF files.
|
||||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||||
|
|
||||||
|
// (Optionally) enable find controller.
|
||||||
|
var pdfFindController = new pdfjsViewer.PDFFindController({
|
||||||
|
linkService: pdfLinkService,
|
||||||
|
});
|
||||||
|
|
||||||
var pdfViewer = new pdfjsViewer.PDFViewer({
|
var pdfViewer = new pdfjsViewer.PDFViewer({
|
||||||
container: container,
|
container: container,
|
||||||
linkService: pdfLinkService,
|
linkService: pdfLinkService,
|
||||||
|
findController: pdfFindController,
|
||||||
});
|
});
|
||||||
pdfLinkService.setViewer(pdfViewer);
|
pdfLinkService.setViewer(pdfViewer);
|
||||||
|
|
||||||
// (Optionally) enable find controller.
|
|
||||||
var pdfFindController = new pdfjsViewer.PDFFindController({
|
|
||||||
pdfViewer: pdfViewer,
|
|
||||||
});
|
|
||||||
pdfViewer.setFindController(pdfFindController);
|
|
||||||
|
|
||||||
container.addEventListener('pagesinit', function () {
|
container.addEventListener('pagesinit', function () {
|
||||||
// We can use pdfViewer now, e.g. let's change default scale.
|
// We can use pdfViewer now, e.g. let's change default scale.
|
||||||
pdfViewer.currentScaleValue = 'page-width';
|
pdfViewer.currentScaleValue = 'page-width';
|
||||||
|
|
||||||
if (SEARCH_FOR) { // We can try search for things
|
if (SEARCH_FOR) { // We can try search for things
|
||||||
pdfFindController.executeCommand('find', {query: SEARCH_FOR});
|
pdfFindController.executeCommand('find', { query: SEARCH_FOR, });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -70,4 +70,5 @@ pdfjsLib.getDocument({
|
|||||||
pdfViewer.setDocument(pdfDocument);
|
pdfViewer.setDocument(pdfDocument);
|
||||||
|
|
||||||
pdfLinkService.setDocument(pdfDocument, null);
|
pdfLinkService.setDocument(pdfDocument, null);
|
||||||
|
pdfFindController.setDocument(pdfDocument);
|
||||||
});
|
});
|
||||||
|
@ -38,24 +38,24 @@ var container = document.getElementById('viewerContainer');
|
|||||||
// (Optionally) enable hyperlinks within PDF files.
|
// (Optionally) enable hyperlinks within PDF files.
|
||||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||||
|
|
||||||
|
// (Optionally) enable find controller.
|
||||||
|
var pdfFindController = new pdfjsViewer.PDFFindController({
|
||||||
|
linkService: pdfLinkService,
|
||||||
|
});
|
||||||
|
|
||||||
var pdfSinglePageViewer = new pdfjsViewer.PDFSinglePageViewer({
|
var pdfSinglePageViewer = new pdfjsViewer.PDFSinglePageViewer({
|
||||||
container: container,
|
container: container,
|
||||||
linkService: pdfLinkService,
|
linkService: pdfLinkService,
|
||||||
|
findController: pdfFindController,
|
||||||
});
|
});
|
||||||
pdfLinkService.setViewer(pdfSinglePageViewer);
|
pdfLinkService.setViewer(pdfSinglePageViewer);
|
||||||
|
|
||||||
// (Optionally) enable find controller.
|
|
||||||
var pdfFindController = new pdfjsViewer.PDFFindController({
|
|
||||||
pdfViewer: pdfSinglePageViewer,
|
|
||||||
});
|
|
||||||
pdfSinglePageViewer.setFindController(pdfFindController);
|
|
||||||
|
|
||||||
container.addEventListener('pagesinit', function () {
|
container.addEventListener('pagesinit', function () {
|
||||||
// We can use pdfSinglePageViewer now, e.g. let's change default scale.
|
// We can use pdfSinglePageViewer now, e.g. let's change default scale.
|
||||||
pdfSinglePageViewer.currentScaleValue = 'page-width';
|
pdfSinglePageViewer.currentScaleValue = 'page-width';
|
||||||
|
|
||||||
if (SEARCH_FOR) { // We can try search for things
|
if (SEARCH_FOR) { // We can try search for things
|
||||||
pdfFindController.executeCommand('find', {query: SEARCH_FOR});
|
pdfFindController.executeCommand('find', { query: SEARCH_FOR, });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -70,4 +70,5 @@ pdfjsLib.getDocument({
|
|||||||
pdfSinglePageViewer.setDocument(pdfDocument);
|
pdfSinglePageViewer.setDocument(pdfDocument);
|
||||||
|
|
||||||
pdfLinkService.setDocument(pdfDocument, null);
|
pdfLinkService.setDocument(pdfDocument, null);
|
||||||
|
pdfFindController.setDocument(pdfDocument);
|
||||||
});
|
});
|
||||||
|
@ -31,7 +31,6 @@ var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/';
|
|||||||
var CMAP_PACKED = true;
|
var CMAP_PACKED = true;
|
||||||
|
|
||||||
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
||||||
var SEARCH_FOR = ''; // try 'Mozilla';
|
|
||||||
|
|
||||||
var container = document.getElementById('viewerContainer');
|
var container = document.getElementById('viewerContainer');
|
||||||
|
|
||||||
@ -46,19 +45,9 @@ var pdfViewer = new pdfjsViewer.PDFViewer({
|
|||||||
});
|
});
|
||||||
pdfLinkService.setViewer(pdfViewer);
|
pdfLinkService.setViewer(pdfViewer);
|
||||||
|
|
||||||
// (Optionally) enable find controller.
|
|
||||||
var pdfFindController = new pdfjsViewer.PDFFindController({
|
|
||||||
pdfViewer: pdfViewer,
|
|
||||||
});
|
|
||||||
pdfViewer.setFindController(pdfFindController);
|
|
||||||
|
|
||||||
container.addEventListener('pagesinit', function () {
|
container.addEventListener('pagesinit', function () {
|
||||||
// We can use pdfViewer now, e.g. let's change default scale.
|
// We can use pdfViewer now, e.g. let's change default scale.
|
||||||
pdfViewer.currentScaleValue = 'page-width';
|
pdfViewer.currentScaleValue = 'page-width';
|
||||||
|
|
||||||
if (SEARCH_FOR) { // We can try search for things
|
|
||||||
pdfFindController.executeCommand('find', {query: SEARCH_FOR});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Loading document.
|
// Loading document.
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
"network_utils_spec.js",
|
"network_utils_spec.js",
|
||||||
"node_stream_spec.js",
|
"node_stream_spec.js",
|
||||||
"parser_spec.js",
|
"parser_spec.js",
|
||||||
"pdf_find_utils.js",
|
"pdf_find_controller_spec.js",
|
||||||
"pdf_history.js",
|
"pdf_find_utils_spec.js",
|
||||||
|
"pdf_history_spec.js",
|
||||||
"primitives_spec.js",
|
"primitives_spec.js",
|
||||||
"stream_spec.js",
|
"stream_spec.js",
|
||||||
"type1_parser_spec.js",
|
"type1_parser_spec.js",
|
||||||
|
@ -67,6 +67,7 @@ function initializePDFJS(callback) {
|
|||||||
'pdfjs-test/unit/network_spec',
|
'pdfjs-test/unit/network_spec',
|
||||||
'pdfjs-test/unit/network_utils_spec',
|
'pdfjs-test/unit/network_utils_spec',
|
||||||
'pdfjs-test/unit/parser_spec',
|
'pdfjs-test/unit/parser_spec',
|
||||||
|
'pdfjs-test/unit/pdf_find_controller_spec',
|
||||||
'pdfjs-test/unit/pdf_find_utils_spec',
|
'pdfjs-test/unit/pdf_find_utils_spec',
|
||||||
'pdfjs-test/unit/pdf_history_spec',
|
'pdfjs-test/unit/pdf_history_spec',
|
||||||
'pdfjs-test/unit/primitives_spec',
|
'pdfjs-test/unit/primitives_spec',
|
||||||
|
99
test/unit/pdf_find_controller_spec.js
Normal file
99
test/unit/pdf_find_controller_spec.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/* Copyright 2018 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { buildGetDocumentParams } from './test_utils';
|
||||||
|
import { EventBus } from '../../web/ui_utils';
|
||||||
|
import { getDocument } from '../../src/display/api';
|
||||||
|
import { PDFFindController } from '../../web/pdf_find_controller';
|
||||||
|
import { SimpleLinkService } from '../../web/pdf_link_service';
|
||||||
|
|
||||||
|
class MockLinkService extends SimpleLinkService {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._page = 1;
|
||||||
|
this._pdfDocument = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDocument(pdfDocument) {
|
||||||
|
this._pdfDocument = pdfDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
get pagesCount() {
|
||||||
|
return this._pdfDocument.numPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
get page() {
|
||||||
|
return this._page;
|
||||||
|
}
|
||||||
|
|
||||||
|
set page(value) {
|
||||||
|
this._page = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('pdf_find_controller', function() {
|
||||||
|
let eventBus;
|
||||||
|
let pdfFindController;
|
||||||
|
|
||||||
|
beforeEach(function(done) {
|
||||||
|
const loadingTask = getDocument(buildGetDocumentParams('tracemonkey.pdf'));
|
||||||
|
loadingTask.promise.then(function(pdfDocument) {
|
||||||
|
const linkService = new MockLinkService();
|
||||||
|
linkService.setDocument(pdfDocument);
|
||||||
|
|
||||||
|
eventBus = new EventBus();
|
||||||
|
|
||||||
|
pdfFindController = new PDFFindController({
|
||||||
|
linkService,
|
||||||
|
eventBus,
|
||||||
|
});
|
||||||
|
pdfFindController.setDocument(pdfDocument);
|
||||||
|
|
||||||
|
eventBus.dispatch('pagesinit');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
eventBus = null;
|
||||||
|
pdfFindController = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('performs a basic search', function(done) {
|
||||||
|
pdfFindController.executeCommand('find', { query: 'Dynamic', });
|
||||||
|
|
||||||
|
const matchesPerPage = [11, 5, 0, 3, 0, 0, 0, 1, 1, 1, 0, 3, 4, 4];
|
||||||
|
const totalPages = matchesPerPage.length;
|
||||||
|
const totalMatches = matchesPerPage.reduce((a, b) => {
|
||||||
|
return a + b;
|
||||||
|
});
|
||||||
|
|
||||||
|
eventBus.on('updatefindmatchescount',
|
||||||
|
function onUpdateFindMatchesCount(evt) {
|
||||||
|
if (pdfFindController.pageMatches.length !== totalPages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eventBus.off('updatefindmatchescount', onUpdateFindMatchesCount);
|
||||||
|
|
||||||
|
expect(evt.matchesCount.total).toBe(totalMatches);
|
||||||
|
for (let i = 0; i < totalPages; i++) {
|
||||||
|
expect(pdfFindController.pageMatches[i].length)
|
||||||
|
.toEqual(matchesPerPage[i]);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
60
web/app.js
60
web/app.js
@ -305,6 +305,12 @@ let PDFViewerApplication = {
|
|||||||
});
|
});
|
||||||
this.downloadManager = downloadManager;
|
this.downloadManager = downloadManager;
|
||||||
|
|
||||||
|
const findController = new PDFFindController({
|
||||||
|
linkService: pdfLinkService,
|
||||||
|
eventBus,
|
||||||
|
});
|
||||||
|
this.findController = findController;
|
||||||
|
|
||||||
let container = appConfig.mainContainer;
|
let container = appConfig.mainContainer;
|
||||||
let viewer = appConfig.viewerContainer;
|
let viewer = appConfig.viewerContainer;
|
||||||
this.pdfViewer = new PDFViewer({
|
this.pdfViewer = new PDFViewer({
|
||||||
@ -314,6 +320,7 @@ let PDFViewerApplication = {
|
|||||||
renderingQueue: pdfRenderingQueue,
|
renderingQueue: pdfRenderingQueue,
|
||||||
linkService: pdfLinkService,
|
linkService: pdfLinkService,
|
||||||
downloadManager,
|
downloadManager,
|
||||||
|
findController,
|
||||||
renderer: AppOptions.get('renderer'),
|
renderer: AppOptions.get('renderer'),
|
||||||
enableWebGL: AppOptions.get('enableWebGL'),
|
enableWebGL: AppOptions.get('enableWebGL'),
|
||||||
l10n: this.l10n,
|
l10n: this.l10n,
|
||||||
@ -342,34 +349,8 @@ let PDFViewerApplication = {
|
|||||||
});
|
});
|
||||||
pdfLinkService.setHistory(this.pdfHistory);
|
pdfLinkService.setHistory(this.pdfHistory);
|
||||||
|
|
||||||
this.findController = new PDFFindController({
|
|
||||||
pdfViewer: this.pdfViewer,
|
|
||||||
eventBus,
|
|
||||||
});
|
|
||||||
this.findController.onUpdateResultsCount = (matchesCount) => {
|
|
||||||
if (this.supportsIntegratedFind) {
|
|
||||||
this.externalServices.updateFindMatchesCount(matchesCount);
|
|
||||||
} else {
|
|
||||||
this.findBar.updateResultsCount(matchesCount);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.findController.onUpdateState = (state, previous, matchesCount) => {
|
|
||||||
if (this.supportsIntegratedFind) {
|
|
||||||
this.externalServices.updateFindControlState({
|
|
||||||
result: state,
|
|
||||||
findPrevious: previous,
|
|
||||||
matchesCount,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.findBar.updateUIState(state, previous, matchesCount);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.pdfViewer.setFindController(this.findController);
|
|
||||||
|
|
||||||
// TODO: improve `PDFFindBar` constructor parameter passing
|
// TODO: improve `PDFFindBar` constructor parameter passing
|
||||||
let findBarConfig = Object.create(appConfig.findBar);
|
let findBarConfig = Object.create(appConfig.findBar);
|
||||||
findBarConfig.findController = this.findController;
|
|
||||||
findBarConfig.eventBus = eventBus;
|
findBarConfig.eventBus = eventBus;
|
||||||
this.findBar = new PDFFindBar(findBarConfig, this.l10n);
|
this.findBar = new PDFFindBar(findBarConfig, this.l10n);
|
||||||
|
|
||||||
@ -593,6 +574,7 @@ let PDFViewerApplication = {
|
|||||||
if (this.pdfDocument) {
|
if (this.pdfDocument) {
|
||||||
this.pdfDocument = null;
|
this.pdfDocument = null;
|
||||||
|
|
||||||
|
this.findController.setDocument(null);
|
||||||
this.pdfThumbnailViewer.setDocument(null);
|
this.pdfThumbnailViewer.setDocument(null);
|
||||||
this.pdfViewer.setDocument(null);
|
this.pdfViewer.setDocument(null);
|
||||||
this.pdfLinkService.setDocument(null);
|
this.pdfLinkService.setDocument(null);
|
||||||
@ -609,7 +591,6 @@ let PDFViewerApplication = {
|
|||||||
this.pdfOutlineViewer.reset();
|
this.pdfOutlineViewer.reset();
|
||||||
this.pdfAttachmentViewer.reset();
|
this.pdfAttachmentViewer.reset();
|
||||||
|
|
||||||
this.findController.reset();
|
|
||||||
this.findBar.reset();
|
this.findBar.reset();
|
||||||
this.toolbar.reset();
|
this.toolbar.reset();
|
||||||
this.secondaryToolbar.reset();
|
this.secondaryToolbar.reset();
|
||||||
@ -917,6 +898,7 @@ let PDFViewerApplication = {
|
|||||||
} else if (PDFJSDev.test('CHROME')) {
|
} else if (PDFJSDev.test('CHROME')) {
|
||||||
baseDocumentUrl = location.href.split('#')[0];
|
baseDocumentUrl = location.href.split('#')[0];
|
||||||
}
|
}
|
||||||
|
this.findController.setDocument(pdfDocument);
|
||||||
this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
|
this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
|
||||||
this.pdfDocumentProperties.setDocument(pdfDocument, this.url);
|
this.pdfDocumentProperties.setDocument(pdfDocument, this.url);
|
||||||
|
|
||||||
@ -1343,6 +1325,8 @@ let PDFViewerApplication = {
|
|||||||
eventBus.on('documentproperties', webViewerDocumentProperties);
|
eventBus.on('documentproperties', webViewerDocumentProperties);
|
||||||
eventBus.on('find', webViewerFind);
|
eventBus.on('find', webViewerFind);
|
||||||
eventBus.on('findfromurlhash', webViewerFindFromUrlHash);
|
eventBus.on('findfromurlhash', webViewerFindFromUrlHash);
|
||||||
|
eventBus.on('updatefindmatchescount', webViewerUpdateFindMatchesCount);
|
||||||
|
eventBus.on('updatefindcontrolstate', webViewerUpdateFindControlState);
|
||||||
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
||||||
eventBus.on('fileinputchange', webViewerFileInputChange);
|
eventBus.on('fileinputchange', webViewerFileInputChange);
|
||||||
}
|
}
|
||||||
@ -1414,6 +1398,8 @@ let PDFViewerApplication = {
|
|||||||
eventBus.off('documentproperties', webViewerDocumentProperties);
|
eventBus.off('documentproperties', webViewerDocumentProperties);
|
||||||
eventBus.off('find', webViewerFind);
|
eventBus.off('find', webViewerFind);
|
||||||
eventBus.off('findfromurlhash', webViewerFindFromUrlHash);
|
eventBus.off('findfromurlhash', webViewerFindFromUrlHash);
|
||||||
|
eventBus.off('updatefindmatchescount', webViewerUpdateFindMatchesCount);
|
||||||
|
eventBus.off('updatefindcontrolstate', webViewerUpdateFindControlState);
|
||||||
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
||||||
eventBus.off('fileinputchange', webViewerFileInputChange);
|
eventBus.off('fileinputchange', webViewerFileInputChange);
|
||||||
}
|
}
|
||||||
@ -1976,6 +1962,26 @@ function webViewerFindFromUrlHash(evt) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function webViewerUpdateFindMatchesCount({ matchesCount, }) {
|
||||||
|
if (PDFViewerApplication.supportsIntegratedFind) {
|
||||||
|
PDFViewerApplication.externalServices.updateFindMatchesCount(matchesCount);
|
||||||
|
} else {
|
||||||
|
PDFViewerApplication.findBar.updateResultsCount(matchesCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function webViewerUpdateFindControlState({ state, previous, matchesCount, }) {
|
||||||
|
if (PDFViewerApplication.supportsIntegratedFind) {
|
||||||
|
PDFViewerApplication.externalServices.updateFindControlState({
|
||||||
|
result: state,
|
||||||
|
findPrevious: previous,
|
||||||
|
matchesCount,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
PDFViewerApplication.findBar.updateUIState(state, previous, matchesCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function webViewerScaleChanging(evt) {
|
function webViewerScaleChanging(evt) {
|
||||||
PDFViewerApplication.toolbar.setPageScale(evt.presetValue, evt.scale);
|
PDFViewerApplication.toolbar.setPageScale(evt.presetValue, evt.scale);
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ const SpreadMode = {
|
|||||||
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
||||||
* @property {DownloadManager} downloadManager - (optional) The download
|
* @property {DownloadManager} downloadManager - (optional) The download
|
||||||
* manager component.
|
* manager component.
|
||||||
|
* @property {PDFFindController} findController - (optional) The find
|
||||||
|
* controller component.
|
||||||
* @property {PDFRenderingQueue} renderingQueue - (optional) The rendering
|
* @property {PDFRenderingQueue} renderingQueue - (optional) The rendering
|
||||||
* queue object.
|
* queue object.
|
||||||
* @property {boolean} removePageBorders - (optional) Removes the border shadow
|
* @property {boolean} removePageBorders - (optional) Removes the border shadow
|
||||||
@ -142,6 +144,7 @@ class BaseViewer {
|
|||||||
this.eventBus = options.eventBus || getGlobalEventBus();
|
this.eventBus = options.eventBus || getGlobalEventBus();
|
||||||
this.linkService = options.linkService || new SimpleLinkService();
|
this.linkService = options.linkService || new SimpleLinkService();
|
||||||
this.downloadManager = options.downloadManager || null;
|
this.downloadManager = options.downloadManager || null;
|
||||||
|
this.findController = options.findController || null;
|
||||||
this.removePageBorders = options.removePageBorders || false;
|
this.removePageBorders = options.removePageBorders || false;
|
||||||
this.textLayerMode = Number.isInteger(options.textLayerMode) ?
|
this.textLayerMode = Number.isInteger(options.textLayerMode) ?
|
||||||
options.textLayerMode : TextLayerMode.ENABLE;
|
options.textLayerMode : TextLayerMode.ENABLE;
|
||||||
@ -913,14 +916,6 @@ class BaseViewer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPageTextContent(pageIndex) {
|
|
||||||
return this.pdfDocument.getPage(pageIndex + 1).then(function(page) {
|
|
||||||
return page.getTextContent({
|
|
||||||
normalizeWhitespace: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {HTMLDivElement} textLayerDiv
|
* @param {HTMLDivElement} textLayerDiv
|
||||||
* @param {number} pageIndex
|
* @param {number} pageIndex
|
||||||
@ -963,10 +958,6 @@ class BaseViewer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setFindController(findController) {
|
|
||||||
this.findController = findController;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {boolean} Whether all pages of the PDF document have identical
|
* @returns {boolean} Whether all pages of the PDF document have identical
|
||||||
* widths and heights.
|
* widths and heights.
|
||||||
|
@ -184,7 +184,7 @@ class PDFDocumentProperties {
|
|||||||
* Note that the overlay will contain no information if this method
|
* Note that the overlay will contain no information if this method
|
||||||
* is not called.
|
* is not called.
|
||||||
*
|
*
|
||||||
* @param {Object} pdfDocument - A reference to the PDF document.
|
* @param {PDFDocumentProxy} pdfDocument - A reference to the PDF document.
|
||||||
* @param {string} url - The URL of the document.
|
* @param {string} url - The URL of the document.
|
||||||
*/
|
*/
|
||||||
setDocument(pdfDocument, url = null) {
|
setDocument(pdfDocument, url = null) {
|
||||||
|
@ -38,15 +38,9 @@ class PDFFindBar {
|
|||||||
this.findResultsCount = options.findResultsCount || null;
|
this.findResultsCount = options.findResultsCount || null;
|
||||||
this.findPreviousButton = options.findPreviousButton || null;
|
this.findPreviousButton = options.findPreviousButton || null;
|
||||||
this.findNextButton = options.findNextButton || null;
|
this.findNextButton = options.findNextButton || null;
|
||||||
this.findController = options.findController || null;
|
|
||||||
this.eventBus = options.eventBus;
|
this.eventBus = options.eventBus;
|
||||||
this.l10n = l10n;
|
this.l10n = l10n;
|
||||||
|
|
||||||
if (this.findController === null) {
|
|
||||||
throw new Error('PDFFindBar cannot be used without a ' +
|
|
||||||
'PDFFindController instance.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add event listeners to the DOM elements.
|
// Add event listeners to the DOM elements.
|
||||||
this.toggleButton.addEventListener('click', () => {
|
this.toggleButton.addEventListener('click', () => {
|
||||||
this.toggle();
|
this.toggle();
|
||||||
|
@ -40,18 +40,24 @@ const CHARACTERS_TO_NORMALIZE = {
|
|||||||
'\u00BE': '3/4', // Vulgar fraction three quarters
|
'\u00BE': '3/4', // Vulgar fraction three quarters
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PDFFindControllerOptions
|
||||||
|
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
||||||
|
* @property {EventBus} eventBus - The application event bus.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides search functionality to find a given string in a PDF document.
|
* Provides search functionality to find a given string in a PDF document.
|
||||||
*/
|
*/
|
||||||
class PDFFindController {
|
class PDFFindController {
|
||||||
constructor({ pdfViewer, eventBus = getGlobalEventBus(), }) {
|
/**
|
||||||
this._pdfViewer = pdfViewer;
|
* @param {PDFFindControllerOptions} options
|
||||||
|
*/
|
||||||
|
constructor({ linkService, eventBus = getGlobalEventBus(), }) {
|
||||||
|
this._linkService = linkService;
|
||||||
this._eventBus = eventBus;
|
this._eventBus = eventBus;
|
||||||
|
|
||||||
this.onUpdateResultsCount = null;
|
this._reset();
|
||||||
this.onUpdateState = null;
|
|
||||||
|
|
||||||
this.reset();
|
|
||||||
|
|
||||||
eventBus.on('findbarclose', () => {
|
eventBus.on('findbarclose', () => {
|
||||||
this._highlightMatches = false;
|
this._highlightMatches = false;
|
||||||
@ -87,8 +93,51 @@ class PDFFindController {
|
|||||||
return this._state;
|
return this._state;
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
/**
|
||||||
|
* Set a reference to the PDF document in order to search it.
|
||||||
|
* Note that searching is not possible if this method is not called.
|
||||||
|
*
|
||||||
|
* @param {PDFDocumentProxy} pdfDocument - The PDF document to search.
|
||||||
|
*/
|
||||||
|
setDocument(pdfDocument) {
|
||||||
|
if (this._pdfDocument) {
|
||||||
|
this._reset();
|
||||||
|
}
|
||||||
|
if (!pdfDocument) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._pdfDocument = pdfDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
executeCommand(cmd, state) {
|
||||||
|
if (!this._pdfDocument) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._state === null || cmd !== 'findagain') {
|
||||||
|
this._dirtyMatch = true;
|
||||||
|
}
|
||||||
|
this._state = state;
|
||||||
|
this._updateUIState(FindState.PENDING);
|
||||||
|
|
||||||
|
this._firstPagePromise.then(() => {
|
||||||
|
this._extractText();
|
||||||
|
|
||||||
|
clearTimeout(this._findTimeout);
|
||||||
|
if (cmd === 'find') {
|
||||||
|
// Trigger the find action with a small delay to avoid starting the
|
||||||
|
// search when the user is still typing (saving resources).
|
||||||
|
this._findTimeout =
|
||||||
|
setTimeout(this._nextMatch.bind(this), FIND_TIMEOUT);
|
||||||
|
} else {
|
||||||
|
this._nextMatch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_reset() {
|
||||||
this._highlightMatches = false;
|
this._highlightMatches = false;
|
||||||
|
this._pdfDocument = null;
|
||||||
this._pageMatches = [];
|
this._pageMatches = [];
|
||||||
this._pageMatchesLength = null;
|
this._pageMatchesLength = null;
|
||||||
this._state = null;
|
this._state = null;
|
||||||
@ -118,28 +167,6 @@ class PDFFindController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
executeCommand(cmd, state) {
|
|
||||||
if (this._state === null || cmd !== 'findagain') {
|
|
||||||
this._dirtyMatch = true;
|
|
||||||
}
|
|
||||||
this._state = state;
|
|
||||||
this._updateUIState(FindState.PENDING);
|
|
||||||
|
|
||||||
this._firstPagePromise.then(() => {
|
|
||||||
this._extractText();
|
|
||||||
|
|
||||||
clearTimeout(this._findTimeout);
|
|
||||||
if (cmd === 'find') {
|
|
||||||
// Trigger the find action with a small delay to avoid starting the
|
|
||||||
// search when the user is still typing (saving resources).
|
|
||||||
this._findTimeout =
|
|
||||||
setTimeout(this._nextMatch.bind(this), FIND_TIMEOUT);
|
|
||||||
} else {
|
|
||||||
this._nextMatch();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_normalize(text) {
|
_normalize(text) {
|
||||||
return text.replace(this._normalizationRegex, function(ch) {
|
return text.replace(this._normalizationRegex, function(ch) {
|
||||||
return CHARACTERS_TO_NORMALIZE[ch];
|
return CHARACTERS_TO_NORMALIZE[ch];
|
||||||
@ -321,12 +348,16 @@ class PDFFindController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let promise = Promise.resolve();
|
let promise = Promise.resolve();
|
||||||
for (let i = 0, ii = this._pdfViewer.pagesCount; i < ii; i++) {
|
for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) {
|
||||||
const extractTextCapability = createPromiseCapability();
|
const extractTextCapability = createPromiseCapability();
|
||||||
this._extractTextPromises[i] = extractTextCapability.promise;
|
this._extractTextPromises[i] = extractTextCapability.promise;
|
||||||
|
|
||||||
promise = promise.then(() => {
|
promise = promise.then(() => {
|
||||||
return this._pdfViewer.getPageTextContent(i).then((textContent) => {
|
return this._pdfDocument.getPage(i + 1).then((pdfPage) => {
|
||||||
|
return pdfPage.getTextContent({
|
||||||
|
normalizeWhitespace: true,
|
||||||
|
});
|
||||||
|
}).then((textContent) => {
|
||||||
const textItems = textContent.items;
|
const textItems = textContent.items;
|
||||||
const strBuf = [];
|
const strBuf = [];
|
||||||
|
|
||||||
@ -350,21 +381,21 @@ class PDFFindController {
|
|||||||
_updatePage(index) {
|
_updatePage(index) {
|
||||||
if (this._selected.pageIdx === index) {
|
if (this._selected.pageIdx === index) {
|
||||||
// If the page is selected, scroll the page into view, which triggers
|
// If the page is selected, scroll the page into view, which triggers
|
||||||
// rendering the page, which adds the textLayer. Once the textLayer is
|
// rendering the page, which adds the text layer. Once the text layer
|
||||||
// build, it will scroll onto the selected match.
|
// is built, it will scroll to the selected match.
|
||||||
this._pdfViewer.currentPageNumber = index + 1;
|
this._linkService.page = index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = this._pdfViewer.getPageView(index);
|
this._eventBus.dispatch('updatetextlayermatches', {
|
||||||
if (page.textLayer) {
|
source: this,
|
||||||
page.textLayer.updateMatches();
|
pageIndex: index,
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_nextMatch() {
|
_nextMatch() {
|
||||||
const previous = this._state.findPrevious;
|
const previous = this._state.findPrevious;
|
||||||
const currentPageIndex = this._pdfViewer.currentPageNumber - 1;
|
const currentPageIndex = this._linkService.page - 1;
|
||||||
const numPages = this._pdfViewer.pagesCount;
|
const numPages = this._linkService.pagesCount;
|
||||||
|
|
||||||
this._highlightMatches = true;
|
this._highlightMatches = true;
|
||||||
|
|
||||||
@ -476,7 +507,7 @@ class PDFFindController {
|
|||||||
|
|
||||||
_advanceOffsetPage(previous) {
|
_advanceOffsetPage(previous) {
|
||||||
const offset = this._offset;
|
const offset = this._offset;
|
||||||
const numPages = this._extractTextPromises.length;
|
const numPages = this._linkService.pagesCount;
|
||||||
offset.pageIdx = (previous ? offset.pageIdx - 1 : offset.pageIdx + 1);
|
offset.pageIdx = (previous ? offset.pageIdx - 1 : offset.pageIdx + 1);
|
||||||
offset.matchIdx = null;
|
offset.matchIdx = null;
|
||||||
|
|
||||||
@ -495,8 +526,8 @@ class PDFFindController {
|
|||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
const previousPage = this._selected.pageIdx;
|
const previousPage = this._selected.pageIdx;
|
||||||
this.selected.pageIdx = this._offset.pageIdx;
|
this._selected.pageIdx = this._offset.pageIdx;
|
||||||
this.selected.matchIdx = this._offset.matchIdx;
|
this._selected.matchIdx = this._offset.matchIdx;
|
||||||
state = (wrapped ? FindState.WRAPPED : FindState.FOUND);
|
state = (wrapped ? FindState.WRAPPED : FindState.FOUND);
|
||||||
|
|
||||||
// Update the currently selected page to wipe out any selected matches.
|
// Update the currently selected page to wipe out any selected matches.
|
||||||
@ -530,19 +561,19 @@ class PDFFindController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updateUIResultsCount() {
|
_updateUIResultsCount() {
|
||||||
if (!this.onUpdateResultsCount) {
|
this._eventBus.dispatch('updatefindmatchescount', {
|
||||||
return;
|
source: this,
|
||||||
}
|
matchesCount: this._requestMatchesCount(),
|
||||||
const matchesCount = this._requestMatchesCount();
|
});
|
||||||
this.onUpdateResultsCount(matchesCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateUIState(state, previous) {
|
_updateUIState(state, previous) {
|
||||||
if (!this.onUpdateState) {
|
this._eventBus.dispatch('updatefindcontrolstate', {
|
||||||
return;
|
source: this,
|
||||||
}
|
state,
|
||||||
const matchesCount = this._requestMatchesCount();
|
previous,
|
||||||
this.onUpdateState(state, previous, matchesCount);
|
matchesCount: this._requestMatchesCount(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ class TextLayerBuilder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
_boundEvents.updateTextLayerMatches = (evt) => {
|
_boundEvents.updateTextLayerMatches = (evt) => {
|
||||||
if (evt.pageIndex !== -1) {
|
if (evt.pageIndex !== this.pageIdx && evt.pageIndex !== -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.updateMatches();
|
this.updateMatches();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user