luciddom 1.0.2 → 1.0.3
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/package.json +1 -1
- package/lucidDOM.js +0 -797
package/package.json
CHANGED
package/lucidDOM.js
DELETED
|
@@ -1,797 +0,0 @@
|
|
|
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
|