@nent/core
Version:
225 lines (219 loc) • 7.84 kB
JavaScript
/*!
* NENT 2022
*/
import { r as registerInstance, a as getElement } from './index-916ca544.js';
import { E as EventEmitter, a as actionBus, e as eventBus } from './index-f7016b94.js';
import { f as debugIf } from './logging-5a93c8af.js';
import { a as state, o as onChange } from './state-27a8a5bc.js';
import { r as resolveChildElementXAttributes } from './elements-1b845a48.js';
import { a as addDataProvider, r as removeDataProvider } from './factory-acbf0d3d.js';
import { D as DATA_EVENTS } from './interfaces-8c5cd1b8.js';
import { d as debounce } from './promises-584c4ece.js';
import './index-4bfabbbd.js';
import './expressions-2c27c47c.js';
import './tokens-78f8cdbe.js';
import './values-ddfac998.js';
import './strings-47d55561.js';
/* istanbul ignore file */
const ELEMENTS_TOPIC = 'elements';
var ELEMENTS_COMMANDS;
(function (ELEMENTS_COMMANDS) {
ELEMENTS_COMMANDS["toggleClass"] = "toggle-class";
ELEMENTS_COMMANDS["addClasses"] = "add-classes";
ELEMENTS_COMMANDS["removeClasses"] = "remove-classes";
ELEMENTS_COMMANDS["setAttribute"] = "set-attribute";
ELEMENTS_COMMANDS["removeAttribute"] = "remove-attribute";
ELEMENTS_COMMANDS["callMethod"] = "call-method";
})(ELEMENTS_COMMANDS || (ELEMENTS_COMMANDS = {}));
/* It listens for actions on the `ELEMENTS_TOPIC` topic and executes the corresponding command on the
element(s) specified by the `selector` property */
class ElementsActionListener {
constructor() {
this.changed = new EventEmitter();
}
/**
* It listens for events on the action bus, and when it receives one, it calls the `commandReceived`
* function
* @param {Window} win - Window - the window object of the browser
* @param {IEventEmitter} actionBus - This is the event bus that the extension listens to for
* commands from the extension.
* @param {IEventEmitter} eventBus - This is the event bus that the plugin is using to communicate
* with the rest of the application.
*/
initialize(win, actionBus, eventBus) {
this.body = win.document.body;
this.eventBus = eventBus;
this.actionsSubscription = actionBus.on(ELEMENTS_TOPIC, async (ev) => {
debugIf(state.debug, `elements-listener: action received ${ev.topic}:${ev.command}`);
await this.commandReceived(ev.command, ev.data);
this.changed.emit('changed');
});
}
async commandReceived(command, data) {
switch (command) {
case ELEMENTS_COMMANDS.toggleClass: {
this.toggleClass(data);
break;
}
case ELEMENTS_COMMANDS.addClasses: {
this.addClasses(data);
break;
}
case ELEMENTS_COMMANDS.removeClasses: {
this.removeClasses(data);
break;
}
case ELEMENTS_COMMANDS.setAttribute: {
this.setAttribute(data);
break;
}
case ELEMENTS_COMMANDS.removeAttribute: {
this.removeAttribute(data);
break;
}
case ELEMENTS_COMMANDS.callMethod: {
this.callMethod(data);
break;
}
}
}
toggleClass(args) {
const { selector, className } = args;
if (!className)
return;
const element = this.body.querySelector(selector);
if (element && className)
element.classList.toggle(className);
}
addClasses(args) {
const { selector, classes } = args;
if (!classes)
return;
const element = this.body.querySelector(selector);
if (element && classes)
classes.split(' ').forEach((c) => {
element.classList.add(c);
});
}
removeClasses(args) {
const { selector, classes } = args;
const element = this.body.querySelector(selector);
if (element && classes)
classes === null || classes === void 0 ? void 0 : classes.split(' ').forEach((c) => {
element === null || element === void 0 ? void 0 : element.classList.remove(c);
});
}
setAttribute(args) {
const { selector, attribute, value } = args;
if (!attribute)
return;
const element = this.body.querySelector(selector);
if (element && attribute)
element.setAttribute(attribute, value || '');
}
removeAttribute(args) {
const { selector, attribute } = args;
if (!attribute)
return;
const element = this.body.querySelector(selector);
if (element && attribute)
element === null || element === void 0 ? void 0 : element.removeAttribute(attribute);
}
callMethod(args) {
const { selector, method, data } = args;
if (!method)
return;
const element = this.body.querySelector(selector);
if (element) {
const elementMethod = element[method];
if (elementMethod && typeof element === 'function') {
elementMethod(data);
}
}
}
destroy() {
this.actionsSubscription();
}
}
/* It listens to changes in the DOM and emits a `changed` event when it detects a change */
class ElementsDataProvider {
/**
* A constructor function that takes in two parameters, a document and an elementListener. It then
* creates a new EventEmitter and assigns it to the changed property. It then creates a new variable
* called change and assigns it to a debounce function. The debounce function takes in three
* parameters, a number, a function, and a boolean. The function that is passed in as a parameter
* emits a DataChanged event. The listenerSubscription property is assigned to the
* elementListener.changed property and is passed in a function that calls the change function.
* @param {Document} doc - Document - this is the document object that is used to create the
* elements.
* @param {ElementsActionListener} elementListener - ElementsActionListener - this is the service
* that listens to the changes in the elements.
*/
constructor(doc, elementListener) {
this.doc = doc;
this.elementListener = elementListener;
this.changed = new EventEmitter();
const change = debounce(1000, () => {
this.changed.emit(DATA_EVENTS.DataChanged, {
provider: 'element',
});
}, true);
this.listenerSubscription = this.elementListener.changed.on('changed', () => {
change();
});
}
async get(key) {
const element = this.doc.querySelector('#' + key);
return (element === null || element === void 0 ? void 0 : element.value) || element.innerText || null;
}
/**
* The function unsubscribes from the listenerSubscription, which is a subscription to the listener
* function
*/
destroy() {
this.listenerSubscription();
}
}
const Elements = class {
constructor(hostRef) {
registerInstance(this, hostRef);
/**
* Turn on debug statements for load, update and render events.
*/
this.debug = false;
}
componentWillLoad() {
debugIf(this.debug, `n-elements: initialized`);
this.listener = new ElementsActionListener();
this.listener.initialize(window, actionBus, eventBus);
state.elementsEnabled = true;
if (state.dataEnabled) {
this.subscribeToDataEvents();
}
else {
const dispose = onChange('dataEnabled', (enabled) => {
if (enabled) {
this.subscribeToDataEvents();
}
dispose();
});
}
}
subscribeToDataEvents() {
this.dataSubscription = eventBus.on(DATA_EVENTS.DataChanged, () => {
debugIf(this.debug, `n-elements: data changed `);
resolveChildElementXAttributes(this.el.ownerDocument.body);
});
this.provider = new ElementsDataProvider(this.el.ownerDocument, this.listener);
addDataProvider('elements', this.provider);
}
disconnectedCallback() {
var _a;
this.listener.destroy();
state.elementsEnabled = false;
(_a = this.dataSubscription) === null || _a === void 0 ? void 0 : _a.call(this);
removeDataProvider('elements');
}
get el() { return getElement(this); }
};
export { Elements as n_elements };