aboutsummaryrefslogtreecommitdiff
path: root/ext/js/app
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/app')
-rw-r--r--ext/js/app/frontend.js53
-rw-r--r--ext/js/app/popup-factory.js32
-rw-r--r--ext/js/app/popup-proxy.js136
-rw-r--r--ext/js/app/popup-window.js125
-rw-r--r--ext/js/app/popup.js127
5 files changed, 473 insertions, 0 deletions
diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js
index bbc0ff85..9fa6009b 100644
--- a/ext/js/app/frontend.js
+++ b/ext/js/app/frontend.js
@@ -21,7 +21,26 @@
* TextSourceRange
*/
+/**
+ * This is the main class responsible for scanning and handling webpage content.
+ */
class Frontend {
+ /**
+ * Creates a new instance.
+ * @param {object} details
+ * @param {string} details.pageType The type of page, one of 'web', 'popup', or 'search'.
+ * @param {PopupFactory} details.popupFactory A PopupFactory instance to use for generating popups.
+ * @param {number} details.depth The nesting depth value of the popup.
+ * @param {number} details.tabId The tab ID of the host tab.
+ * @param {number} details.frameId The frame ID of the host frame.
+ * @param {?string} details.parentPopupId The popup ID of the parent popup if one exists, otherwise null.
+ * @param {?number} details.parentFrameId The frame ID of the parent popup if one exists, otherwise null.
+ * @param {boolean} details.useProxyPopup Whether or not proxy popups should be used.
+ * @param {boolean} details.canUseWindowPopup Whether or not window popups can be used.
+ * @param {boolean} details.allowRootFramePopupProxy Whether or not popups can be hosted in the root frame.
+ * @param {boolean} details.childrenSupported Whether popups can create child popups or not.
+ * @param {HotkeyHandler} details.hotkeyHandler A HotkeyHandler instance.
+ */
constructor({
pageType,
popupFactory,
@@ -83,18 +102,33 @@ class Frontend {
]);
}
+ /**
+ * Get whether or not the text selection can be cleared.
+ * @type {boolean}
+ */
get canClearSelection() {
return this._textScanner.canClearSelection;
}
+ /**
+ * Set whether or not the text selection can be cleared.
+ * @param {boolean} value The new value to assign.
+ */
set canClearSelection(value) {
this._textScanner.canClearSelection = value;
}
+ /**
+ * Gets the popup instance.
+ * @type {Popup}
+ */
get popup() {
return this._popup;
}
+ /**
+ * Prepares the instance for use.
+ */
async prepare() {
await this.updateOptions();
try {
@@ -135,20 +169,35 @@ class Frontend {
this._signalFrontendReady();
}
+ /**
+ * Set whether or not the instance is disabled.
+ * @param {boolean} disabled Whether or not the instance is disabled.
+ */
setDisabledOverride(disabled) {
this._disabledOverride = disabled;
this._updateTextScannerEnabled();
}
+ /**
+ * Set or clear an override options context object.
+ * @param {?object} optionsContext An options context object to use as the override, or `null` to clear the override.
+ */
setOptionsContextOverride(optionsContext) {
this._optionsContextOverride = optionsContext;
}
+ /**
+ * Performs a new search on a specific source.
+ * @param {TextSourceRange|TextSourceElement} textSource The text source to search.
+ */
async setTextSource(textSource) {
this._textScanner.setCurrentTextSource(null);
await this._textScanner.search(textSource);
}
+ /**
+ * Updates the internal options representation.
+ */
async updateOptions() {
try {
await this._updateOptionsInternal();
@@ -159,6 +208,10 @@ class Frontend {
}
}
+ /**
+ * Waits for the previous `showContent` call to be completed.
+ * @returns {Promise} A promise which is resolved when the previous `showContent` call has completed.
+ */
showContentCompleted() {
return this._lastShowPromise;
}
diff --git a/ext/js/app/popup-factory.js b/ext/js/app/popup-factory.js
index 096d145e..05ab1942 100644
--- a/ext/js/app/popup-factory.js
+++ b/ext/js/app/popup-factory.js
@@ -22,7 +22,14 @@
* PopupWindow
*/
+/**
+ * A class which is used to generate and manage popups.
+ */
class PopupFactory {
+ /**
+ * Creates a new instance.
+ * @param {number} frameId The frame ID of the host frame.
+ */
constructor(frameId) {
this._frameId = frameId;
this._frameOffsetForwarder = new FrameOffsetForwarder(frameId);
@@ -32,6 +39,9 @@ class PopupFactory {
// Public functions
+ /**
+ * Prepares the instance for use.
+ */
prepare() {
this._frameOffsetForwarder.prepare();
yomichan.crossFrame.registerHandlers([
@@ -53,6 +63,16 @@ class PopupFactory {
]);
}
+ /**
+ * Gets or creates a popup based on a set of parameters
+ * @param {object} details
+ * @param {?number} [details.frameId] The ID of the frame that should host the popup.
+ * @param {?string} [details.id] A specific ID used to find an existing popup, or to assign to the new popup.
+ * @param {?string} [details.parentPopupId] The ID of the parent popup.
+ * @param {?number} [details.depth] A specific depth value to assign to the popup.
+ * @param {boolean} [details.popupWindow] Whether or not a separate popup window should be used, rather than an iframe.
+ * @param {boolean} [details.childrenSupported] Whether or not the popup is able to show child popups.
+ */
async getOrCreatePopup({
frameId=null,
id=null,
@@ -148,6 +168,13 @@ class PopupFactory {
}
}
+ /**
+ * Force all popups to have a specific visibility value.
+ * @param {boolean} value Whether or not the popups should be visible.
+ * @param {number} priority The priority of the override.
+ * @returns {string} A token which can be passed to clearAllVisibleOverride.
+ * @throws An exception is thrown if any popup fails to have its visibiltiy overridden.
+ */
async setAllVisibleOverride(value, priority) {
const promises = [];
const errors = [];
@@ -173,6 +200,11 @@ class PopupFactory {
throw errors[0];
}
+ /**
+ * Clears a visibility override that was generated by `setAllVisibleOverride`.
+ * @param {string} token The token returned from `setAllVisibleOverride`.
+ * @returns {boolean} `true` if the override existed and was removed, `false` otherwise.
+ */
async clearAllVisibleOverride(token) {
const results = this._allPopupVisibilityTokenMap.get(token);
if (typeof results === 'undefined') { return false; }
diff --git a/ext/js/app/popup-proxy.js b/ext/js/app/popup-proxy.js
index c46821d5..d9e1af8d 100644
--- a/ext/js/app/popup-proxy.js
+++ b/ext/js/app/popup-proxy.js
@@ -15,7 +15,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/**
+ * This class is a proxy for a Popup that is hosted in a different frame.
+ * It effectively forwards all API calls to the underlying Popup.
+ */
class PopupProxy extends EventDispatcher {
+ /**
+ * Creates a new instance.
+ * @param {object} details
+ * @param {string} details.id The ID of the popup.
+ * @param {number} details.depth The depth of the popup.
+ * @param {number} details.frameId The ID of the host frame.
+ * @param {FrameOffsetForwarder} details.frameOffsetForwarder A `FrameOffsetForwarder` instance which is used to determine frame positioning.
+ */
constructor({
id,
depth,
@@ -36,64 +48,137 @@ class PopupProxy extends EventDispatcher {
// Public properties
+ /**
+ * The ID of the popup.
+ * @type {string}
+ */
get id() {
return this._id;
}
+ /**
+ * The parent of the popup, which is always `null` for `PopupProxy` instances,
+ * since any potential parent popups are in a different frame.
+ * @type {Popup}
+ */
get parent() {
return null;
}
+ /**
+ * Attempts to set the parent popup.
+ * @param {Popup} value
+ * @throws Throws an error, since this class doesn't support a direct parent.
+ */
set parent(value) {
throw new Error('Not supported on PopupProxy');
}
+ /**
+ * The popup child popup, which is always null for `PopupProxy` instances,
+ * since any potential child popups are in a different frame.
+ * @type {Popup}
+ */
get child() {
return null;
}
+ /**
+ * Attempts to set the child popup.
+ * @param {Popup} value
+ * @throws Throws an error, since this class doesn't support children.
+ */
set child(value) {
throw new Error('Not supported on PopupProxy');
}
+ /**
+ * The depth of the popup.
+ * @type {numer}
+ */
get depth() {
return this._depth;
}
+ /**
+ * Gets the content window of the frame. This value is null,
+ * since the window is hosted in a different frame.
+ * @type {Window}
+ */
get frameContentWindow() {
return null;
}
+ /**
+ * Gets the DOM node that contains the frame.
+ * @type {Element}
+ */
get container() {
return null;
}
+ /**
+ * Gets the ID of the frame.
+ * @type {number}
+ */
get frameId() {
return this._frameId;
}
// Public functions
+ /**
+ * Sets the options context for the popup.
+ * @param {object} optionsContext The options context object.
+ * @returns {Promise<void>}
+ */
setOptionsContext(optionsContext, source) {
return this._invokeSafe('setOptionsContext', {id: this._id, optionsContext, source});
}
+ /**
+ * Hides the popup.
+ * @param {boolean} changeFocus Whether or not the parent popup or host frame should be focused.
+ * @returns {Promise<void>}
+ */
hide(changeFocus) {
return this._invokeSafe('hide', {id: this._id, changeFocus});
}
+ /**
+ * Returns whether or not the popup is currently visible.
+ * @returns {Promise<boolean>} `true` if the popup is visible, `false` otherwise.
+ */
isVisible() {
return this._invokeSafe('isVisible', {id: this._id}, false);
}
+ /**
+ * Force assigns the visibility of the popup.
+ * @param {boolean} value Whether or not the popup should be visible.
+ * @param {number} priority The priority of the override.
+ * @returns {Promise<string?>} A token used which can be passed to `clearVisibleOverride`,
+ * or null if the override wasn't assigned.
+ */
setVisibleOverride(value, priority) {
return this._invokeSafe('setVisibleOverride', {id: this._id, value, priority}, null);
}
+ /**
+ * Clears a visibility override that was generated by `setVisibleOverride`.
+ * @param {string} token The token returned from `setVisibleOverride`.
+ * @returns {Promise<boolean>} `true` if the override existed and was removed, `false` otherwise.
+ */
clearVisibleOverride(token) {
return this._invokeSafe('clearVisibleOverride', {id: this._id, token}, false);
}
+ /**
+ * Checks whether a point is contained within the popup's rect.
+ * @param {number} x The x coordinate.
+ * @param {number} y The y coordinate.
+ * @returns {Promise<boolean>} `true` if the point is contained within the popup's rect, `false` otherwise.
+ */
async containsPoint(x, y) {
if (this._frameOffsetForwarder !== null) {
await this._updateFrameOffset();
@@ -102,6 +187,12 @@ class PopupProxy extends EventDispatcher {
return await this._invokeSafe('containsPoint', {id: this._id, x, y}, false);
}
+ /**
+ * Shows and updates the positioning and content of the popup.
+ * @param {{optionsContext: object, elementRect: {x: number, y: number, width: number, height: number}, writingMode: string}} details Settings for the outer popup.
+ * @param {object} displayDetails The details parameter passed to `Display.setContent`; see that function for details.
+ * @returns {Promise<void>}
+ */
async showContent(details, displayDetails) {
const {elementRect} = details;
if (typeof elementRect !== 'undefined' && this._frameOffsetForwarder !== null) {
@@ -111,38 +202,83 @@ class PopupProxy extends EventDispatcher {
return await this._invokeSafe('showContent', {id: this._id, details, displayDetails});
}
+ /**
+ * Sets the custom styles for the popup content.
+ * @param {string} css The CSS rules.
+ * @returns {Promise<void>}
+ */
setCustomCss(css) {
return this._invokeSafe('setCustomCss', {id: this._id, css});
}
+ /**
+ * Stops the audio auto-play timer, if one has started.
+ * @returns {Promise<void>}
+ */
clearAutoPlayTimer() {
return this._invokeSafe('clearAutoPlayTimer', {id: this._id});
}
+ /**
+ * Sets the scaling factor of the popup content.
+ * @param {number} scale The scaling factor.
+ * @returns {Promise<void>}
+ */
setContentScale(scale) {
return this._invokeSafe('setContentScale', {id: this._id, scale});
}
+ /**
+ * Returns whether or not the popup is currently visible, synchronously.
+ * @returns {boolean} `true` if the popup is visible, `false` otherwise.
+ * @throws An exception is thrown for `PopupProxy` since it cannot synchronously detect visibility.
+ */
isVisibleSync() {
throw new Error('Not supported on PopupProxy');
}
+ /**
+ * Updates the outer theme of the popup.
+ * @returns {Promise<void>}
+ */
updateTheme() {
return this._invokeSafe('updateTheme', {id: this._id});
}
+ /**
+ * Sets the custom styles for the outer popup container.
+ * @param {string} css The CSS rules.
+ * @param {boolean} useWebExtensionApi Whether or not web extension APIs should be used to inject the rules.
+ * When web extension APIs are used, a DOM node is not generated, making it harder to detect the changes.
+ * @returns {Promise<void>}
+ */
setCustomOuterCss(css, useWebExtensionApi) {
return this._invokeSafe('setCustomOuterCss', {id: this._id, css, useWebExtensionApi});
}
+ /**
+ * Gets the rectangle of the DOM frame, synchronously.
+ * @returns {{x: number, y: number, width: number, height: number, valid: boolean}} The rect.
+ * `valid` is `false` for `PopupProxy`, since the DOM node is hosted in a different frame.
+ */
getFrameRect() {
return {x: 0, y: 0, width: 0, height: 0, valid: false};
}
+ /**
+ * Gets the size of the DOM frame.
+ * @returns {Promise<{width: number, height: number, valid: boolean}>} The size and whether or not it is valid.
+ */
getFrameSize() {
return this._invokeSafe('popup.getFrameSize', {id: this._id}, {width: 0, height: 0, valid: false});
}
+ /**
+ * Sets the size of the DOM frame.
+ * @param {number} width The desired width of the popup.
+ * @param {number} height The desired height of the popup.
+ * @returns {Promise<boolean>} `true` if the size assignment was successful, `false` otherwise.
+ */
setFrameSize(width, height) {
return this._invokeSafe('popup.setFrameSize', {id: this._id, width, height});
}
diff --git a/ext/js/app/popup-window.js b/ext/js/app/popup-window.js
index 6f86c61e..61c627b8 100644
--- a/ext/js/app/popup-window.js
+++ b/ext/js/app/popup-window.js
@@ -15,7 +15,17 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/**
+ * This class represents a popup that is hosted in a new native window.
+ */
class PopupWindow extends EventDispatcher {
+ /**
+ * Creates a new instance.
+ * @param {object} details
+ * @param {string} details.id The ID of the popup.
+ * @param {number} details.depth The depth of the popup.
+ * @param {number} details.frameId The ID of the host frame.
+ */
constructor({
id,
depth,
@@ -30,6 +40,10 @@ class PopupWindow extends EventDispatcher {
// Public properties
+ /**
+ * The ID of the popup.
+ * @type {string}
+ */
get id() {
return this._id;
}
@@ -38,30 +52,63 @@ class PopupWindow extends EventDispatcher {
return null;
}
+ /**
+ * The parent of the popup, which is always `null` for `PopupWindow` instances,
+ * since any potential parent popups are in a different frame.
+ * @param {Popup} value
+ * @type {Popup}
+ */
set parent(value) {
throw new Error('Not supported on PopupProxy');
}
+ /**
+ * The popup child popup, which is always null for `PopupWindow` instances,
+ * since any potential child popups are in a different frame.
+ * @type {Popup}
+ */
get child() {
return null;
}
+ /**
+ * Attempts to set the child popup.
+ * @param {Popup} value
+ * @throws Throws an error, since this class doesn't support children.
+ */
set child(value) {
throw new Error('Not supported on PopupProxy');
}
+ /**
+ * The depth of the popup.
+ * @type {numer}
+ */
get depth() {
return this._depth;
}
+ /**
+ * Gets the content window of the frame. This value is null,
+ * since the window is hosted in a different frame.
+ * @type {Window}
+ */
get frameContentWindow() {
return null;
}
+ /**
+ * Gets the DOM node that contains the frame.
+ * @type {Element}
+ */
get container() {
return null;
}
+ /**
+ * Gets the ID of the frame.
+ * @type {number}
+ */
get frameId() {
return this._frameId;
}
@@ -69,67 +116,145 @@ class PopupWindow extends EventDispatcher {
// Public functions
+ /**
+ * Sets the options context for the popup.
+ * @param {object} optionsContext The options context object.
+ * @returns {Promise<void>}
+ */
setOptionsContext(optionsContext, source) {
return this._invoke(false, 'setOptionsContext', {id: this._id, optionsContext, source});
}
+ /**
+ * Hides the popup. This does nothing for `PopupWindow`.
+ * @param {boolean} _changeFocus Whether or not the parent popup or host frame should be focused.
+ */
hide(_changeFocus) {
// NOP
}
+ /**
+ * Returns whether or not the popup is currently visible.
+ * @returns {Promise<boolean>} `true` if the popup is visible, `false` otherwise.
+ */
async isVisible() {
return (this._popupTabId !== null && await yomichan.api.isTabSearchPopup(this._popupTabId));
}
+ /**
+ * Force assigns the visibility of the popup.
+ * @param {boolean} _value Whether or not the popup should be visible.
+ * @param {number} _priority The priority of the override.
+ * @returns {Promise<string?>} A token used which can be passed to `clearVisibleOverride`,
+ * or null if the override wasn't assigned.
+ */
async setVisibleOverride(_value, _priority) {
return null;
}
+ /**
+ * Clears a visibility override that was generated by `setVisibleOverride`.
+ * @param {string} _token The token returned from `setVisibleOverride`.
+ * @returns {boolean} `true` if the override existed and was removed, `false` otherwise.
+ */
clearVisibleOverride(_token) {
return false;
}
+ /**
+ * Checks whether a point is contained within the popup's rect.
+ * @param {number} _x The x coordinate.
+ * @param {number} _y The y coordinate.
+ * @returns {Promise<boolean>} `true` if the point is contained within the popup's rect, `false` otherwise.
+ */
async containsPoint(_x, _y) {
return false;
}
+ /**
+ * Shows and updates the positioning and content of the popup.
+ * @param {{optionsContext: object, elementRect: {x: number, y: number, width: number, height: number}, writingMode: string}} details Settings for the outer popup.
+ * @param {object} displayDetails The details parameter passed to `Display.setContent`; see that function for details.
+ * @returns {Promise<void>}
+ */
async showContent(_details, displayDetails) {
if (displayDetails === null) { return; }
await this._invoke(true, 'setContent', {id: this._id, details: displayDetails});
}
+ /**
+ * Sets the custom styles for the popup content.
+ * @param {string} css The CSS rules.
+ */
setCustomCss(css) {
return this._invoke(false, 'setCustomCss', {id: this._id, css});
}
+ /**
+ * Stops the audio auto-play timer, if one has started.
+ */
clearAutoPlayTimer() {
return this._invoke(false, 'clearAutoPlayTimer', {id: this._id});
}
+ /**
+ * Sets the scaling factor of the popup content.
+ * @param {number} scale The scaling factor.
+ */
setContentScale(_scale) {
// NOP
}
+ /**
+ * Returns whether or not the popup is currently visible, synchronously.
+ * @returns {boolean} `true` if the popup is visible, `false` otherwise.
+ * @throws An exception is thrown for `PopupWindow` since it cannot synchronously detect visibility.
+ */
isVisibleSync() {
throw new Error('Not supported on PopupWindow');
}
+ /**
+ * Updates the outer theme of the popup.
+ */
updateTheme() {
// NOP
}
+ /**
+ * Sets the custom styles for the outer popup container.
+ * This does nothing for `PopupWindow`.
+ * @param {string} _css The CSS rules.
+ * @param {boolean} _useWebExtensionApi Whether or not web extension APIs should be used to inject the rules.
+ * When web extension APIs are used, a DOM node is not generated, making it harder to detect the changes.
+ */
async setCustomOuterCss(_css, _useWebExtensionApi) {
// NOP
}
+ /**
+ * Gets the rectangle of the DOM frame, synchronously.
+ * @returns {{x: number, y: number, width: number, height: number, valid: boolean}} The rect.
+ * `valid` is `false` for `PopupProxy`, since the DOM node is hosted in a different frame.
+ */
getFrameRect() {
return {x: 0, y: 0, width: 0, height: 0, valid: false};
}
+ /**
+ * Gets the size of the DOM frame.
+ * @returns {Promise<{width: number, height: number, valid: boolean}>} The size and whether or not it is valid.
+ */
async getFrameSize() {
return {width: 0, height: 0, valid: false};
}
+ /**
+ * Sets the size of the DOM frame.
+ * @param {number} _width The desired width of the popup.
+ * @param {number} _height The desired height of the popup.
+ * @returns {Promise<boolean>} `true` if the size assignment was successful, `false` otherwise.
+ */
async setFrameSize(_width, _height) {
return false;
}
diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js
index 3a29563d..7581c8d7 100644
--- a/ext/js/app/popup.js
+++ b/ext/js/app/popup.js
@@ -21,7 +21,18 @@
* dynamicLoader
*/
+/**
+ * This class is the container which hosts the display of search results.
+ */
class Popup extends EventDispatcher {
+ /**
+ * Creates a new instance.
+ * @param {object} details
+ * @param {string} details.id The ID of the popup.
+ * @param {number} details.depth The depth of the popup.
+ * @param {number} details.frameId The ID of the host frame.
+ * @param {boolean} details.childrenSupported Whether or not the popup is able to show child popups.
+ */
constructor({
id,
depth,
@@ -59,44 +70,84 @@ class Popup extends EventDispatcher {
// Public properties
+ /**
+ * The ID of the popup.
+ * @type {string}
+ */
get id() {
return this._id;
}
+ /**
+ * The parent of the popup.
+ * @type {Popup}
+ */
get parent() {
return this._parent;
}
+ /**
+ * Sets the parent popup.
+ * @param {Popup} value The parent popup to assign.
+ */
set parent(value) {
this._parent = value;
}
+ /**
+ * The child of the popup.
+ * @type {Popup}
+ */
get child() {
return this._child;
}
+ /**
+ * Sets the child popup.
+ * @param {Popup} value The child popup to assign.
+ */
set child(value) {
this._child = value;
}
+ /**
+ * The depth of the popup.
+ * @type {numer}
+ */
get depth() {
return this._depth;
}
+ /**
+ * Gets the content window of the frame, which can be `null`
+ * depending on the current state of the frame.
+ * @type {?Window}
+ */
get frameContentWindow() {
return this._frame.contentWindow;
}
+ /**
+ * Gets the DOM node that contains the frame.
+ * @type {Element}
+ */
get container() {
return this._container;
}
+ /**
+ * Gets the ID of the frame.
+ * @type {number}
+ */
get frameId() {
return this._frameId;
}
// Public functions
+ /**
+ * Prepares the popup for use.
+ */
prepare() {
this._frame.addEventListener('mouseover', this._onFrameMouseOver.bind(this));
this._frame.addEventListener('mouseout', this._onFrameMouseOut.bind(this));
@@ -108,11 +159,19 @@ class Popup extends EventDispatcher {
this._onVisibleChange({value: this.isVisibleSync()});
}
+ /**
+ * Sets the options context for the popup.
+ * @param {object} optionsContext The options context object.
+ */
async setOptionsContext(optionsContext) {
await this._setOptionsContext(optionsContext);
await this._invokeSafe('setOptionsContext', {optionsContext});
}
+ /**
+ * Hides the popup.
+ * @param {boolean} changeFocus Whether or not the parent popup or host frame should be focused.
+ */
hide(changeFocus) {
if (!this.isVisibleSync()) {
return;
@@ -127,18 +186,40 @@ class Popup extends EventDispatcher {
}
}
+ /**
+ * Returns whether or not the popup is currently visible.
+ * @returns {Promise<boolean>} `true` if the popup is visible, `false` otherwise.
+ */
async isVisible() {
return this.isVisibleSync();
}
+ /**
+ * Force assigns the visibility of the popup.
+ * @param {boolean} value Whether or not the popup should be visible.
+ * @param {number} priority The priority of the override.
+ * @returns {Promise<string?>} A token used which can be passed to `clearVisibleOverride`,
+ * or null if the override wasn't assigned.
+ */
async setVisibleOverride(value, priority) {
return this._visible.setOverride(value, priority);
}
+ /**
+ * Clears a visibility override that was generated by `setVisibleOverride`.
+ * @param {string} token The token returned from `setVisibleOverride`.
+ * @returns {Promise<boolean>} `true` if the override existed and was removed, `false` otherwise.
+ */
async clearVisibleOverride(token) {
return this._visible.clearOverride(token);
}
+ /**
+ * Checks whether a point is contained within the popup's rect.
+ * @param {number} x The x coordinate.
+ * @param {number} y The y coordinate.
+ * @returns {Promise<boolean>} `true` if the point is contained within the popup's rect, `false` otherwise.
+ */
async containsPoint(x, y) {
for (let popup = this; popup !== null && popup.isVisibleSync(); popup = popup.child) {
const rect = popup.getFrameRect();
@@ -149,6 +230,12 @@ class Popup extends EventDispatcher {
return false;
}
+ /**
+ * Shows and updates the positioning and content of the popup.
+ * @param {{optionsContext: object, elementRect: {x: number, y: number, width: number, height: number}, writingMode: string}} details Settings for the outer popup.
+ * @param {object} displayDetails The details parameter passed to `Display.setContent`; see that function for details.
+ * @returns {Promise<void>}
+ */
async showContent(details, displayDetails) {
if (this._options === null) { throw new Error('Options not assigned'); }
@@ -166,24 +253,43 @@ class Popup extends EventDispatcher {
}
}
+ /**
+ * Sets the custom styles for the popup content.
+ * @param {string} css The CSS rules.
+ */
setCustomCss(css) {
this._invokeSafe('setCustomCss', {css});
}
+ /**
+ * Stops the audio auto-play timer, if one has started.
+ */
clearAutoPlayTimer() {
this._invokeSafe('clearAutoPlayTimer');
}
+ /**
+ * Sets the scaling factor of the popup content.
+ * @param {number} scale The scaling factor.
+ */
setContentScale(scale) {
this._contentScale = scale;
this._frame.style.fontSize = `${scale}px`;
this._invokeSafe('setContentScale', {scale});
}
+ /**
+ * Returns whether or not the popup is currently visible, synchronously.
+ * @returns {boolean} `true` if the popup is visible, `false` otherwise.
+ */
isVisibleSync() {
return this._visible.value;
}
+ /**
+ * Updates the outer theme of the popup.
+ * @returns {Promise<void>}
+ */
updateTheme() {
const {popupTheme, popupOuterTheme} = this._options.general;
this._frame.dataset.theme = popupTheme;
@@ -191,6 +297,12 @@ class Popup extends EventDispatcher {
this._frame.dataset.siteColor = this._getSiteColor();
}
+ /**
+ * Sets the custom styles for the outer popup container.
+ * @param {string} css The CSS rules.
+ * @param {boolean} useWebExtensionApi Whether or not web extension APIs should be used to inject the rules.
+ * When web extension APIs are used, a DOM node is not generated, making it harder to detect the changes.
+ */
async setCustomOuterCss(css, useWebExtensionApi) {
let parentNode = null;
const inShadow = (this._shadow !== null);
@@ -202,16 +314,31 @@ class Popup extends EventDispatcher {
this.trigger('customOuterCssChanged', {node, useWebExtensionApi, inShadow});
}
+ /**
+ * Gets the rectangle of the DOM frame, synchronously.
+ * @returns {{x: number, y: number, width: number, height: number, valid: boolean}} The rect.
+ * `valid` is `false` for `PopupProxy`, since the DOM node is hosted in a different frame.
+ */
getFrameRect() {
const {left, top, width, height} = this._frame.getBoundingClientRect();
return {x: left, y: top, width, height, valid: true};
}
+ /**
+ * Gets the size of the DOM frame.
+ * @returns {Promise<{width: number, height: number, valid: boolean}>} The size and whether or not it is valid.
+ */
async getFrameSize() {
const {width, height} = this._frame.getBoundingClientRect();
return {width, height, valid: true};
}
+ /**
+ * Sets the size of the DOM frame.
+ * @param {number} width The desired width of the popup.
+ * @param {number} height The desired height of the popup.
+ * @returns {Promise<boolean>} `true` if the size assignment was successful, `false` otherwise.
+ */
async setFrameSize(width, height) {
this._setFrameSize(width, height);
return true;