@litejs/ui 25.10.0 → 26.2.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/README.md +14 -2
- package/load.js +13 -9
- package/package.json +3 -3
- package/shim.js +33 -20
- package/ui.js +52 -19
package/README.md
CHANGED
|
@@ -13,18 +13,30 @@ used on heavy-traffic websites since 2006.
|
|
|
13
13
|
|
|
14
14
|
- Dependency-free, weighs around 25kB (+8kB polyfills for old browsers).
|
|
15
15
|
- Written in ES5, compatible with all browsers (including IE5.5).
|
|
16
|
-
|
|
16
|
+
Works seamlessly in ESM projects too.
|
|
17
|
+
- No transpiling/compiling/bundling headache, just write working code.
|
|
18
|
+
|
|
19
|
+
Includes templates, view routing, data binding, i18n, keyboard shortcuts, and touch gestures.
|
|
17
20
|
|
|
18
21
|
For usage instructions, see [Quick-Start](https://github.com/litejs/litejs/wiki/Quick-Start) guide
|
|
19
22
|
and [wiki](https://github.com/litejs/ui/wiki).
|
|
20
23
|
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
- [Simplest example](https://litejs.github.io/ui/simplest.html) —
|
|
27
|
+
[source](/litejs/ui/blob/main/test/html/simplest.html)
|
|
28
|
+
- [Built-in routing](https://litejs.github.io/ui/routed.html) —
|
|
29
|
+
[source](/litejs/ui/blob/main/test/html/routed.html)
|
|
30
|
+
- [Full SVG SPA](https://litejs.github.io/ui/svg-spa.html) —
|
|
31
|
+
[source](/litejs/ui/blob/main/test/html/svg-spa.html)
|
|
32
|
+
|
|
21
33
|
|
|
22
34
|
## Contributing
|
|
23
35
|
|
|
24
36
|
Follow [Coding Style Guide](https://github.com/litejs/litejs/wiki/Style-Guide),
|
|
25
37
|
run tests `npm install; npm test`.
|
|
26
38
|
|
|
27
|
-
> Copyright (c) 2006-
|
|
39
|
+
> Copyright (c) 2006-2026 Lauri Rooden <lauri@rooden.ee>
|
|
28
40
|
[MIT License](https://litejs.com/MIT-LICENSE.txt) |
|
|
29
41
|
[GitHub repo](https://github.com/litejs/ui) |
|
|
30
42
|
[npm package](https://npmjs.org/package/@litejs/ui) |
|
package/load.js
CHANGED
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
/*** log ***/
|
|
57
57
|
, unsentLog = xhr._l = []
|
|
58
58
|
, lastError
|
|
59
|
+
// load.js is expected to be the first script to run and no prior window.onerror exists.
|
|
59
60
|
, onerror = window.onerror = function(message, file, line, col, error) {
|
|
60
61
|
// Do not send multiple copies of the same error.
|
|
61
62
|
// file = document.currentScript.src || import.meta.url
|
|
@@ -77,12 +78,14 @@
|
|
|
77
78
|
|
|
78
79
|
|
|
79
80
|
/*** theme ***/
|
|
81
|
+
, savedTheme
|
|
80
82
|
, ALT_THEME = "dark"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
try {
|
|
84
|
+
savedTheme = window.localStorage.theme
|
|
85
|
+
} catch(e){}
|
|
83
86
|
if (ALT_THEME == (
|
|
84
|
-
|
|
85
|
-
matchMedia &&
|
|
87
|
+
savedTheme ||
|
|
88
|
+
(savedTheme = window.matchMedia) && savedTheme("(prefers-color-scheme:dark)").matches && ALT_THEME
|
|
86
89
|
)) {
|
|
87
90
|
document.documentElement.className = "is-" + ALT_THEME
|
|
88
91
|
}
|
|
@@ -212,10 +215,7 @@
|
|
|
212
215
|
var execResult = (xhr[files[pos].replace(/[^?]+\.|\?.*/g, "")] || execScript)(res[pos], files[pos])
|
|
213
216
|
if (execResult && execResult.then) {
|
|
214
217
|
res[pos] = 0
|
|
215
|
-
return execResult.then(
|
|
216
|
-
res[pos] = ""
|
|
217
|
-
exec()
|
|
218
|
-
})
|
|
218
|
+
return execResult.then(advanceExec, advanceExec)
|
|
219
219
|
}
|
|
220
220
|
} catch(e) {
|
|
221
221
|
/*** log ***/
|
|
@@ -239,6 +239,11 @@
|
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
|
+
function advanceExec(err) {
|
|
243
|
+
if (err) onerror(err, files[pos])
|
|
244
|
+
res[pos] = ""
|
|
245
|
+
exec()
|
|
246
|
+
}
|
|
242
247
|
}
|
|
243
248
|
|
|
244
249
|
load([
|
|
@@ -247,4 +252,3 @@
|
|
|
247
252
|
/**/
|
|
248
253
|
|
|
249
254
|
}(this) // jshint ignore:line
|
|
250
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litejs/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "26.2.0",
|
|
4
4
|
"description": "UI engine for LiteJS full-stack framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lauri Rooden <lauri@rooden.ee>",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"lj-extract-lang": "./bin/extract-lang.js"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
-
"test": "lj t"
|
|
27
|
+
"test": "lj t test/index.js"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@litejs/cli": "
|
|
30
|
+
"@litejs/cli": "26.2.1"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/shim.js
CHANGED
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
/* global El, xhr, escape */
|
|
17
|
-
/* c8 ignore start */
|
|
18
17
|
!function(window, Date, Function, Infinity, P) {
|
|
19
18
|
|
|
20
19
|
// Array#flat() - Chrome69, Firefox62, Safari12
|
|
@@ -26,6 +25,7 @@
|
|
|
26
25
|
|
|
27
26
|
var UNDEF, canCapture, isArray, oKeys
|
|
28
27
|
, O = window
|
|
28
|
+
, NULL = null
|
|
29
29
|
, patched = (window.xhr || window)._p = []
|
|
30
30
|
, jsonRe = /[\x00-\x1f\x22\x5c]/g
|
|
31
31
|
, JSONmap = {"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\"":"\\\"","\\":"\\\\"}
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
, b = "setInterval"
|
|
50
50
|
, setInterval = (window[b] = window[b])
|
|
51
51
|
, c
|
|
52
|
+
/* node:coverage ignore next 19 */
|
|
52
53
|
, ie678 = !+"\v1" && a < 9 // jshint ignore:line
|
|
53
54
|
, ie6789 = ie678 || a == 9
|
|
54
55
|
, ie67 = ie678 && a < 8
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
wheel: wheelEv
|
|
72
73
|
}
|
|
73
74
|
, fixFn = Event.fixFn = {
|
|
75
|
+
/* node:coverage ignore next 17 */
|
|
74
76
|
wheel: wheelEv !== "wheel" && function(el, fn) {
|
|
75
77
|
// DOMMouseScroll Firefox 1 MouseScrollEvent.detail - number of lines to scroll (-32768/+32768 = page up/down)
|
|
76
78
|
return function(e) {
|
|
@@ -119,8 +121,9 @@
|
|
|
119
121
|
patch("cancel" + a, "clearTimeout(a)")
|
|
120
122
|
|
|
121
123
|
|
|
124
|
+
/* node:coverage ignore next 8 */
|
|
122
125
|
if (!IS_NODE && !(onhashchange in window) || ie67) {
|
|
123
|
-
patch(onhashchange,
|
|
126
|
+
patch(onhashchange, NULL)
|
|
124
127
|
setInterval(function() {
|
|
125
128
|
if (lastHash !== (lastHash = location.href.split("#")[1]) && isFn(window[onhashchange])) {
|
|
126
129
|
window[onhashchange]()
|
|
@@ -131,6 +134,7 @@
|
|
|
131
134
|
// Missing PointerEvents with Scribble enable on Safari 14
|
|
132
135
|
// https://mikepk.com/2020/10/iOS-safari-scribble-bug/
|
|
133
136
|
// https://bugs.webkit.org/show_bug.cgi?id=217430
|
|
137
|
+
/* node:coverage ignore next 50 */
|
|
134
138
|
if (!window.PointerEvent) {
|
|
135
139
|
// IE10
|
|
136
140
|
if (window[MS + EV]) {
|
|
@@ -176,6 +180,7 @@
|
|
|
176
180
|
}
|
|
177
181
|
_fn.call(el, e)
|
|
178
182
|
}
|
|
183
|
+
/* node:coverage ignore next 19 */
|
|
179
184
|
function touchToPointer(e) {
|
|
180
185
|
var touch
|
|
181
186
|
, touches = e.changedTouches
|
|
@@ -234,7 +239,7 @@
|
|
|
234
239
|
return (data[id] = "" + val)
|
|
235
240
|
},
|
|
236
241
|
getItem: function(id) {
|
|
237
|
-
return data[id]
|
|
242
|
+
return data[id] || NULL
|
|
238
243
|
},
|
|
239
244
|
removeItem: function(id) {
|
|
240
245
|
delete data[id]
|
|
@@ -270,7 +275,7 @@
|
|
|
270
275
|
// IE 8 serializes `undefined` as `"undefined"`
|
|
271
276
|
return (
|
|
272
277
|
isStr(o) ? "\"" + o.replace(jsonRe, jsonFn) + "\"" :
|
|
273
|
-
o !== o || o ==
|
|
278
|
+
o !== o || o == NULL || o === Infinity || o === -Infinity ? "null" :
|
|
274
279
|
typeof o == "object" ? (
|
|
275
280
|
isFn(o.toJSON) ? stringify(o.toJSON()) :
|
|
276
281
|
isArray(o) ? "[" + o.map(stringify) + "]" :
|
|
@@ -290,11 +295,14 @@
|
|
|
290
295
|
// Since Chrome23/Firefox21 parseInt parses leading-zero strings as decimal, not octal
|
|
291
296
|
b = patch("g:parseInt", "return X(a,(b>>>0)||(Y.test(''+a)?16:10))", _parseInt("08") !== 8, _parseInt, /^\s*[-+]?0[xX]/)
|
|
292
297
|
|
|
298
|
+
O = Math
|
|
299
|
+
patch("log10", "return X(a)/Y", 0, O.log, O.LN10)
|
|
300
|
+
|
|
301
|
+
a = O.pow
|
|
293
302
|
O = Number
|
|
294
303
|
patch("parseInt", b)
|
|
295
304
|
patch("parseFloat", parseFloat)
|
|
296
305
|
patch("isNaN", "return a!==a")
|
|
297
|
-
a = Math.pow
|
|
298
306
|
c = "_SAFE_INTEGER"
|
|
299
307
|
patch("EPSILON", a(2, -52))
|
|
300
308
|
patch(
|
|
@@ -310,6 +318,7 @@
|
|
|
310
318
|
O = O[P]
|
|
311
319
|
// IE8 toJSON does not return milliseconds
|
|
312
320
|
// FF37 returns invalid extended ISO-8601, `29349-01-26T00:00:00.000Z` instead of `+029349-01-26T00:00:00.000Z`
|
|
321
|
+
/* node:coverage ignore next */
|
|
313
322
|
b = O[a = "toISOString"] && new Date(8e14)[a]().length < 27 || ie678
|
|
314
323
|
patch(a, patch("toJSON", [
|
|
315
324
|
"a=t.getUTCFullYear();if(a!==a)throw RangeError('Invalid time');return(b=a<0?'-':a>9999?'+':'')+X(a<0?-a:a,'-',b?6:4", "Month()+1,'-'", "Date(),'T'",
|
|
@@ -352,7 +361,7 @@
|
|
|
352
361
|
|
|
353
362
|
// TODO:2021-02-25:lauri:Accept iterable objects
|
|
354
363
|
//patch("from", "a=S.call(a);return b?a.map(b,c):a")
|
|
355
|
-
patch("from", "a=X(a)?a.split(''):
|
|
364
|
+
patch("from", "a=X(a)?a.split(''):S.call(a);return b?a.map(b,c):a", 0, isStr)
|
|
356
365
|
patch("of", "return S.call(A)")
|
|
357
366
|
|
|
358
367
|
O = O[P]
|
|
@@ -406,9 +415,13 @@
|
|
|
406
415
|
patch("sendBeacon", function(url, data) {
|
|
407
416
|
// The synchronous XMLHttpRequest blocks the process of unloading the document,
|
|
408
417
|
// which in turn causes the next navigation appear to be slower.
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
418
|
+
try {
|
|
419
|
+
url = xhr("POST", url, xhr.unload)
|
|
420
|
+
url.setRequestHeader("Content-Type", "text/plain;charset=UTF-8")
|
|
421
|
+
url.send(data)
|
|
422
|
+
return true
|
|
423
|
+
} catch(e){}
|
|
424
|
+
return false
|
|
412
425
|
})
|
|
413
426
|
|
|
414
427
|
// The HTML5 document.head DOM tree accessor
|
|
@@ -441,8 +454,9 @@
|
|
|
441
454
|
, closest = patch("closest", walk.bind(window, "parentNode", 1))
|
|
442
455
|
, matches = patch("matches", "return!!X(a)(t)", 0, selectorFn)
|
|
443
456
|
|
|
457
|
+
/* node:coverage ignore next 13 */
|
|
444
458
|
try {
|
|
445
|
-
O[a = "addEventListener"]("t",
|
|
459
|
+
O[a = "addEventListener"]("t", NULL, Object.defineProperties({}, {
|
|
446
460
|
capture: { get: function() { canCapture = 1 } }
|
|
447
461
|
}))
|
|
448
462
|
b = "removeEventListener"
|
|
@@ -456,6 +470,7 @@
|
|
|
456
470
|
// https://developer.mozilla.org/en-US/docs/Web/Reference/Events/wheel
|
|
457
471
|
// - IE8 always prevents the default of the mousewheel event.
|
|
458
472
|
patch(a, "return(t.attachEvent('on'+a,b=X(t,a,b)),b)", 0, function(el, ev, fn) {
|
|
473
|
+
/* node:coverage ignore next 8 */
|
|
459
474
|
return function() {
|
|
460
475
|
var e = new Event(ev)
|
|
461
476
|
if (e.clientX !== UNDEF) {
|
|
@@ -474,8 +489,8 @@
|
|
|
474
489
|
|
|
475
490
|
|
|
476
491
|
function selectorFn(str) {
|
|
477
|
-
if (str
|
|
478
|
-
return selectorCache[str
|
|
492
|
+
if (!str || !isStr(str)) throw Error("Invalid selector")
|
|
493
|
+
return selectorCache[str] ||
|
|
479
494
|
(selectorCache[str] = Function("m,c", "return function(_,v,a,b){return " +
|
|
480
495
|
str.split(selectorSplitRe).map(function(sel) {
|
|
481
496
|
var relation, from
|
|
@@ -510,7 +525,7 @@
|
|
|
510
525
|
if (first) return el
|
|
511
526
|
out.push(el)
|
|
512
527
|
}
|
|
513
|
-
return first ?
|
|
528
|
+
return first ? NULL : out
|
|
514
529
|
}
|
|
515
530
|
|
|
516
531
|
function find(node, sel, first) {
|
|
@@ -523,6 +538,7 @@
|
|
|
523
538
|
|
|
524
539
|
// ie6789
|
|
525
540
|
// The documentMode is an IE only property, supported from IE8.
|
|
541
|
+
/* node:coverage ignore next 8 */
|
|
526
542
|
if (ie678) {
|
|
527
543
|
try {
|
|
528
544
|
// Remove background image flickers on hover in IE6
|
|
@@ -535,12 +551,13 @@
|
|
|
535
551
|
function isFn(value) {
|
|
536
552
|
return typeof value === "function"
|
|
537
553
|
}
|
|
538
|
-
|
|
539
|
-
return typeof value === "string"
|
|
540
|
-
}
|
|
554
|
+
/* node:coverage ignore next 3 */
|
|
541
555
|
function isObj(obj) {
|
|
542
556
|
return !!obj && obj.constructor === Object
|
|
543
557
|
}
|
|
558
|
+
function isStr(value) {
|
|
559
|
+
return typeof value === "string"
|
|
560
|
+
}
|
|
544
561
|
function nop() {}
|
|
545
562
|
|
|
546
563
|
function patch(key_, src, force, arg1, arg2) {
|
|
@@ -552,7 +569,3 @@
|
|
|
552
569
|
))
|
|
553
570
|
}
|
|
554
571
|
}(this, Date, Function, Infinity, "prototype") // jshint ignore:line
|
|
555
|
-
/* c8 ignore stop */
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
package/ui.js
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
/* global escape, navigator, xhr */
|
|
5
5
|
|
|
6
|
+
// Conditional compilation via toggle comments (processed by build tool):
|
|
7
|
+
// /*** name ***/ code /**/ - `code` active in source; build can strip it
|
|
8
|
+
// /*** name ***/ code1 /*/ code2 /**/ - `code1` active in source, `code2` commented out; build can swap
|
|
9
|
+
|
|
6
10
|
/*** debug ***/
|
|
7
11
|
console.log("LiteJS is in debug mode, but it's fine for production")
|
|
8
12
|
/**/
|
|
@@ -13,7 +17,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
13
17
|
|
|
14
18
|
var UNDEF, parser, pushBase, styleNode
|
|
15
19
|
, NUL = null
|
|
16
|
-
// THIS will be undefined in strict mode and window in sloppy mode
|
|
20
|
+
// THIS will be `undefined` in strict mode and `window` in sloppy mode
|
|
17
21
|
, THIS = this
|
|
18
22
|
, html = document.documentElement
|
|
19
23
|
, body = document.body
|
|
@@ -22,11 +26,13 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
22
26
|
, plugins = {}
|
|
23
27
|
, sources = []
|
|
24
28
|
, assign = Object.assign
|
|
29
|
+
// bind(fn, ctx, ...args)() calls fn.call(ctx, ...args); closureless partial application
|
|
25
30
|
, bind = El.bind.bind(El.call)
|
|
26
31
|
, create = Object.create
|
|
27
32
|
, hasOwn = bind(plugins.hasOwnProperty)
|
|
28
33
|
, isArr = Array.isArray
|
|
29
34
|
, slice = emptyArr.slice
|
|
35
|
+
// Closureless utilities via Function() to avoid capturing outer scope
|
|
30
36
|
, elReplace = Function("a,b,c", "a&&b&&(c=a.parentNode)&&c.replaceChild(b,a)")
|
|
31
37
|
, elRm = Function("a,b", "a&&(b=a.parentNode)&&b.removeChild(a)")
|
|
32
38
|
, getAttr = Function("a,b", "return a&&a.getAttribute&&a.getAttribute(b)")
|
|
@@ -39,7 +45,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
39
45
|
, ie678 = !+"\v1" // jshint ignore:line
|
|
40
46
|
// innerText is implemented in IE4, textContent in IE9, Node.text in Opera 9-10
|
|
41
47
|
// Safari 2.x innerText results an empty string when style.display=="none" or Node is not in DOM
|
|
42
|
-
, txtAttr = "textContent" in html ? "textContent" : "innerText"
|
|
48
|
+
, txtAttr = El.T = "textContent" in html ? "textContent" : "innerText"
|
|
43
49
|
, elTxt = function(el, txt) {
|
|
44
50
|
if (el[txtAttr] !== txt) el[txtAttr] = txt
|
|
45
51
|
}
|
|
@@ -51,9 +57,12 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
51
57
|
|
|
52
58
|
, elSeq = 0
|
|
53
59
|
, elCache = {}
|
|
60
|
+
// Parses ";name! args" binding expressions from _b attribute
|
|
54
61
|
, renderRe = /[;\s]*([-.\w$]+)(?:(!?)[ :]*((?:(["'\/])(?:\\.|[^\\])*?\4|[^;])*))?/g
|
|
62
|
+
// Parses CSS selectors: .class #id [attr=val] :pseudo
|
|
55
63
|
, selectorRe = /([.#:[])([-\w]+)(?:([~^$*|]?)=(("|')(?:\\.|[^\\])*?\5|[-\w]+))?]?/g
|
|
56
64
|
, fnCache = {}
|
|
65
|
+
// Matches tokens to exclude from scope variable extraction: strings, keywords, member access, labels
|
|
57
66
|
, fnRe = /('|")(?:\\.|[^\\])*?\1|\/(?:\\.|[^\\])+?\/[gim]*|\$el\b|\$[aorsS]\b|\b(?:false|in|if|new|null|this|true|typeof|void|function|var|else|return)\b|\.\w+|\w+:/g
|
|
58
67
|
, wordRe = /[a-z_$][\w$]*/ig
|
|
59
68
|
, bindingsCss = acceptMany(function(el, key, val, current) {
|
|
@@ -75,11 +84,9 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
75
84
|
set: acceptMany(setAttr),
|
|
76
85
|
txt: elTxt,
|
|
77
86
|
/*** form ***/
|
|
78
|
-
val: function elVal(el, val,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
} catch (e) {}
|
|
82
|
-
var step, key, value
|
|
87
|
+
val: function elVal(el, val, ignoreFocus) {
|
|
88
|
+
if (!el) return
|
|
89
|
+
var input, step, key, value
|
|
83
90
|
, i = 0
|
|
84
91
|
, type = el.type
|
|
85
92
|
, opts = el.options
|
|
@@ -95,7 +102,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
95
102
|
// Read-only checkboxes can be changed by the user
|
|
96
103
|
|
|
97
104
|
for (opts = {}; (input = el.elements[i++]); ) if (!input.disabled && (key = input.name || input.id)) {
|
|
98
|
-
value = elVal(input, val != UNDEF ? val[key] : UNDEF)
|
|
105
|
+
value = elVal(input, val != UNDEF ? val[key] : UNDEF, ignoreFocus)
|
|
99
106
|
if (value !== UNDEF) {
|
|
100
107
|
step = opts
|
|
101
108
|
replace(/\[(.*?)\]/g, replacer, key)
|
|
@@ -106,6 +113,9 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
if (val !== UNDEF) {
|
|
116
|
+
try {
|
|
117
|
+
if (!ignoreFocus && document.activeElement === el) return
|
|
118
|
+
} catch (e) {}
|
|
109
119
|
if (opts) {
|
|
110
120
|
for (value = (isArr(val) ? val : [ val ]).map(String); (input = opts[i++]); ) {
|
|
111
121
|
input.selected = value.indexOf(input.value) > -1
|
|
@@ -146,11 +156,13 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
146
156
|
}
|
|
147
157
|
/**/
|
|
148
158
|
}
|
|
159
|
+
// Stores "!" once-bindings; index used in compiled fn to strip from _b after first run
|
|
149
160
|
, bindOnce = []
|
|
150
161
|
, globalScope = {
|
|
151
162
|
El: El,
|
|
152
163
|
$b: bindings
|
|
153
164
|
}
|
|
165
|
+
// Array-like wrapper methods for multi-element collections (mixed into arrays by ElWrap)
|
|
154
166
|
, elArr = {
|
|
155
167
|
append: function(el) {
|
|
156
168
|
var elWrap = this
|
|
@@ -168,6 +180,8 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
168
180
|
}
|
|
169
181
|
}
|
|
170
182
|
|
|
183
|
+
// fixEv: maps custom event names to native (e.g., touch→"" for non-DOM events)
|
|
184
|
+
// fixFn: transforms event handlers for browser compat (e.g., touch→pointer init)
|
|
171
185
|
, Event = window.Event || window
|
|
172
186
|
, fixEv = Event.fixEv || (Event.fixEv = {})
|
|
173
187
|
, fixFn = Event.fixFn || (Event.fixFn = {})
|
|
@@ -260,6 +274,9 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
260
274
|
}
|
|
261
275
|
}
|
|
262
276
|
|
|
277
|
+
// Events stored as triplets [scope, _origin, fn] in emitter._e[type]
|
|
278
|
+
// _origin tracks the unwrapped fn before fixFn (for rmEvent lookup)
|
|
279
|
+
// emptyArr substitutes window as emitter (can't safely add _e property to window)
|
|
263
280
|
function on(emitter, type, fn, scope, _origin) {
|
|
264
281
|
if (emitter && type && fn) {
|
|
265
282
|
if (emitter === window) emitter = emptyArr
|
|
@@ -343,6 +360,10 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
343
360
|
root: body
|
|
344
361
|
}, opts)
|
|
345
362
|
|
|
363
|
+
// View properties:
|
|
364
|
+
// .r route pattern .e template element .p parent view
|
|
365
|
+
// .c active child .o rendered clone .f file dependencies (csv)
|
|
366
|
+
// .s route sequence# .kb keyboard shortcuts
|
|
346
367
|
function View(route, el, parent) {
|
|
347
368
|
var view = views[route]
|
|
348
369
|
if (view) {
|
|
@@ -423,6 +444,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
423
444
|
}
|
|
424
445
|
})
|
|
425
446
|
|
|
447
|
+
// params._p pending async count; ._v current view in traversal; ._c view to close; ._t navigation timestamp
|
|
426
448
|
function bubbleUp(params) {
|
|
427
449
|
var parent
|
|
428
450
|
, view = lastView
|
|
@@ -614,6 +636,11 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
614
636
|
}
|
|
615
637
|
}
|
|
616
638
|
|
|
639
|
+
// Plugin properties:
|
|
640
|
+
// .n name .x parent view name .u parent DOM element
|
|
641
|
+
// .e container el .d done callback .c saved elCache (for %el/%view)
|
|
642
|
+
// When proto is a function, plugin accumulates raw text:
|
|
643
|
+
// .r raw handler .t accumulated text .o original op+text .s separator
|
|
617
644
|
function addPlugin(name, proto, expectContent) {
|
|
618
645
|
plugins[name] = Plugin
|
|
619
646
|
function Plugin(parent, op, sep) {
|
|
@@ -1179,8 +1206,8 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1179
1206
|
rate: rate,
|
|
1180
1207
|
replace: elReplace,
|
|
1181
1208
|
scope: elScope,
|
|
1182
|
-
scrollLeft: scrollLeft,
|
|
1183
|
-
scrollTop: scrollTop,
|
|
1209
|
+
scrollLeft: bind(scrollPos, NUL, "pageXOffset", "scrollLeft"),
|
|
1210
|
+
scrollTop: bind(scrollPos, NUL, "pageYOffset", "scrollTop"),
|
|
1184
1211
|
step: step,
|
|
1185
1212
|
stop: eventStop
|
|
1186
1213
|
})
|
|
@@ -1242,7 +1269,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1242
1269
|
el = before.parentNode
|
|
1243
1270
|
}
|
|
1244
1271
|
el.insertBefore(child, (
|
|
1245
|
-
isNum(before) ? el.childNodes[before < 0 ? el.childNodes.length
|
|
1272
|
+
isNum(before) ? el.childNodes[before < 0 ? el.childNodes.length + before : before] :
|
|
1246
1273
|
isArr(before) ? before[0] :
|
|
1247
1274
|
before
|
|
1248
1275
|
) || NUL)
|
|
@@ -1371,6 +1398,9 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1371
1398
|
hydrate(node, "data-out", scope)
|
|
1372
1399
|
}
|
|
1373
1400
|
|
|
1401
|
+
// Reads binding expression from DOM attr (_b or data-out), compiles via makeFn, executes.
|
|
1402
|
+
// Caches expr on node[attr] to avoid re-reading DOM; true = no bindings (already processed).
|
|
1403
|
+
// Returns truthy if binding replaced the element (if/each), so render() skips children.
|
|
1374
1404
|
function hydrate(node, attr, scope) {
|
|
1375
1405
|
var fn
|
|
1376
1406
|
, expr = node[attr] || (node[attr] = setAttr(node, attr, "") || true)
|
|
@@ -1381,6 +1411,9 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1381
1411
|
throw e + "\n" + attr + ": " + expr
|
|
1382
1412
|
}
|
|
1383
1413
|
}
|
|
1414
|
+
// Compiles binding expression string (e.g. ";txt foo;cls 'active',bar") into a Function.
|
|
1415
|
+
// Extracts free variable names and aliases them from scope ($s.varName).
|
|
1416
|
+
// raw parameter bypasses the $s guard wrapper (used by i18n getExt).
|
|
1384
1417
|
function makeFn(fn, raw, i) {
|
|
1385
1418
|
fn = raw || "$s&&(" + replace(renderRe, function(match, name, op, args) {
|
|
1386
1419
|
return (
|
|
@@ -1398,7 +1431,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1398
1431
|
|
|
1399
1432
|
/*** kb ***/
|
|
1400
1433
|
var kbMaps = []
|
|
1401
|
-
, kbMod = LiteJS.kbMod =
|
|
1434
|
+
, kbMod = LiteJS.kbMod = /\bMac|\biP/.test(navigator.userAgent) ? "metaKey" : "ctrlKey"
|
|
1402
1435
|
, kbCodes = LiteJS.kbCodes = ",,,,,,,,backspace,tab,,,,enter,,,shift,ctrl,alt,pause,caps,,,,,,,esc,,,,,,pgup,pgdown,end,home,left,up,right,down,,,,,ins,del,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,cmd,,,,,,,,,,,,,,,,,,,,,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12".split(splitRe)
|
|
1403
1436
|
|
|
1404
1437
|
El.addKb = addKb
|
|
@@ -1610,6 +1643,9 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1610
1643
|
function nearest(el, sel) {
|
|
1611
1644
|
return el ? find(el, sel) || nearest(el.parentNode, sel) : NUL
|
|
1612
1645
|
}
|
|
1646
|
+
// Wraps fn to accept: space-separated names, object maps {name:val}, CSS selectors, delays.
|
|
1647
|
+
// prepareVal=1: wraps val as event delegate (string val→emit on view, fn+selector→delegation)
|
|
1648
|
+
// After arg normalization, selector is reused as element array, delay as loop counter.
|
|
1613
1649
|
function acceptMany(fn, prepareVal) {
|
|
1614
1650
|
return function f(el, name, val, selector, delay, data) {
|
|
1615
1651
|
if (el && name) {
|
|
@@ -1634,9 +1670,9 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1634
1670
|
if (prepareVal) val = delegate(el, val, selector, data)
|
|
1635
1671
|
selector = !prepareVal && selector ? findAll(el, selector) : isArr(el) ? el : [ el ]
|
|
1636
1672
|
for (delay = 0; (el = selector[delay++]); ) {
|
|
1637
|
-
for (var result, arr = ("" + name).split(splitRe), i = 0, len = arr.length; i < len; ) {
|
|
1673
|
+
for (var result, arr = ("" + name).split(splitRe), i = 0, len = arr.length; i < len; i++) {
|
|
1638
1674
|
if (arr[i]) {
|
|
1639
|
-
result = fn(el, arr[i
|
|
1675
|
+
result = fn(el, arr[i], isArr(val) ? val[i] : val, data)
|
|
1640
1676
|
if (!prepareVal && data > 0) f(el, name, result, "", data)
|
|
1641
1677
|
}
|
|
1642
1678
|
}
|
|
@@ -1729,11 +1765,8 @@ console.log("LiteJS is in debug mode, but it's fine for production")
|
|
|
1729
1765
|
}
|
|
1730
1766
|
}
|
|
1731
1767
|
}
|
|
1732
|
-
function
|
|
1733
|
-
return window
|
|
1734
|
-
}
|
|
1735
|
-
function scrollTop() {
|
|
1736
|
-
return window.pageYOffset || html.scrollTop || body.scrollTop || 0
|
|
1768
|
+
function scrollPos(page, key) {
|
|
1769
|
+
return window[page] || html[key] || body[key] || 0
|
|
1737
1770
|
}
|
|
1738
1771
|
function step(num, factor, mid) {
|
|
1739
1772
|
var x = ("" + factor).split(".")
|