feature: client: dom: events: migrate to ESM

This commit is contained in:
coderiaser 2026-01-17 14:16:46 +02:00
parent a94fa0d465
commit 9cebb2416f
10 changed files with 215 additions and 213 deletions

View file

@ -1,198 +0,0 @@
'use strict';
const itype = require('itype');
const EventStore = require('./event-store');
module.exports = new EventsProto();
function EventsProto() {
const Events = this;
const getEventOptions = (eventName) => {
if (eventName !== 'touchstart')
return false;
return {
passive: true,
};
};
function parseArgs(eventName, element, listener, callback) {
let isFunc;
const args = [
eventName,
element,
listener,
callback,
];
const EVENT_NAME = 1;
const ELEMENT = 0;
const type = itype(eventName);
switch(type) {
default:
if (!type.endsWith('element'))
throw Error(`unknown eventName: ${type}`);
parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback);
break;
case 'string':
isFunc = itype.function(element);
if (isFunc) {
listener = element;
element = null;
}
if (!element)
element = window;
callback(element, [
eventName,
listener,
getEventOptions(eventName),
]);
break;
case 'array':
for (const name of eventName) {
parseArgs(name, element, listener, callback);
}
break;
case 'object':
for (const name of Object.keys(eventName)) {
const eventListener = eventName[name];
parseArgs(name, element, eventListener, callback);
}
break;
}
}
/**
* safe add event listener
*
* @param type
* @param element - document by default
* @param listener
*/
this.add = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
const [name, fn, options] = args;
element.addEventListener(name, fn, options);
EventStore.add(element, name, fn);
});
return Events;
};
/**
* safe add event listener
*
* @param type
* @param listener
* @param element - document by default
*/
this.addOnce = (type, element, listener) => {
const once = (event) => {
Events.remove(type, element, once);
listener(event);
};
if (!listener) {
listener = element;
element = null;
}
this.add(type, element, once);
return Events;
};
/**
* safe remove event listener
*
* @param type
* @param listener
* @param element - document by default
*/
this.remove = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
element.removeEventListener(...args);
});
return Events;
};
/**
* remove all added event listeners
*/
this.removeAll = () => {
const events = EventStore.get();
for (const [el, name, fn] of events)
el.removeEventListener(name, fn);
EventStore.clear();
};
/**
* safe add event keydown listener
*
* @param args
*/
this.addKey = function(...args) {
return Events.add('keydown', ...args);
};
/**
* safe remove event click listener
*
* @param args
*/
this.rmKey = function(...args) {
return Events.remove('keydown', ...args);
};
/**
* safe add event click listener
*/
this.addClick = function(...args) {
return Events.add('click', ...args);
};
/**
* safe remove event click listener
*/
this.rmClick = function(...args) {
return Events.remove('click', ...args);
};
this.addContextMenu = function(...args) {
return Events.add('contextmenu', ...args);
};
/**
* safe add load listener
*/
this.addLoad = function(...args) {
return Events.add('load', ...args);
};
function checkType(type) {
if (!type)
throw Error('type could not be empty!');
}
}

204
client/dom/events/index.mjs Normal file
View file

@ -0,0 +1,204 @@
import itype from 'itype';
import EventStore from './event-store.js';
/**
* safe add event listener
*
* @param type
* @param element - document by default
* @param listener
*/
export const add = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
const [name, fn, options] = args;
element.addEventListener(name, fn, options);
EventStore.add(element, name, fn);
});
return Events;
};
/**
* safe add event listener
*
* @param type
* @param listener
* @param element - document by default
*/
export const addOnce = (type, element, listener) => {
const once = (event) => {
Events.remove(type, element, once);
listener(event);
};
if (!listener) {
listener = element;
element = null;
}
add(type, element, once);
return Events;
};
/**
* safe remove event listener
*
* @param type
* @param listener
* @param element - document by default
*/
export const remove = (type, element, listener) => {
checkType(type);
parseArgs(type, element, listener, (element, args) => {
element.removeEventListener(...args);
});
return Events;
};
/**
* remove all added event listeners
*/
export const removeAll = () => {
const events = EventStore.get();
for (const [el, name, fn] of events)
el.removeEventListener(name, fn);
EventStore.clear();
};
/**
* safe add event keydown listener
*
* @param args
*/
export const addKey = function(...args) {
return add('keydown', ...args);
};
/**
* safe remove event click listener
*
* @param args
*/
export const rmKey = function(...args) {
return Events.remove('keydown', ...args);
};
/**
* safe add event click listener
*/
export const addClick = function(...args) {
return Events.add('click', ...args);
};
/**
* safe remove event click listener
*/
export const rmClick = function(...args) {
return remove('click', ...args);
};
export const addContextMenu = function(...args) {
return add('contextmenu', ...args);
};
/**
* safe add load listener
*/
export const addLoad = function(...args) {
return add('load', ...args);
};
function checkType(type) {
if (!type)
throw Error('type could not be empty!');
}
const getEventOptions = (eventName) => {
if (eventName !== 'touchstart')
return false;
return {
passive: true,
};
};
function parseArgs(eventName, element, listener, callback) {
let isFunc;
const args = [
eventName,
element,
listener,
callback,
];
const EVENT_NAME = 1;
const ELEMENT = 0;
const type = itype(eventName);
switch(type) {
default:
if (!type.endsWith('element'))
throw Error(`unknown eventName: ${type}`);
parseArgs(args[EVENT_NAME], args[ELEMENT], listener, callback);
break;
case 'string':
isFunc = itype.function(element);
if (isFunc) {
listener = element;
element = null;
}
if (!element)
element = window;
callback(element, [
eventName,
listener,
getEventOptions(eventName),
]);
break;
case 'array':
for (const name of eventName) {
parseArgs(name, element, listener, callback);
}
break;
case 'object':
for (const name of Object.keys(eventName)) {
const eventListener = eventName[name];
parseArgs(name, element, eventListener, callback);
}
break;
}
}
const Events = {
add,
addClick,
addContextMenu,
addKey,
addLoad,
addOnce,
remove,
removeAll,
rmClick,
rmKey,
};

