Odoo18-Base/addons/html_editor/static/src/plugin.js
2025-01-06 10:57:38 +07:00

117 lines
3.4 KiB
JavaScript

import { isProtected, isProtecting, isUnprotecting } from "./utils/dom_info";
/**
* @typedef { import("./editor").Editor } Editor
* @typedef { import("./plugin_sets").SharedMethods } SharedMethods
*/
export class Plugin {
static id = "";
static dependencies = [];
static shared = [];
/**
* @param {Editor['document']} document
* @param {Editor['editable']} editable
* @param {SharedMethods} dependencies
* @param {import("./editor").EditorConfig} config
* @param {*} services
*/
constructor(document, editable, dependencies, config, services) {
/** @type { Document } **/
this.document = document;
/** @type { HTMLElement } **/
this.editable = editable;
/** @type { EditorConfig } **/
this.config = config;
this.services = services;
/** @type { SharedMethods } **/
this.dependencies = dependencies;
this._cleanups = [];
/**
* The resources aggregated from all the plugins by the editor.
*/
this._resources = null; // set before start
this.isDestroyed = false;
}
setup() {}
addDomListener(target, eventName, fn, capture) {
const handler = (ev) => {
if (
!isProtecting(ev.target) &&
(!isProtected(ev.target) || isUnprotecting(ev.target))
) {
fn?.call(this, ev);
}
};
target.addEventListener(eventName, handler, capture);
this._cleanups.push(() => target.removeEventListener(eventName, handler, capture));
}
/**
* @param {string} resourceId
* @returns {Array}
*/
getResource(resourceId) {
return this._resources[resourceId] || [];
}
/**
* Execute the functions registered under resourceId with the given
* arguments.
*
* This function is meant to enhance code readability by clearly expressing
* its intent.
*
* This function can be thought as an event dispatcher, calling the handlers
* with `args` as the payload.
*
* Example:
* ```js
* this.dispatchTo("my_event_handlers", arg1, arg2);
* ```
*
* @param {string} resourceId
* @param {...any} args The arguments to pass to the handlers.
*/
dispatchTo(resourceId, ...args) {
this.getResource(resourceId).forEach((handler) => handler(...args));
}
/**
* Execute a series of functions until one of them returns a truthy value.
*
* This function is meant to enhance code readability by clearly expressing
* its intent.
*
* A command "delegates" its execution to one of the overriding functions,
* which return a truthy value to signal it has been handled.
*
* It is the the caller's responsability to stop the execution when this
* function returns true.
*
* Example:
* ```js
* if (this.delegateTo("my_command_overrides", arg1, arg2)) {
* return;
* }
* ```
*
* @param {string} resourceId
* @param {...any} args The arguments to pass to the overrides.
* @returns {boolean} Whether one of the overrides returned a truthy value.
*/
delegateTo(resourceId, ...args) {
return this.getResource(resourceId).some((fn) => fn(...args));
}
destroy() {
for (const cleanup of this._cleanups) {
cleanup();
}
this.isDestroyed = true;
}
}