Merge pull request #14710 from Snuffleupagus/overlays-dialog

Convert the existing overlays to use `<dialog>` elements (issue 14698)
This commit is contained in:
Jonas Jenwald 2022-03-30 11:47:36 +02:00 committed by GitHub
commit d6592b5e37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 270 additions and 302 deletions

13
package-lock.json generated
View File

@ -21,6 +21,7 @@
"canvas": "^2.9.1",
"core-js": "^3.21.1",
"cross-env": "^7.0.3",
"dialog-polyfill": "^0.5.6",
"dommatrix": "^0.0.24",
"es-module-shims": "1.4.7",
"eslint": "^8.11.0",
@ -4350,6 +4351,12 @@
"kuler": "1.0.x"
}
},
"node_modules/dialog-polyfill": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz",
"integrity": "sha512-ZbVDJI9uvxPAKze6z146rmfUZjBqNEwcnFTVamQzXH+svluiV7swmVIGr7miwADgfgt1G2JQIytypM9fbyhX4w==",
"dev": true
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -21951,6 +21958,12 @@
"kuler": "1.0.x"
}
},
"dialog-polyfill": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.5.6.tgz",
"integrity": "sha512-ZbVDJI9uvxPAKze6z146rmfUZjBqNEwcnFTVamQzXH+svluiV7swmVIGr7miwADgfgt1G2JQIytypM9fbyhX4w==",
"dev": true
},
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",

View File

@ -14,6 +14,7 @@
"canvas": "^2.9.1",
"core-js": "^3.21.1",
"cross-env": "^7.0.3",
"dialog-polyfill": "^0.5.6",
"dommatrix": "^0.0.24",
"es-module-shims": "1.4.7",
"eslint": "^8.11.0",

View File

@ -147,7 +147,7 @@ function reloadIfRuntimeIsUnavailable() {
let chromeFileAccessOverlayPromise;
function requestAccessToLocalFile(fileUrl, overlayManager, callback) {
let onCloseOverlay = null;
const dialog = document.getElementById("chromeFileAccessDialog");
if (top !== window) {
// When the extension reloads after receiving new permissions, the pages
// have to be reloaded to restore the extension runtime. Auto-reload
@ -157,20 +157,16 @@ function requestAccessToLocalFile(fileUrl, overlayManager, callback) {
// for detecting unload of the top-level frame. Should this ever change
// (crbug.com/511670), then the user can just reload the tab.
window.addEventListener("focus", reloadIfRuntimeIsUnavailable);
onCloseOverlay = function () {
dialog.addEventListener("close", function () {
window.removeEventListener("focus", reloadIfRuntimeIsUnavailable);
reloadIfRuntimeIsUnavailable();
overlayManager.close("chromeFileAccessOverlay");
};
}
if (!chromeFileAccessOverlayPromise) {
chromeFileAccessOverlayPromise = overlayManager.register(
"chromeFileAccessOverlay",
document.getElementById("chromeFileAccessOverlay"),
onCloseOverlay,
true
);
});
}
chromeFileAccessOverlayPromise ||= overlayManager.register(
dialog,
/* canForceClose = */ true
);
chromeFileAccessOverlayPromise.then(function () {
const iconPath = chrome.runtime.getManifest().icons[48];
document.getElementById("chrome-pdfjs-logo-bg").style.backgroundImage =
@ -229,11 +225,11 @@ function requestAccessToLocalFile(fileUrl, overlayManager, callback) {
originalUrl = "file:///fakepath/to/" + encodeURIComponent(file.name);
}
callback(URL.createObjectURL(file), file.size, originalUrl);
overlayManager.close("chromeFileAccessOverlay");
overlayManager.close(dialog);
}
};
overlayManager.open("chromeFileAccessOverlay");
overlayManager.open(dialog);
});
}

View File