View file

@ -33,7 +33,7 @@ module.exports = DOM;
DOM.uploadDirectory = require('./directory');
DOM.Buffer = require('./buffer');
DOM.Events = require('./events');
DOM.Events = require('./events/index.mjs');
const loadRemote = require('./load-remote');
const selectByPattern = require('./select-by-pattern');

View file

@ -5,7 +5,7 @@ const clipboard = require('@cloudcmd/clipboard');
const {fullstore} = require('fullstore');
const Buffer = require('../dom/buffer');
const Events = require('../dom/events');
const Events = require('../dom/events/index.mjs');
const KEY = require('./key');
const _vim = require('./vim');

View file

@ -11,6 +11,7 @@ const clipboard = require('@cloudcmd/clipboard');
const getRange = require('./get-range');
const uploadFiles = require('../dom/upload-files');
const {FS} = require('../../common/cloudfunc.mjs');
const Events = require('../dom/events/index.mjs');
const getIndex = currify(require('./get-index'));
@ -65,8 +66,6 @@ function header() {
return /^js-(left|right)$/.test(el.dataset.name);
};
const {Events} = DOM;
Events.addClick(fm, (event) => {
const el = event.target;
const parent = el.parentElement;
@ -103,7 +102,6 @@ async function config() {
}
module.exports.initKeysPanel = () => {
const {Events} = DOM;
const keysElement = DOM.getById('js-keyspanel');
if (!keysElement)
@ -150,7 +148,6 @@ const getPanel = (side) => {
};
module.exports.setOnPanel = (side) => {
const {Events} = DOM;
const panel = getPanel(side);
const filesElement = DOM.getByDataName('js-files', panel);
@ -380,7 +377,6 @@ function getFilesRange(from, to) {
}
function contextMenu() {
const {Events} = DOM;
const fm = DOM.getFM();
Events.addOnce('contextmenu', fm, (event) => {
@ -396,7 +392,6 @@ function contextMenu() {
}
function dragndrop() {
const {Events} = DOM;
const panels = DOM.getByClassAll('panel');
const select = ({target}) => {
target.classList.add('selected-panel');
@ -457,7 +452,7 @@ function dragndrop() {
}
function unload() {
DOM.Events.add(['unload', 'beforeunload'], (event) => {
Events.add(['unload', 'beforeunload'], (event) => {
const {Key} = CloudCmd;
const isBind = Key?.isBind();
@ -470,7 +465,7 @@ function unload() {
}
function pop() {
DOM.Events.add('popstate', async ({state}) => {
Events.add('popstate', async ({state}) => {
const path = (state || '').replace(FS, '');
if (!path)
@ -485,7 +480,7 @@ function pop() {
}
function resize() {
DOM.Events.add('resize', () => {
Events.add('resize', () => {
const Info = DOM.CurrentInfo;
const is = globalThis.innerWidth < CloudCmd.MIN_ONE_PANEL_WIDTH;

View file

@ -14,7 +14,7 @@ const createElement = require('@cloudcmd/create-element');
const input = require('./input');
const Images = require('../../dom/images');
const Events = require('../../dom/events');
const Events = require('../../dom/events/index.mjs');
const Files = require('../../dom/files');
const {getTitle} = require('../../../common/cloudfunc.mjs');

View file

@ -3,7 +3,7 @@
/* global CloudCmd */
CloudCmd.EditFileVim = exports;
const Events = require('../dom/events');
const Events = require('../dom/events/index.mjs');
const {Key} = CloudCmd;

View file

@ -3,7 +3,7 @@
/* global CloudCmd */
CloudCmd.EditNamesVim = exports;
const Events = require('../dom/events');
const Events = require('../dom/events/index.mjs');
const {Key} = CloudCmd;
const ConfigView = {

View file

@ -26,7 +26,7 @@ const {
} = require('./types');
const Files = require('../../dom/files');
const Events = require('../../dom/events');
const Events = require('../../dom/events/index.mjs');
const Images = require('../../dom/images');
const {encode} = require('../../../common/entity');