pdf.js/web/overlay_manager.js
Jonas Jenwald 4902ad8923 Use modern DOM methods a bit more (PR 15031 follow-up)
Apparently the ESLint rule added in PR 15031 wasn't able to catch all cases that can be converted, which is probably not all that surprising given how some of these call-sites look.

 - Use `Element.prepend()` to insert nodes before all other ones in the element, rather than using `firstChild` with `insertBefore`-calls; see https://developer.mozilla.org/en-US/docs/Web/API/Element/prepend

 - Fix one *incorrect* `insertBefore` call, in the AnnotationLayer-code.
   Initially the patch simply changed that to an `Element.before()`-call, however that broke one of the integration-tests. It turns out that the `index` may try to access a non-existent select-child, which triggers undefined behaviour; note the warning in https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore#parameters
2022-06-13 10:47:37 +02:00

117 lines
3.6 KiB
JavaScript

/* Copyright 2014 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.
*/
class OverlayManager {
#overlays = new WeakMap();
#active = null;
get active() {
return this.#active;
}
/**
* @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(dialog, canForceClose = false) {
if (typeof dialog !== "object") {
throw new Error("Not enough parameters.");
} else if (this.#overlays.has(dialog)) {
throw new Error("The overlay is already registered.");
}
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);
if (!this._dialogPolyfillCSS) {
this._dialogPolyfillCSS = true;
const style = document.createElement("style");
style.textContent = PDFJSDev.eval("DIALOG_POLYFILL_CSS");
document.head.prepend(style);
}
}
dialog.addEventListener("cancel", evt => {
this.#active = null;
});
}
/**
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
* @returns {Promise} A promise that is resolved when the overlay has been
* unregistered.
*/
async unregister(dialog) {
if (!this.#overlays.has(dialog)) {
throw new Error("The overlay does not exist.");
} else if (this.#active === dialog) {
throw new Error("The overlay cannot be removed while it is active.");
}
this.#overlays.delete(dialog);
}
/**
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
* @returns {Promise} A promise that is resolved when the overlay has been
* opened.
*/
async open(dialog) {
if (!this.#overlays.has(dialog)) {
throw new Error("The overlay does not exist.");
} else if (this.#active) {
if (this.#active === dialog) {
throw new Error("The overlay is already active.");
} else if (this.#overlays.get(dialog).canForceClose) {
await this.close();
} else {
throw new Error("Another overlay is currently active.");
}
}
this.#active = dialog;
dialog.showModal();
}
/**
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
* @returns {Promise} A promise that is resolved when the overlay has been
* closed.
*/
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 !== dialog) {
throw new Error("Another overlay is currently active.");
}
dialog.close();
this.#active = null;
}
}
export { OverlayManager };