@ -14,123 +14,93 @@
*/
class OverlayManager {
#overlays = Object.create(null);
#overlays = new WeakMap();
#active = null;
#keyDownBound = null;
get active() {
return this.#active;
}
/**
* @param {string} name - The name of the overlay that is registered.
* @param {HTMLDivElement} element - The overlay's DOM element.
* @param {function} [callerCloseMethod] - The method that, if present, calls
* `OverlayManager.close` from the object registering the
* overlay. Access to this method is necessary in order to
* run cleanup code when e.g. the overlay is force closed.
* The default is `null`.
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
* @param {boolean} [canForceClose] - Indicates if opening the overlay closes
* an active overlay. The default is `false`.
* @returns {Promise} A promise that is resolved when the overlay has been
* registered.
*/
async register(
name,
element,
callerCloseMethod = null,
canForceClose = false
) {
let container;
if (!name || !element || !(container = element.parentNode)) {
async register(dialog, canForceClose = false) {
if (typeof dialog !== "object") {
throw new Error("Not enough parameters.");
} else if (this.#overlays[name]) {
} else if (this.#overlays.has(dialog)) {
throw new Error("The overlay is already registered.");
}
this.#overlays[name] = {
element,
container,
callerCloseMethod,
canForceClose,
};
this.#overlays.set(dialog, { canForceClose });
if (
typeof PDFJSDev !== "undefined" &&
PDFJSDev.test("GENERIC && !SKIP_BABEL") &&
!dialog.showModal
) {
const dialogPolyfill = require("dialog-polyfill/dist/dialog-polyfill.js");
dialogPolyfill.registerDialog(dialog);
}
dialog.addEventListener("cancel", evt => {
this.#active = null;
});
}
/**
* @param {string} name - The name of the overlay that is unregistered.
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
* @returns {Promise} A promise that is resolved when the overlay has been
* unregistered.
*/
async unregister(name) {
if (!this.#overlays[name]) {
async unregister(dialog) {
if (!this.#overlays.has(dialog)) {
throw new Error("The overlay does not exist.");
} else if (this.#active === name) {
} else if (this.#active === dialog) {
throw new Error("The overlay cannot be removed while it is active.");
}
delete this.#overlays[name];
this.#overlays.delete(dialog);
}
/**
* @param {string} name - The name of the overlay that should be opened.
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
* @returns {Promise} A promise that is resolved when the overlay has been
* opened.
*/
async open(name) {
if (!this.#overlays[name]) {
async open(dialog) {
if (!this.#overlays.has(dialog)) {
throw new Error("The overlay does not exist.");
} else if (this.#active) {
if (this.#active === name) {
if (this.#active === dialog) {
throw new Error("The overlay is already active.");
} else if (this.#overlays[name].canForceClose) {
this.#closeThroughCaller();
} else if (this.#overlays.get(dialog).canForceClose) {
await this.close();
} else {
throw new Error("Another overlay is currently active.");
}
}
this.#active = name;
this.#overlays[this.#active].element.classList.remove("hidden");
this.#overlays[this.#active].container.classList.remove("hidden");
this.#keyDownBound = this.#keyDown.bind(this);
window.addEventListener("keydown", this.#keyDownBound);
this.#active = dialog;
dialog.showModal();
}
/**
* @param {string} name - The name of the overlay that should be closed.
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
* @returns {Promise} A promise that is resolved when the overlay has been
* closed.
*/
async close(name) {
if (!this.#overlays[name]) {
async close(dialog = this.#active) {
if (!this.#overlays.has(dialog)) {
throw new Error("The overlay does not exist.");
} else if (!this.#active) {
throw new Error("The overlay is currently not active.");
} else if (this.#active !== name) {
} else if (this.#active !== dialog) {
throw new Error("Another overlay is currently active.");
}
this.#overlays[this.#active].container.classList.add("hidden");
this.#overlays[this.#active].element.classList.add("hidden");
dialog.close();
this.#active = null;
window.removeEventListener("keydown", this.#keyDownBound);
this.#keyDownBound = null;
}
#keyDown(evt) {
if (this.#active && evt.keyCode === /* Esc = */ 27) {
this.#closeThroughCaller();
evt.preventDefault();
}
}
#closeThroughCaller() {
if (this.#overlays[this.#active].callerCloseMethod) {
this.#overlays[this.#active].callerCloseMethod();
}
if (this.#active) {
this.close(this.#active);
}
}
}

View File

@ -17,8 +17,7 @@ import { PasswordResponses } from "pdfjs-lib";
/**
* @typedef {Object} PasswordPromptOptions
* @property {string} overlayName - Name of the overlay for the overlay manager.
* @property {HTMLDivElement} container - Div container for the overlay.
* @property {HTMLDialogElement} dialog - The overlay's DOM element.
* @property {HTMLParagraphElement} label - Label containing instructions for
* entering the password.
* @property {HTMLInputElement} input - Input field for entering the password.
@ -29,6 +28,10 @@ import { PasswordResponses } from "pdfjs-lib";
*/
class PasswordPrompt {
#updateCallback = null;
#reason = null;
/**
* @param {PasswordPromptOptions} options
* @param {OverlayManager} overlayManager - Manager for the viewer overlays.
@ -37,8 +40,7 @@ class PasswordPrompt {
* an <iframe> or an <object>. The default value is `false`.
*/
constructor(options, overlayManager, l10n, isViewerEmbedded = false) {
this.overlayName = options.overlayName;
this.container = options.container;
this.dialog = options.dialog;
this.label = options.label;
this.input = options.input;
this.submitButton = options.submitButton;
@ -47,9 +49,6 @@ class PasswordPrompt {
this.l10n = l10n;
this._isViewerEmbedded = isViewerEmbedded;
this.updateCallback = null;
this.reason = null;
// Attach the event listeners.
this.submitButton.addEventListener("click", this.#verify.bind(this));
this.cancelButton.addEventListener("click", this.#cancel.bind(this));
@ -59,19 +58,16 @@ class PasswordPrompt {
}
});
this.overlayManager.register(
this.overlayName,
this.container,
this.#cancel.bind(this),
true
);
this.overlayManager.register(this.dialog, /* canForceClose = */ true);
this.dialog.addEventListener("close", this.#cancel.bind(this));
}
async open() {
await this.overlayManager.open(this.overlayName);
await this.overlayManager.open(this.dialog);
const passwordIncorrect =
this.reason === PasswordResponses.INCORRECT_PASSWORD;
this.#reason === PasswordResponses.INCORRECT_PASSWORD;
if (!this._isViewerEmbedded || passwordIncorrect) {
this.input.focus();
@ -82,26 +78,36 @@ class PasswordPrompt {
}
async close() {
await this.overlayManager.close(this.overlayName);
this.input.value = "";
if (this.overlayManager.active === this.dialog) {
this.overlayManager.close(this.dialog);
}
}
#verify() {
const password = this.input.value;
if (password?.length > 0) {
this.close();
this.updateCallback(password);
this.#invokeCallback(password);
}
}
#cancel() {
this.#invokeCallback(new Error("PasswordPrompt cancelled."));
}
#invokeCallback(password) {
if (!this.#updateCallback) {
return; // Ensure that the callback is only invoked once.
}
this.close();
this.updateCallback(new Error("PasswordPrompt cancelled."));
this.input.value = "";
this.#updateCallback(password);
this.#updateCallback = null;
}
setUpdateCallback(updateCallback, reason) {
this.updateCallback = updateCallback;
this.reason = reason;
this.#updateCallback = updateCallback;
this.#reason = reason;
}
}

View File

@ -45,9 +45,8 @@ function getPageName(size, isPortrait, pageNames) {
/**
* @typedef {Object} PDFDocumentPropertiesOptions
* @property {string} overlayName - Name/identifier for the overlay.
* @property {HTMLDialogElement} dialog - The overlay's DOM element.
* @property {Object} fields - Names and elements of the overlay's fields.
* @property {HTMLDivElement} container - Div container for the overlay.
* @property {HTMLButtonElement} closeButton - Button for closing the overlay.
*/
@ -60,15 +59,9 @@ class PDFDocumentProperties {
* @param {EventBus} eventBus - The application event bus.
* @param {IL10n} l10n - Localization service.
*/
constructor(
{ overlayName, fields, container, closeButton },
overlayManager,
eventBus,
l10n
) {
this.overlayName = overlayName;
constructor({ dialog, fields, closeButton }, overlayManager, eventBus, l10n) {
this.dialog = dialog;
this.fields = fields;
this.container = container;
this.overlayManager = overlayManager;
this.l10n = l10n;
@ -76,11 +69,7 @@ class PDFDocumentProperties {
// Bind the event listener for the Close button.
closeButton.addEventListener("click", this.close.bind(this));
this.overlayManager.register(
this.overlayName,
this.container,
this.close.bind(this)
);
this.overlayManager.register(this.dialog);
eventBus._on("pagechanging", evt => {
this._currentPageNumber = evt.pageNumber;
@ -100,7 +89,7 @@ class PDFDocumentProperties {
*/
async open() {
await Promise.all([
this.overlayManager.open(this.overlayName),
this.overlayManager.open(this.dialog),
this._dataAvailableCapability.promise,
]);
const currentPageNumber = this._currentPageNumber;
@ -179,8 +168,8 @@ class PDFDocumentProperties {
/**
* Close the document properties overlay.
*/
close() {
this.overlayManager.close(this.overlayName);
async close() {
this.overlayManager.close(this.dialog);
}
/**
@ -228,7 +217,7 @@ class PDFDocumentProperties {
}
return;
}
if (this.overlayManager.active !== this.overlayName) {
if (this.overlayManager.active !== this.dialog) {
// Don't bother updating the dialog if has already been closed,
// since it will be updated the next time `this.open` is called.
return;

View File

@ -18,6 +18,7 @@ import { PDFPrintServiceFactory, PDFViewerApplication } from "./app.js";
import { getXfaHtmlForPrinting } from "./print_utils.js";
let activeService = null;
let dialog = null;
let overlayManager = null;
// Renders the page to the canvas of the given print service, and returns
@ -115,8 +116,7 @@ PDFPrintService.prototype = {
destroy() {
if (activeService !== this) {
// |activeService| cannot be replaced without calling destroy() first,
// so if it differs then an external consumer has a stale reference to
// us.
// so if it differs then an external consumer has a stale reference to us.
return;
}
this.printContainer.textContent = "";
@ -132,10 +132,9 @@ PDFPrintService.prototype = {
this.scratchCanvas = null;
activeService = null;
ensureOverlay().then(function () {
if (overlayManager.active !== "printServiceOverlay") {
return; // overlay was already closed
if (overlayManager.active === dialog) {
overlayManager.close(dialog);
}
overlayManager.close("printServiceOverlay");
});
},
@ -231,7 +230,7 @@ window.print = function () {
}
ensureOverlay().then(function () {
if (activeService) {
overlayManager.open("printServiceOverlay");
overlayManager.open(dialog);
}
});
@ -241,8 +240,8 @@ window.print = function () {
if (!activeService) {
console.error("Expected print service to be initialized.");
ensureOverlay().then(function () {
if (overlayManager.active === "printServiceOverlay") {
overlayManager.close("printServiceOverlay");
if (overlayManager.active === dialog) {
overlayManager.close(dialog);
}
});
return; // eslint-disable-line no-unsafe-finally
@ -283,10 +282,10 @@ function abort() {
}
function renderProgress(index, total, l10n) {
const progressContainer = document.getElementById("printServiceOverlay");
dialog ||= document.getElementById("printServiceDialog");
const progress = Math.round((100 * index) / total);
const progressBar = progressContainer.querySelector("progress");
const progressPerc = progressContainer.querySelector(".relative-progress");
const progressBar = dialog.querySelector("progress");
const progressPerc = dialog.querySelector(".relative-progress");
progressBar.value = progress;
l10n.get("print_progress_percent", { progress }).then(msg => {
progressPerc.textContent = msg;
@ -338,14 +337,15 @@ function ensureOverlay() {
if (!overlayManager) {
throw new Error("The overlay manager has not yet been initialized.");
}
dialog ||= document.getElementById("printServiceDialog");
overlayPromise = overlayManager.register(
"printServiceOverlay",
document.getElementById("printServiceOverlay"),
abort,
true
dialog,
/* canForceClose = */ true
);
document.getElementById("printCancel").onclick = abort;
dialog.addEventListener("close", abort);
}
return overlayPromise;
}

View File

@ -1,32 +1,30 @@
<div id="chromeFileAccessOverlay" class="container hidden">
<div class="dialog">
<div class="row">
<!-- The extension icon (PDF.js logo) will be shown at the left, to help
users with recognizing which checkbox they have to click when they
visit chrome://extensions.
-->
<p id="chrome-pdfjs-logo-bg" style="
display: block;
padding-left: 60px;
min-height: 48px;
background-size: 48px;
background-repeat: no-repeat;
font-size: 14px;
line-height: 1.8em;
word-break: break-all;">
Click on
"<span id="chrome-file-access-label">Allow access to file URLs</span>"
at
<a id="chrome-link-to-extensions-page">chrome://extensions</a>
<br>
to view <span id="chrome-url-of-local-file">this PDF file.</span>
</p>
</div>
<div class="row">
<p>
or select the file again:
<input type="file" id="chrome-file-fallback" accept=".pdf">
</p>
</div>
<dialog id="chromeFileAccessDialog">
<div class="row">
<!-- The extension icon (PDF.js logo) will be shown at the left, to help
users with recognizing which checkbox they have to click when they
visit chrome://extensions.
-->
<p id="chrome-pdfjs-logo-bg" style="
display: block;
padding-left: 60px;
min-height: 48px;
background-size: 48px;
background-repeat: no-repeat;
font-size: 14px;
line-height: 1.8em;
word-break: break-all;">
Click on
"<span id="chrome-file-access-label">Allow access to file URLs</span>"
at
<a id="chrome-link-to-extensions-page">chrome://extensions</a>
<br>
to view <span id="chrome-url-of-local-file">this PDF file.</span>
</p>
</div>
</div>
<div class="row">
<p>
or select the file again:
<input type="file" id="chrome-file-fallback" accept=".pdf">
</p>
</div>
</dialog>

View File

@ -62,9 +62,9 @@
--doorhanger-hover-color: rgba(12, 12, 13, 1);
--doorhanger-hover-bg-color: rgba(237, 237, 237, 1);
--doorhanger-separator-color: rgba(222, 222, 222, 1);
--overlay-button-border: 0 none;
--overlay-button-bg-color: rgba(12, 12, 13, 0.1);
--overlay-button-hover-bg-color: rgba(12, 12, 13, 0.3);
--dialog-button-border: 0 none;
--dialog-button-bg-color: rgba(12, 12, 13, 0.1);
--dialog-button-hover-bg-color: rgba(12, 12, 13, 0.3);
--loading-icon: url(images/loading.svg);
--treeitem-expanded-icon: url(images/treeitem-expanded.svg);
@ -146,8 +146,8 @@
--doorhanger-hover-color: rgba(249, 249, 250, 1);
--doorhanger-hover-bg-color: rgba(93, 94, 98, 1);
--doorhanger-separator-color: rgba(92, 92, 97, 1);
--overlay-button-bg-color: rgba(92, 92, 97, 1);
--overlay-button-hover-bg-color: rgba(115, 115, 115, 1);
--dialog-button-bg-color: rgba(92, 92, 97, 1);
--dialog-button-hover-bg-color: rgba(115, 115, 115, 1);
/* This image is used in <input> elements, which unfortunately means that
* the `mask-image` approach used with all of the other images doesn't work
@ -168,9 +168,9 @@
--doorhanger-hover-color: ButtonFace;
--doorhanger-border-color-whcm: 1px solid ButtonText;
--doorhanger-triangle-opacity-whcm: 0;
--overlay-button-border: 1px solid Highlight;
--overlay-button-hover-bg-color: Highlight;
--overlay-button-hover-color: ButtonFace;
--dialog-button-border: 1px solid Highlight;
--dialog-button-hover-bg-color: Highlight;
--dialog-button-hover-color: ButtonFace;
--field-border-color: ButtonText;
}
}
@ -628,21 +628,21 @@ select {
.toolbarButton,
.secondaryToolbarButton,
.overlayButton {
.dialogButton {
border: 0 none;
background: none;
width: 28px;
height: 28px;
}
.overlayButton:hover,
.overlayButton:focus-visible {
background-color: var(--overlay-button-hover-bg-color);
.dialogButton:hover,
.dialogButton:focus-visible {
background-color: var(--dialog-button-hover-bg-color);
}
.overlayButton:hover > span,
.overlayButton:focus-visible > span {
color: var(--overlay-button-hover-color);
.dialogButton:hover > span,
.dialogButton:focus-visible > span {
color: var(--dialog-button-hover-color);
}
.toolbarButton > span {
@ -654,7 +654,7 @@ select {
.toolbarButton[disabled],
.secondaryToolbarButton[disabled],
.overlayButton[disabled] {
.dialogButton[disabled] {
opacity: 0.5;
}
@ -697,7 +697,7 @@ select {
.toolbarButton,
.dropdownToolbarButton,
.secondaryToolbarButton,
.overlayButton {
.dialogButton {
min-width: 16px;
margin: 2px 1px;
padding: 2px 6px 0;
@ -1278,32 +1278,17 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
width: 98%;
}
.overlayButton {
.dialogButton {
width: auto;
margin: 3px 4px 2px !important;
padding: 2px 11px;
color: var(--main-color);
background-color: var(--overlay-button-bg-color);
border: var(--overlay-button-border) !important;
background-color: var(--dialog-button-bg-color);
border: var(--dialog-button-border) !important;
}
#overlayContainer {
display: table;
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.2);
z-index: 40000;
}
#overlayContainer > .container {
display: table-cell;
vertical-align: middle;
text-align: center;
}
#overlayContainer > .container > .dialog {
display: inline-block;
dialog {
margin: auto;
padding: 15px;
border-spacing: 4px;
color: var(--main-color);
@ -1314,20 +1299,24 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.2);
user-select: none;
}
.dialog > .row {
dialog > .row {
display: table-row;
}
.dialog > .row > * {
dialog > .row > * {
display: table-cell;
}
.dialog .toolbarField {
dialog .toolbarField {
margin: 5px 0;
}
.dialog .separator {
dialog .separator {
display: block;
margin: 4px 0;
height: 1px;
@ -1335,38 +1324,38 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
background-color: var(--separator-color);
}
.dialog .buttonRow {
dialog .buttonRow {
text-align: center;
vertical-align: middle;
}
.dialog :link {
dialog :link {
color: rgba(255, 255, 255, 1);
}
#passwordOverlay > .dialog {
#passwordDialog {
text-align: center;
}
#passwordOverlay .toolbarField {
#passwordDialog .toolbarField {
width: 200px;
}
#documentPropertiesOverlay > .dialog {
#documentPropertiesDialog {
text-align: left;
}
#documentPropertiesOverlay .row > * {
#documentPropertiesDialog .row > * {
min-width: 100px;
text-align: start;
}
#documentPropertiesOverlay .row > span {
#documentPropertiesDialog .row > span {
width: 125px;
word-wrap: break-word;
}
#documentPropertiesOverlay .row > p {
#documentPropertiesDialog .row > p {
max-width: 225px;
word-wrap: break-word;
}
#documentPropertiesOverlay .buttonRow {
#documentPropertiesDialog .buttonRow {
margin-top: 10px;
}

View File

@ -233,7 +233,7 @@ See https://github.com/adobe-type-tools/cmap-resources
<div class="horizontalToolbarSeparator"></div>
<button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="69" data-l10n-id="document_properties">
<button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="69" data-l10n-id="document_properties" aria-controls="documentPropertiesDialog">
<span data-l10n-id="document_properties_label">Document Properties…</span>
</button>
</div>
@ -352,93 +352,101 @@ See https://github.com/adobe-type-tools/cmap-resources
<!--#endif-->
</div> <!-- mainContainer -->
<div id="overlayContainer" class="hidden">
<div id="passwordOverlay" class="container hidden">
<div class="dialog">
<div class="row">
<p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
</div>
<div class="row">
<input type="password" id="password" class="toolbarField">
</div>
<div class="buttonRow">
<button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button>
<button id="passwordSubmit" class="overlayButton"><span data-l10n-id="password_ok">OK</span></button>
</div>
<div id="dialogContainer">
<dialog id="passwordDialog">
<div class="row">
<label for="password" id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</label>
</div>
</div>
<div id="documentPropertiesOverlay" class="container hidden">
<div class="dialog">
<div class="row">
<span data-l10n-id="document_properties_file_name">File name:</span> <p id="fileNameField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_file_size">File size:</span> <p id="fileSizeField">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span data-l10n-id="document_properties_title">Title:</span> <p id="titleField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_author">Author:</span> <p id="authorField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_subject">Subject:</span> <p id="subjectField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_keywords">Keywords:</span> <p id="keywordsField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_creation_date">Creation Date:</span> <p id="creationDateField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_modification_date">Modification Date:</span> <p id="modificationDateField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_creator">Creator:</span> <p id="creatorField">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span data-l10n-id="document_properties_producer">PDF Producer:</span> <p id="producerField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_version">PDF Version:</span> <p id="versionField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_page_count">Page Count:</span> <p id="pageCountField">-</p>
</div>
<div class="row">
<span data-l10n-id="document_properties_page_size">Page Size:</span> <p id="pageSizeField">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span data-l10n-id="document_properties_linearized">Fast Web View:</span> <p id="linearizedField">-</p>
</div>
<div class="buttonRow">
<button id="documentPropertiesClose" class="overlayButton"><span data-l10n-id="document_properties_close">Close</span></button>
</div>
<div class="row">
<input type="password" id="password" class="toolbarField">
</div>
</div>
<div class="buttonRow">
<button id="passwordCancel" class="dialogButton"><span data-l10n-id="password_cancel">Cancel</span></button>
<button id="passwordSubmit" class="dialogButton"><span data-l10n-id="password_ok">OK</span></button>
</div>
</dialog>
<dialog id="documentPropertiesDialog">
<div class="row">
<span id="fileNameLabel" data-l10n-id="document_properties_file_name">File name:</span>
<p id="fileNameField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="fileSizeLabel" data-l10n-id="document_properties_file_size">File size:</span>
<p id="fileSizeField" aria-labelledby="fileSizeLabel">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span id="titleLabel" data-l10n-id="document_properties_title">Title:</span>
<p id="titleField" aria-labelledby="titleLabel">-</p>
</div>
<div class="row">
<span id="authorLabel" data-l10n-id="document_properties_author">Author:</span>
<p id="authorField" aria-labelledby="authorLabel">-</p>
</div>
<div class="row">
<span id="subjectLabel" data-l10n-id="document_properties_subject">Subject:</span>
<p id="subjectField" aria-labelledby="subjectLabel">-</p>
</div>
<div class="row">
<span id="keywordsLabel" data-l10n-id="document_properties_keywords">Keywords:</span>
<p id="keywordsField" aria-labelledby="keywordsLabel">-</p>
</div>
<div class="row">
<span id="creationDateLabel" data-l10n-id="document_properties_creation_date">Creation Date:</span>
<p id="creationDateField" aria-labelledby="creationDateLabel">-</p>
</div>
<div class="row">
<span id="modificationDateLabel" data-l10n-id="document_properties_modification_date">Modification Date:</span>
<p id="modificationDateField" aria-labelledby="modificationDateLabel">-</p>
</div>
<div class="row">
<span id="creatorLabel" data-l10n-id="document_properties_creator">Creator:</span>
<p id="creatorField" aria-labelledby="creatorLabel">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span id="producerLabel" data-l10n-id="document_properties_producer">PDF Producer:</span>
<p id="producerField" aria-labelledby="producerLabel">-</p>
</div>
<div class="row">
<span id="versionLabel" data-l10n-id="document_properties_version">PDF Version:</span>
<p id="versionField" aria-labelledby="versionLabel">-</p>
</div>
<div class="row">
<span id="pageCountLabel" data-l10n-id="document_properties_page_count">Page Count:</span>
<p id="pageCountField" aria-labelledby="pageCountLabel">-</p>
</div>
<div class="row">
<span id="pageSizeLabel" data-l10n-id="document_properties_page_size">Page Size:</span>
<p id="pageSizeField" aria-labelledby="pageSizeLabel">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span id="linearizedLabel" data-l10n-id="document_properties_linearized">Fast Web View:</span>
<p id="linearizedField" aria-labelledby="linearizedLabel">-</p>
</div>
<div class="buttonRow">
<button id="documentPropertiesClose" class="dialogButton"><span data-l10n-id="document_properties_close">Close</span></button>
</div>
</dialog>
<!--#if !MOZCENTRAL-->
<div id="printServiceOverlay" class="container hidden">
<div class="dialog">
<div class="row">
<span data-l10n-id="print_progress_message">Preparing document for printing…</span>
</div>
<div class="row">
<progress value="0" max="100"></progress>
<span data-l10n-id="print_progress_percent" data-l10n-args='{ "progress": 0 }' class="relative-progress">0%</span>
</div>
<div class="buttonRow">
<button id="printCancel" class="overlayButton"><span data-l10n-id="print_progress_close">Cancel</span></button>
</div>
<dialog id="printServiceDialog" style="min-width: 200px;">
<div class="row">
<span data-l10n-id="print_progress_message">Preparing document for printing…</span>
</div>
</div>
<div class="row">
<progress value="0" max="100"></progress>
<span data-l10n-id="print_progress_percent" data-l10n-args='{ "progress": 0 }' class="relative-progress">0%</span>
</div>
<div class="buttonRow">
<button id="printCancel" class="dialogButton"><span data-l10n-id="print_progress_close">Cancel</span></button>
</div>
</dialog>
<!--#endif-->
<!--#if CHROME-->
<!--#include viewer-snippet-chrome-overlays.html-->
<!--#endif-->
</div> <!-- overlayContainer -->
</div> <!-- dialogContainer -->
</div> <!-- outerContainer -->
<div id="printContainer"></div>

View File

@ -161,16 +161,14 @@ function getViewerConfiguration() {
findNextButton: document.getElementById("findNext"),
},
passwordOverlay: {
overlayName: "passwordOverlay",
container: document.getElementById("passwordOverlay"),
dialog: document.getElementById("passwordDialog"),
label: document.getElementById("passwordText"),
input: document.getElementById("password"),
submitButton: document.getElementById("passwordSubmit"),
cancelButton: document.getElementById("passwordCancel"),
},
documentProperties: {
overlayName: "documentPropertiesOverlay",
container: document.getElementById("documentPropertiesOverlay"),
dialog: document.getElementById("documentPropertiesDialog"),
closeButton: document.getElementById("documentPropertiesClose"),
fields: {
fileName: document.getElementById("fileNameField"),