@litejs/ui 24.5.0 → 24.11.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.
@@ -1,55 +1,65 @@
1
1
 
2
2
  /* litejs.com/MIT-LICENSE.txt */
3
3
 
4
- /* global xhr, getComputedStyle, navigator */
4
+ /* global escape, navigator, xhr */
5
+
6
+ /*** debug ***/
7
+ console.log("LiteJS is in debug mode, but it's fine for production")
8
+ /**/
5
9
 
6
10
  !function(window, document, history, localStorage, location, navigator, Function, Object) {
7
11
  window.El = El
8
- window.LiteJS = LiteJS
12
+ asEmitter(window.LiteJS = LiteJS)
9
13
 
10
- var UNDEF, lastExp, parser, styleNode
14
+ var UNDEF, lastExp, parser, pushBase, styleNode
15
+ , NUL = null
11
16
  , html = document.documentElement
12
17
  , body = document.body
13
- , histBase, histCb, histLast
14
18
  , splitRe = /[,\s]+/
15
19
  , emptyArr = []
20
+ , plugins = {}
21
+ , sources = []
16
22
  , assign = Object.assign
23
+ , bind = El.bind.bind(El.call)
17
24
  , create = Object.create
25
+ , hasOwn = bind(plugins.hasOwnProperty)
18
26
  , isArr = Array.isArray
19
27
  , slice = emptyArr.slice
28
+ , elReplace = Function("a,b,c", "a&&b&&(c=a.parentNode)&&c.replaceChild(b,a)")
29
+ , elRm = Function("a,b", "a&&(b=a.parentNode)&&b.removeChild(a)")
30
+ , getAttr = Function("a,b", "return a&&a.getAttribute&&a.getAttribute(b)")
31
+ , replace = Function("a,b,c", "return a.replace(b,c)")
20
32
 
21
33
  // JScript engine in IE8 and below does not recognize vertical tabulation character `\v`.
22
34
  // http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
23
35
  , ie678 = !+"\v1" // jshint ignore:line
24
- // The documentMode is an IE only property, supported in IE8 and up.
25
- , ie67 = ie678 && (document.documentMode | 0) < 8 // jshint ignore:line
26
36
 
27
37
  , BIND_ATTR = "data-bind"
28
38
  , elSeq = 0
29
39
  , elCache = {}
30
- , formatRe = /{((?:("|')(?:\\\2|[\s\S])*?\2|[^"'{}])+?)}/g
31
- , renderRe = /[;\s]*([-\w$]+)(?:([ :!])((?:(["'\/])(?:\\.|[^\\])*?\4|[^;])*))?/g
40
+ , formatRe = /{((?:("|')(?:\\.|[^\\])*?\2|.)+?)}/g
41
+ , renderRe = /[;\s]*([-.\w$]+)(?:([ :!])((?:(["'\/])(?:\\.|[^\\])*?\4|[^;])*))?/g
32
42
  , selectorRe = /([.#:[])([-\w]+)(?:([~^$*|]?)=(("|')(?:\\.|[^\\])*?\5|[-\w]+))?]?/g
33
43
  , templateRe = /([ \t]*)(%?)((?:("|')(?:\\.|[^\\])*?\4|[-\w:.#[\]~^$*|]=?)*) ?([\/>+=@^;]|)(([\])}]?).*?([[({]?))(?=\x1f|\n|$)+/g
34
44
  , fnCache = {}
35
- , fnRe = /('|")(?:\\.|[^\\])*?\1|\/(?:\\.|[^\\])+?\/[gim]*|\$el\b|\$[as]\b|\b(?:false|in|if|new|null|this|true|typeof|void|function|var|else|return)\b|\.\w+|\w+:/g
45
+ , fnRe = /('|")(?:\\.|[^\\])*?\1|\/(?:\\.|[^\\])+?\/[gim]*|\$el\b|\$[aos]\b|\b(?:false|in|if|new|null|this|true|typeof|void|function|var|else|return)\b|\.\w+|\w+:/g
36
46
  , wordRe = /[a-z_$][\w$]*/ig
37
47
  , camelRe = /\-([a-z])/g
38
48
  // innerText is implemented in IE4, textContent in IE9, Node.text in Opera 9-10
39
49
  // Safari 2.x innerText results an empty string when style.display=="none" or Node is not in DOM
40
- , txtAttr = "textContent" in html ? "textContent" : "innerText"
50
+ , txtAttr = "textContent" in html ? "textContent" /* c8 ignore next */ : "innerText"
41
51
  , bindingsCss = acceptMany(function(el, key, val) {
42
- el.style[key.replace(camelRe, camelFn)] = "" + val
52
+ el.style[replace(key, camelRe, camelFn)] = val
43
53
  })
44
- , bindingsOn = acceptMany(addEvent, function(el, selector, data, handler) {
45
- return isStr(handler) ? function(e) {
54
+ , bindingsOn = acceptMany(addEvent, function(el, val, selector, data) {
55
+ return isStr(val) ? function(e) {
46
56
  var target = selector ? closest(e.target, selector) : el
47
- if (target) emit.apply(elScope(el).$ui, [handler, e, target].concat(data))
57
+ if (target) emit.apply(target, [elScope(el).$ui, val, e, target].concat(data))
48
58
  } :
49
- selector ? function(e) {
50
- if (matches(e.target, selector)) handler(e)
59
+ selector ? function(e, a1, a2) {
60
+ if (matches(e.target, selector)) val(e, a1, a2)
51
61
  } :
52
- handler
62
+ val
53
63
  })
54
64
  , bindings = {
55
65
  cls: acceptMany(cls),
@@ -59,13 +69,11 @@
59
69
  txt: elTxt,
60
70
  val: elVal,
61
71
  view: function(el, url) {
62
- setAttr(el, "href", (histBase || "#") + expand(url || ""))
72
+ setAttr(el, "href", (pushBase || "#") + expand(url || ""))
63
73
  }
64
74
  }
65
75
  , globalScope = {
66
76
  El: El,
67
- _: format,
68
- _f: format,
69
77
  $b: bindings
70
78
  }
71
79
  , elArr = {
@@ -84,19 +92,60 @@
84
92
  return deep
85
93
  }
86
94
  }
87
- , plugins = {}
88
- , sources = [ (findAll(html, "script").pop() || plugins).innerHTML ]
89
- , hasOwn = plugins.hasOwnProperty
90
-
91
- // After iOS 13 iPad with default enabled "desktop" option
92
- // is the only Macintosh with multi-touch
93
- , iOS = /^(Mac|iP)/.test(navigator.platform)
94
- // || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
95
95
 
96
96
  , Event = window.Event || window
97
97
  , fixEv = Event.fixEv || (Event.fixEv = {})
98
98
  , fixFn = Event.fixFn || (Event.fixFn = {})
99
99
 
100
+ /*** markup ***/
101
+ , blockRe = /^(?:(=+|>| -) ([\s\S]+)|\[! *(\S*) *!] ?(.*))/
102
+ , tags = {
103
+ " -": "ul",
104
+ "!": "a",
105
+ "*": "b",
106
+ "+": "ins",
107
+ ",": "sub",
108
+ "-": "del",
109
+ "/": "i",
110
+ ":": "mark",
111
+ ";": "span",
112
+ ">": "blockquote",
113
+ "@": "time",
114
+ "^": "sup",
115
+ "_": "u",
116
+ "`": "code",
117
+ "~": "s"
118
+ }
119
+ function inline(tag, op, text, name, link, attr) {
120
+ return op && !isArr(text) ? "<" +
121
+ (tag = tags[op] || "h" + op.length) +
122
+ (tag == "a" ? " href=\"" + (link || text) + "\"" : op == "@" ? " datetime=\"" + name + "\"" : "") +
123
+ (attr ? " class=\"" + attr.slice(1) + "\">" : ">") +
124
+ (
125
+ op === ">" ? doc(replace(text, /^> ?/gm, "")) :
126
+ tag == "ul" ? "<li>" + text.split(/\n - (?=\S)/).map(inline).join("</li>\n<li>") + "</li>" :
127
+ inline(tag == "a" ? replace(name, /^\w+:\/{0,2}/, "") : text)
128
+ ) +
129
+ "</" + tag + ">" :
130
+ replace(tag, /\[([-!*+,/:;@^_`~])((.+?)(?: (\S+?))?)\1(\.[.\w]+)?]/g, inline)
131
+ }
132
+ function block(tag, op, text, media, alt) {
133
+ return op && !isArr(text) ? inline(tag, op, text) :
134
+ media ? "<img src=\"" + media + "\" alt=\"" + alt + "\">" :
135
+ blockRe.test(tag) ? replace(tag, blockRe, block) :
136
+ tag === "---" ? "<hr>" : "<p>" + inline(tag) + "</p>"
137
+ }
138
+ function doc(txt) {
139
+ return replace(txt.trim(), /^ \b/gm, "<br>").split(/\n\n+/).map(block).join("\n")
140
+ }
141
+ bindings.t = function(el, text) {
142
+ el.innerHTML = inline(replace(text, /</g, "&lt;"))
143
+ }
144
+ bindings.d = function(el, text) {
145
+ el.innerHTML = doc(replace(text, /</g, "&lt;"))
146
+ }
147
+ /**/
148
+
100
149
  /*** svg ***/
101
150
  bindings.xlink = function(el, href) {
102
151
  // In SVG2, xlink namespace is not needed, plain href can be used (Chrome50 2016, Firefox51 2017).
@@ -110,32 +159,29 @@
110
159
  }
111
160
  /**/
112
161
 
113
- Event.asEmitter = asEmitter
114
- Event.stop = eventStop
115
-
116
- if (iOS) {
117
- // iOS doesn't support beforeunload, use pagehide instead
118
- fixEv.beforeunload = "pagehide"
119
- }
120
-
121
-
122
162
  xhr.css = injectCss
123
- xhr.ui = sources.push.bind(sources)
163
+ xhr.ui = function(src) {
164
+ sources.push(src)
165
+ }
124
166
 
125
167
  function asEmitter(obj) {
126
168
  obj.on = on
127
169
  obj.off = off
128
170
  obj.one = one
129
- obj.emit = emit
171
+ obj.emit = wrap(emit)
130
172
  // emitNext, emitLate
173
+ function wrap(fn) {
174
+ return function(a, b, c, d, e) {
175
+ return fn(this, a, b, c, d, e)
176
+ }
177
+ }
131
178
  }
132
179
 
133
180
  function on(type, fn, scope, _origin) {
134
181
  var emitter = this === window ? emptyArr : this
135
- , events = emitter._e || (emitter._e = create(null))
182
+ , events = emitter._e || (emitter._e = create(NUL))
136
183
  if (type && fn) {
137
- if (isStr(fn)) fn = emit.bind(emitter, fn)
138
- emit.call(emitter, "newListener", type, fn, scope, _origin)
184
+ emit(emitter, "newListener", type, fn, scope, _origin)
139
185
  ;(events[type] || (events[type] = [])).unshift(scope, _origin, fn)
140
186
  }
141
187
  return this
@@ -149,7 +195,7 @@
149
195
  for (i = events.length - 2; i > 0; i -= 3) {
150
196
  if ((events[i + 1] === fn || events[i] === fn) && events[i - 1] == scope) {
151
197
  args = events.splice(i - 1, 3)
152
- emit.call(emitter, "removeListener", type, args[2], args[0], args[1])
198
+ emit(emitter, "removeListener", type, args[2], args[0], args[1])
153
199
  if (fn) break
154
200
  }
155
201
  }
@@ -168,20 +214,20 @@
168
214
  return this
169
215
  }
170
216
 
171
- function emit(type) {
217
+ function emit(emitter, type) {
218
+ if (emitter === window) emitter = emptyArr
172
219
  var args, i
173
- , emitter = this === window ? emptyArr : this
174
220
  , _e = emitter._e
175
221
  , arr = _e ? (_e[type] || emptyArr).concat(_e["*"] || emptyArr) : emptyArr
176
222
  if ((_e = arr.length)) {
177
- for (i = _e - 1, args = slice.call(arguments, 1); i > 1; i -= 3) {
223
+ for (i = _e - 1, args = slice.call(arguments, 2); i > 1; i -= 3) {
178
224
  if (arr[i]) arr[i].apply(arr[i - 2] || emitter, args)
179
225
  }
180
226
  }
181
227
  return _e / 3
182
228
  }
183
229
 
184
- function addEvent(el, ev, fn) {
230
+ function addEvent(el, ev, fn, opts) {
185
231
  var fn2 = fixFn[ev] && fixFn[ev](el, fn, ev) || fn
186
232
  , ev2 = fixEv[ev] || ev
187
233
 
@@ -189,7 +235,7 @@
189
235
  // polyfilled addEventListener returns patched function
190
236
  // Since Chrome 56 touchstart/move have the { passive: true } by default.
191
237
  // preventDefault() won't work unless you set passive to false.
192
- fn2 = html.addEventListener.call(el, ev2, fn2, false) || fn2
238
+ fn2 = html.addEventListener.call(el, ev2, fn2, opts != UNDEF ? opts : false) || fn2
193
239
  }
194
240
 
195
241
  on.call(el, ev, fn2, el, fn)
@@ -220,7 +266,6 @@
220
266
 
221
267
  function LiteJS(opts) {
222
268
  opts = assign({
223
- base: "",
224
269
  /*** breakpoints ***/
225
270
  breakpoints: {
226
271
  sm: 0,
@@ -249,10 +294,10 @@
249
294
 
250
295
  if (route.charAt(0) !== "#") {
251
296
  fnStr += "m[" + (view.s = routeSeq++) + "]?("
252
- reStr += "|(" + route.replace(routeRe, function(_, expr) {
297
+ reStr += "|(" + replace(route, routeRe, function(_, expr) {
253
298
  return expr ?
254
299
  (fnStr += "p['" + expr + "']=m[" + (routeSeq++) + "],") && "([^/]+?)" :
255
- _.replace(reEsc, "\\$&")
300
+ replace(_, reEsc, "\\$&")
256
301
  }) + ")"
257
302
  fnStr += "'" + route + "'):"
258
303
  viewFn = 0
@@ -261,48 +306,6 @@
261
306
 
262
307
  asEmitter(View)
263
308
  asEmitter(View.prototype = {
264
- show: function(_params) {
265
- var parent
266
- , params = lastParams = _params || {} // jshint ignore:line
267
- , view = lastView = this // jshint ignore:line
268
- , tmp = params._v || view // Continue bubbleUp from _v
269
- , close = view.o && view
270
-
271
- for (View.route = view.r; tmp; tmp = parent) {
272
- viewEmit(syncResume = params._v = tmp, "ping", params, View)
273
- syncResume = null
274
- if (lastParams !== params) return
275
- if ((parent = tmp.p)) {
276
- if (parent.c && parent.c !== tmp) {
277
- close = parent.c
278
- }
279
- parent.c = tmp
280
- }
281
- if (!tmp.e) {
282
- if (tmp.f) {
283
- xhr.load(
284
- tmp.f.replace(/^|,/g, "$&" + (View.base || "")).split(","),
285
- readTemplates.bind(view, view.wait(tmp.f = null))
286
- )
287
- } else {
288
- if (tmp.r === "404") {
289
- viewParse("%view 404 #\nh2 Not found")
290
- }
291
- View("404").show({origin:params})
292
- }
293
- return
294
- }
295
- }
296
-
297
- for (tmp in params) {
298
- if (tmp.charAt(0) !== "_" && (syncResume = hasOwn.call(paramCb, tmp) && paramCb[tmp] || paramCb["*"])) {
299
- syncResume.call(view, params[tmp], tmp, params, View)
300
- syncResume = null
301
- }
302
- }
303
- viewEmit(view, "nav")
304
- bubbleDown(params, close)
305
- },
306
309
  wait: function() {
307
310
  var params = lastParams
308
311
  params._p = 1 + (params._p | 0) // pending
@@ -311,14 +314,13 @@
311
314
  if (params._d) {
312
315
  bubbleDown(params)
313
316
  } else if (params._v) {
314
- lastView.show(params)
317
+ viewPing(lastView, params)
315
318
  }
316
319
  }
317
320
  }
318
321
  })
319
322
 
320
- var root = opts.root
321
- , viewFn, lastView, lastUrl, syncResume
323
+ var viewFn, lastView, lastUrl, syncResume
322
324
  , fnStr = ""
323
325
  , reStr = ""
324
326
  , reEsc = /[.*+?^${}()|[\]/\\]/g
@@ -328,11 +330,12 @@
328
330
  , views = View.views = {}
329
331
  , paramCb = {}
330
332
  , lastParams = paramCb
331
- , $d = elScope(View("#", root).e, root)
333
+ , root = View("#", opts.root).e
334
+ , $d = elScope(root, root)
332
335
 
333
336
  $d.$ui = assign(View, {
334
- $: find.bind(View, root),
335
- $$: findAll.bind(View, root),
337
+ $: bind(find, View, root),
338
+ $$: bind(findAll, View, root),
336
339
  $d: $d,
337
340
  def: viewDef,
338
341
  get: viewGet,
@@ -358,16 +361,9 @@
358
361
  }
359
362
  })
360
363
 
361
- function appendBind(el, val, sep, q) {
362
- var current = getAttr(el, BIND_ATTR)
363
- setAttr(el, BIND_ATTR, (current ? (
364
- q === "^" ?
365
- val + sep + current :
366
- current + sep + val
367
- ) : val))
368
- }
369
- function bubbleDown(params, close) {
364
+ function bubbleDown(params) {
370
365
  var view = params._v
366
+ , close = params._c
371
367
  , parent = view && view.p
372
368
  if (!view || params._p && /{/.test(view.r)) {
373
369
  return viewClose(close)
@@ -379,10 +375,10 @@
379
375
  viewEmit(parent, "openChild", view, close)
380
376
  viewEmit(view, "open", params)
381
377
  addKb(view.kb)
382
- close = null
378
+ params._c = UNDEF
383
379
  }
384
380
  if ((params._d = params._v = view.c)) {
385
- bubbleDown(params, close)
381
+ bubbleDown(params)
386
382
  }
387
383
  if ((lastView === view)) {
388
384
  viewEmit(view, "show", params)
@@ -395,7 +391,7 @@
395
391
  viewEmit(view.p, "closeChild", view, open)
396
392
  viewClose(view.c)
397
393
  elKill(view.o)
398
- view.o = null
394
+ view.o = UNDEF
399
395
  rmKb(view.kb)
400
396
  viewEmit(view, "close")
401
397
  }
@@ -412,11 +408,16 @@
412
408
  }
413
409
  }
414
410
  function viewEmit(view, event, a, b) {
415
- view.emit(event, a, b)
416
- View.emit(event, view, a, b)
411
+ emit(view, event, a, b)
412
+ emit(View, event, view, a, b)
413
+ emit(LiteJS, event, view, a, b)
417
414
  }
418
415
  function viewEval(str, scope) {
419
- Function("$s,$ui,$d,$,$$", str)(scope, View, $d, View.$, View.$$)
416
+ try {
417
+ Function("$s,$ui,$d,$,$$", str)(scope, View, $d, View.$, View.$$)
418
+ } catch(e) {
419
+ throw e + "\nviewEval: " + str
420
+ }
420
421
  }
421
422
  function viewGet(url, params) {
422
423
  if (!viewFn) {
@@ -443,7 +444,9 @@
443
444
  parent = parentStack.pop()
444
445
  stack.shift()
445
446
  }
446
-
447
+ if (op === "@") {
448
+ text = replace(text, /([\w,.]+):?/, "on!'$1',")
449
+ }
447
450
  if (parent.r) {
448
451
  parent.t += "\n" + all
449
452
  } else if (plugin || mapStart && (sel = "map")) {
@@ -464,21 +467,19 @@
464
467
  }
465
468
  if (text && op != "/") {
466
469
  if (op === ">" || op === "+") {
467
- (indent + (op === "+" ? text : " " + text)).replace(templateRe, work)
470
+ replace(indent + (op === "+" ? text : " " + text), templateRe, work)
468
471
  } else if (op === "=") {
469
472
  append(parent, text) // + "\n")
470
473
  } else {
471
- if (op === "@") {
472
- text = text.replace(/([\w,]+):?/, "on!'$1',")
473
- } else if (op === "") {
474
- text = "txt _('" + text.replace(/'/g, "\\'") + "',$s)"
474
+ if (op === "") {
475
+ text = "txt _(" + quote(text) + ",$s)"
475
476
  }
476
477
  appendBind(parent, text, ";", op)
477
478
  }
478
479
  }
479
480
  }
480
481
  }
481
- str.replace(templateRe, work)
482
+ replace(str, templateRe, work)
482
483
  work("", "")
483
484
  if (parent.childNodes[0]) {
484
485
  append(root, parent.childNodes)
@@ -491,17 +492,55 @@
491
492
  histStart(viewShow)
492
493
  }
493
494
  }
494
- function viewShow(url, _params) {
495
+ function viewPing(view, params) {
496
+ var parent
497
+ , tmp = params._v || view // Continue bubbleUp from _v
498
+ lastParams = params
499
+ lastView = view
500
+ params._c = view.o ? view : params._c
501
+ for (View.route = view.r; tmp; tmp = parent) {
502
+ viewEmit(syncResume = params._v = tmp, "ping", params, View)
503
+ syncResume = UNDEF
504
+ if (lastParams !== params) return
505
+ if ((parent = tmp.p)) {
506
+ if (parent.c && parent.c !== tmp) {
507
+ params._c = parent.c
508
+ }
509
+ parent.c = tmp
510
+ }
511
+ if (tmp.f) {
512
+ return xhr.load(
513
+ replace(tmp.f, /^|,/g, "$&" + (View.path || "")).split(","),
514
+ bind(readTemplates, view, view.wait(tmp.f = ""))
515
+ )
516
+ } else if (!tmp.e) {
517
+ if (tmp.r === "404") {
518
+ viewParse("%view 404 #\nh2 Not found")
519
+ }
520
+ return viewShow("404")
521
+ }
522
+ }
523
+
524
+ for (tmp in params) {
525
+ if (tmp.charAt(0) !== "_" && (syncResume = hasOwn(paramCb, tmp) && paramCb[tmp] || paramCb["*"])) {
526
+ syncResume(params[tmp], tmp, view, params)
527
+ syncResume = UNDEF
528
+ }
529
+ }
530
+ viewEmit(view, "nav")
531
+ bubbleDown(params)
532
+ }
533
+ function viewShow(url) {
495
534
  if (url === true) {
496
535
  if (lastParams._p > 0) return
497
536
  url = lastUrl
498
537
  lastUrl = 0
499
538
  }
500
- var params = _params || {}
539
+ var params = $d.params = { _t: Date.now() }
501
540
  , view = viewGet(url, params)
502
541
  if (!view.o || lastUrl !== url) {
503
- globalScope.url = lastExp = lastUrl = url
504
- view.show(globalScope.params = params)
542
+ $d.url = lastExp = lastUrl = url
543
+ viewPing(view, params)
505
544
  }
506
545
  }
507
546
 
@@ -526,7 +565,7 @@
526
565
  plugin.e.p = plugin
527
566
  }
528
567
  }
529
- if (proto.r) proto.d = Function("p", "p.r(p.o||p.t)")
568
+ if (proto.r) proto.d = Function("p", "p.r(p.o+p.t)")
530
569
  assign(Plugin.prototype, proto)
531
570
  }
532
571
  function usePluginContent(plugin) {
@@ -536,13 +575,13 @@
536
575
  , contentPos = el._cp
537
576
 
538
577
  if (contentPos > -1) {
539
- if (childNodes[contentPos].nodeType == 1 && el._sk) {
578
+ if (childNodes[contentPos].nodeType < 2 && el._sk) {
540
579
  setAttr(childNodes[contentPos], "data-slot", el._sk)
541
580
  }
542
581
  child._s = el._s
543
582
  }
544
583
  if (plugin.c) elCache = plugin.c
545
- el.p = plugin.e = plugin.u = null
584
+ el.p = plugin.e = plugin.u = UNDEF
546
585
  return child
547
586
  }
548
587
 
@@ -553,9 +592,9 @@
553
592
  d: function(plugin) {
554
593
  var slotName = plugin.n || ++elSeq
555
594
  , parent = plugin.u
556
- append(parent, Comm("%slot-" + slotName))
595
+ append(parent, Comm("slot" + slotName))
557
596
  // In IE6 root div is inside documentFragment
558
- for (; (parent.parentNode || plugin).nodeType === 1; parent = parent.parentNode);
597
+ for (; (parent.parentNode || plugin).nodeType < 2; parent = parent.parentNode);
559
598
  ;(parent._s || (parent._s = {}))[slotName] = parent.childNodes.length - 1
560
599
  if (!plugin.n) parent._s._ = parent._sk = slotName
561
600
  parent._cp = parent.childNodes.length - 1
@@ -565,40 +604,36 @@
565
604
  addPlugin("def", { r: viewDef })
566
605
  addPlugin("js", { r: viewEval })
567
606
  addPlugin("each", {
568
- r: function(params) {
607
+ r: function() {
569
608
  var txt = this.t
570
- each(params, function(param) {
571
- viewParse(txt.replace(/{key}/g, param))
609
+ each(this.o, function(param) {
610
+ viewParse(replace(txt, /{key}/g, param))
572
611
  })
573
612
  }
574
613
  })
575
614
  addPlugin("el", {
576
615
  c: 1,
577
- d: function(plugin) {
578
- var parent = plugin.u
579
- , el = usePluginContent(plugin)
616
+ d: function(plugin, el) {
617
+ el = usePluginContent(plugin)
580
618
  elCache[plugin.n] = el
581
- return parent
582
619
  }
583
620
  })
584
621
  plugins.svg = plugins.el
585
622
  addPlugin("map", {
586
- r: function() {
623
+ r: function(txt) {
587
624
  var plugin = this
588
- , txt = plugin.o + plugin.t
589
625
  appendBind(plugin.u, plugin.s ? txt.slice(1) : txt, plugin.s)
590
626
  }
591
627
  })
592
628
  addPlugin("view", {
593
629
  c: 1,
594
630
  d: function(plugin) {
595
- var bind = getAttr(plugin.e, BIND_ATTR)
631
+ var expr = getAttr(plugin.e, BIND_ATTR)
596
632
  , view = View(plugin.n, usePluginContent(plugin), plugin.x)
597
- if (bind) {
598
- bind = bind.replace(renderRe, function(_, name, op, args) {
633
+ if (expr) {
634
+ viewEval(replace(expr, renderRe, function(_, name, op, args) {
599
635
  return "($s." + name + (isFn(view[name]) ? "(" + (args || "") + ")" : "=" + args) + "),"
600
- }) + "1"
601
- viewEval(bind, view)
636
+ }) + "1", view)
602
637
  }
603
638
  }
604
639
  })
@@ -616,19 +651,19 @@
616
651
  next = point
617
652
  }
618
653
 
619
- if ( next != lastSize ) {
654
+ if (next != lastSize) {
620
655
  cls(html, lastSize, 0)
621
656
  cls(html, lastSize = next)
622
657
  }
623
658
 
624
659
  next = width > html.offsetHeight ? "land" : "port"
625
660
 
626
- if ( next != lastOrient) {
661
+ if (next != lastOrient) {
627
662
  cls(html, lastOrient, 0)
628
663
  cls(html, lastOrient = next)
629
664
  }
630
665
 
631
- View.emit("resize")
666
+ emit(View, "resize")
632
667
  }, 99)
633
668
 
634
669
  if (breakpoints) {
@@ -638,80 +673,273 @@
638
673
  /**/
639
674
 
640
675
  /*** i18n ***/
641
- var iData = {}
642
- , iFormat = create(null)
643
- , iGlobals = assignDeep(create(null), opts.locales)
644
- each(iGlobals, function(translations, iKey) {
645
- translations = iData[iKey] = assignDeep(create(iGlobals), opts[iKey])
646
- iFormat[iKey] = function(str, data) {
647
- return format(get(translations, str, str || ""), data)
676
+ globalScope._ = format
677
+ var iFormat = create(NUL)
678
+ each(opts.locales || { en: "en" }, function(translations, lang, locales) {
679
+ translations = formatGet.t = assignDeep(assignDeep(create(opts.globals || NUL), locales), opts[lang])
680
+ formatGet.g = getExt
681
+ iFormat[lang] = formatGet
682
+ var iAlias = {
683
+ "#": "num", "num": "#",
684
+ "*": "plural", "plural": "*",
685
+ "?": "pick", "pick": "?",
686
+ "@": "date", "date": "@",
687
+ "~": "pattern", "pattern": "~"
688
+ }
689
+ , cache = create(NUL)
690
+ , dateRe = /([Md])\1\1\1?|([YMDdHhmswSZ])(\2?)|[uUaSoQ]|'((?:''|[^'])*)'|(["\\\n\r\u2028\u2029])/g
691
+ , date1 = new Date()
692
+ , date2 = new Date()
693
+ , iExt = formatGet.ext = {
694
+ date: function(input, _mask, _zone) {
695
+ var undef
696
+ , offset = 4294967295
697
+ , d = input * (input > offset || input < -offset ? 1 : 1000) || Date.parse(input)
698
+ , t = translations["@"] || {}
699
+ , mask = t[_mask] || _mask || "UTC:Y-MM-DD'T'HH:mm:ss'Z'"
700
+ , zone = _zone != undef ? _zone : Date._tz != undef ? Date._tz : undef
701
+ , utc = mask.slice(0, 4) == "UTC:"
702
+ if (zone != undef && !utc) {
703
+ offset = 60 * zone
704
+ date1.setTime(d + offset * 6e4)
705
+ utc = mask = "UTC:" + mask
706
+ } else {
707
+ date1.setTime(d)
708
+ offset = utc ? 0 : -date1.getTimezoneOffset()
709
+ }
710
+ return isNaN(d) ? "" + date1 : (
711
+ cache[mask] || (cache[mask] = Function("d,a,o,l", "var t;return \"" + dateStr(mask, utc) + "\"")))(
712
+ date1,
713
+ date2,
714
+ offset,
715
+ t
716
+ )
717
+ },
718
+ lo: function(str) {
719
+ return isStr(str) ? str.toLowerCase() : ""
720
+ },
721
+ map: function(input, str, sep, lastSep) {
722
+ var arr = []
723
+ each(input, function(val) {
724
+ arr.push(formatGet(str, val))
725
+ })
726
+ lastSep = lastSep && arr.length > 1 ? lastSep + arr.pop() : ""
727
+ return arr.join(sep || ", ") + lastSep
728
+ },
729
+ num: function(input, format) {
730
+ var t = translations["#"] || {}
731
+ return (
732
+ cache[format = t[format] || "#" + format] || (cache[format] = Function("d", "var N=d<0&&(d=-d),n,r,o;return " + numStr(format, t)))
733
+ )(input)
734
+ },
735
+ pattern: function(str, re) {
736
+ var values = []
737
+ , t = translations["~"] || {}
738
+ , key = replace(str, RegExp(re || t[""] || "[\\d.]+", "g"), function(a) {
739
+ values.push(a)
740
+ return "#"
741
+ })
742
+ return str != key && t[key] ? replace(t[key], /#/g, bind(values.shift, values)) : str
743
+ },
744
+ pick: function(val, word) {
745
+ for (var t = translations["?"] || {}, arr = replace((t[word] || word), /([^;=,]+?)\?/g, "$1=$1;").split(/[;=,]/), i = 1|arr.length; i > 0; ) {
746
+ if ((i-=2) < 0 || arr[i] && (arr[i] == "" + val || +arr[i] <= val)) {
747
+ return arr[i + 1] ? replace(arr[i + 1], "#", val) : ""
748
+ }
749
+ }
750
+ },
751
+ plural: function(n, word, expr) {
752
+ var t = translations["*"] || {}
753
+ return (
754
+ cache[expr = t[""] || "n!=1"] || (cache[expr] = Function("a,n", "return (a[+(" + expr + ")]||a[0]).replace('#',n)"))
755
+ )((t[word] || "# " + word).split(";"), n)
756
+ },
757
+ up: function(str) {
758
+ return isStr(str) ? str.toUpperCase() : ""
759
+ }
760
+ }
761
+
762
+ function dateStr(mask, utc) {
763
+ var get = "d.get" + (utc ? "UTC" : "")
764
+ , dateMap = {
765
+ d: "Day()||7",
766
+ M: "Month()+1",
767
+ D: "Date()",
768
+ H: "Hours()",
769
+ h: "Hours()%12||12",
770
+ m: "Minutes()",
771
+ s: "Seconds()",
772
+ S: "Milliseconds()"
773
+ }
774
+ , setA = "a.setTime(+d+((4-(" + get + dateMap.d + "))*864e5))"
775
+ return replace((utc ? mask.slice(4) : mask), dateRe, function(match, MD, single, pad, text, esc) {
776
+ mask = (
777
+ esc ? replace(replace(escape(esc), /%u/g, "\\u"), /%/g, "\\x") :
778
+ text !== UNDEF ? replace(text, /''/g, "'") :
779
+ MD || match == "dd" ? "l[''][" + get + (MD == "M" ? "Month()+" + (match == "MMM" ? 14 : 26) : "Day()" + (pad ? (pad = "") : "+7")) + "]" :
780
+ match == "u" ? "(d/1000)>>>0" :
781
+ match == "U" ? "+d" :
782
+ match == "Q" ? "((" + get + "Month()/3)|0)+1" :
783
+ match == "a" ? "l[" + get + dateMap.H + ">11?'pm':'am']" :
784
+ match == "o" ? setA + ",a" + get.slice(1) + "FullYear()" :
785
+ single == "Y" ? get + "FullYear()" + (pad == "Y" ? "%100" : "") :
786
+ single == "Z" ? "(t=o)?(t<0?((t=-t),'-'):'+')+(t<600?'0':'')+(0|(t/60))" + (pad ? (pad = "") : "+':'") + "+((t%=60)>9?t:'0'+t):'Z'" :
787
+ single == "w" ? "Math.ceil(((" + setA + "-a.s" + get.slice(3) + "Month(0,1))/864e5+1)/7)" :
788
+ get + dateMap[single || match]
789
+ )
790
+ return text !== UNDEF || esc ? mask : "\"+(" + (
791
+ match == "SS" ? "(t=" + mask + ")>9?t>99?t:'0'+t:'00'+t" :
792
+ pad ? "(t=" + mask + ")>9?t:'0'+t" :
793
+ mask
794
+ ) + ")+\""
795
+ })
796
+ }
797
+
798
+ function numStr(format, t) {
799
+ // format;NaN;negFormat;0;Infinity;-Infinity;roundPoint
800
+ // 🯰🯱🯲🯳🯴🯵🯶🯷🯸🯹
801
+ var conf = format.split(";")
802
+ , nan_value = conf[1] || "-"
803
+ , o = (t.ordinal||"").split(";")
804
+ , pre = {
805
+ a: "(o+=d<1e3?'':d<1e6?(d/=1e3,'k'):d<1e9?(d/=1e6,'M'):d<1e12?(d/=1e9,'G'):d<1e15?(d/=1e12,'T'):d<1e18?(d/=1e15,'P'):(d/=1e18,'E')),"
806
+ }
807
+ , post = {
808
+ o: "r+(o=" + JSON.stringify(o.slice(0,-1)) + "," + o.pop() + ")"
809
+ }
810
+ , m2 = /([^\d#]*)([\d# .,_·']*\/?\d+)(?:(\s*)([a-z%]+)(\d*))?(.*)/.exec(conf[0])
811
+ , m3 = /([.,\/])(\d*)$/.exec(m2[2])
812
+ , decimals = m3 && m3[2].length || 0
813
+ , full = m3 ? m2[2].slice(0, m3.index) : m2[2]
814
+ , num = replace(full, /\D+/g, "")
815
+ , sLen = num.length
816
+ , step = decimals ? +(m3[1] === "/" ? 1 / m3[2] : num + "." + m3[2]) : num
817
+ , decSep = m3 && m3[1]
818
+ , fn = "d===Infinity?(N?" + quote(conf[5]||nan_value) + ":" + quote(conf[4]||nan_value) + "):d>0||d===0?(o=" + quote(m2[3]) + "," + (pre[m2[4]] || "") + "n=" + (
819
+ // Use exponential notation to fix float rounding
820
+ // Math.round(1.005*100)/100 = 1 instead of 1.01
821
+ decimals ?
822
+ "d>1e-" + (decimals + 1) + "?(n=(d+'e" + decimals + "')/" + (step + "e" + decimals) + "":
823
+ "d>"+num+"e-1?(n=d/" + num
824
+ ) + ",Math.floor(n" + (
825
+ conf[6] == 1 ? "%1?n+1:n" : "+" + (conf[6] || 0.5)
826
+ ) + ")*" + step + "):0,r=" + (
827
+ m2[5] ? "(''+(+n.toPrecision(" + (m2[5]) + ")))" :
828
+ decimals ? "n.toFixed(" + decimals + ")" :
829
+ "n+''"
830
+ )
831
+
832
+ if (decimals) {
833
+ if (decSep == "/") {
834
+ fn += ".replace(/\\.\\d+/,'" + (
835
+ m3[2] == 5 ?
836
+ "⅕⅖⅗⅘'.charAt(5" :
837
+ "⅛¼⅜½⅝¾⅞'.charAt(8"
838
+ ) + "*(n%1)-1))"
839
+ } else if (decSep != ".") {
840
+ fn += ".replace('.','" + decSep + "')"
841
+ }
842
+ if (sLen === 0) {
843
+ fn += ",n<1&&(r=r.slice(1)||'0')"
844
+ }
845
+ }
846
+ if (sLen > 1) {
847
+ if (decimals) sLen += decimals + 1
848
+ fn += ",r=(r.length<" + sLen + "?(1e15+r).slice(-" + sLen + "):r)"
849
+ }
850
+
851
+ if ((num = full.match(/[^\d#][\d#]+/g))) {
852
+ fn += ",r=" + numJunk(num.length - 1, 0, decimals ? decimals + 1 : 0)
853
+ }
854
+
855
+ fn += (
856
+ (m2[4] ? ",r=" + (post[m2[4]] || "r+o") : "") +
857
+ // negative format
858
+ ",N&&n>0?" + replace(quote(conf[2] || "-#"), "#", "'+r+'") + ":" +
859
+ (conf[3] ? "n===0?" + quote(conf[3]) + ":" : "") +
860
+ (m2[1] ? quote(m2[1]) + "+r" : "r") +
861
+ (m2[6] ? "+" + quote(m2[6]) : "")
862
+ )
863
+
864
+ return fn + "):" + quote(nan_value)
865
+
866
+ function numJunk(i, lastLen, dec) {
867
+ var len = lastLen + num[i].length - 1
868
+
869
+ return "(n<1e" + len + (
870
+ lastLen ? "?r.slice(0,-" + (lastLen + dec) + "):" : "?r:"
871
+ ) + (
872
+ len < 16 ? numJunk(i?i-1:i, len, dec) : "r.slice(0,-" + (lastLen + dec) + ")"
873
+ ) + "+" + quote(num[i].charAt(0)) + "+r.slice(-" + (len + dec) + (
874
+ lastLen ? ",-" + (lastLen + dec) : ""
875
+ ) + "))"
876
+ }
877
+ }
878
+
879
+ function formatGet(str, data) {
880
+ return format(iGet(translations, str, str || ""), data, getExt)
881
+ }
882
+ function getExt(obj, str) {
883
+ var fn = cache[str] || (cache[str] = (replace(replace(str, /;\s*([#*?@~])(.*)/, function(_, op, arg) {
884
+ return ";" + iAlias[op] + " " + quote(arg)
885
+ }), renderRe, function(_, name, op, args) {
886
+ fn = (_ === name) ? name : "$el." + name + "(" + fn + (args ? "," + args : "") + ")"
887
+ }), fn === str ? str : makeFn(fn, fn)))
888
+ return str == "$" ? obj : isStr(fn) ? iGet(obj, str, "") : isFn(fn) ? fn(iExt, obj, translations) : ""
648
889
  }
649
890
  })
650
- assignDeep(iGlobals, opts.globals)
651
- iSet([localStorage.lang, navigator.language, navigator.userLanguage].concat(navigator.languages, opts.lang).find(iResolve))
652
- $d.locales = Object.keys(iFormat)
653
- View.lang = iSet
654
- function iResolve(lang) {
655
- return lang && (iFormat[lang = ("" + lang).toLowerCase()] || iFormat[lang = lang.split("-")[0]]) && lang
656
- }
657
- function iSet(lang, translations) {
658
- assignDeep(iData[lang = html.lang = $d.lang = localStorage.lang = iResolve(lang) || $d.lang || opts.lang], translations)
659
- return ($d._ = iFormat[lang] || format)
660
- }
891
+ ;[localStorage.lang, opts.lang, navigator.language].concat(navigator.languages, html.lang, $d.locales = Object.keys(iFormat))
892
+ .find(View.lang = function(lang, translations) {
893
+ if (lang && (iFormat[lang = ("" + lang).toLowerCase()] || iFormat[lang = lang.split("-")[0]])) {
894
+ assignDeep(iFormat[html.lang = $d.lang = localStorage.lang = lang].t, translations)
895
+ return ($d._ = iFormat[lang])
896
+ }
897
+ })
898
+ function format(str, data, getter) {
899
+ return replace(str, formatRe, function(all, path) {
900
+ return getter(data, path, "")
901
+ })
902
+ }
903
+ function iGet(obj, path, fallback) {
904
+ return isStr(path) ? (
905
+ isStr(obj[path]) ? obj[path] :
906
+ (path = path.split("."))[1] && isObj(obj = obj[path[0]]) && isStr(obj[path[1]]) ? obj[path[1]] :
907
+ fallback
908
+ ) :
909
+ isArr(path) ? iGet(obj, path[0]) || iGet(obj, path[1]) || iGet(obj, path[2], fallback) :
910
+ fallback
911
+ }
912
+ /*/
913
+ globalScope._ = String
661
914
  /**/
662
915
 
663
916
  return View
664
917
  }
665
918
 
666
- function getUrl() {
667
- return (
668
- /*** pushState ***/
669
- histBase ? location.pathname.slice(histBase.length) :
670
- /**/
671
- // bug in Firefox where location.hash is decoded
672
- // bug in Safari where location.pathname is decoded
673
- location.href.split("#")[1] || ""
674
- ).replace(/^[#\/\!]+|[\s\/]+$/g, "")
675
- }
676
- function setUrl(url, replace) {
919
+ function setUrl(url, rep, checkUrl) {
677
920
  /*** pushState ***/
678
- if (histBase) {
679
- history[replace ? "replaceState" : "pushState"](null, null, histBase + url)
921
+ if (pushBase) {
922
+ history[rep ? "replaceState" : "pushState"](NUL, NUL, pushBase + url)
680
923
  } else {
681
924
  /**/
682
- location[replace ? "replace" : "assign"]("#" + url)
925
+ location[rep ? "replace" : "assign"]("#" + url)
683
926
  /*** pushState ***/
684
927
  }
685
928
  /**/
686
- return checkUrl()
687
- }
688
- function checkUrl() {
689
- if (histLast != (histLast = getUrl())) {
690
- if (histCb) histCb(histLast)
691
- return true
692
- }
929
+ if (checkUrl) checkUrl()
693
930
  }
694
931
 
695
932
  LiteJS.go = setUrl
696
933
  LiteJS.start = histStart
697
934
  function histStart(cb) {
698
- histCb = cb
699
935
  /*** pushState ***/
700
936
  // Chrome5, Firefox4, IE10, Safari5, Opera11.50
701
- var url
702
- , base = find(html, "base")
703
- LiteJS.base = (base || location).href.replace(/[^\/]*(#.*)?$/, "")
704
- if (base) base = base.href.replace(/.*:\/\/[^/]*|[^\/]*$/g, "")
705
- if (base && !history.pushState) {
706
- url = location.pathname.slice(base.length)
707
- if (url) {
708
- location.replace(base + "#" + url)
709
- }
710
- }
711
- if (base && history.pushState) {
712
- histBase = base
937
+ var histLast
938
+ , baseEl = find(html, "base")
939
+ , url = getUrl()
940
+ if (baseEl && history.pushState) {
941
+ pushBase = replace(baseEl.href, /.*:\/\/[^/]*|[^\/]*$/g, "")
713
942
 
714
- url = location.href.split("#")[1]
715
943
  if (url && !getUrl()) {
716
944
  setUrl(url, 1)
717
945
  }
@@ -728,9 +956,19 @@
728
956
  /**/
729
957
  window.onhashchange = checkUrl
730
958
  readTemplates(checkUrl)
959
+ function checkUrl() {
960
+ if (cb && histLast != (histLast = getUrl())) cb(histLast)
961
+ }
962
+ function getUrl() {
963
+ return replace(
964
+ /*** pushState ***/
965
+ pushBase ? location.pathname.slice(pushBase.length) :
966
+ /**/
967
+ // NOTE: in Firefox location.hash is decoded; in Safari location.pathname is decoded
968
+ location.href.split("#")[1] || "", /^[#\/\!]+|[\s\/]+$/g, "")
969
+ }
731
970
  }
732
971
 
733
-
734
972
  function Comm(name, render) {
735
973
  var comm = document.createComment(name)
736
974
  if (render) comm.render = render
@@ -739,7 +977,7 @@
739
977
  function El(name) {
740
978
  var attr
741
979
  , attrs = {}
742
- , el = name.replace(selectorRe, function(_, op, key, fn, val, quotation) {
980
+ , el = replace(name, selectorRe, function(_, op, key, fn, val, quotation) {
743
981
  attr = 1
744
982
  val = quotation ? val.slice(1, -1) : val || key
745
983
  attrs[op =
@@ -773,7 +1011,7 @@
773
1011
  }
774
1012
 
775
1013
  assign(El, bindings, {
776
- emit: elEmit,
1014
+ emit: emit,
777
1015
  empty: elEmpty,
778
1016
  kill: elKill,
779
1017
  off: acceptMany(rmEvent),
@@ -805,57 +1043,65 @@
805
1043
  })
806
1044
 
807
1045
  assign(El, {
808
- append: append,
809
1046
  $b: assign(bindings, {
810
1047
  each: function(el, name, list) {
1048
+ /*** debug ***/
1049
+ if (el._li) throw "Binding each must be type of once: each!" + name
1050
+ /**/
1051
+
811
1052
  var comm = Comm("each " + name, up)
812
1053
  , pos = 0
813
1054
  , nodes = []
1055
+
814
1056
  comm.$s = this
815
1057
  elReplace(el, comm)
816
- up()
817
- return { a: add, r: remove, u: up }
1058
+ each(list, add)
1059
+ return { a: add, u: up }
818
1060
 
819
1061
  function add(item) {
820
1062
  var clone = nodes[pos] = el.cloneNode(true)
821
1063
  , subScope = elScope(clone, comm)
1064
+ append(comm.parentNode, clone, (pos ? nodes[pos - 1] : comm).nextSibling)
822
1065
  subScope.$i = pos++
823
1066
  subScope.$len = list.length
824
1067
  subScope[name] = item
825
1068
  clone[BIND_ATTR] = el[BIND_ATTR]
826
- append(comm.parentNode, clone, comm)
827
- render(clone, subScope)
828
- }
829
- function remove(i) {
830
- elKill(nodes.splice(i, 1)[0])
1069
+ /*** debug ***/
1070
+ clone._li = up
1071
+ /**/
1072
+ render(clone)
831
1073
  }
832
1074
  function up() {
833
- for (; pos; ) remove(--pos)
834
- each(list, add)
1075
+ for (var i = list.length; pos > i; ) elKill(nodes[--pos])
1076
+ for (nodes.length = i; pos < i; ) add(list[pos])
1077
+ for (; i--; ) nodes[i].$s[name] = list[i]
835
1078
  }
836
1079
  },
837
1080
  el: function(el, tag, fallback) {
838
- var child = El(elCache[tag] ? tag : fallback)
839
- , tmp = getAttr(el, BIND_ATTR)
840
- , tmp2 = getAttr(child, BIND_ATTR)
841
- if (tmp) setAttr(child, BIND_ATTR, tmp2 ? tmp + ";" + tmp2 : tmp)
842
- if ((tmp = el.className)) cls(child, tmp)
843
- child.$s = el.$s
844
- elReplace(el, child)
845
- render(child, this)
846
- return child
1081
+ tag = elCache[tag] ? tag : fallback
1082
+ if (el._el !== tag) {
1083
+ var child = El(tag)
1084
+ , tmp = child._elb = el._el ? el._elb : el[BIND_ATTR]
1085
+ if (tmp) appendBind(child, tmp, ";", "^")
1086
+ child.$s = el.$s
1087
+ child._el = tag
1088
+ elReplace(el, child)
1089
+ if ((tmp = child._elc = el._el ? (elKill(el), el._elc) : el.className)) cls(child, tmp)
1090
+ render(child)
1091
+ return true
1092
+ }
847
1093
  },
848
1094
  "if": function(el, enabled) {
849
1095
  if (enabled) {
850
1096
  elReplace(el._if, el)
851
1097
  } else {
852
- elReplace(el, el._if || (el._if = Comm("if", render.bind(el, el, this))))
1098
+ elReplace(el, el._if || (el._if = Comm("if", bind(render, el, el, this))))
853
1099
  return true
854
1100
  }
855
1101
  },
856
1102
  is: function(el, val, opts, prefix) {
857
1103
  if (!prefix) prefix = "is-"
858
- var match = format(val, opts)
1104
+ var match = elScope(el)._.ext.pick(val, opts)
859
1105
  cls(el, el[prefix + opts], 0)
860
1106
  cls(el, el[prefix + opts] = match && prefix + match)
861
1107
  },
@@ -872,38 +1118,37 @@
872
1118
  })
873
1119
  }
874
1120
  }),
1121
+ $d: globalScope,
1122
+ append: append,
1123
+ asEmitter: asEmitter,
875
1124
  blur: blur,
876
1125
  cache: elCache,
877
1126
  closest: closest,
878
- $d: globalScope,
879
1127
  get: getAttr,
880
1128
  hasClass: hasClass,
881
1129
  matches: matches,
1130
+ nearest: nearest,
1131
+ next: bind(walk, El, "nextSibling"),
1132
+ prev: bind(walk, El, "previousSibling"),
882
1133
  rate: rate,
883
1134
  replace: elReplace,
884
1135
  scope: elScope,
885
1136
  scrollLeft: scrollLeft,
886
1137
  scrollTop: scrollTop,
887
1138
  step: step,
888
- style: function(el, key) {
889
- return getComputedStyle(el).getPropertyValue(key)
890
- }
1139
+ stop: eventStop
891
1140
  })
892
1141
 
893
- function getAttr(el, key) {
894
- return el && el.getAttribute && el.getAttribute(key)
895
- }
896
-
897
1142
  function setAttr(el, key, val) {
898
1143
  var current = getAttr(el, key)
899
1144
 
900
1145
  /*** ie8 ***/
901
- // Bug: IE5-7 doesn't set styles and removes events when you try to set them.
1146
+ // NOTE: IE5-7 doesn't set styles and removes events when you try to set them.
902
1147
  // IE6 label with a for attribute will re-select the first option of SELECT list instead of just giving focus.
903
1148
  // http://webbugtrack.blogspot.com/2007/09/bug-116-for-attribute-woes-in-ie6.html
1149
+ // IE8 and below have a bug where changed 'name' not accepted on form submit
904
1150
  /* c8 ignore next 3 */
905
- if (ie67 && (key === "id" || key === "name" || key === "checked" || key === "style")) {
906
- // IE8 and below have a bug where changed 'name' not accepted on form submit
1151
+ if (ie678 && (key === "id" || key === "name" || key === "checked" || key === "style")) {
907
1152
  el.mergeAttributes(document.createElement("<INPUT " + key + "='" + val + "'>"), false)
908
1153
  } else
909
1154
  /**/
@@ -928,14 +1173,14 @@
928
1173
  , i = 0
929
1174
  if (child) {
930
1175
  if (isStr(child) || isNum(child)) child = document.createTextNode(child)
931
- else if ( !child.nodeType && (i = child.length) ) {
1176
+ else if (!child.nodeType && (i = child.length)) {
932
1177
  for (tmp = document.createDocumentFragment(); i--; ) append(tmp, child[i], 0)
933
1178
  child = tmp
934
1179
  }
935
1180
 
936
1181
  if (child.nodeType) {
937
1182
  if ((i = setAttr(child, "slot", "") || getAttr(el, "data-slot"))) {
938
- i = "%slot-" + i
1183
+ i = "slot" + i
939
1184
  for (tmp = el.firstChild; tmp; tmp = next) {
940
1185
  if (tmp.nodeType === 8 && tmp.nodeValue === i) {
941
1186
  el = tmp
@@ -954,7 +1199,7 @@
954
1199
  isNum(before) ? el.childNodes[before < 0 ? el.childNodes.length - before - 2 : before] :
955
1200
  isArr(before) ? before[0] :
956
1201
  before
957
- ) || null)
1202
+ ) || NUL)
958
1203
  /*** debug ***/
959
1204
  if (el.namespaceURI && child.namespaceURI && el.namespaceURI !== child.namespaceURI && el.tagName !== "foreignObject" && child.tagName !== "svg") {
960
1205
  console.error("NAMESPACE CHANGE!", el, child)
@@ -964,6 +1209,15 @@
964
1209
  }
965
1210
  }
966
1211
 
1212
+ function appendBind(el, val, sep, q) {
1213
+ var current = getAttr(el, BIND_ATTR)
1214
+ setAttr(el, BIND_ATTR, (current ? (
1215
+ q === "^" ?
1216
+ val + sep + current :
1217
+ current + sep + val
1218
+ ) : val))
1219
+ }
1220
+
967
1221
  function hasClass(el, name) {
968
1222
  var current = el.className || ""
969
1223
 
@@ -979,17 +1233,19 @@
979
1233
  // className is object on SVGElements
980
1234
  var current = el.className || ""
981
1235
  , useAttr = !isStr(current)
1236
+ , SP = " "
982
1237
 
983
1238
  if (useAttr) {
984
- current = el.getAttribute("class") || ""
1239
+ current = getAttr(el, "class") || ""
985
1240
  }
986
1241
 
987
1242
  if (set === UNDEF || set) {
1243
+ if (set && set !== el && set.nodeType < 2) cls(set, name, 0)
988
1244
  if (current) {
989
- name = current.split(splitRe).indexOf(name) > -1 ? current : current + " " + name
1245
+ name = current.split(SP).indexOf(name) > -1 ? current : current + SP + name
990
1246
  }
991
1247
  } else {
992
- name = current ? (" " + current + " ").replace(" " + name + " ", " ").trim() : current
1248
+ name = current ? replace(SP + current + SP, SP + name + SP, SP).trim() : current
993
1249
  }
994
1250
 
995
1251
  if (current != name) {
@@ -1001,9 +1257,6 @@
1001
1257
  }
1002
1258
  }
1003
1259
 
1004
- function elEmit(el) {
1005
- emit.apply(el, slice.call(arguments, 1))
1006
- }
1007
1260
  function elEmpty(el) {
1008
1261
  for (; el.lastChild; elKill(el.lastChild));
1009
1262
  }
@@ -1011,34 +1264,28 @@
1011
1264
  if (el) {
1012
1265
  if (delay > 0) return setTimeout(elKill, delay, el, tr)
1013
1266
  if (tr) {
1014
- cls(el, tr, tr = "transitionend")
1267
+ if (isStr(tr)) cls(el, tr)
1268
+ if (isObj(tr)) bindingsCss(el, tr)
1269
+ tr = "transitionend"
1015
1270
  // transitionend fires for each property transitioned
1016
- if ("on" + tr in el) return addEvent(el, tr, elKill.bind(el, el, el = null))
1271
+ if ("on" + tr in el) return addEvent(el, tr, bind(elKill, el, el, el = UNDEF))
1017
1272
  }
1018
1273
  if (el._e) {
1019
- emit.call(el, "kill")
1274
+ emit(el, "kill")
1020
1275
  el._e = UNDEF
1021
1276
  }
1022
1277
  elRm(el)
1023
- el.$s = UNDEF
1024
- if (el.nodeType != 1) {
1025
- if (el.kill) el.kill()
1026
- } else {
1278
+ if (el.nodeType < 2) {
1279
+ el.$s = UNDEF
1027
1280
  elEmpty(el)
1028
1281
  if (el.valObject !== UNDEF) {
1029
1282
  el.valObject = UNDEF
1030
1283
  }
1284
+ } else {
1285
+ if (el.kill) el.kill()
1031
1286
  }
1032
1287
  }
1033
1288
  }
1034
- function elReplace(oldChild, newChild) {
1035
- var parent = oldChild && oldChild.parentNode
1036
- if (parent && newChild) parent.replaceChild(newChild, oldChild)
1037
- }
1038
- function elRm(el) {
1039
- var parent = el && el.parentNode
1040
- if (parent) parent.removeChild(el)
1041
- }
1042
1289
  function elScope(el, parent) {
1043
1290
  return el.$s || (
1044
1291
  parent ? ((parent = elScope(parent)), el.$s = assign(create(parent), { $up: parent })) :
@@ -1069,7 +1316,7 @@
1069
1316
  value = elVal(input, val != UNDEF ? val[key] : UNDEF)
1070
1317
  if (value !== UNDEF) {
1071
1318
  step = opts
1072
- key.replace(/\[(.*?)\]/g, replacer)
1319
+ replace(key, /\[(.*?)\]/g, replacer)
1073
1320
  step[key || step.length] = value
1074
1321
  }
1075
1322
  }
@@ -1078,8 +1325,7 @@
1078
1325
 
1079
1326
  if (val !== UNDEF) {
1080
1327
  if (opts) {
1081
- value = (isArr(val) ? val : [ val ]).map(String)
1082
- for (; (input = opts[i++]); ) {
1328
+ for (value = (isArr(val) ? val : [ val ]).map(String); (input = opts[i++]); ) {
1083
1329
  input.selected = value.indexOf(input.value) > -1
1084
1330
  }
1085
1331
  } else if (el.val) {
@@ -1107,12 +1353,12 @@
1107
1353
  }
1108
1354
 
1109
1355
  return checkbox && !el.checked ?
1110
- (type === "radio" ? UNDEF : null) :
1356
+ (type === "radio" ? UNDEF : NUL) :
1111
1357
  el.valObject !== UNDEF ? el.valObject : el.value
1112
1358
 
1113
1359
  function replacer(_, _key, offset) {
1114
1360
  if (step == opts) key = key.slice(0, offset)
1115
- step = step[key] || (step[key] = step[key] === null || _key && +_key != _key ? {} : [])
1361
+ step = step[key] || (step[key] = step[key] === NUL || _key && +_key != _key ? {} : [])
1116
1362
  key = _key
1117
1363
  }
1118
1364
  }
@@ -1125,15 +1371,14 @@
1125
1371
  }
1126
1372
 
1127
1373
  function render(node, $s) {
1128
- if (!node) return
1129
- var bind, next
1130
- , scope = node.$s || $s || closestScope(node)
1131
-
1132
- if (node.nodeType != 1) {
1133
- if (node.render) node.render(scope)
1374
+ if (!node || node.nodeType != 1) {
1375
+ if (node && node.render) node.render()
1134
1376
  return
1135
1377
  }
1136
1378
 
1379
+ var el, next
1380
+ , scope = node.$s || $s || closestScope(node)
1381
+
1137
1382
  /*** ie8 ***/
1138
1383
  if (ie678 && node.tagName === "SELECT") {
1139
1384
  node.parentNode.insertBefore(node, node)
@@ -1141,53 +1386,46 @@
1141
1386
  /**/
1142
1387
 
1143
1388
  if (hydrate(node, BIND_ATTR, scope)) return
1144
- for (bind = node.firstChild; bind; bind = next) {
1145
- next = bind.nextSibling
1146
- render(bind, scope)
1389
+ for (el = node.firstChild; el; el = next) {
1390
+ next = el.nextSibling
1391
+ render(el, scope)
1147
1392
  }
1148
1393
  hydrate(node, "data-out", scope)
1149
1394
  }
1150
1395
 
1151
1396
  function hydrate(node, attr, scope) {
1152
1397
  var fn
1153
- , bind = node[attr] || (node[attr] = setAttr(node, attr, "") || true)
1154
- if (bind !== true) try {
1155
- fn = fnCache[bind] || (fnCache[bind] = makeFn(bind))
1156
- scope.$o = fn.o
1157
- return fn(node, scope, attr)
1398
+ , expr = node[attr] || (node[attr] = setAttr(node, attr, "") || true)
1399
+ if (expr !== true) try {
1400
+ fn = fnCache[expr] || (fnCache[expr] = makeFn(expr))
1401
+ return fn(node, scope, attr, fn.o)
1158
1402
  } catch (e) {
1159
- /*** debug ***/
1160
- console.error(e)
1161
- console.error("BINDING: " + bind, node)
1162
- /**/
1163
- if (window.onerror) {
1164
- window.onerror(e.message, e.fileName, e.lineNumber)
1165
- }
1403
+ throw e + "\n" + attr + ": " + expr
1166
1404
  }
1167
1405
  }
1168
- function makeFn(fn) {
1406
+ function makeFn(fn, raw) {
1169
1407
  var i = 0
1170
1408
  , bindOnce = []
1171
- fn = "$s&&(" + fn.replace(renderRe, function(match, name, op, args) {
1409
+ fn = raw || "$s&&(" + replace(fn, renderRe, function(match, name, op, args) {
1172
1410
  return (
1173
1411
  (op === "!" && (bindOnce[i] = match)) ?
1174
1412
  "($el[$a]=$el[$a].replace($o[" + (i++)+ "],''),0)||" :
1175
1413
  ""
1176
- ) + "$b['" + (bindings[name] ? name + "'].call($s,$el" : "set']($el,'" + name + "'") + (args ? "," + args.replace(/^\s*(\w+) in /,"'$1',") : "") + ")||"
1414
+ ) + "$b['" + (bindings[name] ? name + "'].call($s,$el" : "set']($el,'" + name + "'") + (args ? "," + replace(args, /^\s*(\w+) in /,"'$1',") : "") + ")||"
1177
1415
  }) + "$r)"
1178
- var vars = fn.replace(fnRe, "").match(wordRe) || []
1416
+ var vars = replace(fn, fnRe, "").match(wordRe) || []
1179
1417
  for (i = vars.length; i--; ) {
1180
1418
  if (vars.indexOf(vars[i]) !== i) vars.splice(i, 1)
1181
1419
  else vars[i] += "=$s." + vars[i]
1182
1420
  }
1183
- fn = Function("$el,$s,$a,$r", "var " + vars + ";return " + fn)
1421
+ fn = Function("$el,$s,$a,$o,$r", (vars[0] ? "var " + vars : "") + ";return " + fn)
1184
1422
  fn.o = bindOnce
1185
1423
  return fn
1186
1424
  }
1187
1425
 
1188
1426
  /*** kb ***/
1189
1427
  var kbMaps = []
1190
- , kbMod = LiteJS.kbMod = iOS ? "metaKey" : "ctrlKey"
1428
+ , kbMod = LiteJS.kbMod = /^(Mac|iP)/.test(navigator.platform) ? "metaKey" : "ctrlKey"
1191
1429
  , 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)
1192
1430
 
1193
1431
  El.addKb = addKb
@@ -1196,7 +1434,7 @@
1196
1434
  if (map) {
1197
1435
  kbMaps.unshift(map)
1198
1436
  if (killEl) {
1199
- addEvent(killEl, "kill", rmKb.bind(map, map))
1437
+ addEvent(killEl, "kill", bind(rmKb, map, map))
1200
1438
  }
1201
1439
  }
1202
1440
  }
@@ -1204,19 +1442,6 @@
1204
1442
  map = kbMaps.indexOf(map)
1205
1443
  if (map > -1) kbMaps.splice(map, 1)
1206
1444
  }
1207
- function runKb(e, code, chr) {
1208
- var fn, map
1209
- , i = 0
1210
- , el = e.target || e.srcElement
1211
- , input = /INPUT|TEXTAREA|SELECT/i.test((el.nodeType == 3 ? el.parentNode : el).tagName)
1212
-
1213
- for (; (map = kbMaps[i++]) && (
1214
- !(fn = !input || map.input ? map[code] || map[chr] || map.num && code > 47 && code < 58 && (chr|=0, map.num) || map.all : fn) &&
1215
- map.bubble
1216
- ););
1217
- if (isStr(fn)) setUrl(fn)
1218
- if (isFn(fn)) fn(e, chr, el)
1219
- }
1220
1445
 
1221
1446
  addEvent(document, "keydown", function(e) {
1222
1447
  if (kbMaps[0]) {
@@ -1229,31 +1454,42 @@
1229
1454
  if (code == 8 && kbMaps[0].backspace) {
1230
1455
  eventStop(e)
1231
1456
  }
1232
- runKb(e, code, key)
1233
- if (e.shiftKey && code != 16) runKb(e, code, "shift+" + key)
1457
+ runKb(key)
1458
+ if (e.shiftKey && code != 16) runKb("shift+" + key)
1234
1459
  // people in Poland use Right-Alt+S to type in Ś.
1235
1460
  // Right-Alt+S is mapped internally to Ctrl+Alt+S.
1236
1461
  // THANKS: Marcin Wichary - disappearing Polish Ś [https://medium.engineering/fa398313d4df]
1237
1462
  if (e.altKey) {
1238
- if (code != 18) runKb(e, code, "alt+" + key)
1463
+ if (code != 18) runKb("alt+" + key)
1239
1464
  } else if (code != 17) {
1240
- if (e.ctrlKey) runKb(e, code, "ctrl+" + key)
1241
- if (e[kbMod] && code != 91) runKb(e, code, "mod+" + key)
1465
+ if (e.ctrlKey) runKb("ctrl+" + key)
1466
+ if (e[kbMod] && code != 91) runKb("mod+" + key)
1242
1467
  }
1243
1468
  }
1469
+ function runKb(chr) {
1470
+ for (
1471
+ var fn, map
1472
+ , i = 0
1473
+ , el = e.target
1474
+ , input = /INPUT|TEXTAREA|SELECT/i.test((el.nodeType < 2 ? el : el.parentNode).tagName);
1475
+ (map = kbMaps[i++]) && !(
1476
+ fn = !input || map.input ? map[code] || map[chr] || map.num && code > 47 && code < 58 && (chr|=0, map.num) || map.all : fn
1477
+ ) && map.bubble; );
1478
+ if (isStr(fn)) setUrl(fn)
1479
+ if (isFn(fn)) fn(e, chr, el)
1480
+ }
1244
1481
  })
1245
1482
  /**/
1246
1483
 
1247
1484
  /*** touch ***/
1248
- var touchEl, touchDist, touchAngle, touchMode
1485
+ var touchEl, touchDist, touchAngle, touchMode, touchTick
1249
1486
  , START = "start"
1250
1487
  , END = "end"
1251
- , MS_WHICH = [0, 1, 4, 2]
1252
1488
  , touches = []
1253
1489
  , touchEv = {}
1254
1490
 
1255
1491
  // tap, swipe + left/right/up/down
1256
- each("pan pinch rotate", function(name) {
1492
+ each("pan pinch rotate tap", function(name) {
1257
1493
  fixEv[name] = fixEv[name + START] = fixEv[name + END] = ""
1258
1494
  fixFn[name] = touchInit
1259
1495
  })
@@ -1265,110 +1501,116 @@
1265
1501
  bindingsCss(el, "touchAction msTouchAction", "none")
1266
1502
  el._ti = 1
1267
1503
  }
1268
- }
1269
- function touchDown(e, e2) {
1270
- var len = e ? touches.push(e) : touches.length
1271
- , MOVE = "pointermove"
1272
- if (touchMode) {
1273
- elEmit(touchEl, touchMode + END, e2, touchEv, touchEl)
1274
- touchMode = UNDEF
1275
- }
1276
- if (len === 0) {
1277
- touchEl = null
1278
- }
1279
- if (len === 1) {
1280
- if (e) {
1281
- touchEl = e.currentTarget || e.target
1282
- if (e.button === 2 || matches(e.target, "INPUT,TEXTAREA,SELECT,.no-drag")) return
1283
- } else {
1284
- e = touches[0]
1504
+ function touchDown(e, e2) {
1505
+ clearTimeout(touchTick)
1506
+ var len = e ? touches.push(e) : touches.length
1507
+ , MOVE = "pointermove"
1508
+ if (touchMode || len < 1) {
1509
+ emit(touchEl, touchMode ? touchMode + END : "tap", e2, touchEv, touchEl)
1510
+ touchMode = UNDEF
1285
1511
  }
1286
- touchEv.X = e.clientX
1287
- touchEv.Y = e.clientY
1288
- touchPos("left", "offsetWidth")
1289
- touchPos("top", "offsetHeight")
1290
- moveOne(e)
1291
- }
1292
- if (len === 2) {
1293
- touchDist = touchAngle = null
1294
- moveTwo(e)
1295
- }
1296
- ;(len === 1 ? addEvent : rmEvent)(document, MOVE, moveOne)
1297
- ;(len === 2 ? addEvent : rmEvent)(document, MOVE, moveTwo)
1298
- return eventStop(e)
1299
- function touchPos(name, offset) {
1300
- var val = (
1301
- touchEl.getBBox ?
1302
- touchEl.getAttributeNS(null, name == "top" ? "y":"x") :
1303
- touchEl.style[name]
1304
- )
1305
- touchEv[name] = parseInt(val, 10) || 0
1306
- if (val && val.indexOf("%") > -1) {
1307
- touchEv[name] *= touchEl.parentNode[offset] / 100
1512
+ if (len < 0) {
1513
+ touchEl = UNDEF
1308
1514
  }
1309
- }
1310
- }
1311
- function touchUp(e) {
1312
- for (var i = touches.length; i--; ) {
1313
- if (touches[i].pointerId == e.pointerId) {
1314
- touches.splice(i, 1)
1315
- break
1515
+ if (len === 1) {
1516
+ if (e) {
1517
+ touchEl = e.currentTarget || e.target
1518
+ touchEv.X = e.clientX
1519
+ touchEv.Y = e.clientY
1520
+ touchPos("left", "offsetWidth")
1521
+ touchPos("top", "offsetHeight")
1522
+ if (e.button === 2 || matches(touchEl, "INPUT,TEXTAREA,SELECT,.no-drag")) return
1523
+ touchTick = setTimeout(moveOne, 1500, e, 1)
1524
+ }
1525
+ moveOne(e || touches[0])
1316
1526
  }
1317
- }
1318
- touchDown(null, e)
1319
- }
1320
- function touchWheel(e) {
1321
- // IE10 enabled pinch-to-zoom gestures from multi-touch trackpad’s as mousewheel event with ctrlKey.
1322
- // Chrome M35 and Firefox 55 followed up.
1323
- if (!touches[0]) {
1324
- var ev = e.ctrlKey ? "pinch" : e.altKey ? "rotate" : UNDEF
1325
- if (ev && emit.call(e.currentTarget || e.target, ev, e, e.deltaY/20, 0)) {
1326
- return eventStop(e)
1527
+ if (len === 2) {
1528
+ touchDist = touchAngle = UNDEF
1529
+ moveTwo(e)
1530
+ }
1531
+ ;(len === 1 ? addEvent : rmEvent)(document, MOVE, moveOne)
1532
+ ;(len === 2 ? addEvent : rmEvent)(document, MOVE, moveTwo)
1533
+ function touchPos(name, offset) {
1534
+ var val = (
1535
+ touchEl.getBBox ?
1536
+ touchEl.getAttributeNS(NUL, name == "top" ? "y":"x") :
1537
+ touchEl.style[name]
1538
+ )
1539
+ touchEv[name] = parseInt(val, 10) || 0
1540
+ if (val && val.indexOf("%") > -1) {
1541
+ touchEv[name] *= touchEl.parentNode[offset] / 100
1542
+ }
1327
1543
  }
1328
1544
  }
1329
- }
1330
- function moveOne(e) {
1331
- // In IE9 mousedown.buttons is OK but mousemove.buttons == 0
1332
- if (touches[0].buttons && touches[0].buttons !== (e.buttons || MS_WHICH[e.which || 0])) {
1333
- return touchUp(e)
1545
+ function touchUp(e) {
1546
+ for (var i = touches.length; i--; ) {
1547
+ if (touches[i].pointerId == e.pointerId) {
1548
+ touches.splice(i, 1)
1549
+ break
1550
+ }
1551
+ }
1552
+ touchDown(UNDEF, e)
1553
+ }
1554
+ function touchWheel(e) {
1555
+ // IE10 enabled pinch-to-zoom gestures from multi-touch trackpad’s as mousewheel event with ctrlKey.
1556
+ // Chrome M35 and Firefox 55 followed up.
1557
+ if (!touches[0]) {
1558
+ var ev = e.ctrlKey ? "pinch" : e.altKey ? "rotate" : UNDEF
1559
+ if (ev && emit(e.currentTarget || e.target, ev, e, e.deltaY/20, 0)) {
1560
+ return eventStop(e)
1561
+ }
1562
+ }
1334
1563
  }
1335
- touchEv.x = e.clientX - touchEv.X
1336
- touchEv.y = e.clientY - touchEv.Y
1337
- touchEv.leftPos = touchEv.x + touchEv.left
1338
- touchEv.topPos = touchEv.y + touchEv.top
1339
- if (!touchMode) {
1340
- var evs = touchEl._e
1341
- touchMode = (
1342
- evs.pan && (touchEv.x > 10 || touchEv.x < -10 || touchEv.y > 10 || touchEv.y < -10) ? "pan" :
1343
- UNDEF
1344
- )
1345
- if (!touchMode) return
1346
- elEmit(touchEl, touchMode + START, e, touchEv, touchEl)
1564
+ function moveOne(e, fromTimer) {
1565
+ // In IE9 mousedown.buttons is OK but mousemove.buttons == 0
1566
+ if (touches[0].buttons && touches[0].buttons !== (e.buttons || [0, 1, 4, 2][e.which || 0])) {
1567
+ return touchUp(e)
1568
+ }
1569
+ touchEv.x = e.clientX - touchEv.X
1570
+ touchEv.y = e.clientY - touchEv.Y
1571
+ touchEv.leftPos = touchEv.x + touchEv.left
1572
+ touchEv.topPos = touchEv.y + touchEv.top
1573
+ if (!touchMode) {
1574
+ var evs = touchEl._e
1575
+ touchMode = (
1576
+ haveEv("pan", touchEv.x > 10 || touchEv.x < -10 || touchEv.y > 10 || touchEv.y < -10) ||
1577
+ haveEv("hold", fromTimer)
1578
+ )
1579
+ if (!touchMode) return
1580
+ clearTimeout(touchTick)
1581
+ emit(touchEl, touchMode + START, e, touchEv, touchEl)
1582
+ }
1583
+ emit(touchEl, touchMode, e, touchEv, touchEl)
1584
+ function haveEv(name, set) {
1585
+ return set && (evs[name] || evs[name + START] || evs[name + END]) && name
1586
+ }
1347
1587
  }
1348
- elEmit(touchEl, touchMode, e, touchEv, touchEl)
1349
- }
1350
- function moveTwo(e) {
1351
- touches[ touches[0].pointerId == e.pointerId ? 0 : 1] = e
1352
- var diff
1353
- , x = touchEv.X - touches[1].clientX
1354
- , y = touchEv.Y - touches[1].clientY
1355
- , dist = Math.sqrt(x*x + y*y) | 0
1356
- , angle = Math.atan2(y, x)
1357
-
1358
- if (touchDist !== null) {
1359
- diff = dist - touchDist
1360
- if (diff) elEmit(touchEl, "pinch", e, diff, angle)
1361
- // GestureEvent onGestureChange: function(e) {
1362
- // e.target.style.transform =
1363
- // 'scale(' + e.scale + startScale + ') rotate(' + e.rotation + startRotation + 'deg)'
1364
- diff = angle - touchAngle
1365
- if (diff) elEmit(touchEl, "rotate", e, diff * (180/Math.PI))
1588
+ function moveTwo(e) {
1589
+ touches[ touches[0].pointerId == e.pointerId ? 0 : 1] = e
1590
+ var diff
1591
+ , x = touchEv.X - touches[1].clientX
1592
+ , y = touchEv.Y - touches[1].clientY
1593
+ , dist = Math.sqrt(x*x + y*y) | 0
1594
+ , angle = Math.atan2(y, x)
1595
+
1596
+ if (touchDist !== UNDEF) {
1597
+ diff = dist - touchDist
1598
+ if (diff) emit(touchEl, "pinch", e, diff, angle)
1599
+ // GestureEvent onGestureChange: function(e) {
1600
+ // e.target.style.transform =
1601
+ // 'scale(' + e.scale + startScale + ') rotate(' + e.rotation + startRotation + 'deg)'
1602
+ diff = angle - touchAngle
1603
+ if (diff) emit(touchEl, "rotate", e, diff * (180/Math.PI))
1604
+ }
1605
+ touchDist = dist
1606
+ touchAngle = angle
1366
1607
  }
1367
- touchDist = dist
1368
- touchAngle = angle
1369
1608
  }
1370
1609
  /**/
1371
1610
 
1611
+ function closest(el, sel) {
1612
+ return el && html.closest.call(el.nodeType < 2 ? el : el.parentNode, sel)
1613
+ }
1372
1614
  function find(root, sel, startNode) {
1373
1615
  return html.querySelector.call(startNode || root, sel)
1374
1616
  }
@@ -1378,48 +1620,52 @@
1378
1620
  function matches(el, sel) {
1379
1621
  return el && html.matches.call(el, sel)
1380
1622
  }
1381
- function closest(el, sel) {
1382
- return el && html.closest.call(el.closest ? el : el.parentNode, sel)
1623
+ function nearest(el, sel) {
1624
+ return el ? find(el, sel) || nearest(el.parentNode, sel) : NUL
1625
+ }
1626
+ function walk(attr, el, sel) {
1627
+ for (; el && !matches(el = el[attr], sel); );
1628
+ return el
1383
1629
  }
1384
1630
  function acceptMany(fn, prepareVal) {
1385
- return function f(el, names, selector, data, val, delay) {
1386
- if (el && names) {
1631
+ return function f(el, name, val, selector, delay, data) {
1632
+ if (el && name) {
1387
1633
  var i = arguments.length
1388
- if (i == 3 || i == 4 && isNum(data)) {
1389
- delay = data
1390
- val = selector
1391
- selector = data = null
1392
- } else if (i == 4 || i == 5 && isNum(val)) {
1393
- delay = val
1394
- val = data
1395
- if (isStr(selector)) {
1396
- data = null
1397
- } else {
1634
+ if (i > 3 && i < 6) {
1635
+ if (isArr(selector)) {
1398
1636
  data = selector
1399
- selector = null
1637
+ delay = selector = UNDEF
1638
+ } else if (isNum(selector)) {
1639
+ data = delay
1640
+ delay = selector
1641
+ selector = UNDEF
1400
1642
  }
1401
1643
  }
1402
1644
  if (delay > 0) {
1403
- setTimeout(f, delay, el, names, selector, data, val, 0)
1645
+ setTimeout(f, delay, el, name, val, selector, 0, data)
1404
1646
  return
1405
1647
  }
1406
- if (isObj(names)) {
1407
- for (delay in names) if (hasOwn.call(names, delay)) {
1408
- f(el, delay, selector, data, names[delay])
1648
+ if (isObj(name)) {
1649
+ for (delay in name) if (hasOwn(name, delay)) {
1650
+ f(el, delay, name[delay], selector, 0, data)
1409
1651
  }
1410
1652
  return
1411
1653
  }
1412
- if (prepareVal) val = prepareVal(el, selector, data, val)
1413
- selector = !prepareVal && selector ? findAll(el, selector) : [ el ]
1414
- var arr = ("" + names).split(splitRe), len = arr.length
1415
- for (delay = 0; (el = selector[delay++]); )
1416
- for (i = 0; i < len; ) if (arr[i]) fn(el, arr[i++], isArr(val) ? val[i - 1] : val)
1654
+ if (prepareVal) val = prepareVal(el, val, selector, data)
1655
+ selector = !prepareVal && selector ? findAll(el, selector) : isArr(el) ? el : [ el ]
1656
+ var arr = ("" + name).split(splitRe), len = arr.length
1657
+ for (delay = 0; (el = selector[delay++]); ) {
1658
+ for (i = 0; i < len; ) {
1659
+ if (arr[i]) fn(el, arr[i++], isArr(val) ? val[i - 1] : val)
1660
+ }
1661
+ }
1417
1662
  }
1418
1663
  }
1419
1664
  }
1420
1665
  function assignDeep(target, map) {
1421
- if (map) for (var k in map) if (hasOwn.call(map, k)) {
1422
- target[k] = isObj(map[k]) && isObj(target[k]) ? assignDeep(target[k], map[k]) : map[k]
1666
+ if (map) for (var k in map) if (hasOwn(map, k)) {
1667
+ if (isObj(map[k]) && isObj(target[k]) && hasOwn(target, k)) assignDeep(target[k], map[k])
1668
+ else target[k] = map[k]
1423
1669
  }
1424
1670
  return target
1425
1671
  }
@@ -1435,9 +1681,11 @@
1435
1681
  return a.toUpperCase()
1436
1682
  }
1437
1683
  function each(arr, fn, scope, key) {
1438
- if (isStr(arr)) arr = arr.split(splitRe)
1439
- if (isArr(arr)) arr.forEach(fn, scope)
1440
- else if (arr) for (key in arr) if (hasOwn.call(arr, key)) fn.call(scope, arr[key], key, arr)
1684
+ if (arr) {
1685
+ if (isStr(arr)) arr = arr.split(splitRe)
1686
+ if (isArr(arr)) arr.forEach(fn, scope)
1687
+ else for (key in arr) if (hasOwn(arr, key)) fn.call(scope, arr[key], key, arr)
1688
+ }
1441
1689
  }
1442
1690
  function expand(str) {
1443
1691
  var first = str.charAt(0)
@@ -1448,19 +1696,6 @@
1448
1696
  (lastExp = str)
1449
1697
  )
1450
1698
  }
1451
- function format(str, data) {
1452
- return str.replace(formatRe, function(all, path) {
1453
- return get(data, path, "")
1454
- })
1455
- }
1456
- function get(obj, path, fallback) {
1457
- return isStr(path) ? (
1458
- obj[path] !== UNDEF ? obj[path] :
1459
- (path = path.split("."))[1] && isObj(obj = obj[path[0]]) && obj[path[1]] !== UNDEF ? obj[path[1]] : fallback
1460
- ) :
1461
- isArr(path) ? get(obj, path[0]) || get(obj, path[1]) || get(obj, path[2], fallback) :
1462
- fallback
1463
- }
1464
1699
  function injectCss(cssText) {
1465
1700
  if (!styleNode) {
1466
1701
  // Safari and IE6-8 requires dynamically created
@@ -1483,13 +1718,15 @@
1483
1718
  function isStr(str) {
1484
1719
  return typeof str === "string"
1485
1720
  }
1486
- // Maximum call rate for Function
1487
- // leading edge, trailing edge
1721
+ function quote(str) {
1722
+ return "'" + replace(replace(str || "", /'/g, "\\'"), /\n/g, "\\n") + "'"
1723
+ }
1724
+ // Maximum call rate for Function with optional leading edge and trailing edge
1488
1725
  function rate(fn, ms, onStart, onEnd) {
1489
1726
  var tick
1490
1727
  , next = 0
1491
- onStart = isFn(onStart) ? onStart : (onStart === UNDEF || onStart) && fn
1492
- onEnd = isFn(onEnd) ? onEnd : (onEnd === UNDEF || onEnd) && fn
1728
+ onStart = isFn(onStart) ? onStart : (onStart === tick || onStart) && fn
1729
+ onEnd = isFn(onEnd) ? onEnd : (onEnd === tick || onEnd) && fn
1493
1730
  return function() {
1494
1731
  var now = Date.now()
1495
1732
  clearTimeout(tick)
@@ -1498,7 +1735,8 @@
1498
1735
  if (onStart) onStart()
1499
1736
  } else fn()
1500
1737
  next = now + ms
1501
- } else if (onEnd) {
1738
+ }
1739
+ if (onEnd) {
1502
1740
  tick = setTimeout(onEnd, next - now)
1503
1741
  }
1504
1742
  }
@@ -1523,14 +1761,14 @@
1523
1761
  elKill(el)
1524
1762
  return el.src
1525
1763
  }), function(res) {
1526
- res = res.concat(sources).filter(Boolean)
1764
+ res = res.concat(sources, next && next.src && next.innerHTML).filter(Boolean)
1527
1765
  if (res[sources.length = 0]) {
1528
1766
  if (!parser) LiteJS.ui = LiteJS()
1529
1767
  each(res, parser)
1530
1768
  }
1531
- if (next) next()
1769
+ if (isFn(next)) next()
1532
1770
  }, 1)
1533
1771
  }
1534
- readTemplates()
1772
+ readTemplates(findAll(html, "script").pop())
1535
1773
  }(this, document, history, localStorage, location, navigator, Function, Object) // jshint ignore:line
1536
1774