jj 0.1.1 → 2.1.0
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/LICENSE +21 -0
- package/README.md +36 -7
- package/lib/WC.d.ts +45 -0
- package/lib/WC.js +118 -0
- package/lib/WC.js.map +1 -0
- package/lib/WDF.d.ts +11 -0
- package/lib/WDF.js +31 -0
- package/lib/WDF.js.map +1 -0
- package/lib/WE.d.ts +43 -0
- package/lib/WE.js +133 -0
- package/lib/WE.js.map +1 -0
- package/lib/WHE.d.ts +21 -0
- package/lib/WHE.js +75 -0
- package/lib/WHE.js.map +1 -0
- package/lib/WN-mixin.d.ts +9 -0
- package/lib/WN-mixin.js +59 -0
- package/lib/WN-mixin.js.map +1 -0
- package/lib/WN.d.ts +34 -0
- package/lib/WN.js +145 -0
- package/lib/WN.js.map +1 -0
- package/lib/WSH.d.ts +11 -0
- package/lib/WSH.js +29 -0
- package/lib/WSH.js.map +1 -0
- package/lib/WT.d.ts +12 -0
- package/lib/WT.js +39 -0
- package/lib/WT.js.map +1 -0
- package/lib/bundle.js +706 -0
- package/lib/bundle.js.map +7 -0
- package/lib/bundle.min.js +2 -0
- package/lib/case.d.ts +3 -0
- package/lib/case.js +34 -0
- package/lib/case.js.map +1 -0
- package/lib/case.test.d.ts +1 -0
- package/lib/case.test.js +79 -0
- package/lib/case.test.js.map +1 -0
- package/lib/h.d.ts +3 -0
- package/lib/h.js +9 -0
- package/lib/h.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +12 -0
- package/lib/index.js.map +1 -0
- package/lib/util.d.ts +4 -0
- package/lib/util.js +11 -0
- package/lib/util.js.map +1 -0
- package/package.json +56 -26
- package/CSS.js +0 -145
- package/Router.js +0 -89
- package/Selector.js +0 -175
- package/Tag.js +0 -827
- package/control.js +0 -74
- package/dist/jj.js +0 -1580
- package/dist/jj.js.gz +0 -0
- package/dist/jj.min.js +0 -1
- package/dist/jj.min.js.gz +0 -0
- package/dist/jj.min.js.map +0 -1
- package/events.js +0 -16
- package/index.js +0 -26
- package/observer.js +0 -27
- package/rollup.config.js +0 -25
- package/unit.js +0 -78
- package/util.js +0 -153
- package/win.js +0 -11
package/dist/jj.js
DELETED
|
@@ -1,1580 +0,0 @@
|
|
|
1
|
-
const INDENT = ' ';
|
|
2
|
-
const NEWLINE = '\n';
|
|
3
|
-
|
|
4
|
-
function isArr(x) {
|
|
5
|
-
return Array.isArray(x)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function arrFrom(x) {
|
|
9
|
-
return Array.from(x)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function ind(indentation, addition = 0) {
|
|
13
|
-
if (indentation < 0) {
|
|
14
|
-
return ''
|
|
15
|
-
}
|
|
16
|
-
indentation += addition;
|
|
17
|
-
if (ind.cache[indentation] === undefined) {
|
|
18
|
-
ind.cache[indentation] = INDENT.repeat(indentation);
|
|
19
|
-
}
|
|
20
|
-
return ind.cache[indentation]
|
|
21
|
-
}
|
|
22
|
-
ind.cache = ['', INDENT];
|
|
23
|
-
|
|
24
|
-
function nl(indentation) {
|
|
25
|
-
return indentation < 0 ? '' : NEWLINE
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function mapKeyVal(obj, fn) {
|
|
29
|
-
return Object.entries(obj).map(([k, v]) => fn(k, v, obj))
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function isObj(a) {
|
|
33
|
-
return a && typeof a === 'object'
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function isStr(a, minLength = 0) {
|
|
37
|
-
return typeof a === 'string' && a.length >= minLength
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function isNum(a) {
|
|
41
|
-
return typeof a === 'number' && Number.isFinite(a)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function isFn(a) {
|
|
45
|
-
return typeof a === 'function'
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function camel2kebab(str) {
|
|
49
|
-
return str.replace(/([A-Z])/g, ch => '-' + ch.toLowerCase())
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function embed(start, end, ...contents) {
|
|
53
|
-
return start + contents.join('') + end
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function qut(...strArr) {
|
|
57
|
-
const str = strArr.join('').replace('"', '\\"');
|
|
58
|
-
return embed('"', '"', str)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function ent(entity) {
|
|
62
|
-
if (isStr(entity)) {
|
|
63
|
-
return '&' + entity + ';'
|
|
64
|
-
} else if (isNum(entity) && Number.isInteger(entity)) {
|
|
65
|
-
return `&#${entity};`
|
|
66
|
-
}
|
|
67
|
-
throw new TypeError(`Cannot make HTML entity from ${entity}`)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function sqBra(...strArr) {
|
|
71
|
-
return embed('[', ']', ...strArr)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function rnd(prefix) {
|
|
75
|
-
const randomStr = Math.random().toString(36).substr(2);
|
|
76
|
-
// the resulting string should always start with a letter, otherwise it won't work as class or id
|
|
77
|
-
return isStr(prefix) ? `${prefix}-${randomStr}` : randomStr
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function alias(obj, aliasDic) {
|
|
81
|
-
const prt = obj.prototype;
|
|
82
|
-
|
|
83
|
-
function assignTarget(dst, src) {
|
|
84
|
-
if (prt[dst] !== undefined) {
|
|
85
|
-
throw new Error(`${obj.name} already has a method called ${dst}`)
|
|
86
|
-
}
|
|
87
|
-
prt[dst] = prt[src];
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
mapKeyVal(aliasDic, (src, dst) => {
|
|
91
|
-
if (isArr(dst)) {
|
|
92
|
-
dst.forEach(d => assignTarget(d, src));
|
|
93
|
-
} else {
|
|
94
|
-
assignTarget(dst, src);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const ranOnce = Symbol('ran once flag');
|
|
100
|
-
function runOnce(fn, ...args) {
|
|
101
|
-
if (isFn(fn) && !fn[ranOnce]) {
|
|
102
|
-
fn.apply(undefined, args);
|
|
103
|
-
fn[ranOnce] = true;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const doc = {
|
|
108
|
-
el(tagName, ns) {
|
|
109
|
-
return isStr(ns) ? document.createElementNS(ns, tagName) : document.createElement(tagName)
|
|
110
|
-
},
|
|
111
|
-
frag() {
|
|
112
|
-
return document.createDocumentFragment()
|
|
113
|
-
},
|
|
114
|
-
text(...strArr) {
|
|
115
|
-
return document.createTextNode(String(strArr.flat().join('')))
|
|
116
|
-
},
|
|
117
|
-
comm(...strArr) {
|
|
118
|
-
return document.createComment(String(strArr.flat().join('')))
|
|
119
|
-
},
|
|
120
|
-
get body() {
|
|
121
|
-
return document.body
|
|
122
|
-
},
|
|
123
|
-
get head() {
|
|
124
|
-
return document.body.head
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
function isComponent(obj) {
|
|
129
|
-
return isObj(obj) && isObj(obj.root)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
class Dim {
|
|
133
|
-
constructor(value, unit) {
|
|
134
|
-
if (isStr(value)) {
|
|
135
|
-
this.parse(value);
|
|
136
|
-
} else {
|
|
137
|
-
this.value = value;
|
|
138
|
-
this.unit = unit;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
clone() {
|
|
143
|
-
return new Dim(this.value, this.unit)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
parse(str) {
|
|
147
|
-
const parts = str.match(/([-+]?[0-9.]+)([%\w]*)/);
|
|
148
|
-
if (parts) {
|
|
149
|
-
const [, value, unit] = parts;
|
|
150
|
-
this.value = value;
|
|
151
|
-
this.unit = unit;
|
|
152
|
-
}
|
|
153
|
-
throw new SyntaxError(`Could not parse ${str} as a CSS Dimention`)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
toString() {
|
|
157
|
-
return `${this.value}${this.unit}`
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
[Symbol.toPrimitive](hint) {
|
|
161
|
-
if (hint === 'string') {
|
|
162
|
-
return this.toString()
|
|
163
|
-
}
|
|
164
|
-
return this.value
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
alias(Dim, {
|
|
169
|
-
toString: 'toJSON'
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
function isDim(val) {
|
|
173
|
-
return val instanceof Dim
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function perc(num) {
|
|
177
|
-
return new Dim(num, '%')
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function em(num) {
|
|
181
|
-
return new Dim(num, 'em')
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function rem(num) {
|
|
185
|
-
return new Dim(num, 'rem')
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function px(num) {
|
|
189
|
-
return new Dim(num, 'px')
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function vh(num) {
|
|
193
|
-
return new Dim(num, 'vh')
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function vw(num) {
|
|
197
|
-
return new Dim(num, 'vw')
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function col(r, g, b, a) {
|
|
201
|
-
if (g === undefined && b === undefined && a === undefined) {
|
|
202
|
-
if (isStr(r, 1)) {
|
|
203
|
-
return `#${r}`
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
throw new Error('TODO: Use case not implemented yet')
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
class Selector {
|
|
210
|
-
constructor(selector = '') {
|
|
211
|
-
this.selector = selector;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
toString() {
|
|
215
|
-
return this.selector
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
css(ruleObj) {
|
|
219
|
-
return { [this.selector]: ruleObj }
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
clone() {
|
|
223
|
-
return new Selector(this.selector)
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
append(...str) {
|
|
227
|
-
if (str.length) {
|
|
228
|
-
this.selector += str.map(s => isSel(s) ? s.selector : s).join('');
|
|
229
|
-
}
|
|
230
|
-
return this
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
at(str) {
|
|
234
|
-
return this.append('@', str)
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
get _() {
|
|
238
|
-
return this.append(' ')
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// [attribute] [target] Selects all elements with a target attribute
|
|
242
|
-
// [attribute=value] [target=_blank] Selects all elements with target="_blank"
|
|
243
|
-
attr(attrName, attrValue) {
|
|
244
|
-
return attrValue === undefined ?
|
|
245
|
-
this.append(sqBra(attrName)) :
|
|
246
|
-
this.append(sqBra(attrName, '=', qut(attrValue)))
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// [attribute~=value] [title~=flower] Selects all elements with a title attribute containing the word "flower"
|
|
250
|
-
attrValArrContains(attrName, attrValue) {
|
|
251
|
-
return this.append(sqBra(attrName, '~=', qut(attrValue)))
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// [attribute^=value] a[href^="https"] Selects every <a> element whose href attribute value begins with "https"
|
|
255
|
-
attrValStartsWith(attrName, attrValue) {
|
|
256
|
-
return this.append(sqBra(attrName, '^=', qut(attrValue)))
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// [attribute$=value] a[href$=".pdf"] Selects every <a> element whose href attribute value ends with ".pdf"
|
|
260
|
-
attrValEndsWith(attrName, attrValue) {
|
|
261
|
-
return this.append(sqBra(attrName, '$=', qut(attrValue)))
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// [attribute*=value] a[href*="w3schools"] Selects every <a> element whose href attribute value contains the substring "w3schools"
|
|
265
|
-
attrValContains(attrName, attrValue) {
|
|
266
|
-
return this.append(sqBra(attrName, '*=', qut(attrValue)))
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
class(...classNames) {
|
|
270
|
-
classNames.forEach(c => this.append('.', c));
|
|
271
|
-
return this
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
BEM(block, element, modifier) {
|
|
275
|
-
this.B(block);
|
|
276
|
-
if (element !== undefined) {
|
|
277
|
-
this.E(element);
|
|
278
|
-
}
|
|
279
|
-
if (modifier !== undefined) {
|
|
280
|
-
this.M(modifier);
|
|
281
|
-
}
|
|
282
|
-
return this
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
E(element) {
|
|
286
|
-
return this.append('__', element)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
M(modifier) {
|
|
290
|
-
return this.append('--', modifier)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
id(idString) {
|
|
294
|
-
return this.append('#', idString)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
pClass(pseudo) {
|
|
298
|
-
return this.append(':', pseudo)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
pEl(pseudo) {
|
|
302
|
-
return this.append('::', pseudo)
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
par(...str) {
|
|
306
|
-
return this.append('(', ...str, ')')
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
prop(prop, val) {
|
|
310
|
-
return this.par(prop, ':', val)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
nthChild(str) {
|
|
314
|
-
return this.pClass(`nth-child(${str})`)
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
firstChild() {
|
|
318
|
-
return this.pClass(`first-child`)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
rnd(prefix = '') {
|
|
322
|
-
return this.append(rnd(prefix))
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
[Symbol.toPrimitive](hint) {
|
|
326
|
-
if (hint === 'string') {
|
|
327
|
-
return this.toString()
|
|
328
|
-
}
|
|
329
|
-
return this.value
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// B, E, M are for Block Element Modifier: http://getbem.com/introduction/
|
|
334
|
-
alias(Selector, {
|
|
335
|
-
class: 'B',
|
|
336
|
-
append: ['add', 'el', 'tag', 'com', 'cond', 'star', 'all', 'sel', 'concat'],
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
const shortHands = {
|
|
340
|
-
[Symbol.toPrimitive]: 'toString',
|
|
341
|
-
'>': ['gt', 'parentOf'],
|
|
342
|
-
'*': ['star', 'all'],
|
|
343
|
-
'~': ['tilde', 'precedes'],
|
|
344
|
-
'+': ['plus', 'followedBy'],
|
|
345
|
-
',': ['comma', 'or'],
|
|
346
|
-
// TODO: there's :not() pseudo-class as well and that one takes a selector
|
|
347
|
-
'not': ['not'],
|
|
348
|
-
'only': ['only'],
|
|
349
|
-
'and': ['and'],
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
mapKeyVal(shortHands, (str, vals) => {
|
|
353
|
-
vals.forEach(v => {
|
|
354
|
-
Selector.prototype[v] = function () {
|
|
355
|
-
return this.append(str)
|
|
356
|
-
};
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
function isSel(v) {
|
|
361
|
-
return v instanceof Selector
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
function _sel(param) {
|
|
365
|
-
if (isSel(param)) {
|
|
366
|
-
return param
|
|
367
|
-
}
|
|
368
|
-
return new Selector(param)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const sel = new Proxy(_sel, {
|
|
372
|
-
get(_sel, prop) {
|
|
373
|
-
const selector = new Selector();
|
|
374
|
-
if (prop in selector) {
|
|
375
|
-
return selector[prop]
|
|
376
|
-
} else {
|
|
377
|
-
selector.append(prop);
|
|
378
|
-
return selector
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
function parseRangeArguments(arr) {
|
|
384
|
-
if (arr.length < 2) {
|
|
385
|
-
throw new TypeError(`Expected at least 2 arguments but got ${arr}`)
|
|
386
|
-
}
|
|
387
|
-
if (!isNum(arr[0])) {
|
|
388
|
-
throw new TypeError(`The first argument must be a number but got ${arr[0]}`)
|
|
389
|
-
}
|
|
390
|
-
if (isFn(arr[1])) {
|
|
391
|
-
// range(end, fn, ...extraParams)
|
|
392
|
-
const [ end, fn, ...extraParams ] = arr;
|
|
393
|
-
return { start: 0, end, step: 1, fn, extraParams }
|
|
394
|
-
} else if (isFn(arr[2])) {
|
|
395
|
-
// range(start, end, fn, ...extraParams)
|
|
396
|
-
const [ start, end, fn, ...extraParams ] = arr;
|
|
397
|
-
return { start, end, step: 1, fn, extraParams }
|
|
398
|
-
} else if (isFn(arr[3])) {
|
|
399
|
-
// // range(start, end, step, fn, ...extraParams)
|
|
400
|
-
const [ start, end, step, fn, ...extraParams ] = arr;
|
|
401
|
-
return { start, end, step, fn, extraParams }
|
|
402
|
-
}
|
|
403
|
-
throw new TypeError(`Which function do you want to run? Got ${arr}`)
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const control = {
|
|
407
|
-
/**
|
|
408
|
-
* @remark if inside the function you need to refer to the tag (exposed as `this`), just remember
|
|
409
|
-
* to use a classic function instead of an arrow function
|
|
410
|
-
*/
|
|
411
|
-
if(condition, fn, ...extraParams) {
|
|
412
|
-
if (condition) {
|
|
413
|
-
return this.run(fn, ...extraParams)
|
|
414
|
-
}
|
|
415
|
-
return this
|
|
416
|
-
},
|
|
417
|
-
|
|
418
|
-
forEach(arr, fn, ...extraParams) {
|
|
419
|
-
arr.forEach(item => {
|
|
420
|
-
this.run(fn, item, ...extraParams);
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
return this
|
|
424
|
-
},
|
|
425
|
-
|
|
426
|
-
times(n, fn, ...extraParams) {
|
|
427
|
-
return this.range(1, n + 1, 1, fn, ...extraParams)
|
|
428
|
-
},
|
|
429
|
-
|
|
430
|
-
// range(start, end, step, fn, ...extraParams)
|
|
431
|
-
// range(start, end, fn, ...extraParams) // step = 1
|
|
432
|
-
// range(end, fn, ...extraParams) // start = 0, step = 1
|
|
433
|
-
range() {
|
|
434
|
-
const { start, end, step, fn, extraParams } = parseRangeArguments(Array.from(arguments));
|
|
435
|
-
if (!isNum(start) || !isNum(end) || !isNum(step)) {
|
|
436
|
-
throw new TypeError(`Expected numbers but got: start=${start}, end=${end}, step=${step}`)
|
|
437
|
-
}
|
|
438
|
-
if (step === 0) {
|
|
439
|
-
throw new Error(`The step cannot be zero`)
|
|
440
|
-
}
|
|
441
|
-
if ((start < end && step < 0) || (start > end && step > 0)) {
|
|
442
|
-
throw new Error(`This loop will never end: start=${start}, end=${end}, step=${step}`)
|
|
443
|
-
}
|
|
444
|
-
for (let i = start; i < end; i += step) {
|
|
445
|
-
this.run(fn, i, ...extraParams);
|
|
446
|
-
}
|
|
447
|
-
return this
|
|
448
|
-
},
|
|
449
|
-
|
|
450
|
-
run(fn, ...extraParams) {
|
|
451
|
-
fn.call(this, this, ...extraParams);
|
|
452
|
-
return this
|
|
453
|
-
},
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
const events = {
|
|
457
|
-
on(eventName, handler) {
|
|
458
|
-
this.el.addEventListener(eventName, handler);
|
|
459
|
-
return this
|
|
460
|
-
},
|
|
461
|
-
|
|
462
|
-
once(eventName, handler) {
|
|
463
|
-
this.el.addEventListener(eventName, handler, { once: true });
|
|
464
|
-
return this
|
|
465
|
-
},
|
|
466
|
-
|
|
467
|
-
off(eventName, handler) {
|
|
468
|
-
this.el.removeEventListener(eventName, handler);
|
|
469
|
-
return this
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
function isAtRule(selectorTxt) {
|
|
474
|
-
return selectorTxt.trimLeft().startsWith('@')
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function toValue(val) {
|
|
478
|
-
if (isStr(val)) {
|
|
479
|
-
if (val.trim() === '') {
|
|
480
|
-
return qut(val)
|
|
481
|
-
}
|
|
482
|
-
return val
|
|
483
|
-
}
|
|
484
|
-
if (isNum(val)) {
|
|
485
|
-
return String(val)
|
|
486
|
-
}
|
|
487
|
-
if (isDim(val)) {
|
|
488
|
-
return String(val)
|
|
489
|
-
} else if (isArr(val)) {
|
|
490
|
-
return val.join(' ')
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
function extractRules(selectorTxt, bodyObj) {
|
|
495
|
-
const baseRule = new SimpleRule(selectorTxt);
|
|
496
|
-
const ownProps = baseRule.bodyObj;
|
|
497
|
-
const nestedRules = [baseRule];
|
|
498
|
-
mapKeyVal(bodyObj, (key, val) => {
|
|
499
|
-
const v = toValue(val);
|
|
500
|
-
if (v !== undefined) {
|
|
501
|
-
ownProps[key] = v;
|
|
502
|
-
} else if (isAtRule(key)) {
|
|
503
|
-
nestedRules.push(new WrapperRule(key, { [selectorTxt]: val }));
|
|
504
|
-
} else {
|
|
505
|
-
let nestedSelectorTxt = key.replace(/&/g, selectorTxt);
|
|
506
|
-
if (nestedSelectorTxt === key) {
|
|
507
|
-
// No & was present, so the replacement didn't do anything. Nest the selectors
|
|
508
|
-
nestedSelectorTxt = selectorTxt + ' ' + key;
|
|
509
|
-
}
|
|
510
|
-
nestedRules.push(new NestedRule(nestedSelectorTxt, val));
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
return nestedRules
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function propVal(indentation, prop, val) {
|
|
517
|
-
const colon = indentation < 0 ? ':' : ': ';
|
|
518
|
-
return camel2kebab(prop)
|
|
519
|
-
+ colon
|
|
520
|
-
+ toValue(val)
|
|
521
|
-
+ ';'
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
class SimpleRule {
|
|
525
|
-
constructor(selectorTxt, bodyObj = {}) {
|
|
526
|
-
this.selectorTxt = selectorTxt;
|
|
527
|
-
this.bodyObj = bodyObj;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
get isEmpty() {
|
|
531
|
-
return Object.keys(this.bodyObj).length === 0
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
toString(indentation = 0) {
|
|
535
|
-
if (this.isEmpty) {
|
|
536
|
-
return indentation >= 0 ? ind(indentation) + `/* ${this.selectorTxt} {} */`: ''
|
|
537
|
-
}
|
|
538
|
-
let ret = ind(indentation) + this.selectorTxt;
|
|
539
|
-
if (indentation >= 0) {
|
|
540
|
-
ret += ' ';
|
|
541
|
-
}
|
|
542
|
-
ret += '{' + nl(indentation);
|
|
543
|
-
const space = ind(indentation, 1);
|
|
544
|
-
ret += mapKeyVal(this.bodyObj, (key, val) => space + propVal(indentation, key, val))
|
|
545
|
-
.join(nl(indentation));
|
|
546
|
-
if (indentation >= 0) {
|
|
547
|
-
ret += nl(indentation) + ind(indentation);
|
|
548
|
-
}
|
|
549
|
-
ret += '}';
|
|
550
|
-
return ret
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
class NestedRule {
|
|
555
|
-
constructor(selectorTxt, bodyObj) {
|
|
556
|
-
this.selectorTxt = selectorTxt;
|
|
557
|
-
this.bodyObj = bodyObj;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
toString(indentation = 0) {
|
|
561
|
-
if (isObj(this.bodyObj)) {
|
|
562
|
-
return extractRules(this.selectorTxt, this.bodyObj)
|
|
563
|
-
.map(rule => rule.toString(indentation))
|
|
564
|
-
.join(nl(indentation))
|
|
565
|
-
}
|
|
566
|
-
const v = toValue(this.bodyObj);
|
|
567
|
-
if (v !== undefined) {
|
|
568
|
-
return ind(indentation) + propVal(indentation, this.selectorTxt, v)
|
|
569
|
-
}
|
|
570
|
-
return ind(indentation) + this.selectorTxt
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
class WrapperRule {
|
|
575
|
-
constructor(selectorTxt, ruleSet) {
|
|
576
|
-
this.selectorTxt = selectorTxt;
|
|
577
|
-
this.ruleSet = ruleSet;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
toString(indentation = 0) {
|
|
581
|
-
let ret = ind(indentation) + this.selectorTxt;
|
|
582
|
-
if (isObj(this.ruleSet)) {
|
|
583
|
-
const childIndentation = indentation >= 0 ? indentation + 1 : -1;
|
|
584
|
-
if (indentation >= 0) {
|
|
585
|
-
ret += ' ';
|
|
586
|
-
}
|
|
587
|
-
ret += '{' + nl(indentation);
|
|
588
|
-
ret += objToRulesArr(this.ruleSet)
|
|
589
|
-
.map(rule => rule.toString(childIndentation))
|
|
590
|
-
.join(nl(indentation));
|
|
591
|
-
ret += nl(indentation);
|
|
592
|
-
ret += ind(indentation) + '}';
|
|
593
|
-
} else {
|
|
594
|
-
ret += ';';
|
|
595
|
-
}
|
|
596
|
-
return ret
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
function objToRulesArr(obj) {
|
|
601
|
-
if (!isObj(obj)){
|
|
602
|
-
if (isStr(obj)) {
|
|
603
|
-
obj = { [obj]: null };
|
|
604
|
-
} else {
|
|
605
|
-
throw new TypeError(`Invalid style descriptor: ${obj}`)
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
return mapKeyVal(obj, (selectorTxt, bodyObj) => {
|
|
609
|
-
if (isAtRule(selectorTxt)) {
|
|
610
|
-
return new WrapperRule(selectorTxt, bodyObj)
|
|
611
|
-
}
|
|
612
|
-
return new NestedRule(selectorTxt, bodyObj)
|
|
613
|
-
})
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
class Window {
|
|
617
|
-
constructor(windowRef) {
|
|
618
|
-
this.el = windowRef;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
Object.assign(Window.prototype, events);
|
|
623
|
-
|
|
624
|
-
const win = new Window(window);
|
|
625
|
-
|
|
626
|
-
function match(regexp, pathname) {
|
|
627
|
-
if(isStr(regexp)) {
|
|
628
|
-
console.log('boo', regexp, pathname);
|
|
629
|
-
return regexp === pathname
|
|
630
|
-
}
|
|
631
|
-
if (regexp instanceof RegExp) {
|
|
632
|
-
const parseResult = pathname.match(regexp);
|
|
633
|
-
return parseResult || false
|
|
634
|
-
}
|
|
635
|
-
throw new TypeError(`Invalid route regexp: ${regexp}`)
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
const rootRouterMap = new WeakMap();
|
|
639
|
-
|
|
640
|
-
class Router {
|
|
641
|
-
constructor(root) {
|
|
642
|
-
if (!isObj(root) || !isFn(root.run)) {
|
|
643
|
-
throw new Error(`Root must have a run method but got ${root}`)
|
|
644
|
-
}
|
|
645
|
-
this.routes = [];
|
|
646
|
-
this.root = root;
|
|
647
|
-
this.isMatched = false;
|
|
648
|
-
rootRouterMap.set(root, this);
|
|
649
|
-
|
|
650
|
-
const matchThis = (state) => this.runMatches(state);
|
|
651
|
-
win.on('popstate', matchThis).on('hashchange', matchThis);
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
addRoute(regexp, handler) {
|
|
655
|
-
if (isFn(this.defRouteHandler)) {
|
|
656
|
-
throw new Error(`Cannot add a route after the default route is set`)
|
|
657
|
-
}
|
|
658
|
-
if (!isFn(handler)) {
|
|
659
|
-
throw new TypeError(`Expected a route handler function but got ${handler}`)
|
|
660
|
-
}
|
|
661
|
-
const newRoute = { regexp, handler };
|
|
662
|
-
this.routes.push(newRoute);
|
|
663
|
-
if (!this.isMatched) {
|
|
664
|
-
this._runRoute(undefined, newRoute);
|
|
665
|
-
}
|
|
666
|
-
return this
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
addDefRoute(handler) {
|
|
670
|
-
if (isFn(this.defRouteHandler)) {
|
|
671
|
-
throw new Error(`There is already a default route handler`)
|
|
672
|
-
}
|
|
673
|
-
if (!isFn(handler)) {
|
|
674
|
-
throw new TypeError(`Expected a default route handler function but got ${handler}`)
|
|
675
|
-
}
|
|
676
|
-
this.defRouteHandler = handler;
|
|
677
|
-
if (!this.isMatched) {
|
|
678
|
-
this._runDefRoute();
|
|
679
|
-
}
|
|
680
|
-
return this
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
_runRoute(state, { regexp, handler}, pathname = window.location.pathname) {
|
|
684
|
-
const matchResult = match(regexp, pathname);
|
|
685
|
-
if (matchResult) {
|
|
686
|
-
this.isMatched = true;
|
|
687
|
-
this.root.run(handler, state, matchResult);
|
|
688
|
-
}
|
|
689
|
-
return !!matchResult
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
_runDefRoute() {
|
|
693
|
-
this.root.run(this.defRouteHandler);
|
|
694
|
-
return this
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
runMatches(state, pathname = window.location.pathname) {
|
|
698
|
-
const someRouteMatched = this.routes.some(route => this._runRoute(state, route, pathname));
|
|
699
|
-
if (!someRouteMatched) {
|
|
700
|
-
return this._runDefRoute()
|
|
701
|
-
}
|
|
702
|
-
return this
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
function router(root) {
|
|
707
|
-
if (!isObj(root) || !isFn(root.run)) {
|
|
708
|
-
throw new TypeError(`root should be a Tag instance. Got ${root}`)
|
|
709
|
-
}
|
|
710
|
-
return rootRouterMap.get(root) || new Router(root)
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
const HTTP_WWW_W3_ORG = 'http://www.w3.org/';
|
|
714
|
-
const SVG_NS = HTTP_WWW_W3_ORG + '2000/svg';
|
|
715
|
-
const MATH_NS = HTTP_WWW_W3_ORG + '1998/mathml';
|
|
716
|
-
const jaTag = Symbol('jaTag');
|
|
717
|
-
|
|
718
|
-
const STYLE = 'style';
|
|
719
|
-
const HIDDEN = 'hidden';
|
|
720
|
-
const MOUSE = 'mouse';
|
|
721
|
-
|
|
722
|
-
class Node {
|
|
723
|
-
constructor(el) {
|
|
724
|
-
if (isObj(el) && Node.validNodeTypes.includes(el.nodeType)) {
|
|
725
|
-
this.el = el;
|
|
726
|
-
} else {
|
|
727
|
-
throw new TypeError(`Invalid parameter to Node constructor: ${el}`)
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
mount(rootTagOrEl) {
|
|
732
|
-
const root = toTag(rootTagOrEl);
|
|
733
|
-
return root.setChild(this)
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
addTo(targetElement) {
|
|
737
|
-
toTag(targetElement).append(this);
|
|
738
|
-
return this
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
addToHead() {
|
|
742
|
-
return this.appendTo(document.head)
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
addToBody() {
|
|
746
|
-
return this.appendTo(document.body)
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
preTo(targetElement) {
|
|
750
|
-
toTag(targetElement).prepend(this);
|
|
751
|
-
return this
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
addComment(str) {
|
|
755
|
-
this.append(doc.comm(str));
|
|
756
|
-
return this.norm()
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
preComment(str) {
|
|
760
|
-
this.prepend(doc.comm(str));
|
|
761
|
-
return this.norm()
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
//#region child
|
|
765
|
-
addChildren(...children) {
|
|
766
|
-
if (children.length) {
|
|
767
|
-
this.el.append(toNativeFrag(...children));
|
|
768
|
-
}
|
|
769
|
-
return this
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
preChildren(...children) {
|
|
773
|
-
if (children.length) {
|
|
774
|
-
this.el.prepend(toNativeFrag(...children));
|
|
775
|
-
}
|
|
776
|
-
return this
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
// TODO: Clean data and events
|
|
780
|
-
// https://github.com/jquery/jquery/blob/438b1a3e8a52d3e4efd8aba45498477038849c97/src/manipulation.js#L355
|
|
781
|
-
// https://github.com/jquery/jquery/blob/438b1a3e8a52d3e4efd8aba45498477038849c97/src/manipulation.js#L265
|
|
782
|
-
rmChildren(...children) {
|
|
783
|
-
if (children.length) {
|
|
784
|
-
children.map(child => toNativeEl(child)).forEach(nativeChild => this.el.removeChild(nativeChild));
|
|
785
|
-
} else {
|
|
786
|
-
while(this.el.firstChild){
|
|
787
|
-
this.el.removeChild(this.el.firstChild);
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
return this
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
setChildren(...children) {
|
|
794
|
-
this.empty().addChildren(...children);
|
|
795
|
-
return this
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
getChildren() {
|
|
799
|
-
return arrFrom(this.el.childNodes).map(childNode => toTag(childNode))
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
hasChildren(...children) {
|
|
803
|
-
if (children.length === 0) {
|
|
804
|
-
return this.el.hasChildren
|
|
805
|
-
}
|
|
806
|
-
return children.every(child => this.el.contains(toNativeEl(child)))
|
|
807
|
-
}
|
|
808
|
-
//#endregion child
|
|
809
|
-
|
|
810
|
-
//#region text
|
|
811
|
-
addText(...strings) {
|
|
812
|
-
strings.flat().forEach(str => this.append(doc.text(str)));
|
|
813
|
-
return this.norm()
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
preText(...strings) {
|
|
817
|
-
strings.flat().forEach(str => this.prepend(doc.text(str)));
|
|
818
|
-
return this.norm()
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
rmText() {
|
|
822
|
-
this.childNodes.filter(c => c instanceof Text).forEach(c => c.remove());
|
|
823
|
-
return this
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
setText(...strings) {
|
|
827
|
-
return this.rmText().addText(...strings)
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
json(obj) {
|
|
831
|
-
return this.setText(JSON.stringify(obj, null, 2))
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
getText() {
|
|
835
|
-
return this.childNodes.map(c => c instanceof Text ? c.wholeText : '').join('')
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
hasText() {
|
|
839
|
-
return this.childNodes.some(c => c instanceof Text)
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
normText() {
|
|
843
|
-
this.el.normalize();
|
|
844
|
-
return this
|
|
845
|
-
}
|
|
846
|
-
//#endregion text
|
|
847
|
-
|
|
848
|
-
//#region query
|
|
849
|
-
queryId(id) {
|
|
850
|
-
const result = this.el.getElementById(id);
|
|
851
|
-
if (result) {
|
|
852
|
-
return toTag(result)
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
query(selector) {
|
|
857
|
-
const result = this.el.querySelector(selector);
|
|
858
|
-
if (result) {
|
|
859
|
-
return toTag(result)
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
queryAll(selector) {
|
|
864
|
-
const result = arrFrom(this.el.querySelectorAll(selector));
|
|
865
|
-
if (result) {
|
|
866
|
-
return result.map(r => toTag(r))
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
//#endregion query
|
|
870
|
-
|
|
871
|
-
toString() {
|
|
872
|
-
return this.el.outerHTML
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
alias(Node, {
|
|
877
|
-
addTo: ['appendTo'],
|
|
878
|
-
addToHead: 'appendToHead',
|
|
879
|
-
addToBody: 'appendToBody',
|
|
880
|
-
addComment: 'comment',
|
|
881
|
-
preTo: ['prependTo'],
|
|
882
|
-
setChildren: ['setChild'],
|
|
883
|
-
addChildren: ['append', 'children', 'child', 'addChild'],
|
|
884
|
-
preChildren: ['prepend', 'prependChildren', 'prependChild'],
|
|
885
|
-
addText: ['text'],
|
|
886
|
-
normText: ['norm'],
|
|
887
|
-
rmChildren: ['empty', 'clear', 'rmChild'],
|
|
888
|
-
toString: 'stringify',
|
|
889
|
-
});
|
|
890
|
-
|
|
891
|
-
class Frag extends Node {
|
|
892
|
-
constructor() {
|
|
893
|
-
super(doc.frag());
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
clone(deep) {
|
|
897
|
-
return new Frag(this.el.cloneNode(deep))
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
function frag(...children) {
|
|
902
|
-
const ret = new Frag();
|
|
903
|
-
ret.append(children);
|
|
904
|
-
return ret
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
// See: https://developer.mozilla.org/en-US/docs/Web/API/Node
|
|
908
|
-
Node.validNodeTypes = [1, 9, 11];
|
|
909
|
-
|
|
910
|
-
class Tag extends Node {
|
|
911
|
-
constructor(x) {
|
|
912
|
-
// TODO if x is a Tag, we're essentially creating two tag objects pointing to the same native element!
|
|
913
|
-
super(x instanceof Tag ? x.el : x);
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
clone(deep) {
|
|
917
|
-
return new Tag(this.el.cloneNode(deep))
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
get parent() {
|
|
921
|
-
return toTag(this.el.parentElement)
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
get ns() {
|
|
925
|
-
return this.el.namespaceURI
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
get classList() {
|
|
929
|
-
return this.el.classList
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
get childNodes() {
|
|
933
|
-
return arrFrom(this.el.childNodes)
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
style(styles) {
|
|
937
|
-
if (isObj(styles)) {
|
|
938
|
-
mapKeyVal(styles, (k, v) => this.el.style[k] = v);
|
|
939
|
-
} else {
|
|
940
|
-
this.rmProp(STYLE);
|
|
941
|
-
}
|
|
942
|
-
return this
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
//#region class
|
|
946
|
-
setClasses(...classNames) {
|
|
947
|
-
this.el.className = classNames.join(' ');
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
getClass() {
|
|
951
|
-
return this.el.className
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
getClasses() {
|
|
955
|
-
return arrFrom(this.el.className)
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
hasClasses(...classNames) {
|
|
959
|
-
return classNames.every(className => this.classList.contains(className))
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
addClasses(...classNames) {
|
|
963
|
-
this.classList.add(...classNames);
|
|
964
|
-
return this
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
rmClasses(...classNames) {
|
|
968
|
-
this.classList.remove(...classNames);
|
|
969
|
-
return this
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
mvClass(oldClassName, newClassName) {
|
|
973
|
-
this.classList.replace(oldClassName, newClassName);
|
|
974
|
-
return this
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
mvClasses(classNamesDic) {
|
|
978
|
-
mapKeyVal(classNamesDic, (oldClassName, newClassName) => this.mvClass(oldClassName, newClassName));
|
|
979
|
-
return this
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
togClass(className, force) {
|
|
983
|
-
this.classList.toggle(className, force);
|
|
984
|
-
return this
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
togClassObj(classNameDic) {
|
|
988
|
-
mapKeyVal(classNameDic, (className, force) => this.togClass(className, force));
|
|
989
|
-
return this
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
togClasses(...classNames) {
|
|
993
|
-
classNames.forEach(className => this.togClass(className));
|
|
994
|
-
return this
|
|
995
|
-
}
|
|
996
|
-
//#endregion class
|
|
997
|
-
|
|
998
|
-
//#region attr
|
|
999
|
-
setAttr(attrName, attrValue) {
|
|
1000
|
-
if (attrName.toLowerCase() === STYLE) {
|
|
1001
|
-
return this.style(attrValue)
|
|
1002
|
-
}
|
|
1003
|
-
if (attrValue === undefined) {
|
|
1004
|
-
attrValue = '';
|
|
1005
|
-
}
|
|
1006
|
-
this.el.setAttribute(attrName, attrValue);
|
|
1007
|
-
return this
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
setAttrs(attrsDic) {
|
|
1011
|
-
if (!isObj(attrsDic)) {
|
|
1012
|
-
throw new TypeError(`Expected an object but got ${attrsDic}`)
|
|
1013
|
-
}
|
|
1014
|
-
mapKeyVal(attrsDic, (attrName, attrValue) => this.setAttr(attrName, attrValue));
|
|
1015
|
-
return this
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
getAttr(attrName) {
|
|
1019
|
-
return this.el.getAttribute(attrName)
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
getAttrs(...attrNames) {
|
|
1023
|
-
return Object.fromEntries(
|
|
1024
|
-
attrNames.map(attrName => [attrName, this.getAttr(attrName)])
|
|
1025
|
-
)
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
hasAttrs(...attrNames) {
|
|
1029
|
-
return attrNames.every(attrName => this.this.el.hasAttribute(attrName))
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
rmAttrs(...attrNames) {
|
|
1033
|
-
attrNames.forEach((attrName) => {
|
|
1034
|
-
this.el.removeAttribute(attrName);
|
|
1035
|
-
});
|
|
1036
|
-
return this
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
togAttr(attrName, force) {
|
|
1040
|
-
this.el.toggleAttribute(attrName, force);
|
|
1041
|
-
return this
|
|
1042
|
-
}
|
|
1043
|
-
//#endregion attr
|
|
1044
|
-
|
|
1045
|
-
//#region prop
|
|
1046
|
-
setProp(propName, propValue) {
|
|
1047
|
-
if (propName.toLowerCase() === STYLE) {
|
|
1048
|
-
return this.style(propValue)
|
|
1049
|
-
}
|
|
1050
|
-
this.el[propName] = propValue;
|
|
1051
|
-
return this
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
setPropsObj(propsDic) {
|
|
1055
|
-
mapKeyVal(propsDic, (propName, propValue) => this.setProp(propName, propValue));
|
|
1056
|
-
return this
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
getProp(propName) {
|
|
1060
|
-
return this.el[propName]
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
getPropsObj(...propNames) {
|
|
1064
|
-
return Object.fromEntries(
|
|
1065
|
-
propNames.map(propName => [propName, this.getProp(propName)])
|
|
1066
|
-
)
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
hasProps(...propNames) {
|
|
1070
|
-
return propNames.every(propName => propName in this.el)
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
rmProps(...propNames) {
|
|
1074
|
-
propNames.forEach((propName) => {
|
|
1075
|
-
try {
|
|
1076
|
-
delete this.el[propName];
|
|
1077
|
-
}
|
|
1078
|
-
catch (e) {
|
|
1079
|
-
this.el[propName] = undefined;
|
|
1080
|
-
}
|
|
1081
|
-
});
|
|
1082
|
-
return this
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
togProp(propName, force = false) {
|
|
1086
|
-
if (arguments.length === 2) {
|
|
1087
|
-
this.setProp(propName, !!force);
|
|
1088
|
-
} else {
|
|
1089
|
-
this.setProp(propName, !!this.getProp(propName));
|
|
1090
|
-
}
|
|
1091
|
-
return this
|
|
1092
|
-
}
|
|
1093
|
-
//#endregion prop
|
|
1094
|
-
|
|
1095
|
-
//#region data
|
|
1096
|
-
setData(name, value) {
|
|
1097
|
-
this.el.dataset[name] = value;
|
|
1098
|
-
return this
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
setDataObj(dataDic) {
|
|
1102
|
-
mapKeyVal(dataDic, (name, value) => this.setData(name, value));
|
|
1103
|
-
return this
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
getData(name) {
|
|
1107
|
-
return this.el.dataset[name]
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
getDataObj(...names) {
|
|
1111
|
-
return Object.fromEntries(names.map(name => [name, this.getData(name)]))
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
hasData(name) {
|
|
1115
|
-
return name in this.el.dataset
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
rmData(name) {
|
|
1119
|
-
return delete this.el.dataset[name]
|
|
1120
|
-
}
|
|
1121
|
-
//#endregion data
|
|
1122
|
-
|
|
1123
|
-
//#region visibility
|
|
1124
|
-
tog(show) {
|
|
1125
|
-
if (arguments.length === 1) {
|
|
1126
|
-
return this.togProp(HIDDEN, !show)
|
|
1127
|
-
}
|
|
1128
|
-
return this.togProp(HIDDEN)
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
hide() {
|
|
1132
|
-
return this.setProp(HIDDEN, false)
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
show() {
|
|
1136
|
-
return this.setProp(HIDDEN, true)
|
|
1137
|
-
}
|
|
1138
|
-
//#endregion visibility
|
|
1139
|
-
|
|
1140
|
-
//#region query
|
|
1141
|
-
closest(selector) {
|
|
1142
|
-
return this.el.closest(selector) || undefined
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
matches(selector) {
|
|
1146
|
-
return this.el.matches(selector)
|
|
1147
|
-
}
|
|
1148
|
-
//#endregion query
|
|
1149
|
-
|
|
1150
|
-
//#reguin animation
|
|
1151
|
-
animFrame(fn, ...extraParams) {
|
|
1152
|
-
// TODO we should throw if a loop is already running (or merge loops)
|
|
1153
|
-
const runFn = () => {
|
|
1154
|
-
if (this.isAttached()) {
|
|
1155
|
-
this.run(fn, ...extraParams);
|
|
1156
|
-
}
|
|
1157
|
-
scheduleCall();
|
|
1158
|
-
};
|
|
1159
|
-
|
|
1160
|
-
const scheduleCall = () => {
|
|
1161
|
-
this.animFrameRequestId = window.requestAnimationFrame(runFn);
|
|
1162
|
-
};
|
|
1163
|
-
|
|
1164
|
-
scheduleCall();
|
|
1165
|
-
return this
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
clearAnimFrame() {
|
|
1169
|
-
window.requestAnimationFrame(this.animFrameRequestId);
|
|
1170
|
-
return this
|
|
1171
|
-
}
|
|
1172
|
-
//#endregion animation
|
|
1173
|
-
|
|
1174
|
-
//#region routing
|
|
1175
|
-
route(regex, fn) {
|
|
1176
|
-
router(this).addRoute(regex, fn);
|
|
1177
|
-
return this
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
defRoute(fn) {
|
|
1181
|
-
router(this).addDefRoute(fn);
|
|
1182
|
-
return this
|
|
1183
|
-
}
|
|
1184
|
-
//#endregion routing
|
|
1185
|
-
|
|
1186
|
-
css(cssRef, prefix, styles) {
|
|
1187
|
-
if (styles === undefined) {
|
|
1188
|
-
styles = prefix;
|
|
1189
|
-
prefix = undefined;
|
|
1190
|
-
}
|
|
1191
|
-
if (!(cssRef instanceof StyleTag)) {
|
|
1192
|
-
throw new Error(`Expected an instance of StyleTag but got ${cssRef}`)
|
|
1193
|
-
}
|
|
1194
|
-
const rndClassName = rnd(prefix);
|
|
1195
|
-
this.addClass(rndClassName);
|
|
1196
|
-
cssRef.append(
|
|
1197
|
-
sel().class(rndClassName).css(styles)
|
|
1198
|
-
);
|
|
1199
|
-
return this
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
aria(noun, value) {
|
|
1203
|
-
return this.setAttr(`aria-${noun}`, value)
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
wrap(wrapper) {
|
|
1207
|
-
wrapper = toTag(wrapper);
|
|
1208
|
-
return wrapper.append(this)
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
swap(otherTag) {
|
|
1212
|
-
this.el.replaceWith(otherTag.el);
|
|
1213
|
-
return otherTag
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
isAttached() {
|
|
1217
|
-
return document.documentElement.contains(this.el)
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
queryId(id) {
|
|
1221
|
-
const result = this.el.querySelector('#' + id);
|
|
1222
|
-
if (result) {
|
|
1223
|
-
return toTag(result)
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
toString() {
|
|
1228
|
-
return this.el.outerHTML
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
Object.assign(Tag.prototype, control, events);
|
|
1233
|
-
|
|
1234
|
-
const attrShorthands = [
|
|
1235
|
-
'alt',
|
|
1236
|
-
'aria-role',
|
|
1237
|
-
'checked',
|
|
1238
|
-
'content',
|
|
1239
|
-
'height',
|
|
1240
|
-
HIDDEN,
|
|
1241
|
-
'href',
|
|
1242
|
-
'htmlFor',
|
|
1243
|
-
'id',
|
|
1244
|
-
'is',
|
|
1245
|
-
'label',
|
|
1246
|
-
'lang',
|
|
1247
|
-
'name',
|
|
1248
|
-
'placeholder',
|
|
1249
|
-
'readonly',
|
|
1250
|
-
'rel',
|
|
1251
|
-
'required',
|
|
1252
|
-
'role',
|
|
1253
|
-
'selected',
|
|
1254
|
-
'src',
|
|
1255
|
-
'title',
|
|
1256
|
-
'type',
|
|
1257
|
-
'value',
|
|
1258
|
-
'width',
|
|
1259
|
-
];
|
|
1260
|
-
|
|
1261
|
-
attrShorthands.forEach(attrName => {
|
|
1262
|
-
Tag.prototype[attrName] = function (attrValue) {
|
|
1263
|
-
return this.setAttr(attrName, attrValue)
|
|
1264
|
-
};
|
|
1265
|
-
});
|
|
1266
|
-
|
|
1267
|
-
const eventShorthands = [
|
|
1268
|
-
'attached',
|
|
1269
|
-
'blur',
|
|
1270
|
-
'change',
|
|
1271
|
-
'click',
|
|
1272
|
-
'contextmenu',
|
|
1273
|
-
'dblclick',
|
|
1274
|
-
'detached',
|
|
1275
|
-
'error',
|
|
1276
|
-
'focus',
|
|
1277
|
-
'focusout',
|
|
1278
|
-
'hover',
|
|
1279
|
-
'keydown',
|
|
1280
|
-
'keydpress',
|
|
1281
|
-
'keydup',
|
|
1282
|
-
'load',
|
|
1283
|
-
MOUSE + 'down',
|
|
1284
|
-
MOUSE + 'enter',
|
|
1285
|
-
MOUSE + 'leave',
|
|
1286
|
-
MOUSE + 'move',
|
|
1287
|
-
MOUSE + 'out',
|
|
1288
|
-
MOUSE + 'over',
|
|
1289
|
-
MOUSE + 'up',
|
|
1290
|
-
'resize',
|
|
1291
|
-
'scroll',
|
|
1292
|
-
'select',
|
|
1293
|
-
'submit',
|
|
1294
|
-
'unload',
|
|
1295
|
-
];
|
|
1296
|
-
|
|
1297
|
-
eventShorthands.forEach(eventName => {
|
|
1298
|
-
Tag.prototype[eventName] = function (...handlers) {
|
|
1299
|
-
this.on(eventName, ...handlers);
|
|
1300
|
-
return this
|
|
1301
|
-
};
|
|
1302
|
-
});
|
|
1303
|
-
|
|
1304
|
-
alias(Tag, {
|
|
1305
|
-
addClasses: ['addClass', 'class', 'classes'],
|
|
1306
|
-
class: 'className',
|
|
1307
|
-
hasClasses: 'hasClass',
|
|
1308
|
-
rmClasses: 'rmClass',
|
|
1309
|
-
setClasses: 'setClass',
|
|
1310
|
-
togClass: 'toggleClass',
|
|
1311
|
-
|
|
1312
|
-
hasAttrs: 'hasAttr',
|
|
1313
|
-
rmAttrs: 'rmAttr',
|
|
1314
|
-
setAttr: 'attr',
|
|
1315
|
-
setAttrs: 'attrs',
|
|
1316
|
-
togAttr: 'toggleAttr',
|
|
1317
|
-
|
|
1318
|
-
hasProps: 'hasProp',
|
|
1319
|
-
rmProps: 'rmProp',
|
|
1320
|
-
setProp: 'prop',
|
|
1321
|
-
setProps: 'props',
|
|
1322
|
-
|
|
1323
|
-
tog: 'toggle',
|
|
1324
|
-
swap: ['swapWith', 'replaceWith', 'replace'],
|
|
1325
|
-
|
|
1326
|
-
value: 'val',
|
|
1327
|
-
htmlFor: 'for',
|
|
1328
|
-
});
|
|
1329
|
-
|
|
1330
|
-
class StyleTag {
|
|
1331
|
-
constructor(...rulesetObjArr) {
|
|
1332
|
-
this.rulesetObjArr = rulesetObjArr;
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
|
-
get isAttached() {
|
|
1336
|
-
return this._root && this._root.isAttached()
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
get root() {
|
|
1340
|
-
if (!this._root) {
|
|
1341
|
-
this._root = html(STYLE)
|
|
1342
|
-
.type('text/css')
|
|
1343
|
-
.rel('stylesheet')
|
|
1344
|
-
.on('attached', () => this.update());
|
|
1345
|
-
}
|
|
1346
|
-
return this._root
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
appendToHead() {
|
|
1350
|
-
if (!document.head.contains(this.root.el)) {
|
|
1351
|
-
this.root.appendToHead();
|
|
1352
|
-
}
|
|
1353
|
-
return this
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
append(...rulesetObjArr) {
|
|
1357
|
-
if (rulesetObjArr.length) {
|
|
1358
|
-
rulesetObjArr.flat().forEach(r => this.rulesetObjArr.push(r));
|
|
1359
|
-
if (this.isAttached) {
|
|
1360
|
-
return this.update()
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
return this
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
get disabled() {
|
|
1367
|
-
return this.root.el.disabled
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
disable(isDisabled = true) {
|
|
1371
|
-
this.root.el.disabled = isDisabled;
|
|
1372
|
-
return this
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
enable(isEnabled = true) {
|
|
1376
|
-
return this.disable(!isEnabled)
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
title(tagTitle) {
|
|
1380
|
-
this.root.el.title = tagTitle;
|
|
1381
|
-
return this
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
|
-
rm() {
|
|
1385
|
-
this.root.rm();
|
|
1386
|
-
this._root = undefined;
|
|
1387
|
-
return this
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
minified(val) {
|
|
1391
|
-
this.minified = val;
|
|
1392
|
-
return this
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
toString(minified = this.minified) {
|
|
1396
|
-
const indentation = minified ? -1 : 0;
|
|
1397
|
-
const separator = nl(indentation);
|
|
1398
|
-
return this.rulesetObjArr
|
|
1399
|
-
.map(rule => objToRulesArr(rule)
|
|
1400
|
-
.map(rule => rule.toString(indentation))
|
|
1401
|
-
.join(separator)
|
|
1402
|
-
)
|
|
1403
|
-
.join(separator)
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
update() {
|
|
1407
|
-
const content = this.toString();
|
|
1408
|
-
// Only if successful, empty it
|
|
1409
|
-
this.root.setText(content);
|
|
1410
|
-
return this
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
function css(...rulesetObjArr) {
|
|
1415
|
-
return new StyleTag(...rulesetObjArr)
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
function toTag(x) {
|
|
1419
|
-
if (x instanceof Element) {
|
|
1420
|
-
return x[jaTag] || new Tag(x)
|
|
1421
|
-
}
|
|
1422
|
-
if (x instanceof Tag) {
|
|
1423
|
-
return x
|
|
1424
|
-
}
|
|
1425
|
-
if (isComponent(x)) {
|
|
1426
|
-
return toTag(x.root)
|
|
1427
|
-
}
|
|
1428
|
-
if (isTagObj(x)) {
|
|
1429
|
-
return objToTag(x)
|
|
1430
|
-
}
|
|
1431
|
-
throw new Error(`Invalid Tag or Element instance: ${x}`)
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
function isTagObj(x) {
|
|
1435
|
-
return isObj(x) && isStr(x.name)
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
function objToTag(x) {
|
|
1439
|
-
const { name, ns } = x;
|
|
1440
|
-
const el = doc.el(name, ns);
|
|
1441
|
-
const ret = new Tag(el);
|
|
1442
|
-
mapKeyVal(x, (method, param) => {
|
|
1443
|
-
if (method !== 'name' && method !== 'ns' && isFn(ret[method])) {
|
|
1444
|
-
if (isArr(param)) {
|
|
1445
|
-
ret[method](...param);
|
|
1446
|
-
} else {
|
|
1447
|
-
ret[method](param);
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
});
|
|
1451
|
-
return ret
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
function toNativeFrag(...xArr) {
|
|
1455
|
-
const ret = doc.frag();
|
|
1456
|
-
xArr.forEach(x => x !== undefined && ret.appendChild(toNative(x)));
|
|
1457
|
-
return ret
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
function toNativeEl(x) {
|
|
1461
|
-
if (arguments.length === 0 || x === undefined) {
|
|
1462
|
-
throw new TypeError(`Cannot convert ${x} to native DOM`)
|
|
1463
|
-
}
|
|
1464
|
-
if (x instanceof Element || x instanceof Text || x instanceof DocumentFragment || x instanceof Comment) {
|
|
1465
|
-
return x
|
|
1466
|
-
}
|
|
1467
|
-
if (x instanceof Tag || x instanceof Frag) {
|
|
1468
|
-
return x.el
|
|
1469
|
-
}
|
|
1470
|
-
if (isComponent(x)) {
|
|
1471
|
-
return toNativeEl(x.root)
|
|
1472
|
-
}
|
|
1473
|
-
if (isTagObj(x)) {
|
|
1474
|
-
return objToTag(x).el
|
|
1475
|
-
}
|
|
1476
|
-
// Whatever else will convert to a text node
|
|
1477
|
-
return doc.text(x)
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
|
-
function toNative(x) {
|
|
1481
|
-
if (isArr(x)) {
|
|
1482
|
-
return toNativeFrag(...x)
|
|
1483
|
-
}
|
|
1484
|
-
return toNativeEl(x)
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
function h(tagName, attrs, children) {
|
|
1488
|
-
return html(tagName).setAttrs(attrs).append(children)
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
function htmlTag(tagName = 'html') {
|
|
1492
|
-
return toTag(isStr(tagName) ? doc.el(tagName) : tagName)
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
function svgTag(tagName = 'svg') {
|
|
1496
|
-
return toTag(isStr(tagName) ? doc.el(tagName, SVG_NS) : tagName)
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
function mathMlTag(tagName = 'math') {
|
|
1500
|
-
return toTag(isStr(tagName) ? doc.el(tagName, MATH_NS) : tagName)
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
const sugarProxy = {
|
|
1504
|
-
get(target, tagName) {
|
|
1505
|
-
const tag = target(tagName);
|
|
1506
|
-
return function proxiedTag(...children) {
|
|
1507
|
-
return tag.append(...children)
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
};
|
|
1511
|
-
|
|
1512
|
-
const html = new Proxy(htmlTag, sugarProxy);
|
|
1513
|
-
const svg = new Proxy(svgTag, sugarProxy);
|
|
1514
|
-
const mathMl = new Proxy(mathMlTag, sugarProxy);
|
|
1515
|
-
|
|
1516
|
-
function queryId(elementId) {
|
|
1517
|
-
return toTag(document.getElementById(elementId))
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
function query(selector, root = document.body) {
|
|
1521
|
-
if (isSel(selector)) {
|
|
1522
|
-
selector = selector.selector;
|
|
1523
|
-
}
|
|
1524
|
-
return toTag(root).query(selector)
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
function queryAll(selector, root = document.body) {
|
|
1528
|
-
if (isSel(selector)) {
|
|
1529
|
-
selector = selector.selector;
|
|
1530
|
-
}
|
|
1531
|
-
return toTag(root).queryAll(selector)
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
// https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
|
|
1535
|
-
const attachedEvent = new Event('attached');
|
|
1536
|
-
const detachedEvent = new Event('detached');
|
|
1537
|
-
|
|
1538
|
-
function mutationObservationCb(mutationsList, observer) {
|
|
1539
|
-
for (var mutation of mutationsList) {
|
|
1540
|
-
if (mutation.type == 'childList') {
|
|
1541
|
-
mutation.addedNodes.forEach(n => n.dispatchEvent(attachedEvent));
|
|
1542
|
-
mutation.removedNodes.forEach(n => n.dispatchEvent(detachedEvent));
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
var mo;
|
|
1547
|
-
|
|
1548
|
-
function startObserving(observationRoot = document.documentElement) {
|
|
1549
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
|
|
1550
|
-
mo = new MutationObserver(mutationObservationCb);
|
|
1551
|
-
const config = { childList: true, subtree: true };
|
|
1552
|
-
mo.observe(observationRoot, config);
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
function stopObserving() {
|
|
1556
|
-
if (mo) {
|
|
1557
|
-
mo.disconnect();
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
const DOMContentLoaded = 'DOMContentLoaded';
|
|
1562
|
-
|
|
1563
|
-
function ready(fn) {
|
|
1564
|
-
const { document: { readyState } } = window;
|
|
1565
|
-
if (readyState === 'complete' || readyState === 'loaded' || readyState === 'interactive') {
|
|
1566
|
-
fn();
|
|
1567
|
-
} else {
|
|
1568
|
-
function onReady() {
|
|
1569
|
-
win.off(DOMContentLoaded, onReady);
|
|
1570
|
-
fn();
|
|
1571
|
-
}
|
|
1572
|
-
win.on(DOMContentLoaded, onReady);
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
win.on('unload', () => stopObserving());
|
|
1577
|
-
|
|
1578
|
-
ready(() => startObserving());
|
|
1579
|
-
|
|
1580
|
-
export { col, css, doc, em, ent, frag, h, html, isDim, isSel, mathMl, mathMlTag, perc, px, query, queryAll, queryId, qut, ready, rem, rnd, router, runOnce, sel, svg, svgTag, toTag, vh, vw };
|