JSDoc update (#1996)
* Update core.js docs to include types. * Update docs
This commit is contained in:
parent
f978819a33
commit
2dc8394c72
@ -21,7 +21,26 @@
|
|||||||
* TextSourceRange
|
* TextSourceRange
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the main class responsible for scanning and handling webpage content.
|
||||||
|
*/
|
||||||
class Frontend {
|
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({
|
constructor({
|
||||||
pageType,
|
pageType,
|
||||||
popupFactory,
|
popupFactory,
|
||||||
@ -83,18 +102,33 @@ class Frontend {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether or not the text selection can be cleared.
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
get canClearSelection() {
|
get canClearSelection() {
|
||||||
return this._textScanner.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) {
|
set canClearSelection(value) {
|
||||||
this._textScanner.canClearSelection = value;
|
this._textScanner.canClearSelection = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the popup instance.
|
||||||
|
* @type {Popup}
|
||||||
|
*/
|
||||||
get popup() {
|
get popup() {
|
||||||
return this._popup;
|
return this._popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the instance for use.
|
||||||
|
*/
|
||||||
async prepare() {
|
async prepare() {
|
||||||
await this.updateOptions();
|
await this.updateOptions();
|
||||||
try {
|
try {
|
||||||
@ -135,20 +169,35 @@ class Frontend {
|
|||||||
this._signalFrontendReady();
|
this._signalFrontendReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether or not the instance is disabled.
|
||||||
|
* @param {boolean} disabled Whether or not the instance is disabled.
|
||||||
|
*/
|
||||||
setDisabledOverride(disabled) {
|
setDisabledOverride(disabled) {
|
||||||
this._disabledOverride = disabled;
|
this._disabledOverride = disabled;
|
||||||
this._updateTextScannerEnabled();
|
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) {
|
setOptionsContextOverride(optionsContext) {
|
||||||
this._optionsContextOverride = optionsContext;
|
this._optionsContextOverride = optionsContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a new search on a specific source.
|
||||||
|
* @param {TextSourceRange|TextSourceElement} textSource The text source to search.
|
||||||
|
*/
|
||||||
async setTextSource(textSource) {
|
async setTextSource(textSource) {
|
||||||
this._textScanner.setCurrentTextSource(null);
|
this._textScanner.setCurrentTextSource(null);
|
||||||
await this._textScanner.search(textSource);
|
await this._textScanner.search(textSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the internal options representation.
|
||||||
|
*/
|
||||||
async updateOptions() {
|
async updateOptions() {
|
||||||
try {
|
try {
|
||||||
await this._updateOptionsInternal();
|
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() {
|
showContentCompleted() {
|
||||||
return this._lastShowPromise;
|
return this._lastShowPromise;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,14 @@
|
|||||||
* PopupWindow
|
* PopupWindow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class which is used to generate and manage popups.
|
||||||
|
*/
|
||||||
class PopupFactory {
|
class PopupFactory {
|
||||||
|
/**
|
||||||
|
* Creates a new instance.
|
||||||
|
* @param {number} frameId The frame ID of the host frame.
|
||||||
|
*/
|
||||||
constructor(frameId) {
|
constructor(frameId) {
|
||||||
this._frameId = frameId;
|
this._frameId = frameId;
|
||||||
this._frameOffsetForwarder = new FrameOffsetForwarder(frameId);
|
this._frameOffsetForwarder = new FrameOffsetForwarder(frameId);
|
||||||
@ -32,6 +39,9 @@ class PopupFactory {
|
|||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the instance for use.
|
||||||
|
*/
|
||||||
prepare() {
|
prepare() {
|
||||||
this._frameOffsetForwarder.prepare();
|
this._frameOffsetForwarder.prepare();
|
||||||
yomichan.crossFrame.registerHandlers([
|
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({
|
async getOrCreatePopup({
|
||||||
frameId=null,
|
frameId=null,
|
||||||
id=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) {
|
async setAllVisibleOverride(value, priority) {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
const errors = [];
|
const errors = [];
|
||||||
@ -173,6 +200,11 @@ class PopupFactory {
|
|||||||
throw errors[0];
|
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) {
|
async clearAllVisibleOverride(token) {
|
||||||
const results = this._allPopupVisibilityTokenMap.get(token);
|
const results = this._allPopupVisibilityTokenMap.get(token);
|
||||||
if (typeof results === 'undefined') { return false; }
|
if (typeof results === 'undefined') { return false; }
|
||||||
|
@ -15,7 +15,19 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* 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 {
|
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({
|
constructor({
|
||||||
id,
|
id,
|
||||||
depth,
|
depth,
|
||||||
@ -36,64 +48,137 @@ class PopupProxy extends EventDispatcher {
|
|||||||
|
|
||||||
// Public properties
|
// Public properties
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the popup.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
get id() {
|
get id() {
|
||||||
return this._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() {
|
get parent() {
|
||||||
return null;
|
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) {
|
set parent(value) {
|
||||||
throw new Error('Not supported on PopupProxy');
|
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() {
|
get child() {
|
||||||
return null;
|
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) {
|
set child(value) {
|
||||||
throw new Error('Not supported on PopupProxy');
|
throw new Error('Not supported on PopupProxy');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The depth of the popup.
|
||||||
|
* @type {numer}
|
||||||
|
*/
|
||||||
get depth() {
|
get depth() {
|
||||||
return this._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() {
|
get frameContentWindow() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the DOM node that contains the frame.
|
||||||
|
* @type {Element}
|
||||||
|
*/
|
||||||
get container() {
|
get container() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID of the frame.
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get frameId() {
|
get frameId() {
|
||||||
return this._frameId;
|
return this._frameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the options context for the popup.
|
||||||
|
* @param {object} optionsContext The options context object.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
setOptionsContext(optionsContext, source) {
|
setOptionsContext(optionsContext, source) {
|
||||||
return this._invokeSafe('setOptionsContext', {id: this._id, 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) {
|
hide(changeFocus) {
|
||||||
return this._invokeSafe('hide', {id: this._id, 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() {
|
isVisible() {
|
||||||
return this._invokeSafe('isVisible', {id: this._id}, false);
|
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) {
|
setVisibleOverride(value, priority) {
|
||||||
return this._invokeSafe('setVisibleOverride', {id: this._id, value, priority}, null);
|
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) {
|
clearVisibleOverride(token) {
|
||||||
return this._invokeSafe('clearVisibleOverride', {id: this._id, token}, false);
|
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) {
|
async containsPoint(x, y) {
|
||||||
if (this._frameOffsetForwarder !== null) {
|
if (this._frameOffsetForwarder !== null) {
|
||||||
await this._updateFrameOffset();
|
await this._updateFrameOffset();
|
||||||
@ -102,6 +187,12 @@ class PopupProxy extends EventDispatcher {
|
|||||||
return await this._invokeSafe('containsPoint', {id: this._id, x, y}, false);
|
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) {
|
async showContent(details, displayDetails) {
|
||||||
const {elementRect} = details;
|
const {elementRect} = details;
|
||||||
if (typeof elementRect !== 'undefined' && this._frameOffsetForwarder !== null) {
|
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});
|
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) {
|
setCustomCss(css) {
|
||||||
return this._invokeSafe('setCustomCss', {id: this._id, css});
|
return this._invokeSafe('setCustomCss', {id: this._id, css});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the audio auto-play timer, if one has started.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
clearAutoPlayTimer() {
|
clearAutoPlayTimer() {
|
||||||
return this._invokeSafe('clearAutoPlayTimer', {id: this._id});
|
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) {
|
setContentScale(scale) {
|
||||||
return this._invokeSafe('setContentScale', {id: this._id, 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() {
|
isVisibleSync() {
|
||||||
throw new Error('Not supported on PopupProxy');
|
throw new Error('Not supported on PopupProxy');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the outer theme of the popup.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
updateTheme() {
|
updateTheme() {
|
||||||
return this._invokeSafe('updateTheme', {id: this._id});
|
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) {
|
setCustomOuterCss(css, useWebExtensionApi) {
|
||||||
return this._invokeSafe('setCustomOuterCss', {id: this._id, 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() {
|
getFrameRect() {
|
||||||
return {x: 0, y: 0, width: 0, height: 0, valid: false};
|
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() {
|
getFrameSize() {
|
||||||
return this._invokeSafe('popup.getFrameSize', {id: this._id}, {width: 0, height: 0, valid: false});
|
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) {
|
setFrameSize(width, height) {
|
||||||
return this._invokeSafe('popup.setFrameSize', {id: this._id, width, height});
|
return this._invokeSafe('popup.setFrameSize', {id: this._id, width, height});
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,17 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* 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 {
|
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({
|
constructor({
|
||||||
id,
|
id,
|
||||||
depth,
|
depth,
|
||||||
@ -30,6 +40,10 @@ class PopupWindow extends EventDispatcher {
|
|||||||
|
|
||||||
// Public properties
|
// Public properties
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the popup.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
get id() {
|
get id() {
|
||||||
return this._id;
|
return this._id;
|
||||||
}
|
}
|
||||||
@ -38,30 +52,63 @@ class PopupWindow extends EventDispatcher {
|
|||||||
return null;
|
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) {
|
set parent(value) {
|
||||||
throw new Error('Not supported on PopupProxy');
|
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() {
|
get child() {
|
||||||
return null;
|
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) {
|
set child(value) {
|
||||||
throw new Error('Not supported on PopupProxy');
|
throw new Error('Not supported on PopupProxy');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The depth of the popup.
|
||||||
|
* @type {numer}
|
||||||
|
*/
|
||||||
get depth() {
|
get depth() {
|
||||||
return this._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() {
|
get frameContentWindow() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the DOM node that contains the frame.
|
||||||
|
* @type {Element}
|
||||||
|
*/
|
||||||
get container() {
|
get container() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID of the frame.
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get frameId() {
|
get frameId() {
|
||||||
return this._frameId;
|
return this._frameId;
|
||||||
}
|
}
|
||||||
@ -69,67 +116,145 @@ class PopupWindow extends EventDispatcher {
|
|||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the options context for the popup.
|
||||||
|
* @param {object} optionsContext The options context object.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
setOptionsContext(optionsContext, source) {
|
setOptionsContext(optionsContext, source) {
|
||||||
return this._invoke(false, 'setOptionsContext', {id: this._id, 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) {
|
hide(_changeFocus) {
|
||||||
// NOP
|
// NOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the popup is currently visible.
|
||||||
|
* @returns {Promise<boolean>} `true` if the popup is visible, `false` otherwise.
|
||||||
|
*/
|
||||||
async isVisible() {
|
async isVisible() {
|
||||||
return (this._popupTabId !== null && await yomichan.api.isTabSearchPopup(this._popupTabId));
|
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) {
|
async setVisibleOverride(_value, _priority) {
|
||||||
return null;
|
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) {
|
clearVisibleOverride(_token) {
|
||||||
return false;
|
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) {
|
async containsPoint(_x, _y) {
|
||||||
return false;
|
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) {
|
async showContent(_details, displayDetails) {
|
||||||
if (displayDetails === null) { return; }
|
if (displayDetails === null) { return; }
|
||||||
await this._invoke(true, 'setContent', {id: this._id, details: displayDetails});
|
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) {
|
setCustomCss(css) {
|
||||||
return this._invoke(false, 'setCustomCss', {id: this._id, css});
|
return this._invoke(false, 'setCustomCss', {id: this._id, css});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the audio auto-play timer, if one has started.
|
||||||
|
*/
|
||||||
clearAutoPlayTimer() {
|
clearAutoPlayTimer() {
|
||||||
return this._invoke(false, 'clearAutoPlayTimer', {id: this._id});
|
return this._invoke(false, 'clearAutoPlayTimer', {id: this._id});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the scaling factor of the popup content.
|
||||||
|
* @param {number} scale The scaling factor.
|
||||||
|
*/
|
||||||
setContentScale(_scale) {
|
setContentScale(_scale) {
|
||||||
// NOP
|
// 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() {
|
isVisibleSync() {
|
||||||
throw new Error('Not supported on PopupWindow');
|
throw new Error('Not supported on PopupWindow');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the outer theme of the popup.
|
||||||
|
*/
|
||||||
updateTheme() {
|
updateTheme() {
|
||||||
// NOP
|
// 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) {
|
async setCustomOuterCss(_css, _useWebExtensionApi) {
|
||||||
// NOP
|
// 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() {
|
getFrameRect() {
|
||||||
return {x: 0, y: 0, width: 0, height: 0, valid: false};
|
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() {
|
async getFrameSize() {
|
||||||
return {width: 0, height: 0, valid: false};
|
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) {
|
async setFrameSize(_width, _height) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,18 @@
|
|||||||
* dynamicLoader
|
* dynamicLoader
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is the container which hosts the display of search results.
|
||||||
|
*/
|
||||||
class Popup extends EventDispatcher {
|
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({
|
constructor({
|
||||||
id,
|
id,
|
||||||
depth,
|
depth,
|
||||||
@ -59,44 +70,84 @@ class Popup extends EventDispatcher {
|
|||||||
|
|
||||||
// Public properties
|
// Public properties
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the popup.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
get id() {
|
get id() {
|
||||||
return this._id;
|
return this._id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent of the popup.
|
||||||
|
* @type {Popup}
|
||||||
|
*/
|
||||||
get parent() {
|
get parent() {
|
||||||
return this._parent;
|
return this._parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the parent popup.
|
||||||
|
* @param {Popup} value The parent popup to assign.
|
||||||
|
*/
|
||||||
set parent(value) {
|
set parent(value) {
|
||||||
this._parent = value;
|
this._parent = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The child of the popup.
|
||||||
|
* @type {Popup}
|
||||||
|
*/
|
||||||
get child() {
|
get child() {
|
||||||
return this._child;
|
return this._child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the child popup.
|
||||||
|
* @param {Popup} value The child popup to assign.
|
||||||
|
*/
|
||||||
set child(value) {
|
set child(value) {
|
||||||
this._child = value;
|
this._child = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The depth of the popup.
|
||||||
|
* @type {numer}
|
||||||
|
*/
|
||||||
get depth() {
|
get depth() {
|
||||||
return this._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() {
|
get frameContentWindow() {
|
||||||
return this._frame.contentWindow;
|
return this._frame.contentWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the DOM node that contains the frame.
|
||||||
|
* @type {Element}
|
||||||
|
*/
|
||||||
get container() {
|
get container() {
|
||||||
return this._container;
|
return this._container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID of the frame.
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
get frameId() {
|
get frameId() {
|
||||||
return this._frameId;
|
return this._frameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the popup for use.
|
||||||
|
*/
|
||||||
prepare() {
|
prepare() {
|
||||||
this._frame.addEventListener('mouseover', this._onFrameMouseOver.bind(this));
|
this._frame.addEventListener('mouseover', this._onFrameMouseOver.bind(this));
|
||||||
this._frame.addEventListener('mouseout', this._onFrameMouseOut.bind(this));
|
this._frame.addEventListener('mouseout', this._onFrameMouseOut.bind(this));
|
||||||
@ -108,11 +159,19 @@ class Popup extends EventDispatcher {
|
|||||||
this._onVisibleChange({value: this.isVisibleSync()});
|
this._onVisibleChange({value: this.isVisibleSync()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the options context for the popup.
|
||||||
|
* @param {object} optionsContext The options context object.
|
||||||
|
*/
|
||||||
async setOptionsContext(optionsContext) {
|
async setOptionsContext(optionsContext) {
|
||||||
await this._setOptionsContext(optionsContext);
|
await this._setOptionsContext(optionsContext);
|
||||||
await this._invokeSafe('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) {
|
hide(changeFocus) {
|
||||||
if (!this.isVisibleSync()) {
|
if (!this.isVisibleSync()) {
|
||||||
return;
|
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() {
|
async isVisible() {
|
||||||
return this.isVisibleSync();
|
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) {
|
async setVisibleOverride(value, priority) {
|
||||||
return this._visible.setOverride(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) {
|
async clearVisibleOverride(token) {
|
||||||
return this._visible.clearOverride(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) {
|
async containsPoint(x, y) {
|
||||||
for (let popup = this; popup !== null && popup.isVisibleSync(); popup = popup.child) {
|
for (let popup = this; popup !== null && popup.isVisibleSync(); popup = popup.child) {
|
||||||
const rect = popup.getFrameRect();
|
const rect = popup.getFrameRect();
|
||||||
@ -149,6 +230,12 @@ class Popup extends EventDispatcher {
|
|||||||
return false;
|
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) {
|
async showContent(details, displayDetails) {
|
||||||
if (this._options === null) { throw new Error('Options not assigned'); }
|
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) {
|
setCustomCss(css) {
|
||||||
this._invokeSafe('setCustomCss', {css});
|
this._invokeSafe('setCustomCss', {css});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the audio auto-play timer, if one has started.
|
||||||
|
*/
|
||||||
clearAutoPlayTimer() {
|
clearAutoPlayTimer() {
|
||||||
this._invokeSafe('clearAutoPlayTimer');
|
this._invokeSafe('clearAutoPlayTimer');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the scaling factor of the popup content.
|
||||||
|
* @param {number} scale The scaling factor.
|
||||||
|
*/
|
||||||
setContentScale(scale) {
|
setContentScale(scale) {
|
||||||
this._contentScale = scale;
|
this._contentScale = scale;
|
||||||
this._frame.style.fontSize = `${scale}px`;
|
this._frame.style.fontSize = `${scale}px`;
|
||||||
this._invokeSafe('setContentScale', {scale});
|
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() {
|
isVisibleSync() {
|
||||||
return this._visible.value;
|
return this._visible.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the outer theme of the popup.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
updateTheme() {
|
updateTheme() {
|
||||||
const {popupTheme, popupOuterTheme} = this._options.general;
|
const {popupTheme, popupOuterTheme} = this._options.general;
|
||||||
this._frame.dataset.theme = popupTheme;
|
this._frame.dataset.theme = popupTheme;
|
||||||
@ -191,6 +297,12 @@ class Popup extends EventDispatcher {
|
|||||||
this._frame.dataset.siteColor = this._getSiteColor();
|
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) {
|
async setCustomOuterCss(css, useWebExtensionApi) {
|
||||||
let parentNode = null;
|
let parentNode = null;
|
||||||
const inShadow = (this._shadow !== null);
|
const inShadow = (this._shadow !== null);
|
||||||
@ -202,16 +314,31 @@ class Popup extends EventDispatcher {
|
|||||||
this.trigger('customOuterCssChanged', {node, useWebExtensionApi, inShadow});
|
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() {
|
getFrameRect() {
|
||||||
const {left, top, width, height} = this._frame.getBoundingClientRect();
|
const {left, top, width, height} = this._frame.getBoundingClientRect();
|
||||||
return {x: left, y: top, width, height, valid: true};
|
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() {
|
async getFrameSize() {
|
||||||
const {width, height} = this._frame.getBoundingClientRect();
|
const {width, height} = this._frame.getBoundingClientRect();
|
||||||
return {width, height, valid: true};
|
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) {
|
async setFrameSize(width, height) {
|
||||||
this._setFrameSize(width, height);
|
this._setFrameSize(width, height);
|
||||||
return true;
|
return true;
|
||||||
|
130
ext/js/core.js
130
ext/js/core.js
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an `Error` object to a serializable JSON object.
|
* Converts an `Error` object to a serializable JSON object.
|
||||||
* @param error An error object to convert.
|
* @param {*} error An error object to convert.
|
||||||
* @returns A simple object which can be serialized by `JSON.stringify()`.
|
* @returns {{name: string, message: string, stack: string, data?: *}|{value: *, hasValue: boolean}} A simple object which can be serialized by `JSON.stringify()`.
|
||||||
*/
|
*/
|
||||||
function serializeError(error) {
|
function serializeError(error) {
|
||||||
try {
|
try {
|
||||||
@ -44,8 +44,8 @@ function serializeError(error) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a serialized erorr into a standard `Error` object.
|
* Converts a serialized erorr into a standard `Error` object.
|
||||||
* @param serializedError A simple object which was initially generated by serializeError.
|
* @param {{name: string, message: string, stack: string, data?: *}|{value: *, hasValue: boolean}} serializedError A simple object which was initially generated by serializeError.
|
||||||
* @returns A new `Error` instance.
|
* @returns {Error|*} A new `Error` instance.
|
||||||
*/
|
*/
|
||||||
function deserializeError(serializedError) {
|
function deserializeError(serializedError) {
|
||||||
if (serializedError.hasValue) {
|
if (serializedError.hasValue) {
|
||||||
@ -62,8 +62,8 @@ function deserializeError(serializedError) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a given value is a non-array object.
|
* Checks whether a given value is a non-array object.
|
||||||
* @param value The value to check.
|
* @param {*} value The value to check.
|
||||||
* @returns `true` if the value is an object and not an array, `false` otherwise.
|
* @returns {boolean} `true` if the value is an object and not an array, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
function isObject(value) {
|
function isObject(value) {
|
||||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||||
@ -72,8 +72,8 @@ function isObject(value) {
|
|||||||
/**
|
/**
|
||||||
* Converts any string into a form that can be passed into the RegExp constructor.
|
* Converts any string into a form that can be passed into the RegExp constructor.
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
||||||
* @param string The string to convert to a valid regular expression.
|
* @param {string} string The string to convert to a valid regular expression.
|
||||||
* @returns The escaped string.
|
* @returns {string} The escaped string.
|
||||||
*/
|
*/
|
||||||
function escapeRegExp(string) {
|
function escapeRegExp(string) {
|
||||||
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
|
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
|
||||||
@ -81,8 +81,8 @@ function escapeRegExp(string) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverses a string.
|
* Reverses a string.
|
||||||
* @param string The string to reverse.
|
* @param {string} string The string to reverse.
|
||||||
* @returns The returned string, which retains proper UTF-16 surrogate pair order.
|
* @returns {string} The returned string, which retains proper UTF-16 surrogate pair order.
|
||||||
*/
|
*/
|
||||||
function stringReverse(string) {
|
function stringReverse(string) {
|
||||||
return [...string].reverse().join('');
|
return [...string].reverse().join('');
|
||||||
@ -90,8 +90,8 @@ function stringReverse(string) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a deep clone of an object or value. This is similar to `JSON.parse(JSON.stringify(value))`.
|
* Creates a deep clone of an object or value. This is similar to `JSON.parse(JSON.stringify(value))`.
|
||||||
* @param value The value to clone.
|
* @param {*} value The value to clone.
|
||||||
* @returns A new clone of the value.
|
* @returns {*} A new clone of the value.
|
||||||
* @throws An error if the value is circular and cannot be cloned.
|
* @throws An error if the value is circular and cannot be cloned.
|
||||||
*/
|
*/
|
||||||
const clone = (() => {
|
const clone = (() => {
|
||||||
@ -163,9 +163,9 @@ const clone = (() => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an object or value is deeply equal to another object or value.
|
* Checks if an object or value is deeply equal to another object or value.
|
||||||
* @param value1 The first value to check.
|
* @param {*} value1 The first value to check.
|
||||||
* @param value2 The second value to check.
|
* @param {*} value2 The second value to check.
|
||||||
* @returns `true` if the values are the same object, or deeply equal without cycles. `false` otherwise.
|
* @returns {boolean} `true` if the values are the same object, or deeply equal without cycles. `false` otherwise.
|
||||||
*/
|
*/
|
||||||
const deepEqual = (() => {
|
const deepEqual = (() => {
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow
|
||||||
@ -235,8 +235,8 @@ const deepEqual = (() => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new base-16 (lower case) string of a sequence of random bytes of the given length.
|
* Creates a new base-16 (lower case) string of a sequence of random bytes of the given length.
|
||||||
* @param length The number of bytes the string represents. The returned string's length will be twice as long.
|
* @param {number} length The number of bytes the string represents. The returned string's length will be twice as long.
|
||||||
* @returns A string of random characters.
|
* @returns {string} A string of random characters.
|
||||||
*/
|
*/
|
||||||
function generateId(length) {
|
function generateId(length) {
|
||||||
const array = new Uint8Array(length);
|
const array = new Uint8Array(length);
|
||||||
@ -250,7 +250,7 @@ function generateId(length) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an unresolved promise that can be resolved later, outside the promise's executor function.
|
* Creates an unresolved promise that can be resolved later, outside the promise's executor function.
|
||||||
* @returns An object `{promise, resolve, reject}`, containing the promise and the resolve/reject functions.
|
* @returns {{promise: Promise, resolve: function, reject: function}} An object `{promise, resolve, reject}`, containing the promise and the resolve/reject functions.
|
||||||
*/
|
*/
|
||||||
function deferPromise() {
|
function deferPromise() {
|
||||||
let resolve;
|
let resolve;
|
||||||
@ -264,9 +264,9 @@ function deferPromise() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a promise that is resolved after a set delay.
|
* Creates a promise that is resolved after a set delay.
|
||||||
* @param delay How many milliseconds until the promise should be resolved. If 0, the promise is immediately resolved.
|
* @param {number} delay How many milliseconds until the promise should be resolved. If 0, the promise is immediately resolved.
|
||||||
* @param resolveValue Optional; the value returned when the promise is resolved.
|
* @param {*} [resolveValue] The value returned when the promise is resolved.
|
||||||
* @returns A promise with two additional properties: `resolve` and `reject`, which can be used to complete the promise early.
|
* @returns {Promise} A promise with two additional properties: `resolve` and `reject`, which can be used to complete the promise early.
|
||||||
*/
|
*/
|
||||||
function promiseTimeout(delay, resolveValue) {
|
function promiseTimeout(delay, resolveValue) {
|
||||||
if (delay <= 0) {
|
if (delay <= 0) {
|
||||||
@ -306,8 +306,8 @@ function promiseTimeout(delay, resolveValue) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a promise that will resolve after the next animation frame, using `requestAnimationFrame`.
|
* Creates a promise that will resolve after the next animation frame, using `requestAnimationFrame`.
|
||||||
* @param timeout Optional; a maximum duration (in milliseconds) to wait until the promise resolves. If null or omitted, no timeout is used.
|
* @param {number} [timeout] A maximum duration (in milliseconds) to wait until the promise resolves. If null or omitted, no timeout is used.
|
||||||
* @returns A promise that is resolved with `{time, timeout}`, where `time` is the timestamp from `requestAnimationFrame`,
|
* @returns {Promise<{time: number, timeout: number}>} A promise that is resolved with `{time, timeout}`, where `time` is the timestamp from `requestAnimationFrame`,
|
||||||
* and `timeout` is a boolean indicating whether the cause was a timeout or not.
|
* and `timeout` is a boolean indicating whether the cause was a timeout or not.
|
||||||
* @throws The promise throws an error if animation is not supported in this context, such as in a service worker.
|
* @throws The promise throws an error if animation is not supported in this context, such as in a service worker.
|
||||||
*/
|
*/
|
||||||
@ -349,16 +349,17 @@ function promiseAnimationFrame(timeout=null) {
|
|||||||
/**
|
/**
|
||||||
* Invokes a standard message handler. This function is used to react and respond
|
* Invokes a standard message handler. This function is used to react and respond
|
||||||
* to communication messages within the extension.
|
* to communication messages within the extension.
|
||||||
* @param handler A handler function which is passed `params` and `...extraArgs` as arguments.
|
* @param {object} details
|
||||||
* @param async Whether or not the handler is async or not. Values include `false`, `true`, or `'dynamic'`.
|
* @param {function} details.handler A handler function which is passed `params` and `...extraArgs` as arguments.
|
||||||
|
* @param {boolean|string} details.async Whether or not the handler is async or not. Values include `false`, `true`, or `'dynamic'`.
|
||||||
* When the value is `'dynamic'`, the handler should return an object of the format `{async: boolean, result: any}`.
|
* When the value is `'dynamic'`, the handler should return an object of the format `{async: boolean, result: any}`.
|
||||||
* @param params Information which was passed with the original message.
|
* @param {object} params Information which was passed with the original message.
|
||||||
* @param callback A callback function which is invoked after the handler has completed. The value passed
|
* @param {function} callback A callback function which is invoked after the handler has completed. The value passed
|
||||||
* to the function is in the format:
|
* to the function is in the format:
|
||||||
* * `{result: any}` if the handler invoked successfully.
|
* * `{result: any}` if the handler invoked successfully.
|
||||||
* * `{error: object}` if the handler thew an error. The error is serialized.
|
* * `{error: object}` if the handler thew an error. The error is serialized.
|
||||||
* @param extraArgs Additional arguments which are passed to the `handler` function.
|
* @param {...*} extraArgs Additional arguments which are passed to the `handler` function.
|
||||||
* @returns `true` if the function is invoked asynchronously, `false` otherwise.
|
* @returns {boolean} `true` if the function is invoked asynchronously, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
function invokeMessageHandler({handler, async}, params, callback, ...extraArgs) {
|
function invokeMessageHandler({handler, async}, params, callback, ...extraArgs) {
|
||||||
try {
|
try {
|
||||||
@ -395,9 +396,9 @@ class EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers an event with the given name and specified argument.
|
* Triggers an event with the given name and specified argument.
|
||||||
* @param eventName The string representing the event's name.
|
* @param {string} eventName The string representing the event's name.
|
||||||
* @param details Optional; the argument passed to the callback functions.
|
* @param {*} [details] The argument passed to the callback functions.
|
||||||
* @returns `true` if any callbacks were registered, `false` otherwise.
|
* @returns {boolean} `true` if any callbacks were registered, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
trigger(eventName, details) {
|
trigger(eventName, details) {
|
||||||
const callbacks = this._eventMap.get(eventName);
|
const callbacks = this._eventMap.get(eventName);
|
||||||
@ -411,8 +412,8 @@ class EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a single event listener to a specific event.
|
* Adds a single event listener to a specific event.
|
||||||
* @param eventName The string representing the event's name.
|
* @param {string} eventName The string representing the event's name.
|
||||||
* @param callback The event listener callback to add.
|
* @param {function} callback The event listener callback to add.
|
||||||
*/
|
*/
|
||||||
on(eventName, callback) {
|
on(eventName, callback) {
|
||||||
let callbacks = this._eventMap.get(eventName);
|
let callbacks = this._eventMap.get(eventName);
|
||||||
@ -425,9 +426,9 @@ class EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a single event listener from a specific event.
|
* Removes a single event listener from a specific event.
|
||||||
* @param eventName The string representing the event's name.
|
* @param {string} eventName The string representing the event's name.
|
||||||
* @param callback The event listener callback to add.
|
* @param {function} callback The event listener callback to add.
|
||||||
* @returns `true` if the callback was removed, `false` otherwise.
|
* @returns {boolean} `true` if the callback was removed, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
off(eventName, callback) {
|
off(eventName, callback) {
|
||||||
const callbacks = this._eventMap.get(eventName);
|
const callbacks = this._eventMap.get(eventName);
|
||||||
@ -448,8 +449,8 @@ class EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an event has any listeners.
|
* Checks if an event has any listeners.
|
||||||
* @param eventName The string representing the event's name.
|
* @param {string} eventName The string representing the event's name.
|
||||||
* @returns `true` if the event has listeners, `false` otherwise.
|
* @returns {boolean} `true` if the event has listeners, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
hasListeners(eventName) {
|
hasListeners(eventName) {
|
||||||
const callbacks = this._eventMap.get(eventName);
|
const callbacks = this._eventMap.get(eventName);
|
||||||
@ -470,7 +471,7 @@ class EventListenerCollection {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of event listeners that are currently in the object.
|
* Returns the number of event listeners that are currently in the object.
|
||||||
* @returns The number of event listeners that are currently in the object.
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
get size() {
|
get size() {
|
||||||
return this._eventListeners.length;
|
return this._eventListeners.length;
|
||||||
@ -478,9 +479,9 @@ class EventListenerCollection {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener of a generic type.
|
* Adds an event listener of a generic type.
|
||||||
* @param type The type of event listener, which can be 'addEventListener', 'addListener', or 'on'.
|
* @param {string} type The type of event listener, which can be 'addEventListener', 'addListener', or 'on'.
|
||||||
* @param object The object to add the event listener to.
|
* @param {object} object The object to add the event listener to.
|
||||||
* @param args The argument array passed to the object's event listener adding function.
|
* @param {...*} args The argument array passed to the object's event listener adding function.
|
||||||
* @throws An error if type is not an expected value.
|
* @throws An error if type is not an expected value.
|
||||||
*/
|
*/
|
||||||
addGeneric(type, object, ...args) {
|
addGeneric(type, object, ...args) {
|
||||||
@ -494,8 +495,8 @@ class EventListenerCollection {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener using `object.addEventListener`. The listener will later be removed using `object.removeEventListener`.
|
* Adds an event listener using `object.addEventListener`. The listener will later be removed using `object.removeEventListener`.
|
||||||
* @param object The object to add the event listener to.
|
* @param {object} object The object to add the event listener to.
|
||||||
* @param args The argument array passed to the `addEventListener`/`removeEventListener` functions.
|
* @param {...*} args The argument array passed to the `addEventListener`/`removeEventListener` functions.
|
||||||
*/
|
*/
|
||||||
addEventListener(object, ...args) {
|
addEventListener(object, ...args) {
|
||||||
object.addEventListener(...args);
|
object.addEventListener(...args);
|
||||||
@ -504,8 +505,8 @@ class EventListenerCollection {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener using `object.addListener`. The listener will later be removed using `object.removeListener`.
|
* Adds an event listener using `object.addListener`. The listener will later be removed using `object.removeListener`.
|
||||||
* @param object The object to add the event listener to.
|
* @param {object} object The object to add the event listener to.
|
||||||
* @param args The argument array passed to the `addListener`/`removeListener` function.
|
* @param {...*} args The argument array passed to the `addListener`/`removeListener` function.
|
||||||
*/
|
*/
|
||||||
addListener(object, ...args) {
|
addListener(object, ...args) {
|
||||||
object.addListener(...args);
|
object.addListener(...args);
|
||||||
@ -514,8 +515,8 @@ class EventListenerCollection {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event listener using `object.on`. The listener will later be removed using `object.off`.
|
* Adds an event listener using `object.on`. The listener will later be removed using `object.off`.
|
||||||
* @param object The object to add the event listener to.
|
* @param {object} object The object to add the event listener to.
|
||||||
* @param args The argument array passed to the `on`/`off` function.
|
* @param {...*} args The argument array passed to the `on`/`off` function.
|
||||||
*/
|
*/
|
||||||
on(object, ...args) {
|
on(object, ...args) {
|
||||||
object.on(...args);
|
object.on(...args);
|
||||||
@ -553,7 +554,7 @@ class EventListenerCollection {
|
|||||||
class DynamicProperty extends EventDispatcher {
|
class DynamicProperty extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* Creates a new instance with the specified value.
|
* Creates a new instance with the specified value.
|
||||||
* @param value The value to assign.
|
* @param {*} value The value to assign.
|
||||||
*/
|
*/
|
||||||
constructor(value) {
|
constructor(value) {
|
||||||
super();
|
super();
|
||||||
@ -565,6 +566,7 @@ class DynamicProperty extends EventDispatcher {
|
|||||||
/**
|
/**
|
||||||
* Gets the default value for the property, which is assigned to the
|
* Gets the default value for the property, which is assigned to the
|
||||||
* public value property when no overrides are present.
|
* public value property when no overrides are present.
|
||||||
|
* @type {*}
|
||||||
*/
|
*/
|
||||||
get defaultValue() {
|
get defaultValue() {
|
||||||
return this._defaultValue;
|
return this._defaultValue;
|
||||||
@ -574,7 +576,7 @@ class DynamicProperty extends EventDispatcher {
|
|||||||
* Assigns the default value for the property. If no overrides are present
|
* Assigns the default value for the property. If no overrides are present
|
||||||
* and if the value is different than the current default value,
|
* and if the value is different than the current default value,
|
||||||
* the 'change' event will be triggered.
|
* the 'change' event will be triggered.
|
||||||
* @param value The value to assign.
|
* @param {*} value The value to assign.
|
||||||
*/
|
*/
|
||||||
set defaultValue(value) {
|
set defaultValue(value) {
|
||||||
this._defaultValue = value;
|
this._defaultValue = value;
|
||||||
@ -583,6 +585,7 @@ class DynamicProperty extends EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current value for the property, taking any overrides into account.
|
* Gets the current value for the property, taking any overrides into account.
|
||||||
|
* @type {*}
|
||||||
*/
|
*/
|
||||||
get value() {
|
get value() {
|
||||||
return this._value;
|
return this._value;
|
||||||
@ -590,6 +593,7 @@ class DynamicProperty extends EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of overrides added to the property.
|
* Gets the number of overrides added to the property.
|
||||||
|
* @type {*}
|
||||||
*/
|
*/
|
||||||
get overrideCount() {
|
get overrideCount() {
|
||||||
return this._overrides.length;
|
return this._overrides.length;
|
||||||
@ -602,9 +606,9 @@ class DynamicProperty extends EventDispatcher {
|
|||||||
* If the newly added override has the highest priority of all overrides
|
* If the newly added override has the highest priority of all overrides
|
||||||
* and if the override value is different from the current value,
|
* and if the override value is different from the current value,
|
||||||
* the 'change' event will be fired.
|
* the 'change' event will be fired.
|
||||||
* @param value The override value to assign.
|
* @param {*} value The override value to assign.
|
||||||
* @param priority The priority value to use, as a number.
|
* @param {number} [priority] The priority value to use, as a number.
|
||||||
* @returns A string token which can be passed to the clearOverride function
|
* @returns {string} A string token which can be passed to the clearOverride function
|
||||||
* to remove the override.
|
* to remove the override.
|
||||||
*/
|
*/
|
||||||
setOverride(value, priority=0) {
|
setOverride(value, priority=0) {
|
||||||
@ -623,8 +627,8 @@ class DynamicProperty extends EventDispatcher {
|
|||||||
* Removes a specific override value. If the removed override
|
* Removes a specific override value. If the removed override
|
||||||
* had the highest priority, and the new value is different from
|
* had the highest priority, and the new value is different from
|
||||||
* the previous value, the 'change' event will be fired.
|
* the previous value, the 'change' event will be fired.
|
||||||
* @param token The token for the corresponding override which is to be removed.
|
* @param {string} token The token for the corresponding override which is to be removed.
|
||||||
* @returns true if an override was returned, false otherwise.
|
* @returns {boolean} `true` if an override was returned, `false` otherwise.
|
||||||
*/
|
*/
|
||||||
clearOverride(token) {
|
clearOverride(token) {
|
||||||
for (let i = 0, ii = this._overrides.length; i < ii; ++i) {
|
for (let i = 0, ii = this._overrides.length; i < ii; ++i) {
|
||||||
@ -670,10 +674,10 @@ class Logger extends EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a generic error. This will trigger the 'log' event with the same arguments as the function invocation.
|
* Logs a generic error. This will trigger the 'log' event with the same arguments as the function invocation.
|
||||||
* @param error The error to log. This is typically an `Error` or `Error`-like object.
|
* @param {Error|object|*} error The error to log. This is typically an `Error` or `Error`-like object.
|
||||||
* @param level The level to log at. Values include `'info'`, `'debug'`, `'warn'`, and `'error'`.
|
* @param {string} level The level to log at. Values include `'info'`, `'debug'`, `'warn'`, and `'error'`.
|
||||||
* Other values will be logged at a non-error level.
|
* Other values will be logged at a non-error level.
|
||||||
* @param context An optional context object for the error which should typically include a `url` field.
|
* @param {?object} [context] An optional context object for the error which should typically include a `url` field.
|
||||||
*/
|
*/
|
||||||
log(error, level, context=null) {
|
log(error, level, context=null) {
|
||||||
if (!isObject(context)) {
|
if (!isObject(context)) {
|
||||||
@ -735,8 +739,8 @@ class Logger extends EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs a warning. This function invokes `log` internally.
|
* Logs a warning. This function invokes `log` internally.
|
||||||
* @param error The error to log. This is typically an `Error` or `Error`-like object.
|
* @param {Error|object|*} error The error to log. This is typically an `Error` or `Error`-like object.
|
||||||
* @param context An optional context object for the error which should typically include a `url` field.
|
* @param {?object} context An optional context object for the error which should typically include a `url` field.
|
||||||
*/
|
*/
|
||||||
warn(error, context=null) {
|
warn(error, context=null) {
|
||||||
this.log(error, 'warn', context);
|
this.log(error, 'warn', context);
|
||||||
@ -744,8 +748,8 @@ class Logger extends EventDispatcher {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs an error. This function invokes `log` internally.
|
* Logs an error. This function invokes `log` internally.
|
||||||
* @param error The error to log. This is typically an `Error` or `Error`-like object.
|
* @param {Error|object|*} error The error to log. This is typically an `Error` or `Error`-like object.
|
||||||
* @param context An optional context object for the error which should typically include a `url` field.
|
* @param {?object} context An optional context object for the error which should typically include a `url` field.
|
||||||
*/
|
*/
|
||||||
error(error, context=null) {
|
error(error, context=null) {
|
||||||
this.log(error, 'error', context);
|
this.log(error, 'error', context);
|
||||||
|
@ -39,7 +39,13 @@ if ((() => {
|
|||||||
chrome = browser;
|
chrome = browser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Yomichan class is a core component through which various APIs are handled and invoked.
|
||||||
|
*/
|
||||||
class Yomichan extends EventDispatcher {
|
class Yomichan extends EventDispatcher {
|
||||||
|
/**
|
||||||
|
* Creates a new instance. The instance should not be used until it has been fully prepare()'d.
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -72,24 +78,44 @@ class Yomichan extends EventDispatcher {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public
|
/**
|
||||||
|
* Whether the current frame is the background page/service worker or not.
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
get isBackground() {
|
get isBackground() {
|
||||||
return this._isBackground;
|
return this._isBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the extension is unloaded.
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
get isExtensionUnloaded() {
|
get isExtensionUnloaded() {
|
||||||
return this._isExtensionUnloaded;
|
return this._isExtensionUnloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the API instance for communicating with the backend.
|
||||||
|
* This value will be null on the background page/service worker.
|
||||||
|
* @type {API}
|
||||||
|
*/
|
||||||
get api() {
|
get api() {
|
||||||
return this._api;
|
return this._api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the CrossFrameAPI instance for communicating with different frames.
|
||||||
|
* This value will be null on the background page/service worker.
|
||||||
|
* @type {CrossFrameAPI}
|
||||||
|
*/
|
||||||
get crossFrame() {
|
get crossFrame() {
|
||||||
return this._crossFrame;
|
return this._crossFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the instance for use.
|
||||||
|
* @param {boolean} [isBackground=false] Assigns whether this instance is being used from the background page/service worker.
|
||||||
|
*/
|
||||||
async prepare(isBackground=false) {
|
async prepare(isBackground=false) {
|
||||||
this._isBackground = isBackground;
|
this._isBackground = isBackground;
|
||||||
chrome.runtime.onMessage.addListener(this._onMessage.bind(this));
|
chrome.runtime.onMessage.addListener(this._onMessage.bind(this));
|
||||||
@ -107,11 +133,20 @@ class Yomichan extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message to the backend indicating that the frame is ready and all script
|
||||||
|
* setup has completed.
|
||||||
|
*/
|
||||||
ready() {
|
ready() {
|
||||||
this._isReady = true;
|
this._isReady = true;
|
||||||
this.sendMessage({action: 'yomichanReady'});
|
this.sendMessage({action: 'yomichanReady'});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether or not a URL is an extension URL.
|
||||||
|
* @param {string} url The URL to check.
|
||||||
|
* @returns true if the URL is an extension URL, false otherwise.
|
||||||
|
*/
|
||||||
isExtensionUrl(url) {
|
isExtensionUrl(url) {
|
||||||
try {
|
try {
|
||||||
return url.startsWith(chrome.runtime.getURL('/'));
|
return url.startsWith(chrome.runtime.getURL('/'));
|
||||||
@ -120,6 +155,11 @@ class Yomichan extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs chrome.runtime.sendMessage() with additional exception handling events.
|
||||||
|
* @param {...*} args The arguments to be passed to chrome.runtime.sendMessage().
|
||||||
|
* @returns {void} The result of the chrome.runtime.sendMessage() call.
|
||||||
|
*/
|
||||||
sendMessage(...args) {
|
sendMessage(...args) {
|
||||||
try {
|
try {
|
||||||
return chrome.runtime.sendMessage(...args);
|
return chrome.runtime.sendMessage(...args);
|
||||||
@ -129,6 +169,11 @@ class Yomichan extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs chrome.runtime.connect() with additional exception handling events.
|
||||||
|
* @param {...*} args The arguments to be passed to chrome.runtime.connect().
|
||||||
|
* @returns {Port} The resulting port.
|
||||||
|
*/
|
||||||
connect(...args) {
|
connect(...args) {
|
||||||
try {
|
try {
|
||||||
return chrome.runtime.connect(...args);
|
return chrome.runtime.connect(...args);
|
||||||
@ -138,6 +183,9 @@ class Yomichan extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs chrome.runtime.connect() with additional exception handling events.
|
||||||
|
*/
|
||||||
triggerExtensionUnloaded() {
|
triggerExtensionUnloaded() {
|
||||||
this._isExtensionUnloaded = true;
|
this._isExtensionUnloaded = true;
|
||||||
if (this._isTriggeringExtensionUnloaded) { return; }
|
if (this._isTriggeringExtensionUnloaded) { return; }
|
||||||
@ -200,4 +248,7 @@ class Yomichan extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default Yomichan class instance.
|
||||||
|
*/
|
||||||
const yomichan = new Yomichan();
|
const yomichan = new Yomichan();
|
||||||
|
Loading…
Reference in New Issue
Block a user