/* Copyright 2016 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 { animationStarted, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, docStyle, MAX_SCALE, MIN_SCALE, noContextMenuHandler, } from './ui_utils.js'; import { AnnotationEditorType } from 'pdfjs-dist'; const PAGE_NUMBER_LOADING_INDICATOR = 'visiblePageIsLoading'; /** * @typedef {Object} ToolbarOptions * @property {HTMLDivElement} container - Container for the secondary toolbar. * @property {HTMLSpanElement} numPages - Label that contains number of pages. * @property {HTMLInputElement} pageNumber - Control for display and user input * of the current page number. * @property {HTMLSelectElement} scaleSelect - Scale selection control. * Its width is adjusted, when necessary, on UI localization. * @property {HTMLOptionElement} customScaleOption - The item used to display * a non-predefined scale. * @property {HTMLButtonElement} previous - Button to go to the previous page. * @property {HTMLButtonElement} next - Button to go to the next page. * @property {HTMLButtonElement} zoomIn - Button to zoom in the pages. * @property {HTMLButtonElement} zoomOut - Button to zoom out the pages. * @property {HTMLButtonElement} viewFind - Button to open find bar. * @property {HTMLButtonElement} openFile - Button to open a new document. * @property {HTMLButtonElement} presentationModeButton - Button to switch to * presentation mode. * @property {HTMLButtonElement} editorNoneButton - Button to disable editing. * @property {HTMLButtonElement} editorFreeTextButton - Button to switch to * FreeText editing. * @property {HTMLButtonElement} download - Button to download the document. * @property {HTMLAnchorElement} viewBookmark - Button to obtain a bookmark link * to the current location in the document. */ class Toolbar { #wasLocalized = false; /** * @param {ToolbarOptions} options * @param {EventBus} eventBus * @param {IL10n} l10n - Localization service. */ constructor(options, eventBus, l10n) { this.toolbar = options.container; this.eventBus = eventBus; this.l10n = l10n; this.buttons = [ { element: options.previous, eventName: 'previouspage' }, { element: options.next, eventName: 'nextpage' }, { element: options.zoomIn, eventName: 'zoomin' }, { element: options.zoomOut, eventName: 'zoomout' }, { element: options.print, eventName: 'print' }, { element: options.download, eventName: 'download' }, ]; this.items = { numPages: options.numPages, pageNumber: options.pageNumber, scaleSelect: options.scaleSelect, customScaleOption: options.customScaleOption, previous: options.previous, next: options.next, zoomIn: options.zoomIn, zoomOut: options.zoomOut, fullscreen: options.fullscreen, }; // Bind the event listeners for click and various other actions. this.#bindListeners(options); this.reset(); } setPageNumber(pageNumber, pageLabel) { this.pageNumber = pageNumber; this.pageLabel = pageLabel; this.#updateUIState(false); } setPagesCount(pagesCount, hasPageLabels) { this.pagesCount = pagesCount; this.hasPageLabels = hasPageLabels; this.#updateUIState(true); } setPageScale(pageScaleValue, pageScale) { this.pageScaleValue = (pageScaleValue || pageScale).toString(); this.pageScale = pageScale; this.#updateUIState(false); } reset() { this.pageNumber = 0; this.pageLabel = null; this.hasPageLabels = false; this.pagesCount = 0; this.pageScaleValue = DEFAULT_SCALE_VALUE; this.pageScale = DEFAULT_SCALE; this.#updateUIState(true); this.updateLoadingIndicatorState(); // Reset the Editor buttons too, since they're document specific. this.eventBus.dispatch('toolbarreset', { source: this }); } #bindListeners(options) { const { pageNumber, scaleSelect, fullscreen } = this.items; const self = this; // The buttons within the toolbar. for (const { element, eventName, eventDetails } of this.buttons) { for (let i = 0; i < element.length; i++) { element[i].addEventListener('click', (evt) => { if (eventName !== null) { const details = { source: this }; if (eventDetails) { for (const property in eventDetails) { details[property] = eventDetails[property]; } } this.eventBus.dispatch(eventName, details); } }); } } for (let i = 0; i < pageNumber.length; i++) { pageNumber[i].addEventListener('click', function () { this.select(); }); pageNumber[i].addEventListener('change', function () { self.eventBus.dispatch('pagenumberchanged', { source: self, value: this.value, }); }); } for (let i = 0; i < scaleSelect.length; i++) { scaleSelect[i].addEventListener('change', function () { if (this.value === 'custom') { return; } self.eventBus.dispatch('scalechanged', { source: self, value: this.value, }); }); } for (let i = 0; i < fullscreen.length; i++) { fullscreen[i].addEventListener('click', function (evt) { const target = evt.target; let pdf_target_id = target.getAttribute('data-pdf-id'); let frame = window.parent.document.querySelector( '#wppdf-emb-iframe-' + pdf_target_id, ); let container = window.parent.document.querySelector( '#wppdfemb-frame-container-' + pdf_target_id, ); if (frame.classList.contains('wppdf-fullscreen')) { container.append(frame); frame.classList.remove('wppdf-fullscreen'); } else { frame.classList.add('wppdf-fullscreen'); parent.document.body.append(frame); } }); let deboune; window.parent.document.addEventListener('keyup', function (e) { switch (e.keyCode) { case 27: // Escape let pdf_target_id = fullscreen[i].getAttribute('data-pdf-id'); let frame = window.parent.document.getElementById( 'wppdf-emb-iframe-' + pdf_target_id, ); let container = window.parent.document.querySelector( '#wppdfemb-frame-container-' + pdf_target_id, ); if (frame.classList.contains('wppdf-fullscreen')) { frame.classList.remove('wppdf-fullscreen'); container.appendChild(frame); } break; } }); document.addEventListener('keyup', function (e) { switch (e.keyCode) { case 27: // Escape let pdf_target_id = fullscreen[i].getAttribute('data-pdf-id'); let frame = window.parent.document.getElementById( 'wppdf-emb-iframe-' + pdf_target_id, ); let container = window.parent.document.querySelector( '#wppdfemb-frame-container-' + pdf_target_id, ); if (frame.classList.contains('wppdf-fullscreen')) { frame.classList.remove('wppdf-fullscreen'); container.appendChild(frame); } break; } }); } // Here we depend on browsers dispatching the "click" event *after* the // "change" event, when the