@litejs/ui 25.5.0 → 25.10.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/ui.js CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  /* litejs.com/MIT-LICENSE.txt */
3
3
 
4
- /* global escape, navigator, xhr, addEventListener */
4
+ /* global escape, navigator, xhr */
5
5
 
6
6
  /*** debug ***/
7
7
  console.log("LiteJS is in debug mode, but it's fine for production")
@@ -11,7 +11,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
11
11
  window.El = El
12
12
  asEmitter(window.LiteJS = LiteJS)
13
13
 
14
- var UNDEF, parser, pushBase, styleNode, canCapture
14
+ var UNDEF, parser, pushBase, styleNode
15
15
  , NUL = null
16
16
  // THIS will be undefined in strict mode and window in sloppy mode
17
17
  , THIS = this
@@ -30,43 +30,121 @@ console.log("LiteJS is in debug mode, but it's fine for production")
30
30
  , elReplace = Function("a,b,c", "a&&b&&(c=a.parentNode)&&c.replaceChild(b,a)")
31
31
  , elRm = Function("a,b", "a&&(b=a.parentNode)&&b.removeChild(a)")
32
32
  , getAttr = Function("a,b", "return a&&a.getAttribute&&a.getAttribute(b)")
33
- , replace = Function("a,b,c", "return a.replace(b,c)")
33
+ , replace = Function("a,b,c", "return c.replace(a,b)")
34
+ , toCamel = replace.bind(NUL, /\-([a-z])/g, Function("a,b", "return b.toUpperCase()"))
34
35
 
36
+ /*** ie9 ***/
35
37
  // JScript engine in IE8 and below does not recognize vertical tabulation character `\v`.
36
38
  // http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
37
39
  , ie678 = !+"\v1" // jshint ignore:line
40
+ // innerText is implemented in IE4, textContent in IE9, Node.text in Opera 9-10
41
+ // 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"
43
+ , elTxt = function(el, txt) {
44
+ if (el[txtAttr] !== txt) el[txtAttr] = txt
45
+ }
46
+ /*/
47
+ , elTxt = function(el, txt) {
48
+ if (el.textContent !== txt) el.textContent = txt
49
+ }
50
+ /**/
38
51
 
39
52
  , elSeq = 0
40
53
  , elCache = {}
41
54
  , renderRe = /[;\s]*([-.\w$]+)(?:(!?)[ :]*((?:(["'\/])(?:\\.|[^\\])*?\4|[^;])*))?/g
42
55
  , selectorRe = /([.#:[])([-\w]+)(?:([~^$*|]?)=(("|')(?:\\.|[^\\])*?\5|[-\w]+))?]?/g
43
56
  , fnCache = {}
44
- , 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
57
+ , 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
45
58
  , wordRe = /[a-z_$][\w$]*/ig
46
- , camelRe = /\-([a-z])/g
47
- // innerText is implemented in IE4, textContent in IE9, Node.text in Opera 9-10
48
- // Safari 2.x innerText results an empty string when style.display=="none" or Node is not in DOM
49
- , txtAttr = "textContent" in html ? "textContent" /* c8 ignore next */ : "innerText"
50
- , bindingsCss = acceptMany(function(el, key, val) {
51
- el.style[replace(key, camelRe, camelFn)] = val
52
- })
53
- , bindingsOn = acceptMany(addEvent, function(el, val, selector, data) {
54
- return isStr(val) ? function(e) {
55
- var target = selector ? closest(e.target, selector) : el
56
- if (target) emit.apply(target, [elScope(el).$ui, val, e, target].concat(data))
57
- } :
58
- selector ? function(e, touchEv, touchEl) {
59
- if (matches(touchEl = e.target, selector)) val(e, touchEv, touchEl, data)
60
- } :
61
- val
59
+ , bindingsCss = acceptMany(function(el, key, val, current) {
60
+ current = el.style[key = toCamel(key)]
61
+ el.style[key] = val
62
+ return current
62
63
  })
64
+ , bindingsOn = acceptMany(addEvent, 1)
63
65
  , bindings = {
64
66
  cls: acceptMany(cls),
65
67
  css: bindingsCss,
66
68
  on: bindingsOn,
69
+ one: acceptMany(function(el, ev, fn) {
70
+ addEvent(el, ev, function remove() {
71
+ rmEvent(el, ev, remove)
72
+ fn.apply(el, arguments)
73
+ })
74
+ }, 1),
67
75
  set: acceptMany(setAttr),
68
76
  txt: elTxt,
69
- val: elVal,
77
+ /*** form ***/
78
+ val: function elVal(el, val, input) {
79
+ try {
80
+ if (!el || !input && document.activeElement === el) return
81
+ } catch (e) {}
82
+ var step, key, value
83
+ , i = 0
84
+ , type = el.type
85
+ , opts = el.options
86
+ , checkbox = type === "checkbox" || type === "radio"
87
+
88
+ if (el.tagName === "FORM") {
89
+ // Disabled controls do not receive focus,
90
+ // are skipped in tabbing navigation, cannot be successfully posted.
91
+ //
92
+ // Read-only elements receive focus but cannot be modified by the user,
93
+ // are included in tabbing navigation, are successfully posted.
94
+ //
95
+ // Read-only checkboxes can be changed by the user
96
+
97
+ for (opts = {}; (input = el.elements[i++]); ) if (!input.disabled && (key = input.name || input.id)) {
98
+ value = elVal(input, val != UNDEF ? val[key] : UNDEF)
99
+ if (value !== UNDEF) {
100
+ step = opts
101
+ replace(/\[(.*?)\]/g, replacer, key)
102
+ step[key || step.length] = value
103
+ }
104
+ }
105
+ return opts
106
+ }
107
+
108
+ if (val !== UNDEF) {
109
+ if (opts) {
110
+ for (value = (isArr(val) ? val : [ val ]).map(String); (input = opts[i++]); ) {
111
+ input.selected = value.indexOf(input.value) > -1
112
+ }
113
+ } else if (el.val) {
114
+ el.val(val)
115
+ } else if (checkbox) {
116
+ el.checked = !!val
117
+ } else {
118
+ el.value = val
119
+ }
120
+ return
121
+ }
122
+
123
+ if (opts) {
124
+ if (type === "select-multiple") {
125
+ for (val = []; (input = opts[i++]); ) {
126
+ if (input.selected && !input.disabled) {
127
+ val.push(input.valObject || input.value)
128
+ }
129
+ }
130
+ return val
131
+ }
132
+ // IE8 throws error when accessing to options[-1]
133
+ value = el.selectedIndex
134
+ el = value > -1 && opts[value] || el
135
+ }
136
+
137
+ return checkbox && !el.checked ?
138
+ (type === "radio" ? UNDEF : NUL) :
139
+ el.valObject !== UNDEF ? el.valObject : el.value
140
+
141
+ function replacer(_, _key, offset) {
142
+ if (step == opts) key = key.slice(0, offset)
143
+ step = step[key] || (step[key] = step[key] === NUL || _key && +_key != _key ? {} : [])
144
+ key = _key
145
+ }
146
+ }
147
+ /**/
70
148
  }
71
149
  , bindOnce = []
72
150
  , globalScope = {
@@ -119,27 +197,27 @@ console.log("LiteJS is in debug mode, but it's fine for production")
119
197
  (tag == "a" ? " href=\"" + (link || text) + "\"" : op == "@" ? " datetime=\"" + name + "\"" : "") +
120
198
  (attr ? " class=\"" + attr.slice(1) + "\">" : ">") +
121
199
  (
122
- op === ">" ? doc(replace(text, /^> ?/gm, "")) :
200
+ op === ">" ? doc(replace(/^> ?/gm, "", text)) :
123
201
  tag == "ul" ? "<li>" + text.split(/\n - (?=\S)/).map(inline).join("</li>\n<li>") + "</li>" :
124
- inline(tag == "a" ? replace(name, /^\w+:\/{0,2}/, "") : text)
202
+ inline(tag == "a" ? replace(/^\w+:\/{0,2}/, "", name) : text)
125
203
  ) +
126
204
  "</" + tag + ">" :
127
- replace(tag, /\[([-!*+,/:;@^_`~])((.+?)(?: (\S+?))?)\1(\.[.\w]+)?]/g, inline)
205
+ replace(/\[([-!*+,/:;@^_`~])((.+?)(?: (\S+?))?)\1(\.[.\w]+)?]/g, inline, tag)
128
206
  }
129
207
  function block(tag, op, text, media, alt) {
130
208
  return op && !isArr(text) ? inline(tag, op, text) :
131
209
  media ? "<img src=\"" + media + "\" alt=\"" + alt + "\">" :
132
- blockRe.test(tag) ? replace(tag, blockRe, block) :
210
+ blockRe.test(tag) ? replace(blockRe, block, tag) :
133
211
  tag === "---" ? "<hr>" : "<p>" + inline(tag) + "</p>"
134
212
  }
135
213
  function doc(txt) {
136
- return replace(txt.trim(), /^ \b/gm, "<br>").split(/\n\n+/).map(block).join("\n")
214
+ return replace(/^ \b/gm, "<br>", txt.trim()).split(/\n\n+/).map(block).join("\n")
137
215
  }
138
216
  bindings.t = function(el, text) {
139
- el.innerHTML = inline(replace(text, /</g, "&lt;"))
217
+ el.innerHTML = inline(replace(/</g, "&lt;", text))
140
218
  }
141
219
  bindings.d = function(el, text) {
142
- el.innerHTML = doc(replace(text, /</g, "&lt;"))
220
+ el.innerHTML = doc(replace(/</g, "&lt;", text))
143
221
  }
144
222
  /**/
145
223
 
@@ -172,12 +250,19 @@ console.log("LiteJS is in debug mode, but it's fine for production")
172
250
  return fn(this, a, b, c, d, e)
173
251
  }
174
252
  }
253
+ function one(type, fn, scope) {
254
+ var emitter = this
255
+ on(emitter, type, function remove() {
256
+ off.call(emitter, type, remove, scope)
257
+ fn.apply(scope, arguments)
258
+ }, scope)
259
+ return emitter
260
+ }
175
261
  }
176
262
 
177
263
  function on(emitter, type, fn, scope, _origin) {
178
264
  if (emitter && type && fn) {
179
265
  if (emitter === window) emitter = emptyArr
180
- emit(emitter, "newListener", type, fn, scope, _origin)
181
266
  var events = emitter._e || (emitter._e = create(NUL))
182
267
  ;(events[type] || (events[type] = [])).unshift(scope, _origin, fn)
183
268
  }
@@ -185,14 +270,13 @@ console.log("LiteJS is in debug mode, but it's fine for production")
185
270
  }
186
271
 
187
272
  function off(type, fn, scope) {
188
- var i, args
273
+ var i
189
274
  , emitter = this === window ? emptyArr : this
190
275
  , events = emitter._e && emitter._e[type]
191
276
  if (events) {
192
277
  for (i = events.length - 2; i > 0; i -= 3) {
193
278
  if ((events[i + 1] === fn || events[i] === fn) && events[i - 1] == scope) {
194
- args = events.splice(i - 1, 3)
195
- emit(emitter, "removeListener", type, args[2], args[0], args[1])
279
+ events.splice(i - 1, 3)
196
280
  if (fn) break
197
281
  }
198
282
  }
@@ -200,18 +284,6 @@ console.log("LiteJS is in debug mode, but it's fine for production")
200
284
  return this
201
285
  }
202
286
 
203
- function one(type, fn, scope) {
204
- var emitter = this === window ? emptyArr : this
205
-
206
- function remove() {
207
- off.call(emitter, type, fn, scope)
208
- off.call(emitter, type, remove, scope)
209
- }
210
- on(emitter, type, remove, scope)
211
- on(emitter, type, fn, scope)
212
- return this
213
- }
214
-
215
287
  function emit(emitter, type) {
216
288
  if (emitter === window) emitter = emptyArr
217
289
  var args, i
@@ -225,10 +297,6 @@ console.log("LiteJS is in debug mode, but it's fine for production")
225
297
  return _e / 3
226
298
  }
227
299
 
228
- try {
229
- addEventListener("t", NUL, { get capture() { canCapture = 1 }})
230
- } catch(e){}
231
-
232
300
  function addEvent(el, ev, fn, opts) {
233
301
  var fn2 = fixFn[ev] && fixFn[ev](el, fn, ev) || fn
234
302
  , ev2 = fixEv[ev] || ev
@@ -237,15 +305,13 @@ console.log("LiteJS is in debug mode, but it's fine for production")
237
305
  // polyfilled addEventListener returns patched function
238
306
  // useCapture defaults to false
239
307
  // Chrome56 touchstart/move sets {passive:true} by default; use {passive:false} to enable preventDefault()
240
- fn2 = html.addEventListener.call(
241
- el, ev2, fn2, !canCapture && isObj(opts) ? !!opts.capture : opts || false
242
- ) || fn2
308
+ fn2 = html.addEventListener.call(el, ev2, fn2, opts) || fn2
243
309
  }
244
310
 
245
311
  on(el, ev, fn2, el, fn)
246
312
  }
247
313
 
248
- function rmEvent(el, ev, fn) {
314
+ function rmEvent(el, ev, fn, opts) {
249
315
  var evs = el._e && el._e[ev]
250
316
  , id = evs && evs.indexOf(fn)
251
317
  , ev2 = fixEv[ev] || ev
@@ -254,7 +320,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
254
320
  evs[id + 1]._rm()
255
321
  }
256
322
  if (ev2 !== "" && "on" + ev2 in el) {
257
- html.removeEventListener.call(el, ev2, evs[id + 1])
323
+ html.removeEventListener.call(el, ev2, evs[id + 1], opts)
258
324
  }
259
325
  evs.splice(id - 1, 3)
260
326
  }
@@ -271,11 +337,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
271
337
  function LiteJS(opts) {
272
338
  opts = assign({
273
339
  /*** breakpoints ***/
274
- breakpoints: {
275
- sm: 0,
276
- md: 601,
277
- lg: 1025
278
- },
340
+ breakpoints: "sm,601=md,1025=lg",
279
341
  /**/
280
342
  home: "home",
281
343
  root: body
@@ -298,11 +360,11 @@ console.log("LiteJS is in debug mode, but it's fine for production")
298
360
 
299
361
  if (route.charAt(0) !== "#") {
300
362
  fnStr += "m[" + (view.s = routeSeq++) + "]?("
301
- reStr += "|(" + replace(route, routeRe, function(_, expr) {
363
+ reStr += "|(" + replace(routeRe, function(_, expr) {
302
364
  return expr ?
303
365
  (fnStr += "p['" + expr + "']=m[" + (routeSeq++) + "],") && "([^/]+?)" :
304
- replace(_, reEsc, "\\$&")
305
- }) + ")"
366
+ replace(reEsc, "\\$&", _)
367
+ }, route) + ")"
306
368
  fnStr += "'" + route + "'):"
307
369
  viewFn = 0
308
370
  }
@@ -315,11 +377,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
315
377
  params._p = 1 + (params._p | 0) // pending
316
378
  return function() {
317
379
  if (--params._p || lastParams !== params || syncResume) return
318
- if (params._d) {
319
- bubbleDown(params)
320
- } else if (params._v) {
321
- viewPing(lastView, params)
322
- }
380
+ bubbleUp(params)
323
381
  }
324
382
  }
325
383
  })
@@ -365,6 +423,42 @@ console.log("LiteJS is in debug mode, but it's fine for production")
365
423
  }
366
424
  })
367
425
 
426
+ function bubbleUp(params) {
427
+ var parent
428
+ , view = lastView
429
+ , tmp = params._v || view // Continue bubbleUp from _v
430
+ params._c = view.o ? view : params._c
431
+ for (View.route = view.r; tmp; tmp = parent) {
432
+ viewEmit(syncResume = params._v = tmp, "ping", params, View)
433
+ syncResume = UNDEF
434
+ if (lastParams !== params) return
435
+ if ((parent = tmp.p)) {
436
+ if (parent.c && parent.c !== tmp) {
437
+ params._c = parent.c
438
+ }
439
+ parent.c = tmp
440
+ }
441
+ if (tmp.f) {
442
+ return xhr.load(
443
+ replace(/^|,/g, "$&" + (View.path || ""), tmp.f).split(","),
444
+ bind(readTemplates, view, view.wait(tmp.f = ""))
445
+ )
446
+ } else if (!tmp.e) {
447
+ if (tmp.r === "404") {
448
+ viewParse("%view 404 #\nh2 Not found")
449
+ }
450
+ return viewShow("404")
451
+ }
452
+ }
453
+
454
+ for (tmp in params) {
455
+ if (tmp.charAt(0) !== "_" && (syncResume = hasOwn(paramCb, tmp) && paramCb[tmp] || paramCb["*"])) {
456
+ syncResume(params[tmp], tmp, view, params)
457
+ syncResume = UNDEF
458
+ }
459
+ }
460
+ bubbleDown(params)
461
+ }
368
462
  function bubbleDown(params) {
369
463
  var view = params._v
370
464
  , close = params._c
@@ -383,27 +477,30 @@ console.log("LiteJS is in debug mode, but it's fine for production")
383
477
  /**/
384
478
  params._c = UNDEF
385
479
  }
386
- if ((params._d = params._v = view.c)) {
480
+ if ((params._v = view.c)) {
387
481
  bubbleDown(params)
388
482
  }
389
483
  if ((lastView === view)) {
390
- viewEmit(view, "show", params)
484
+ for (; view; view = view.p) {
485
+ viewEmit(view, "pong", params, View)
486
+ }
487
+ viewEmit(lastView, "show", params)
391
488
  blur()
392
489
  }
393
- }
394
-
395
- function viewClose(view, open) {
396
- if (view && view.o) {
397
- viewEmit(view.p, "closeChild", view, open)
398
- viewClose(view.c)
399
- elKill(view.o)
400
- view.o = UNDEF
401
- /*** kb ***/
402
- rmKb(view.kb)
403
- /**/
404
- viewEmit(view, "close")
490
+ function viewClose(view, open) {
491
+ if (view && view.o) {
492
+ viewEmit(view.p, "closeChild", view, open)
493
+ viewClose(view.c)
494
+ elKill(view.o)
495
+ view.o = UNDEF
496
+ /*** kb ***/
497
+ rmKb(view.kb)
498
+ /**/
499
+ viewEmit(view, "close")
500
+ }
405
501
  }
406
502
  }
503
+
407
504
  function viewDef(str) {
408
505
  for (var match, re = /(\S+) (\S+)/g; (match = re.exec(str)); ) {
409
506
  each(match[1], def)
@@ -437,24 +534,37 @@ console.log("LiteJS is in debug mode, but it's fine for production")
437
534
  return View(url ? viewFn(url, params || {}, "404") : View.home)
438
535
  }
439
536
  function viewParse(str) {
537
+ if (!str) return
440
538
  var parent = El("div")
441
539
  , stack = [-1]
442
540
  , parentStack = []
443
- , templateRe = /([ \t]*)(%?)((?:("|')(?:\\.|[^\\])*?\4|[-\w:.#[\]~^$*|]=?)*) ?([\/>=@^;]|)(([\])}]?).*?([[({]?))(?=\x1f|$)/gm
541
+ , templateRe = /([ \t]*)(%?)((?:("|')(?:\\.|[^\\])*?\4|[-#:.\w[\]](?:[~^$*|]?=)?)*) ?([\/>=@^;]|)(([\])}]?).*?([[({]?))(?=\x1f|$)/gm
542
+ replace(templateRe, work, str)
543
+ work("", "")
544
+ if (parent.childNodes[0]) {
545
+ append(root, parent.childNodes)
546
+ render(root)
547
+ /*** debug ***/
548
+ console.log("Outside view defined elements are rendered immediately into UI")
549
+ /**/
550
+ }
551
+ if (parent.i) {
552
+ histStart(viewShow)
553
+ }
444
554
 
445
555
  function work(all, indent, plugin, sel, q, op, text, mapEnd, mapStart, offset) {
446
556
  if (offset && all === indent) return
447
557
 
448
558
  for (q = indent.length; q <= stack[0]; ) {
449
- if (parent.p) {
450
- if (parent.p.c && !parent.p.e.childNodes[0]) break
451
- parent.p.d(parent.p)
559
+ if ((offset = parent.p)) {
560
+ if (offset.c && !offset.e.childNodes[0]) break
561
+ offset.d(offset)
452
562
  }
453
563
  parent = parentStack.pop()
454
564
  stack.shift()
455
565
  }
456
566
  if (op === "@") {
457
- text = replace(text, /([\w,.]+):?/, "on!'$1',")
567
+ text = replace(/([\w,.]+)[!:]?/, /^\w+!/.test(text) ? "one!'$1'," : "on!'$1',", text)
458
568
  }
459
569
  if (parent.r) {
460
570
  parent.t += "\n" + all
@@ -476,7 +586,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
476
586
  }
477
587
  if (text && op != "/") {
478
588
  if (op === ">") {
479
- replace(indent + " " + text, templateRe, work)
589
+ replace(templateRe, work, indent + " " + text)
480
590
  } else if (op === "=") {
481
591
  append(parent, text) // + "\n")
482
592
  } else {
@@ -488,56 +598,6 @@ console.log("LiteJS is in debug mode, but it's fine for production")
488
598
  }
489
599
  }
490
600
  }
491
- replace(str, templateRe, work)
492
- work("", "")
493
- if (parent.childNodes[0]) {
494
- append(root, parent.childNodes)
495
- render(root)
496
- /*** debug ***/
497
- console.log("Outside view defined elements are rendered immediately into UI")
498
- /**/
499
- }
500
- if (parent.i) {
501
- histStart(viewShow)
502
- }
503
- }
504
- function viewPing(view, params) {
505
- var parent
506
- , tmp = params._v || view // Continue bubbleUp from _v
507
- lastParams = params
508
- lastView = view
509
- params._c = view.o ? view : params._c
510
- for (View.route = view.r; tmp; tmp = parent) {
511
- viewEmit(syncResume = params._v = tmp, "ping", params, View)
512
- syncResume = UNDEF
513
- if (lastParams !== params) return
514
- if ((parent = tmp.p)) {
515
- if (parent.c && parent.c !== tmp) {
516
- params._c = parent.c
517
- }
518
- parent.c = tmp
519
- }
520
- if (tmp.f) {
521
- return xhr.load(
522
- replace(tmp.f, /^|,/g, "$&" + (View.path || "")).split(","),
523
- bind(readTemplates, view, view.wait(tmp.f = ""))
524
- )
525
- } else if (!tmp.e) {
526
- if (tmp.r === "404") {
527
- viewParse("%view 404 #\nh2 Not found")
528
- }
529
- return viewShow("404")
530
- }
531
- }
532
-
533
- for (tmp in params) {
534
- if (tmp.charAt(0) !== "_" && (syncResume = hasOwn(paramCb, tmp) && paramCb[tmp] || paramCb["*"])) {
535
- syncResume(params[tmp], tmp, view, params)
536
- syncResume = UNDEF
537
- }
538
- }
539
- viewEmit(view, "nav")
540
- bubbleDown(params)
541
601
  }
542
602
  function viewShow(url) {
543
603
  if (url === true) {
@@ -549,11 +609,12 @@ console.log("LiteJS is in debug mode, but it's fine for production")
549
609
  , view = viewGet(url, params)
550
610
  if (!view.o || lastUrl !== url) {
551
611
  $d.url = lastUrl = expand(url)
552
- viewPing(view, params)
612
+ viewEmit(lastView = view, "nav", lastParams = params)
613
+ bubbleUp(params)
553
614
  }
554
615
  }
555
616
 
556
- function addPlugin(name, proto) {
617
+ function addPlugin(name, proto, expectContent) {
557
618
  plugins[name] = Plugin
558
619
  function Plugin(parent, op, sep) {
559
620
  var plugin = this
@@ -567,15 +628,14 @@ console.log("LiteJS is in debug mode, but it's fine for production")
567
628
  plugin.o = op
568
629
  plugin.s = sep
569
630
  } else {
570
- if (plugin.c) {
631
+ if (expectContent) {
571
632
  elCache = create(plugin.c = elCache)
572
633
  }
573
634
  plugin.e = El(name === "svg" ? name : "div")
574
635
  plugin.e.p = plugin
575
636
  }
576
637
  }
577
- if (proto.r) proto.d = Function("p", "p.r(p.o+p.t)")
578
- assign(Plugin.prototype, proto)
638
+ assign(Plugin.prototype, isFn(proto) ? { d: Function("p", "p.r(p.o+p.t)"), r: proto } : proto)
579
639
  }
580
640
  function usePluginContent(plugin) {
581
641
  var el = plugin.e
@@ -609,69 +669,44 @@ console.log("LiteJS is in debug mode, but it's fine for production")
609
669
  parent._cp = parent.childNodes.length - 1
610
670
  }
611
671
  })
612
- addPlugin("css", { r: injectCss })
613
- addPlugin("def", { r: viewDef })
614
- addPlugin("js", { r: viewEval })
615
- addPlugin("each", {
616
- r: function() {
617
- var txt = this.t
618
- each(this.o, function(param) {
619
- viewParse(replace(txt, /{key}/g, param))
620
- })
621
- }
672
+ addPlugin("css", injectCss)
673
+ addPlugin("def", viewDef)
674
+ addPlugin("js", viewEval)
675
+ addPlugin("each", function() {
676
+ var txt = this.t
677
+ each(this.o, function(param) {
678
+ viewParse(replace(/{key}/g, param, txt))
679
+ })
622
680
  })
623
681
  addPlugin("el", {
624
- c: 1,
625
682
  d: function(plugin, el) {
626
683
  el = usePluginContent(plugin)
627
684
  elCache[plugin.n] = el
628
685
  }
629
- })
686
+ }, 1)
630
687
  plugins.svg = plugins.el
631
- addPlugin("map", {
632
- r: function(txt) {
633
- var plugin = this
634
- appendBind(plugin.u, plugin.s ? txt.slice(1) : txt, plugin.s)
635
- }
688
+ addPlugin("map", function(txt) {
689
+ var plugin = this
690
+ appendBind(plugin.u, plugin.s ? txt.slice(1) : txt, plugin.s)
636
691
  })
637
692
  addPlugin("view", {
638
- c: 1,
639
693
  d: function(plugin) {
640
694
  var expr = getAttr(plugin.e, "_b")
641
695
  , view = View(plugin.n, usePluginContent(plugin), plugin.x)
642
696
  if (expr) {
643
- viewEval(replace(expr, renderRe, function(_, name, op, args) {
697
+ viewEval(replace(renderRe, function(_, name, op, args) {
644
698
  return "($s." + name + (isFn(view[name]) ? "(" + (args || "") + ")" : "=" + args) + "),"
645
- }) + "1", view)
699
+ }, expr) + "1", view)
646
700
  }
647
701
  }
648
- })
702
+ }, 1)
649
703
 
650
704
  /*** breakpoints ***/
651
- var lastSize, lastOrient
652
- , breakpoints = opts.breakpoints
653
- , setBreakpointsRated = rate(function() {
705
+ var breakpoints = opts.breakpoints
706
+ , setBreakpointsRated = rate(function(width) {
654
707
  // document.documentElement.clientWidth is 0 in IE5
655
- var point, next
656
- , width = html.offsetWidth
657
-
658
- for (point in breakpoints) {
659
- if (breakpoints[point] > width) break
660
- next = point
661
- }
662
-
663
- if (next != lastSize) {
664
- cls(html, lastSize, 0)
665
- cls(html, lastSize = next)
666
- }
667
-
668
- next = width > html.offsetHeight ? "land" : "port"
669
-
670
- if (next != lastOrient) {
671
- cls(html, lastOrient, 0)
672
- cls(html, lastOrient = next)
673
- }
674
-
708
+ bindingsIs(html, (width = html.offsetWidth), breakpoints, "")
709
+ bindingsIs(html, +(width > html.offsetHeight), "port,1=land", "")
675
710
  emit(View, "resize")
676
711
  }, 99)
677
712
 
@@ -744,18 +779,15 @@ console.log("LiteJS is in debug mode, but it's fine for production")
744
779
  pattern: function(str, re) {
745
780
  var values = []
746
781
  , t = translations["~"] || {}
747
- , key = replace(str, RegExp(re || t[""] || "[\\d.]+", "g"), function(a) {
782
+ , key = replace(RegExp(re || t[""] || "[\\d.]+", "g"), function(a) {
748
783
  values.push(a)
749
784
  return "#"
750
- })
751
- return str != key ? replace(iGet(t, key, str), /#/g, bind(values.shift, values)) : str
785
+ }, str)
786
+ return str != key ? replace(/#/g, bind(values.shift, values), iGet(t, key, str)) : str
752
787
  },
753
788
  pick: function(val, word) {
754
- for (var t = translations["?"] || {}, arr = replace((t[word] || word), /([^;=,]+?)\?/g, "$1=$1;").split(/[;=,]/), i = 1|arr.length; i > 0; ) {
755
- if ((i-=2) < 0 || arr[i] && (arr[i] == "" + val || +arr[i] <= val)) {
756
- return arr[i + 1] ? replace(arr[i + 1], "#", val) : ""
757
- }
758
- }
789
+ var t = translations["?"] || {}
790
+ return pick(val, t[word] || word)
759
791
  },
760
792
  plural: function(n, word, expr) {
761
793
  var t = translations["*"] || {}
@@ -781,10 +813,10 @@ console.log("LiteJS is in debug mode, but it's fine for production")
781
813
  S: "Milliseconds()"
782
814
  }
783
815
  , setA = "a.setTime(+d+((4-(" + get + dateMap.d + "))*864e5))"
784
- return replace((utc ? mask.slice(4) : mask), dateRe, function(match, MD, single, pad, text, esc) {
816
+ return replace(dateRe, function(match, MD, single, pad, text, esc) {
785
817
  mask = (
786
- esc ? replace(replace(escape(esc), /%u/g, "\\u"), /%/g, "\\x") :
787
- text !== UNDEF ? replace(text, /''/g, "'") :
818
+ esc ? replace(/%/g, "\\x", replace(/%u/g, "\\u", escape(esc))) :
819
+ text !== UNDEF ? replace(/''/g, "'", text) :
788
820
  MD || match == "dd" ? "l[''][" + get + (MD == "M" ? "Month()+" + (match == "MMM" ? 14 : 26) : "Day()" + (pad ? (pad = "") : "+7")) + "]" :
789
821
  match == "u" ? "(d/1000)>>>0" :
790
822
  match == "U" ? "+d" :
@@ -801,7 +833,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
801
833
  pad ? "(t=" + mask + ")>9?t:'0'+t" :
802
834
  mask
803
835
  ) + ")+\""
804
- })
836
+ }, (utc ? mask.slice(4) : mask))
805
837
  }
806
838
 
807
839
  function numStr(format, t) {
@@ -820,7 +852,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
820
852
  , m3 = /([.,\/])(\d*)$/.exec(m2[2])
821
853
  , decimals = m3 && m3[2].length || 0
822
854
  , full = m3 ? m2[2].slice(0, m3.index) : m2[2]
823
- , num = replace(full, /\D+/g, "")
855
+ , num = replace(/\D+/g, "", full)
824
856
  , sLen = num.length
825
857
  , step = decimals ? +(m3[1] === "/" ? 1 / m3[2] : num + "." + m3[2]) : num
826
858
  , decSep = m3 && m3[1]
@@ -864,7 +896,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
864
896
  fn += (
865
897
  (m2[4] ? ",r=" + (post[m2[4]] || "r+o") : "") +
866
898
  // negative format
867
- ",N&&n>0?" + replace(quote(conf[2] || "-#"), "#", "'+r+'") + ":" +
899
+ ",N&&n>0?" + replace("#", "'+r+'", quote(conf[2] || "-#")) + ":" +
868
900
  (conf[3] ? "n===0?" + quote(conf[3]) + ":" : "") +
869
901
  (m2[1] ? quote(m2[1]) + "+r" : "r") +
870
902
  (m2[6] ? "+" + quote(m2[6]) : "")
@@ -889,11 +921,11 @@ console.log("LiteJS is in debug mode, but it's fine for production")
889
921
  return format(iGet(translations, str, str || ""), data, getExt)
890
922
  }
891
923
  function getExt(obj, str) {
892
- var fn = cache[str] || (cache[str] = (replace(replace(str, /;\s*([#*?@~])(.*)/, function(_, op, arg) {
893
- return ";" + iAlias[op] + " " + quote(arg)
894
- }), renderRe, function(_, name, op, args) {
924
+ var fn = cache[str] || (cache[str] = (replace(renderRe, function(_, name, op, args) {
895
925
  fn = (_ === name) ? name : "$el." + name + "(" + fn + (args ? "," + args : "") + ")"
896
- }), fn === str ? str : makeFn(fn, fn)))
926
+ }, replace(/;\s*([#*?@~])(.*)/, function(_, op, arg) {
927
+ return ";" + iAlias[op] + " " + quote(arg)
928
+ }, str)), fn === str ? str : makeFn(fn, fn)))
897
929
  return str == "$" ? obj : isStr(fn) ? iGet(obj, str, "") : isFn(fn) ? fn(iExt, obj, translations) : ""
898
930
  }
899
931
  })
@@ -924,7 +956,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
924
956
  }
925
957
  function iGet(obj, path, fallback, tmp) {
926
958
  return isStr(path) ? (
927
- isStr(obj[path]) ? obj[path] :
959
+ NUL != obj[path] ? obj[path] :
928
960
  isStr(obj[tmp = path.toLowerCase()]) ? (
929
961
  path.slice(1) === tmp.slice(1) ? obj[tmp].charAt(0).toUpperCase() + obj[tmp].slice(1) :
930
962
  path === tmp.toUpperCase() ? obj[tmp].toUpperCase() :
@@ -943,17 +975,13 @@ console.log("LiteJS is in debug mode, but it's fine for production")
943
975
  return View
944
976
  }
945
977
 
946
- function setUrl(url, rep, checkUrl) {
978
+ function setUrl(url, rep) {
947
979
  /*** pushState ***/
948
980
  if (pushBase) {
949
981
  history[rep ? "replaceState" : "pushState"](NUL, NUL, pushBase + url)
950
- } else {
982
+ } else
951
983
  /**/
952
984
  location[rep ? "replace" : "assign"]("#" + url)
953
- /*** pushState ***/
954
- }
955
- /**/
956
- if (checkUrl) checkUrl()
957
985
  }
958
986
 
959
987
  LiteJS.go = setUrl
@@ -965,7 +993,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
965
993
  , baseEl = find(html, "base")
966
994
  , url = getUrl()
967
995
  if (baseEl && history.pushState) {
968
- pushBase = replace(baseEl.href, /.*:\/\/[^/]*|[^\/]*$/g, "")
996
+ pushBase = replace(/.*:\/\/[^/]*|[^\/]*$/g, "", baseEl.href)
969
997
 
970
998
  if (url && !getUrl()) {
971
999
  setUrl(url, 1)
@@ -987,12 +1015,12 @@ console.log("LiteJS is in debug mode, but it's fine for production")
987
1015
  if (cb && histLast != (histLast = getUrl())) cb(histLast)
988
1016
  }
989
1017
  function getUrl() {
990
- return replace(
1018
+ return replace(/^[#\/\!]+|[\s\/]+$/g, "",
991
1019
  /*** pushState ***/
992
1020
  pushBase ? location.pathname.slice(pushBase.length) :
993
1021
  /**/
994
1022
  // NOTE: in Firefox location.hash is decoded; in Safari location.pathname is decoded
995
- location.href.split("#")[1] || "", /^[#\/\!]+|[\s\/]+$/g, "")
1023
+ location.href.split("#")[1] || "")
996
1024
  }
997
1025
  }
998
1026
 
@@ -1004,7 +1032,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1004
1032
  function El(name) {
1005
1033
  var attr
1006
1034
  , attrs = {}
1007
- , el = replace(name, selectorRe, function(_, op, key, fn, val, quotation) {
1035
+ , el = replace(selectorRe, function(_, op, key, fn, val, quotation) {
1008
1036
  attr = 1
1009
1037
  val = quotation ? val.slice(1, -1) : val || key
1010
1038
  attrs[op =
@@ -1018,7 +1046,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1018
1046
  attrs[op] + (fn === "~" ? " " : "") + val :
1019
1047
  val
1020
1048
  return ""
1021
- }) || "div"
1049
+ }, name) || "div"
1022
1050
 
1023
1051
  // NOTE: IE-s cloneNode consolidates the two text nodes together as one
1024
1052
  // http://brooknovak.wordpress.com/2009/08/23/ies-clonenode-doesnt-actually-clone/
@@ -1042,14 +1070,6 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1042
1070
  empty: elEmpty,
1043
1071
  kill: elKill,
1044
1072
  off: acceptMany(rmEvent),
1045
- one: acceptMany(function(el, ev, fn) {
1046
- function remove() {
1047
- rmEvent(el, ev, fn)
1048
- rmEvent(el, ev, remove)
1049
- }
1050
- addEvent(el, ev, fn)
1051
- addEvent(el, ev, remove)
1052
- }),
1053
1073
  render: render,
1054
1074
  rm: elRm
1055
1075
  })
@@ -1126,12 +1146,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1126
1146
  return true
1127
1147
  }
1128
1148
  },
1129
- is: function(el, val, opts, prefix) {
1130
- if (!isStr(prefix)) prefix = "is-"
1131
- var match = elScope(el)._.ext.pick(val, opts)
1132
- cls(el, el[prefix + opts], 0)
1133
- cls(el, el[prefix + opts] = match && prefix + match)
1134
- },
1149
+ is: bindingsIs,
1135
1150
  name: function(el, name) {
1136
1151
  setAttr(el, "name", expand(name, 1))
1137
1152
  },
@@ -1173,12 +1188,12 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1173
1188
  function setAttr(el, key, val) {
1174
1189
  var current = getAttr(el, key)
1175
1190
 
1176
- /*** ie8 ***/
1177
1191
  // NOTE: IE5-7 doesn't set styles and removes events when you try to set them.
1178
1192
  // IE6 label with a for attribute will re-select the first option of SELECT list instead of just giving focus.
1179
1193
  // http://webbugtrack.blogspot.com/2007/09/bug-116-for-attribute-woes-in-ie6.html
1180
1194
  // IE8 and below have a bug where changed 'name' not accepted on form submit
1181
- /* c8 ignore next 3 */
1195
+ /* c8 ignore next 4 */
1196
+ /*** ie9 ***/
1182
1197
  if (ie678 && (key === "id" || key === "name" || key === "checked" || key === "style")) {
1183
1198
  el.mergeAttributes(document.createElement("<INPUT " + key + "='" + val + "'>"), false)
1184
1199
  } else
@@ -1276,7 +1291,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1276
1291
  name = current.split(SP).indexOf(name) > -1 ? current : current + SP + name
1277
1292
  }
1278
1293
  } else {
1279
- name = current ? replace(SP + current + SP, SP + name + SP, SP).trim() : current
1294
+ name = current ? replace(SP + name + SP, SP, SP + current + SP).trim() : current
1280
1295
  }
1281
1296
 
1282
1297
  if (current != name) {
@@ -1286,6 +1301,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1286
1301
  el.className = name
1287
1302
  }
1288
1303
  }
1304
+ return current
1289
1305
  }
1290
1306
 
1291
1307
  function elEmpty(el) {
@@ -1299,7 +1315,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1299
1315
  if (isObj(tr)) bindingsCss(el, tr)
1300
1316
  tr = "transitionend"
1301
1317
  // transitionend fires for each property transitioned
1302
- if ("on" + tr in el) return addEvent(el, tr, bind(elKill, el, el, el = UNDEF))
1318
+ if ("on" + tr in el) return addEvent(el, tr, bind(elKill, el, el))
1303
1319
  }
1304
1320
  if (el._e) {
1305
1321
  emit(el, "kill")
@@ -1324,76 +1340,6 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1324
1340
  closestScope(el)
1325
1341
  )
1326
1342
  }
1327
- function elTxt(el, txt) {
1328
- if (el[txtAttr] !== txt) el[txtAttr] = txt
1329
- }
1330
- function elVal(el, val) {
1331
- if (!el) return ""
1332
- var input, step, key, value
1333
- , i = 0
1334
- , type = el.type
1335
- , opts = el.options
1336
- , checkbox = type === "checkbox" || type === "radio"
1337
-
1338
- if (el.tagName === "FORM") {
1339
- // Disabled controls do not receive focus,
1340
- // are skipped in tabbing navigation, cannot be successfully posted.
1341
- //
1342
- // Read-only elements receive focus but cannot be modified by the user,
1343
- // are included in tabbing navigation, are successfully posted.
1344
- //
1345
- // Read-only checkboxes can be changed by the user
1346
-
1347
- for (opts = {}; (input = el.elements[i++]); ) if (!input.disabled && (key = input.name || input.id)) {
1348
- value = elVal(input, val != UNDEF ? val[key] : UNDEF)
1349
- if (value !== UNDEF) {
1350
- step = opts
1351
- replace(key, /\[(.*?)\]/g, replacer)
1352
- step[key || step.length] = value
1353
- }
1354
- }
1355
- return opts
1356
- }
1357
-
1358
- if (val !== UNDEF) {
1359
- if (opts) {
1360
- for (value = (isArr(val) ? val : [ val ]).map(String); (input = opts[i++]); ) {
1361
- input.selected = value.indexOf(input.value) > -1
1362
- }
1363
- } else if (el.val) {
1364
- el.val(val)
1365
- } else if (checkbox) {
1366
- el.checked = !!val
1367
- } else {
1368
- el.value = val
1369
- }
1370
- return
1371
- }
1372
-
1373
- if (opts) {
1374
- if (type === "select-multiple") {
1375
- for (val = []; (input = opts[i++]); ) {
1376
- if (input.selected && !input.disabled) {
1377
- val.push(input.valObject || input.value)
1378
- }
1379
- }
1380
- return val
1381
- }
1382
- // IE8 throws error when accessing to options[-1]
1383
- value = el.selectedIndex
1384
- el = value > -1 && opts[value] || el
1385
- }
1386
-
1387
- return checkbox && !el.checked ?
1388
- (type === "radio" ? UNDEF : NUL) :
1389
- el.valObject !== UNDEF ? el.valObject : el.value
1390
-
1391
- function replacer(_, _key, offset) {
1392
- if (step == opts) key = key.slice(0, offset)
1393
- step = step[key] || (step[key] = step[key] === NUL || _key && +_key != _key ? {} : [])
1394
- key = _key
1395
- }
1396
- }
1397
1343
 
1398
1344
  function closestScope(node) {
1399
1345
  for (; (node = node.parentNode); ) {
@@ -1411,7 +1357,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1411
1357
  var el, next
1412
1358
  , scope = node.$s || $s || closestScope(node)
1413
1359
 
1414
- /*** ie8 ***/
1360
+ /*** ie9 ***/
1415
1361
  if (ie678 && node.tagName === "SELECT") {
1416
1362
  node.parentNode.insertBefore(node, node)
1417
1363
  }
@@ -1430,23 +1376,23 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1430
1376
  , expr = node[attr] || (node[attr] = setAttr(node, attr, "") || true)
1431
1377
  if (expr !== true) try {
1432
1378
  fn = fnCache[expr] || (fnCache[expr] = makeFn(expr))
1433
- return fn(node, scope, attr, bindOnce)
1379
+ return fn(node, scope, attr, bindOnce, elScope)
1434
1380
  } catch (e) {
1435
1381
  throw e + "\n" + attr + ": " + expr
1436
1382
  }
1437
1383
  }
1438
1384
  function makeFn(fn, raw, i) {
1439
- fn = raw || "$s&&(" + replace(fn, renderRe, function(match, name, op, args) {
1385
+ fn = raw || "$s&&(" + replace(renderRe, function(match, name, op, args) {
1440
1386
  return (
1441
1387
  op ? "($el[$a]=$el[$a].replace($o[" + (i = bindOnce.indexOf(match), i < 0 ? bindOnce.push(match) - 1 : i)+ "],''),0)||" : ""
1442
- ) + "$b['" + (bindings[name] ? name + "'].call($s" + (name == "$s" ? "=El.scope($el,$el)": "") + ",$el" : "set']($el,'" + name + "'") + (args ? "," + args : "") + ")||"
1443
- }) + "$r)"
1444
- var vars = replace(fn, fnRe, "").match(wordRe) || []
1388
+ ) + "$b['" + (bindings[name] ? name + "'].call($s" + (name == "$s" ? "=$S($el,$el)": "") + ",$el" : "set']($el,'" + name + "'") + (args ? "," + args : "") + ")||"
1389
+ }, fn) + "$r)"
1390
+ var vars = replace(fnRe, "", fn).match(wordRe) || []
1445
1391
  for (i = vars.length; i--; ) {
1446
- if (vars.indexOf(vars[i]) !== i) vars.splice(i, 1)
1392
+ if (window[vars[i]] || vars.indexOf(vars[i]) !== i) vars.splice(i, 1)
1447
1393
  else vars[i] += "=$s." + vars[i]
1448
1394
  }
1449
- fn = Function("$el,$s,$a,$o,$r", (vars[0] ? "var " + vars : "") + ";return " + fn)
1395
+ fn = Function("$el,$s,$a,$o,$S,$r", (vars[0] ? "var " + vars : "") + ";return " + fn)
1450
1396
  return fn
1451
1397
  }
1452
1398
 
@@ -1636,6 +1582,19 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1636
1582
  }
1637
1583
  /**/
1638
1584
 
1585
+ function bindingsIs(el, val, opts, prefix) {
1586
+ if (!isStr(prefix)) prefix = "is-"
1587
+ var match = pick(val, opts)
1588
+ cls(el, el[prefix + opts], 0)
1589
+ cls(el, el[prefix + opts] = match && prefix + match)
1590
+ }
1591
+ function pick(val, word) {
1592
+ for (var arr = replace(/([^;=,]+?)\?/g, "$1=$1;", word).split(/[;=,]/), i = 1|arr.length; i > 0; ) {
1593
+ if ((i-=2) < 0 || arr[i] && (arr[i] == "" + val || +arr[i] <= val)) {
1594
+ return arr[i + 1] ? replace("#", val, arr[i + 1]) : ""
1595
+ }
1596
+ }
1597
+ }
1639
1598
  function closest(el, sel) {
1640
1599
  return el && html.closest.call(el.nodeType < 2 ? el : el.parentNode, sel)
1641
1600
  }
@@ -1672,15 +1631,28 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1672
1631
  }
1673
1632
  return
1674
1633
  }
1675
- if (prepareVal) val = prepareVal(el, val, selector, data)
1634
+ if (prepareVal) val = delegate(el, val, selector, data)
1676
1635
  selector = !prepareVal && selector ? findAll(el, selector) : isArr(el) ? el : [ el ]
1677
1636
  for (delay = 0; (el = selector[delay++]); ) {
1678
- for (var arr = ("" + name).split(splitRe), i = 0, len = arr.length; i < len; ) {
1679
- if (arr[i]) fn(el, arr[i++], isArr(val) ? val[i - 1] : val, data)
1637
+ for (var result, arr = ("" + name).split(splitRe), i = 0, len = arr.length; i < len; ) {
1638
+ if (arr[i]) {
1639
+ result = fn(el, arr[i++], isArr(val) ? val[i - 1] : val, data)
1640
+ if (!prepareVal && data > 0) f(el, name, result, "", data)
1641
+ }
1680
1642
  }
1681
1643
  }
1682
1644
  }
1683
1645
  }
1646
+ function delegate(el, val, selector, data) {
1647
+ return isStr(val) ? function(e) {
1648
+ var target = selector ? closest(e.target, selector) : el
1649
+ if (target) emit.apply(target, [elScope(el).$ui, val, e, target].concat(data))
1650
+ } :
1651
+ selector ? function(e, touchEv, touchEl) {
1652
+ if (matches(touchEl = e.target, selector)) val(e, touchEv, touchEl, data)
1653
+ } :
1654
+ val
1655
+ }
1684
1656
  }
1685
1657
  function assignDeep(target, map) {
1686
1658
  if (map) for (var k in map) if (hasOwn(map, k)) {
@@ -1695,9 +1667,6 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1695
1667
  document.activeElement.blur()
1696
1668
  } catch(e) {}
1697
1669
  }
1698
- function camelFn(_, a) {
1699
- return a.toUpperCase()
1700
- }
1701
1670
  function each(arr, fn, scope, key) {
1702
1671
  if (arr) {
1703
1672
  if (isStr(arr)) arr = arr.split(splitRe)
@@ -1738,7 +1707,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1738
1707
  return typeof str === "string"
1739
1708
  }
1740
1709
  function quote(str) {
1741
- return "'" + replace(replace(str || "", /'/g, "\\'"), /\n/g, "\\n") + "'"
1710
+ return "'" + replace(/\n/g, "\\n", replace(/'/g, "\\'", str || "")) + "'"
1742
1711
  }
1743
1712
  // Maximum call rate for Function with optional leading edge and trailing edge
1744
1713
  function rate(fn, ms, onStart, onEnd) {
@@ -1780,7 +1749,7 @@ console.log("LiteJS is in debug mode, but it's fine for production")
1780
1749
  elKill(el)
1781
1750
  return el.src
1782
1751
  }), function(res) {
1783
- res = res.concat(sources, next && next.src && next.innerHTML).filter(Boolean)
1752
+ res = res.concat(sources, next && next.src && next.innerHTML)
1784
1753
  if (res[sources.length = 0]) {
1785
1754
  if (!parser) LiteJS.ui = LiteJS()
1786
1755
  each(res, parser)