Convert the existing overlays to use <dialog>
elements (issue 14698)
This replaces our *custom* overlays with standard `<dialog>` DOM elements, see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog, thus simplifying the related CSS, HTML, and JavaScript code. With these changes, some of the functionality of the `OverlayManager` class is now handled natively (e.g. `Esc` to close the dialog). However, since we still need to be able to prevent dialogs from overlaying one another, it still makes sense to keep this functionality (as far as I'm concerned).
This commit is contained in:
parent
0dd6bc9a85
commit
f0aa08b464
@ -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,18 +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
|
||||
"chromeFileAccessDialog",
|
||||
dialog,
|
||||
/* canForceClose = */ true
|
||||
);
|
||||
}
|
||||
chromeFileAccessOverlayPromise.then(function () {
|
||||
@ -233,7 +231,7 @@ function requestAccessToLocalFile(fileUrl, overlayManager, callback) {
|
||||
}
|
||||
};
|
||||
|
||||
overlayManager.open("chromeFileAccessOverlay");
|
||||
overlayManager.open("chromeFileAccessDialog");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -18,43 +18,29 @@ class OverlayManager {
|
||||
|
||||
#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(name, dialog, canForceClose = false) {
|
||||
if (!name || !dialog) {
|
||||
throw new Error("Not enough parameters.");
|
||||
} else if (this.#overlays[name]) {
|
||||
throw new Error("The overlay is already registered.");
|
||||
}
|
||||
this.#overlays[name] = {
|
||||
element,
|
||||
container,
|
||||
callerCloseMethod,
|
||||
canForceClose,
|
||||
};
|
||||
this.#overlays[name] = { dialog, canForceClose };
|
||||
|
||||
dialog.addEventListener("cancel", evt => {
|
||||
this.#active = null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,17 +69,13 @@ class OverlayManager {
|
||||
if (this.#active === name) {
|
||||
throw new Error("The overlay is already active.");
|
||||
} else if (this.#overlays[name].canForceClose) {
|
||||
this.#closeThroughCaller();
|
||||
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.#overlays[this.#active].dialog.showModal();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +83,7 @@ class OverlayManager {
|
||||
* @returns {Promise} A promise that is resolved when the overlay has been
|
||||
* closed.
|
||||
*/
|
||||
async close(name) {
|
||||
async close(name = this.#active) {
|
||||
if (!this.#overlays[name]) {
|
||||
throw new Error("The overlay does not exist.");
|
||||
} else if (!this.#active) {
|
||||
@ -109,28 +91,8 @@ class OverlayManager {
|
||||
} else if (this.#active !== name) {
|
||||
throw new Error("Another overlay is currently active.");
|
||||
}
|
||||
this.#overlays[this.#active].container.classList.add("hidden");
|
||||
this.#overlays[this.#active].element.classList.add("hidden");
|
||||
this.#overlays[this.#active].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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@ 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 {string} dialogName - Name/identifier for the dialog.
|
||||
* @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 +29,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 +41,8 @@ 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.dialogName = options.dialogName;
|
||||
this.dialog = options.dialog;
|
||||
this.label = options.label;
|
||||
this.input = options.input;
|
||||
this.submitButton = options.submitButton;
|
||||
@ -47,9 +51,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));
|
||||
@ -60,18 +61,19 @@ class PasswordPrompt {
|
||||
});
|
||||
|
||||
this.overlayManager.register(
|
||||
this.overlayName,
|
||||
this.container,
|
||||
this.#cancel.bind(this),
|
||||
true
|
||||
this.dialogName,
|
||||
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.dialogName);
|
||||
|
||||
const passwordIncorrect =
|
||||
this.reason === PasswordResponses.INCORRECT_PASSWORD;
|
||||
this.#reason === PasswordResponses.INCORRECT_PASSWORD;
|
||||
|
||||
if (!this._isViewerEmbedded || passwordIncorrect) {
|
||||
this.input.focus();
|
||||
@ -82,26 +84,36 @@ class PasswordPrompt {
|
||||
}
|
||||
|
||||
async close() {
|
||||
await this.overlayManager.close(this.overlayName);
|
||||
this.input.value = "";
|
||||
if (this.overlayManager.active === this.dialogName) {
|
||||
this.overlayManager.close(this.dialogName);
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,9 +45,9 @@ function getPageName(size, isPortrait, pageNames) {
|
||||
|
||||
/**
|
||||
* @typedef {Object} PDFDocumentPropertiesOptions
|
||||
* @property {string} overlayName - Name/identifier for the overlay.
|
||||
* @property {string} dialogName - Name/identifier for the dialog.
|
||||
* @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.
|
||||
*/
|
||||
|
||||
@ -61,14 +61,14 @@ class PDFDocumentProperties {
|
||||
* @param {IL10n} l10n - Localization service.
|
||||
*/
|
||||
constructor(
|
||||
{ overlayName, fields, container, closeButton },
|
||||
{ dialogName, dialog, fields, closeButton },
|
||||
overlayManager,
|
||||
eventBus,
|
||||
l10n
|
||||
) {
|
||||
this.overlayName = overlayName;
|
||||
this.dialogName = dialogName;
|
||||
this.dialog = dialog;
|
||||
this.fields = fields;
|
||||
this.container = container;
|
||||
this.overlayManager = overlayManager;
|
||||
this.l10n = l10n;
|
||||
|
||||
@ -76,11 +76,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.dialogName, this.dialog);
|
||||
|
||||
eventBus._on("pagechanging", evt => {
|
||||
this._currentPageNumber = evt.pageNumber;
|
||||
@ -100,7 +96,7 @@ class PDFDocumentProperties {
|
||||
*/
|
||||
async open() {
|
||||
await Promise.all([
|
||||
this.overlayManager.open(this.overlayName),
|
||||
this.overlayManager.open(this.dialogName),
|
||||
this._dataAvailableCapability.promise,
|
||||
]);
|
||||
const currentPageNumber = this._currentPageNumber;
|
||||
@ -179,8 +175,8 @@ class PDFDocumentProperties {
|
||||
/**
|
||||
* Close the document properties overlay.
|
||||
*/
|
||||
close() {
|
||||
this.overlayManager.close(this.overlayName);
|
||||
async close() {
|
||||
this.overlayManager.close(this.dialogName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,7 +224,7 @@ class PDFDocumentProperties {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.overlayManager.active !== this.overlayName) {
|
||||
if (this.overlayManager.active !== this.dialogName) {
|
||||
// Don't bother updating the dialog if has already been closed,
|
||||
// since it will be updated the next time `this.open` is called.
|
||||
return;
|
||||
|
@ -115,8 +115,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 +131,9 @@ PDFPrintService.prototype = {
|
||||
this.scratchCanvas = null;
|
||||
activeService = null;
|
||||
ensureOverlay().then(function () {
|
||||
if (overlayManager.active !== "printServiceOverlay") {
|
||||
return; // overlay was already closed
|
||||
if (overlayManager.active === "printServiceDialog") {
|
||||
overlayManager.close("printServiceDialog");
|
||||
}
|
||||
overlayManager.close("printServiceOverlay");
|
||||
});
|
||||
},
|
||||
|
||||
@ -231,7 +229,7 @@ window.print = function () {
|
||||
}
|
||||
ensureOverlay().then(function () {
|
||||
if (activeService) {
|
||||
overlayManager.open("printServiceOverlay");
|
||||
overlayManager.open("printServiceDialog");
|
||||
}
|
||||
});
|
||||
|
||||
@ -241,8 +239,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 === "printServiceDialog") {
|
||||
overlayManager.close("printServiceDialog");
|
||||
}
|
||||
});
|
||||
return; // eslint-disable-line no-unsafe-finally
|
||||
@ -283,10 +281,10 @@ function abort() {
|
||||
}
|
||||
|
||||
function renderProgress(index, total, l10n) {
|
||||
const progressContainer = document.getElementById("printServiceOverlay");
|
||||
const progressDialog = document.getElementById("printServiceDialog");
|
||||
const progress = Math.round((100 * index) / total);
|
||||
const progressBar = progressContainer.querySelector("progress");
|
||||
const progressPerc = progressContainer.querySelector(".relative-progress");
|
||||
const progressBar = progressDialog.querySelector("progress");
|
||||
const progressPerc = progressDialog.querySelector(".relative-progress");
|
||||
progressBar.value = progress;
|
||||
l10n.get("print_progress_percent", { progress }).then(msg => {
|
||||
progressPerc.textContent = msg;
|
||||
@ -338,14 +336,16 @@ function ensureOverlay() {
|
||||
if (!overlayManager) {
|
||||
throw new Error("The overlay manager has not yet been initialized.");
|
||||
}
|
||||
const dialog = document.getElementById("printServiceDialog");
|
||||
|
||||
overlayPromise = overlayManager.register(
|
||||
"printServiceOverlay",
|
||||
document.getElementById("printServiceOverlay"),
|
||||
abort,
|
||||
true
|
||||
"printServiceDialog",
|
||||
dialog,
|
||||
/* canForceClose = */ true
|
||||
);
|
||||
|
||||
document.getElementById("printCancel").onclick = abort;
|
||||
dialog.addEventListener("close", abort);
|
||||
}
|
||||
return overlayPromise;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
152
web/viewer.html
152
web/viewer.html
@ -352,93 +352,87 @@ 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">
|
||||
<p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
|
||||
</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 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="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">
|
||||
<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>
|
||||
|
@ -161,16 +161,16 @@ function getViewerConfiguration() {
|
||||
findNextButton: document.getElementById("findNext"),
|
||||
},
|
||||
passwordOverlay: {
|
||||
overlayName: "passwordOverlay",
|
||||
container: document.getElementById("passwordOverlay"),
|
||||
dialogName: "passwordDialog",
|
||||
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"),
|
||||
dialogName: "documentPropertiesDialog",
|
||||
dialog: document.getElementById("documentPropertiesDialog"),
|
||||
closeButton: document.getElementById("documentPropertiesClose"),
|
||||
fields: {
|
||||
fileName: document.getElementById("fileNameField"),
|
||||
|
Loading…
Reference in New Issue
Block a user