mirror of
https://codeberg.org/vlw/elevent.git
synced 2025-09-13 16:23:40 +02:00
Initial code commit
This commit is contained in:
parent
c602dbe39d
commit
6f254bf581
4 changed files with 147 additions and 0 deletions
16
.gitignore
vendored
Executable file
16
.gitignore
vendored
Executable file
|
@ -0,0 +1,16 @@
|
|||
# Bootstrapping #
|
||||
#################
|
||||
vendor
|
||||
.env.ini
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.directory
|
16
.npmignore
Normal file
16
.npmignore
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Bootstrapping #
|
||||
#################
|
||||
vendor
|
||||
.env.ini
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.directory
|
13
package.json
Normal file
13
package.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "elevent",
|
||||
"version": "1.1.2",
|
||||
"main": "src/Elevent.mjs",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": {
|
||||
"default": "./src/Elevent.mjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
102
src/Elevent.mjs
Normal file
102
src/Elevent.mjs
Normal file
|
@ -0,0 +1,102 @@
|
|||
export class Elevent {
|
||||
_type;
|
||||
_callback;
|
||||
_selector;
|
||||
|
||||
_boundElements = new WeakSet();
|
||||
_controller = new AbortController();
|
||||
_observer = new MutationObserver((mutations) => this.#mutationEvent(mutations));
|
||||
|
||||
/**
|
||||
* Create a new Elevent instance.
|
||||
* @param {string|null} eventType
|
||||
* @param {HTMLCollection|HTMLElement|string|null} target Strings will be treated as CSS selectors, null will create a template instance
|
||||
* @param {function} callback
|
||||
*/
|
||||
constructor(eventType = null, target = null, callback) {
|
||||
this._type = eventType;
|
||||
this._callback = callback;
|
||||
|
||||
if (target) {
|
||||
switch (target.constructor) {
|
||||
case HTMLCollection:
|
||||
this.#bindHTMLCollection(target);
|
||||
break;
|
||||
|
||||
case String:
|
||||
this._selector = target;
|
||||
this.#bindHTMLCollection(document.querySelectorAll(target));
|
||||
|
||||
// Automatically bind new DOM elements that match the provided CSS selector string
|
||||
this._observer.observe(document.body, {
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
if (target instanceof HTMLElement) {
|
||||
this.bind(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for this._observer
|
||||
* @param {array} mutations
|
||||
*/
|
||||
#mutationEvent(mutations) {
|
||||
// Iterate over all MutationRecords
|
||||
mutations.forEach(mutation => mutation.addedNodes.forEach(node => {
|
||||
// Bind new element if its CSS selector matches and has not already been bound
|
||||
if (node.matches(this._selector) && !this._boundElements.has(node)) {
|
||||
this.bind(node);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind all HTMLElements inside an HTMLCollection
|
||||
* @param {HTMLCollection} collection
|
||||
*/
|
||||
#bindHTMLCollection(collection) {
|
||||
[...collection].forEach(element => this.bind(element));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind an element to this instance.
|
||||
* @param {HTMLElement} target
|
||||
*/
|
||||
bind(target) {
|
||||
/**
|
||||
* Bind event listener of EventType on target element.
|
||||
* The instance provided callback will only be executed if the target element is present in the bound elements Set.
|
||||
*/
|
||||
target.addEventListener(this._type, (event) => this._boundElements.has(target) && this._callback(event, this), {
|
||||
signal: this._controller.signal
|
||||
});
|
||||
|
||||
this._boundElements.add(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all event listeners created from this instance.
|
||||
* @param {HTMLElement} [target=null] An optional HTMLElement can be provided to soft-remove a specific element.
|
||||
*/
|
||||
remove(target = null) {
|
||||
/**
|
||||
* Soft-remove a single element from the bound elements Set.
|
||||
* This will still trigger the event listener but the instance provided callback will not be executed.
|
||||
*/
|
||||
if (target) {
|
||||
this._boundElements.delete(target);
|
||||
return;
|
||||
}
|
||||
|
||||
this._controller.abort();
|
||||
this._observer.disconnect();
|
||||
|
||||
this._boundElements = new WeakSet();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue