luciddom 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -5
- package/lucidDOM.js +797 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,9 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
LucidDOM.js is a lightweight browser-side DOM helper. It wraps a parent element and provides methods for creating elements, selecting descendants, updating content, handling events, applying inline styles, and removing elements.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### npm
|
|
8
|
+
|
|
9
|
+
Install LucidDOM from npm:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install luciddom
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Import the default export in your app. Use a bundler that resolves npm packages:
|
|
8
16
|
|
|
9
17
|
```html
|
|
10
18
|
<div id="app"></div>
|
|
@@ -13,7 +21,7 @@ Copy `lucidDOM.js` into your project and import its default export from a JavaSc
|
|
|
13
21
|
|
|
14
22
|
```js
|
|
15
23
|
// app.js
|
|
16
|
-
import LucidDOM from '
|
|
24
|
+
import LucidDOM from 'luciddom';
|
|
17
25
|
|
|
18
26
|
const app = new LucidDOM(document.querySelector('#app'));
|
|
19
27
|
|
|
@@ -26,6 +34,23 @@ const message = app.addElement({
|
|
|
26
34
|
message.styles({ color: 'darkslateblue', fontWeight: 'bold' });
|
|
27
35
|
```
|
|
28
36
|
|
|
37
|
+
### unpkg CDN
|
|
38
|
+
|
|
39
|
+
For a browser module without an npm install or bundler, import the package directly from unpkg:
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<div id="app"></div>
|
|
43
|
+
<script type="module">
|
|
44
|
+
import LucidDOM from 'https://unpkg.com/luciddom@1.0.1/lucidDOM.js';
|
|
45
|
+
|
|
46
|
+
const app = new LucidDOM(document.querySelector('#app'));
|
|
47
|
+
app.addElement({
|
|
48
|
+
tag: 'p',
|
|
49
|
+
value: 'Hello from LucidDOM!'
|
|
50
|
+
});
|
|
51
|
+
</script>
|
|
52
|
+
```
|
|
53
|
+
|
|
29
54
|
The constructor accepts a DOM element and scopes queries and element creation to it. If no parent is passed, it defaults to `document.body`.
|
|
30
55
|
|
|
31
56
|
## Common operations
|
|
@@ -114,14 +139,14 @@ When nothing matches, `current` is an empty NodeList and helper methods do nothi
|
|
|
114
139
|
|
|
115
140
|
## Build
|
|
116
141
|
|
|
117
|
-
The package includes an esbuild script to create a minified
|
|
142
|
+
The package includes an esbuild script to create a minified browser bundle:
|
|
118
143
|
|
|
119
144
|
```sh
|
|
120
145
|
npm install
|
|
121
146
|
npm run build
|
|
122
147
|
```
|
|
123
148
|
|
|
124
|
-
The output is written to `dist/
|
|
149
|
+
The output is written to `dist/luciddom.min.js`.
|
|
125
150
|
|
|
126
151
|
## Documentation
|
|
127
152
|
|
package/lucidDOM.js
ADDED
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A lightweight DOM helper that wraps a parent element and exposes fluent
|
|
3
|
+
* methods for creating, selecting, styling, and removing elements.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const app = new LucidDOM(document.querySelector('#root'));
|
|
7
|
+
*
|
|
8
|
+
* const header = app.select('header');
|
|
9
|
+
* header.update({ className: 'love' });
|
|
10
|
+
* header.styles({ backgroundColor: 'red' });
|
|
11
|
+
* header.on('click', () => console.log('clicked'));
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
class LucidDOM{
|
|
15
|
+
constructor(parent = document.querySelector('body')){
|
|
16
|
+
this.parent = parent;
|
|
17
|
+
this.element;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates an HTML element, applies attributes, appends it to the parent,
|
|
22
|
+
* and returns a small handle for interacting with the created element.
|
|
23
|
+
*
|
|
24
|
+
* @param {Object} options
|
|
25
|
+
* @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
|
|
26
|
+
* @param {string} [options.className] - Value for the element's `class` attribute.
|
|
27
|
+
* @param {string} [options.id] - Value for the element's `id` attribute.
|
|
28
|
+
* @param {string} [options.value] - Text content / value for the element.
|
|
29
|
+
* @param {string} [options.type] - `type` attribute (mainly for `<input>`).
|
|
30
|
+
* @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
|
|
31
|
+
* @param {string} [options.name] - `name` attribute.
|
|
32
|
+
* @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
|
|
33
|
+
* @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
|
|
34
|
+
* @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
|
|
35
|
+
* @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
|
|
36
|
+
* @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
|
|
37
|
+
* @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
|
|
38
|
+
* @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
|
|
39
|
+
* @param {string} [options.title] - `title` attribute.
|
|
40
|
+
* @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
|
|
41
|
+
*
|
|
42
|
+
* @returns {{
|
|
43
|
+
* on: (event?: string, callback?: (e: Event) => void) => void,
|
|
44
|
+
* addChildren: (attrs?: {
|
|
45
|
+
* className?: string,
|
|
46
|
+
* id?: string,
|
|
47
|
+
* value?: string,
|
|
48
|
+
* type?: string,
|
|
49
|
+
* placeholder?: string,
|
|
50
|
+
* name?: string,
|
|
51
|
+
* htmlFor?: string,
|
|
52
|
+
* formAction?: string,
|
|
53
|
+
* formMethod?: string,
|
|
54
|
+
* formTarget?: string,
|
|
55
|
+
* formEnctype?: string,
|
|
56
|
+
* formNoValidate?: boolean,
|
|
57
|
+
* ariaLabel?: string,
|
|
58
|
+
* title?: string,
|
|
59
|
+
* html?: string}),
|
|
60
|
+
* off: (event?: string, callback?: (e: Event) => void) => void,
|
|
61
|
+
* styles: (styles?: Partial<CSSStyleDeclaration>) => void,
|
|
62
|
+
* remove: () => void
|
|
63
|
+
* }} A handle exposing event, style, and removal helpers for the created element.
|
|
64
|
+
*
|
|
65
|
+
* @throws {Error} If element creation or attribute assignment fails
|
|
66
|
+
* (wraps a generic {@link DOMException}).
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* const div = app.addElement({
|
|
70
|
+
* tag: 'div',
|
|
71
|
+
* className: 'card',
|
|
72
|
+
* value: 'Hello',
|
|
73
|
+
* html: '<strong>Hello</strong>'
|
|
74
|
+
* });
|
|
75
|
+
* div.styles({ padding: '8px', backgroundColor: 'red' });
|
|
76
|
+
* div.on('click', () => console.log('clicked'));
|
|
77
|
+
*/
|
|
78
|
+
addElement({tag, className,id, value,type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html}){
|
|
79
|
+
|
|
80
|
+
try{
|
|
81
|
+
// ATTRIBUTES
|
|
82
|
+
this.element = document.createElement(tag);
|
|
83
|
+
className?this.element.className = className: '';
|
|
84
|
+
type?this.element.type = type: '';
|
|
85
|
+
value?this.element.innerText = value : '';
|
|
86
|
+
this.element.value = value;
|
|
87
|
+
id?this.element.id = id: '';
|
|
88
|
+
html?this.element.innerHTML = html: '';
|
|
89
|
+
placeholder? this.element.placeholder = placeholder: '';
|
|
90
|
+
this.element.name = name;
|
|
91
|
+
title?this.element.title = title: '';
|
|
92
|
+
ariaLabel?this.element.ariaLabel = ariaLabel: '';
|
|
93
|
+
this.element.htmlFor = htmlFor;
|
|
94
|
+
formAction?this.element.formAction = formAction: '';
|
|
95
|
+
formEnctype?this.element.formEnctype = formEnctype: '';
|
|
96
|
+
formMethod?this.element.formMethod =formMethod: '';
|
|
97
|
+
formTarget?this.element.formTarget = formTarget: '';
|
|
98
|
+
formNoValidate?this.element.formNoValidate =formNoValidate: '';
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
// APPENDING ELEMENT TO PARENT
|
|
104
|
+
this.parent.appendChild(this.element);
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
return{
|
|
109
|
+
on: (event = '', callback = () => {}) =>{
|
|
110
|
+
this.element.addEventListener(event, callback);
|
|
111
|
+
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
off: (event = '', callback = () => {}) => {
|
|
115
|
+
this.element.removeEventListener(event, callback)
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
styles : (styles = {}) => {
|
|
119
|
+
Object.assign(this.element.style, styles)
|
|
120
|
+
},
|
|
121
|
+
remove: ()=> {
|
|
122
|
+
this.element.remove();
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Creates an HTML element, applies attributes, appends it to the parent,
|
|
127
|
+
* and returns a small handle for interacting with the created element.
|
|
128
|
+
*
|
|
129
|
+
* @param {Object} options
|
|
130
|
+
* @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
|
|
131
|
+
* @param {string} [options.className] - Value for the element's `class` attribute.
|
|
132
|
+
* @param {string} [options.id] - Value for the element's `id` attribute.
|
|
133
|
+
* @param {string} [options.value] - Text content / value for the element.
|
|
134
|
+
* @param {string} [options.type] - `type` attribute (mainly for `<input>`).
|
|
135
|
+
* @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
|
|
136
|
+
* @param {string} [options.name] - `name` attribute.
|
|
137
|
+
* @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
|
|
138
|
+
* @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
|
|
139
|
+
* @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
|
|
140
|
+
* @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
|
|
141
|
+
* @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
|
|
142
|
+
* @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
|
|
143
|
+
* @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
|
|
144
|
+
* @param {string} [options.title] - `title` attribute.
|
|
145
|
+
* @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
|
|
146
|
+
*
|
|
147
|
+
* @returns {{
|
|
148
|
+
* on: (event?: string, callback?: (e: Event) => void) => void,
|
|
149
|
+
* off: (event?: string, callback?: (e: Event) => void) => void,
|
|
150
|
+
* styles: (styles?: Partial<CSSStyleDeclaration>) => void,
|
|
151
|
+
* remove: () => void
|
|
152
|
+
* }} A handle exposing event, style, and removal helpers for the created element.
|
|
153
|
+
*
|
|
154
|
+
* @throws {Error} If element creation or attribute assignment fails
|
|
155
|
+
* (wraps a generic {@link DOMException}).
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* const div = app.addElement({
|
|
159
|
+
* tag: 'div',
|
|
160
|
+
* className: 'card',
|
|
161
|
+
* value: 'Hello',
|
|
162
|
+
* html: '<strong>Hello</strong>'
|
|
163
|
+
* });
|
|
164
|
+
* div.styles({ padding: '8px', backgroundColor: 'red' });
|
|
165
|
+
* div.on('click', () => console.log('clicked'));
|
|
166
|
+
*/
|
|
167
|
+
addChildren: ({tag, className,id, value,type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html}) =>{
|
|
168
|
+
|
|
169
|
+
// ATTRIBUTES
|
|
170
|
+
let element;
|
|
171
|
+
element = document.createElement(tag);
|
|
172
|
+
className?element.className = className: '';
|
|
173
|
+
type?element.type = type: '';
|
|
174
|
+
value?element.innerText = value : '';
|
|
175
|
+
element.value = value;
|
|
176
|
+
id?element.id = id: '';
|
|
177
|
+
html?element.innerHTML = html: '';
|
|
178
|
+
placeholder? element.placeholder = placeholder: '';
|
|
179
|
+
element.name = name;
|
|
180
|
+
title?element.title = title: '';
|
|
181
|
+
ariaLabel?element.ariaLabel = ariaLabel: '';
|
|
182
|
+
this.element.htmlFor = htmlFor;
|
|
183
|
+
formAction?element.formAction = formAction: '';
|
|
184
|
+
formEnctype?element.formEnctype = formEnctype: '';
|
|
185
|
+
formMethod?element.formMethod =formMethod: '';
|
|
186
|
+
formTarget?element.formTarget = formTarget: '';
|
|
187
|
+
formNoValidate?element.formNoValidate =formNoValidate: '';
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
// APPENDING ELEMENT TO PARENT
|
|
193
|
+
this.element.appendChild(element);
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
return{
|
|
198
|
+
on: (event = '', callback = () => {}) =>{
|
|
199
|
+
this.element.addEventListener(event, callback);
|
|
200
|
+
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
off: (event = '', callback = () => {}) => {
|
|
204
|
+
this.element.removeEventListener(event, callback)
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
styles : (styles = {}) => {
|
|
208
|
+
Object.assign(this.element.style, styles)
|
|
209
|
+
},
|
|
210
|
+
remove: ()=> {
|
|
211
|
+
this.element.remove();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
}catch{
|
|
221
|
+
throw new Error(new DOMException);
|
|
222
|
+
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Attaches an event listener to the parent element.
|
|
230
|
+
*
|
|
231
|
+
* @param {string} [event=''] - Event type to listen for (e.g. 'click', 'input').
|
|
232
|
+
* @param {(e: Event) => void} [callback=() => {}] - Handler invoked when the event fires.
|
|
233
|
+
* @returns {void}
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* app.on('click', (e) => console.log('parent clicked'));
|
|
237
|
+
*/
|
|
238
|
+
on(event = '', callback = () => {}){
|
|
239
|
+
this.parent.addEventListener(event, callback)
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Removes a previously attached event listener from the parent element.
|
|
245
|
+
*
|
|
246
|
+
* @param {string} [event=''] - Event type the listener was registered for.
|
|
247
|
+
* @param {(e: Event) => void} [callback=() => {}] - The exact handler reference
|
|
248
|
+
* originally passed to `on`. Inline arrow functions cannot be removed.
|
|
249
|
+
* @returns {void}
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* const handler = () => console.log('clicked');
|
|
253
|
+
* app.on('click', handler);
|
|
254
|
+
* app.off('click', handler);
|
|
255
|
+
*/
|
|
256
|
+
off(event = '', callback = () => {}){
|
|
257
|
+
this.parent.removeEventListener(event, callback)
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Merges the given styles into the parent element's inline style.
|
|
262
|
+
*
|
|
263
|
+
* @param {Partial<CSSStyleDeclaration>} [styles={}] - Object of camelCased CSS
|
|
264
|
+
* properties and their values (e.g. `{ backgroundColor: 'red' }`).
|
|
265
|
+
* @returns {void}
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* app.styles({ width: '100vw', height: '2rem' });
|
|
269
|
+
*/
|
|
270
|
+
styles(styles = {}){
|
|
271
|
+
Object.assign(this.parent.style, styles)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @param {ClassAccessorDecoratorContext} [className={}]
|
|
277
|
+
*The addClass() method adds the given tokens to the list, omitting any that are already present.
|
|
278
|
+
MDN Reference
|
|
279
|
+
|
|
280
|
+
* @returns {void}
|
|
281
|
+
*/
|
|
282
|
+
addClass(className) {
|
|
283
|
+
this.element.classList.add(className);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @param {ClassAccessorDecoratorContext} [className={}]
|
|
288
|
+
*The removeClass() method removes the given tokens from the specified list.
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
* @returns {void}
|
|
292
|
+
*/
|
|
293
|
+
removeClass (className) {
|
|
294
|
+
this.element.classList.remove(className);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Element selector
|
|
298
|
+
/**
|
|
299
|
+
* Selects the first descendant of the parent matching `selector` and returns
|
|
300
|
+
* a handle for interacting with it.
|
|
301
|
+
*
|
|
302
|
+
* @param {string} selector - Any valid CSS selector (e.g. 'header', '.card', '#root').
|
|
303
|
+
* @returns {{
|
|
304
|
+
* current: Element | null,
|
|
305
|
+
* on: (event?: string, callback?: (e: Event) => void) => void,
|
|
306
|
+
* off: (event?: string, callback?: (e: Event) => void) => void,
|
|
307
|
+
* styles: (styles?: Partial<CSSStyleDeclaration>) => void,
|
|
308
|
+
* addChildren: (attrs?: {
|
|
309
|
+
* className?: string,
|
|
310
|
+
* id?: string,
|
|
311
|
+
* value?: string,
|
|
312
|
+
* type?: string,
|
|
313
|
+
* placeholder?: string,
|
|
314
|
+
* name?: string,
|
|
315
|
+
* htmlFor?: string,
|
|
316
|
+
* formAction?: string,
|
|
317
|
+
* formMethod?: string,
|
|
318
|
+
* formTarget?: string,
|
|
319
|
+
* formEnctype?: string,
|
|
320
|
+
* formNoValidate?: boolean,
|
|
321
|
+
* ariaLabel?: string,
|
|
322
|
+
* title?: string,
|
|
323
|
+
* html?: string}),
|
|
324
|
+
* remove: () => void,
|
|
325
|
+
* update: (attrs?: {
|
|
326
|
+
* className?: string,
|
|
327
|
+
* id?: string,
|
|
328
|
+
* value?: string,
|
|
329
|
+
* type?: string,
|
|
330
|
+
* placeholder?: string,
|
|
331
|
+
* name?: string,
|
|
332
|
+
* htmlFor?: string,
|
|
333
|
+
* formAction?: string,
|
|
334
|
+
* formMethod?: string,
|
|
335
|
+
* formTarget?: string,
|
|
336
|
+
* formEnctype?: string,
|
|
337
|
+
* formNoValidate?: boolean,
|
|
338
|
+
* ariaLabel?: string,
|
|
339
|
+
* title?: string,
|
|
340
|
+
* html?: string
|
|
341
|
+
* }) => void
|
|
342
|
+
* }} A wrapper around the matched element. `current` is `null` if nothing matched.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* const header = app.select('header');
|
|
346
|
+
* header.update({ className: 'love', id: 'hatred' });
|
|
347
|
+
* header.styles({ backgroundColor: 'red' });
|
|
348
|
+
* header.on('click', () => console.log('clicked'));
|
|
349
|
+
*/
|
|
350
|
+
select(selector){
|
|
351
|
+
const element = this.parent.querySelector(selector);
|
|
352
|
+
return {
|
|
353
|
+
// Element
|
|
354
|
+
current: element,
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Attaches an event listener to the matched element.
|
|
358
|
+
* @param {string} [event='']
|
|
359
|
+
* @param {(e: Event) => void} [callback=() => {}]
|
|
360
|
+
* @returns {void}
|
|
361
|
+
*/
|
|
362
|
+
on: (event = '', callback = () => {}) =>{
|
|
363
|
+
element.addEventListener(event, callback)
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Removes an event listener from the matched element.
|
|
368
|
+
* @param {string} [event='']
|
|
369
|
+
* @param {(e: Event) => void} [callback=() => {}]
|
|
370
|
+
* @returns {void}
|
|
371
|
+
*/
|
|
372
|
+
off: (event = '', callback = () => {}) => {
|
|
373
|
+
element.removeEventListener(event, callback)
|
|
374
|
+
},
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Merges styles into the matched element's inline style.
|
|
378
|
+
* @param {Partial<CSSStyleDeclaration>} [styles={}]
|
|
379
|
+
* @returns {void}
|
|
380
|
+
*/
|
|
381
|
+
styles : (styles = {}) => {
|
|
382
|
+
Object.assign(element.style, styles)
|
|
383
|
+
},
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Removes the matched element from the DOM.
|
|
387
|
+
* @returns {void}
|
|
388
|
+
*/
|
|
389
|
+
remove: ()=> {
|
|
390
|
+
element.remove();
|
|
391
|
+
},
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* @param {ClassAccessorDecoratorContext} [className={}]
|
|
395
|
+
*The addClass() method adds the given tokens to the list, omitting any that are already present.
|
|
396
|
+
MDN Reference
|
|
397
|
+
|
|
398
|
+
* @returns {void}
|
|
399
|
+
*/
|
|
400
|
+
addClass: (className) => {
|
|
401
|
+
element.classList.add(className);
|
|
402
|
+
},
|
|
403
|
+
/**
|
|
404
|
+
* @param {ClassAccessorDecoratorContext} [className={}]
|
|
405
|
+
*The removeClass() method removes the given tokens from the specified list.
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
* @returns {void}
|
|
409
|
+
*/
|
|
410
|
+
removeClass: (className) => {
|
|
411
|
+
element.classList.remove(className);
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Updates attributes and content on the matched element.
|
|
416
|
+
*
|
|
417
|
+
* @param {{
|
|
418
|
+
* className?: string,
|
|
419
|
+
* id?: string,
|
|
420
|
+
* value?: string,
|
|
421
|
+
* type?: string,
|
|
422
|
+
* placeholder?: string,
|
|
423
|
+
* name?: string,
|
|
424
|
+
* htmlFor?: string,
|
|
425
|
+
* formAction?: string,
|
|
426
|
+
* formMethod?: string,
|
|
427
|
+
* formTarget?: string,
|
|
428
|
+
* formEnctype?: string,
|
|
429
|
+
* formNoValidate?: boolean,
|
|
430
|
+
* ariaLabel?: string,
|
|
431
|
+
* title?: string,
|
|
432
|
+
* html?: string
|
|
433
|
+
* }} [attrs]
|
|
434
|
+
* @returns {void}
|
|
435
|
+
*/
|
|
436
|
+
update: ({ className,id, value,type, placeholder, name, htmlFor,formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title,html}) => {
|
|
437
|
+
className?element.className = className: '';
|
|
438
|
+
id?element.id= id: '';
|
|
439
|
+
value?element.value = value: '';
|
|
440
|
+
value?element.innerText = value : '';
|
|
441
|
+
type?element.type = type: '';
|
|
442
|
+
html?element.innerHTML = html: '';
|
|
443
|
+
placeholder? element.placeholder = placeholder: '';
|
|
444
|
+
element.name = name;
|
|
445
|
+
element.htmlFor = htmlFor;
|
|
446
|
+
formAction?element.formAction = formAction: '';
|
|
447
|
+
formEnctype?element.formEnctype = formEnctype: '';
|
|
448
|
+
formMethod?element.formMethod =formMethod: '';
|
|
449
|
+
formTarget?element.formTarget = formTarget: '';
|
|
450
|
+
formNoValidate?element.formNoValidate =formNoValidate: '';
|
|
451
|
+
title?element.title = title: '';
|
|
452
|
+
ariaLabel?element.ariaLabel = ariaLabel: '';
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Creates an HTML element, applies attributes, appends it to the parent,
|
|
457
|
+
* and returns a small handle for interacting with the created element.
|
|
458
|
+
*
|
|
459
|
+
* @param {Object} options
|
|
460
|
+
* @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
|
|
461
|
+
* @param {string} [options.className] - Value for the element's `class` attribute.
|
|
462
|
+
* @param {string} [options.id] - Value for the element's `id` attribute.
|
|
463
|
+
* @param {string} [options.value] - Text content / value for the element.
|
|
464
|
+
* @param {string} [options.type] - `type` attribute (mainly for `<input>`).
|
|
465
|
+
* @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
|
|
466
|
+
* @param {string} [options.name] - `name` attribute.
|
|
467
|
+
* @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
|
|
468
|
+
* @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
|
|
469
|
+
* @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
|
|
470
|
+
* @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
|
|
471
|
+
* @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
|
|
472
|
+
* @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
|
|
473
|
+
* @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
|
|
474
|
+
* @param {string} [options.title] - `title` attribute.
|
|
475
|
+
* @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
|
|
476
|
+
*
|
|
477
|
+
* @returns {{
|
|
478
|
+
* on: (event?: string, callback?: (e: Event) => void) => void,
|
|
479
|
+
* off: (event?: string, callback?: (e: Event) => void) => void,
|
|
480
|
+
* styles: (styles?: Partial<CSSStyleDeclaration>) => void,
|
|
481
|
+
* remove: () => void
|
|
482
|
+
* }} A handle exposing event, style, and removal helpers for the created element.
|
|
483
|
+
*
|
|
484
|
+
* @throws {Error} If element creation or attribute assignment fails
|
|
485
|
+
* (wraps a generic {@link DOMException}).
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* const div = app.addElement({
|
|
489
|
+
* tag: 'div',
|
|
490
|
+
* className: 'card',
|
|
491
|
+
* value: 'Hello',
|
|
492
|
+
* html: '<strong>Hello</strong>'
|
|
493
|
+
* });
|
|
494
|
+
* div.styles({ padding: '8px', backgroundColor: 'red' });
|
|
495
|
+
* div.on('click', () => console.log('clicked'));
|
|
496
|
+
*/
|
|
497
|
+
addChildren: ({tag, className,id, value,type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html}) =>{
|
|
498
|
+
try{
|
|
499
|
+
// ATTRIBUTES
|
|
500
|
+
this.element = document.createElement(tag);
|
|
501
|
+
className?this.element.className = className: '';
|
|
502
|
+
type?this.element.type = type: '';
|
|
503
|
+
value?this.element.innerText = value : '';
|
|
504
|
+
this.element.value = value;
|
|
505
|
+
id?this.element.id = id: '';
|
|
506
|
+
html?this.element.innerHTML = html: '';
|
|
507
|
+
placeholder? this.element.placeholder = placeholder: '';
|
|
508
|
+
this.element.name = name;
|
|
509
|
+
title?this.element.title = title: '';
|
|
510
|
+
ariaLabel?this.element.ariaLabel = ariaLabel: '';
|
|
511
|
+
this.element.htmlFor = htmlFor;
|
|
512
|
+
formAction?this.element.formAction = formAction: '';
|
|
513
|
+
formEnctype?this.element.formEnctype = formEnctype: '';
|
|
514
|
+
formMethod?this.element.formMethod =formMethod: '';
|
|
515
|
+
formTarget?this.element.formTarget = formTarget: '';
|
|
516
|
+
formNoValidate?this.element.formNoValidate =formNoValidate: '';
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
// APPENDING ELEMENT TO PARENT
|
|
522
|
+
element.appendChild(this.element);
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
return{
|
|
527
|
+
on: (event = '', callback = () => {}) =>{
|
|
528
|
+
this.element.addEventListener(event, callback);
|
|
529
|
+
|
|
530
|
+
},
|
|
531
|
+
|
|
532
|
+
off: (event = '', callback = () => {}) => {
|
|
533
|
+
this.element.removeEventListener(event, callback)
|
|
534
|
+
},
|
|
535
|
+
|
|
536
|
+
styles : (styles = {}) => {
|
|
537
|
+
Object.assign(this.element.style, styles)
|
|
538
|
+
},
|
|
539
|
+
remove: ()=> {
|
|
540
|
+
this.element.remove();
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
}catch{
|
|
546
|
+
throw new Error(new DOMException);
|
|
547
|
+
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
// Element selector bulk
|
|
555
|
+
/**
|
|
556
|
+
* Selects all descendants of the parent matching `selector` and returns a
|
|
557
|
+
* handle for interacting with the matched elements as a group.
|
|
558
|
+
*
|
|
559
|
+
* @param {string} selector - Any valid CSS selector (e.g. '.card', 'li', 'input[type="text"]').
|
|
560
|
+
* @returns {{
|
|
561
|
+
* current: NodeListOf<Element>,
|
|
562
|
+
* on: (event?: string, callback?: (e: Event) => void) => void,
|
|
563
|
+
* off: (event?: string, callback?: (e: Event) => void) => void,
|
|
564
|
+
* styles: (styles?: Partial<CSSStyleDeclaration>) => void,
|
|
565
|
+
* remove: () => void,
|
|
566
|
+
* addChildren: (attrs?: {
|
|
567
|
+
* className?: string,
|
|
568
|
+
* id?: string,
|
|
569
|
+
* value?: string,
|
|
570
|
+
* type?: string,
|
|
571
|
+
* placeholder?: string,
|
|
572
|
+
* name?: string,
|
|
573
|
+
* htmlFor?: string,
|
|
574
|
+
* formAction?: string,
|
|
575
|
+
* formMethod?: string,
|
|
576
|
+
* formTarget?: string,
|
|
577
|
+
* formEnctype?: string,
|
|
578
|
+
* formNoValidate?: boolean,
|
|
579
|
+
* ariaLabel?: string,
|
|
580
|
+
* title?: string,
|
|
581
|
+
* html?: string}),
|
|
582
|
+
* update: (attrs?: {
|
|
583
|
+
* className?: string,
|
|
584
|
+
* id?: string,
|
|
585
|
+
* value?: string,
|
|
586
|
+
* type?: string,
|
|
587
|
+
* placeholder?: string,
|
|
588
|
+
* name?: string,
|
|
589
|
+
* htmlFor?: string,
|
|
590
|
+
* formAction?: string,
|
|
591
|
+
* formMethod?: string,
|
|
592
|
+
* formTarget?: string,
|
|
593
|
+
* formEnctype?: string,
|
|
594
|
+
* formNoValidate?: boolean,
|
|
595
|
+
* ariaLabel?: string,
|
|
596
|
+
* title?: string,
|
|
597
|
+
* html?: string
|
|
598
|
+
* }) => void
|
|
599
|
+
* }} A wrapper around the matched elements. `current` is an empty `NodeList`
|
|
600
|
+
* if nothing matched.
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* const items = app.selectAll('.item');
|
|
604
|
+
* items.styles({ color: 'red' });
|
|
605
|
+
* items.on('click', (e) => console.log('clicked', e.currentTarget));
|
|
606
|
+
*/
|
|
607
|
+
selectAll(selector){
|
|
608
|
+
const elements = this.parent.querySelectorAll(selector);
|
|
609
|
+
return {
|
|
610
|
+
// Element
|
|
611
|
+
/** @type {NodeListOf<Element>} The matched elements (may be empty). */
|
|
612
|
+
current: elements,
|
|
613
|
+
/**
|
|
614
|
+
* Attaches an event listener to the matched elements.
|
|
615
|
+
* @param {string} [event='']
|
|
616
|
+
* @param {(e: Event) => void} [callback=() => {}]
|
|
617
|
+
* @returns {void}
|
|
618
|
+
*/
|
|
619
|
+
on: (event = '', callback = () => {}) =>{
|
|
620
|
+
elements.forEach((element) => element.addEventListener(event, callback));
|
|
621
|
+
},
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Removes an event listener from the matched elements.
|
|
625
|
+
* @param {string} [event='']
|
|
626
|
+
* @param {(e: Event) => void} [callback=() => {}]
|
|
627
|
+
* @returns {void}
|
|
628
|
+
*/
|
|
629
|
+
off: (event = '', callback = () => {}) => {
|
|
630
|
+
elements.forEach((element) => element.removeEventListener(event, callback));
|
|
631
|
+
},
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Merges styles into each matched element's inline style.
|
|
635
|
+
* @param {Partial<CSSStyleDeclaration>} [styles={}]
|
|
636
|
+
* @returns {void}
|
|
637
|
+
*/
|
|
638
|
+
styles : (styles = {}) => {
|
|
639
|
+
elements.forEach((element) => Object.assign(element.style, styles));
|
|
640
|
+
},
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Removes all matched elements from the DOM.
|
|
644
|
+
* @returns {void}
|
|
645
|
+
*/
|
|
646
|
+
remove: ()=> {
|
|
647
|
+
elements.forEach((element) => element.remove());
|
|
648
|
+
},
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* @param {ClassAccessorDecoratorContext} [className={}]
|
|
653
|
+
*The addClass() method adds the given tokens to the list, omitting any that are already present.
|
|
654
|
+
MDN Reference
|
|
655
|
+
|
|
656
|
+
* @returns {void}
|
|
657
|
+
*/
|
|
658
|
+
addClass: (className) => {
|
|
659
|
+
elements.forEach((element) => element.classList.add(className));
|
|
660
|
+
},
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* @param {ClassAccessorDecoratorContext} [className={}]
|
|
664
|
+
*The removeClass() method removes the given tokens from the specified list.
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
* @returns {void}
|
|
668
|
+
*/
|
|
669
|
+
removeClass: (className) => {
|
|
670
|
+
elements.forEach((element) => element.classList.remove(className));
|
|
671
|
+
},
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Updates attributes and content on each matched element.
|
|
675
|
+
*
|
|
676
|
+
* @param {{
|
|
677
|
+
* className?: string,
|
|
678
|
+
* id?: string,
|
|
679
|
+
* value?: string,
|
|
680
|
+
* type?: string,
|
|
681
|
+
* placeholder?: string,
|
|
682
|
+
* name?: string,
|
|
683
|
+
* htmlFor?: string,
|
|
684
|
+
* formAction?: string,
|
|
685
|
+
* formMethod?: string,
|
|
686
|
+
* formTarget?: string,
|
|
687
|
+
* formEnctype?: string,
|
|
688
|
+
* formNoValidate?: boolean,
|
|
689
|
+
* ariaLabel?: string,
|
|
690
|
+
* title?: string,
|
|
691
|
+
* html?: string
|
|
692
|
+
* }} [attrs]
|
|
693
|
+
* @returns {void}
|
|
694
|
+
*/
|
|
695
|
+
update: (attrs = {}) => {
|
|
696
|
+
const { className, id, value, type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html } = attrs;
|
|
697
|
+
elements.forEach((element) => {
|
|
698
|
+
if (className !== undefined) element.className = className;
|
|
699
|
+
if (id !== undefined) element.id = id;
|
|
700
|
+
if (value !== undefined) {
|
|
701
|
+
element.value = value;
|
|
702
|
+
element.innerText = value;
|
|
703
|
+
}
|
|
704
|
+
if (type !== undefined) element.type = type;
|
|
705
|
+
if (placeholder !== undefined) element.placeholder = placeholder;
|
|
706
|
+
if (name !== undefined) element.name = name;
|
|
707
|
+
if (html !== undefined) element.innerHTML = html;
|
|
708
|
+
if (htmlFor !== undefined) element.htmlFor = htmlFor;
|
|
709
|
+
if (formAction !== undefined) element.formAction = formAction;
|
|
710
|
+
if (formEnctype !== undefined) element.formEnctype = formEnctype;
|
|
711
|
+
if (formMethod !== undefined) element.formMethod = formMethod;
|
|
712
|
+
if (formTarget !== undefined) element.formTarget = formTarget;
|
|
713
|
+
if (formNoValidate !== undefined) element.formNoValidate = formNoValidate;
|
|
714
|
+
if (title !== undefined) element.title = title;
|
|
715
|
+
if (ariaLabel !== undefined) element.ariaLabel = ariaLabel;
|
|
716
|
+
});
|
|
717
|
+
},
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Creates an HTML element, applies attributes, appends it to the parent,
|
|
721
|
+
* and returns a small handle for interacting with the created element.
|
|
722
|
+
*
|
|
723
|
+
* @param {Object} options
|
|
724
|
+
* @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
|
|
725
|
+
* @param {string} [options.className] - Value for the element's `class` attribute.
|
|
726
|
+
* @param {string} [options.id] - Value for the element's `id` attribute.
|
|
727
|
+
* @param {string} [options.value] - Text content / value for the element.
|
|
728
|
+
* @param {string} [options.type] - `type` attribute (mainly for `<input>`).
|
|
729
|
+
* @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
|
|
730
|
+
* @param {string} [options.name] - `name` attribute.
|
|
731
|
+
* @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
|
|
732
|
+
* @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
|
|
733
|
+
* @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
|
|
734
|
+
* @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
|
|
735
|
+
* @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
|
|
736
|
+
* @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
|
|
737
|
+
* @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
|
|
738
|
+
* @param {string} [options.title] - `title` attribute.
|
|
739
|
+
* @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
|
|
740
|
+
*
|
|
741
|
+
* @returns {{
|
|
742
|
+
* on: (event?: string, callback?: (e: Event) => void) => void,
|
|
743
|
+
* off: (event?: string, callback?: (e: Event) => void) => void,
|
|
744
|
+
* styles: (styles?: Partial<CSSStyleDeclaration>) => void,
|
|
745
|
+
* remove: () => void
|
|
746
|
+
* }} A handle exposing event, style, and removal helpers for the created element.
|
|
747
|
+
*
|
|
748
|
+
* @throws {Error} If element creation or attribute assignment fails
|
|
749
|
+
* (wraps a generic {@link DOMException}).
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* const div = app.addElement({
|
|
753
|
+
* tag: 'div',
|
|
754
|
+
* className: 'card',
|
|
755
|
+
* value: 'Hello',
|
|
756
|
+
* html: '<strong>Hello</strong>'
|
|
757
|
+
* });
|
|
758
|
+
* div.styles({ padding: '8px', backgroundColor: 'red' });
|
|
759
|
+
* div.on('click', () => console.log('clicked'));
|
|
760
|
+
*/
|
|
761
|
+
addChildren: (attrs) => {
|
|
762
|
+
const children = [];
|
|
763
|
+
elements.forEach((parent) => {
|
|
764
|
+
const child = document.createElement(attrs.tag);
|
|
765
|
+
const { tag, className, id, value, type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html } = attrs;
|
|
766
|
+
if (className !== undefined) child.className = className;
|
|
767
|
+
if (id !== undefined) child.id = id;
|
|
768
|
+
if (value !== undefined) {
|
|
769
|
+
child.innerText = value;
|
|
770
|
+
child.value = value;
|
|
771
|
+
}
|
|
772
|
+
if (type !== undefined) child.type = type;
|
|
773
|
+
if (placeholder !== undefined) child.placeholder = placeholder;
|
|
774
|
+
if (name !== undefined) child.name = name;
|
|
775
|
+
if (htmlFor !== undefined) child.htmlFor = htmlFor;
|
|
776
|
+
if (formAction !== undefined) child.formAction = formAction;
|
|
777
|
+
if (formMethod !== undefined) child.formMethod = formMethod;
|
|
778
|
+
if (formTarget !== undefined) child.formTarget = formTarget;
|
|
779
|
+
if (formEnctype !== undefined) child.formEnctype = formEnctype;
|
|
780
|
+
if (formNoValidate !== undefined) child.formNoValidate = formNoValidate;
|
|
781
|
+
if (ariaLabel !== undefined) child.ariaLabel = ariaLabel;
|
|
782
|
+
if (title !== undefined) child.title = title;
|
|
783
|
+
if (html !== undefined) child.innerHTML = html;
|
|
784
|
+
|
|
785
|
+
parent.appendChild(child);
|
|
786
|
+
children.push(child);
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
return children;
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
export default LucidDOM
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "luciddom",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "LucidDOM.js is a lightweight browser-side DOM helper. It wraps a parent element and provides methods for creating elements, selecting descendants, updating content, handling events, applying inline styles, and removing elements.",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "lucidDOM.js",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"esbuild": "^0.28.2"
|
|
8
8
|
},
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
12
|
"build": "esbuild lucidDOM.js --bundle --minify --sourcemap --outfile=dist/luciddom.min.js"
|
|
13
13
|
},
|
|
14
|
-
"keywords": [],
|
|
15
|
-
"author": "",
|
|
14
|
+
"keywords": ["LucidDOM", "DOM helper", "Jquery", "DOM", "javascript", "js", "helper lib", "New Dom Helper", "2026"],
|
|
15
|
+
"author": "Prince B. Adu",
|
|
16
16
|
"license": "ISC",
|
|
17
17
|
"type": "module"
|
|
18
18
|
}
|