UNPKG

61.5 kBJavaScriptView Raw
1/*
2* @version 19.5.1
3* @author Lauri Rooden <lauri@rooden.ee>
4* @license MIT License
5*/
6
7
8
9!function(Date, proto) {
10 var Date$prototype = Date[proto]
11 , String$prototype = String[proto]
12 , Number$prototype = Number[proto]
13 , maskRe = /(\[)((?:\\?.)*?)\]|([YMD])\3\3\3?|([YMDHhmsWSZ])(\4?)|[uUASwoQ]|(["\\\n\r\u2028\u2029])/g
14 , dateRe = /(\d+)[-.\/](\d+)[-.\/](\d+)/
15 , timeRe = /(\d+):(\d+)(?::(\d+))?(\.\d+)?(?:\s*(?:(a)|(p))\.?m\.?)?(\s*(?:Z|GMT|UTC)?(?:([-+]\d\d):?(\d\d)?)?)?/i
16 , fns = Object.create(null)
17 , aliases = {
18 sec: "s",
19 second: "s",
20 seconds: "s",
21 min: "m",
22 minute: "m",
23 minutes: "m",
24 hr: "h",
25 hour: "h",
26 hours: "h",
27 day: "D",
28 days: "D",
29 week: "W",
30 weeks: "W",
31 month: "M",
32 months: "M",
33 year: "Y",
34 years: "Y"
35 }
36 , units = {
37 S: 1,
38 s: 1000,
39 m: 60000,
40 h: 3600000,
41 D: 86400000,
42 W: 604800000
43 }
44 , tmp1 = new Date()
45 , tmp2 = new Date()
46 , map = Date.fnMap = {
47 w: "Day()||7",
48 Y: "FullYear()%100",
49 M: "Month()+1",
50 D: "Date()",
51 h: "Hours()",
52 H: "Hours()%12||12",
53 m: "Minutes()",
54 s: "Seconds()",
55 S: "Milliseconds()"
56 }
57 , locales = Date.locales = {
58 en: {
59 am: "AM",
60 pm: "PM",
61 names: "JanFebMarAprMayJunJulAugSepOctNovDecJanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecemberSunMonTueWedThuFriSatSundayMondayTuesdayWednesdayThursdayFridaySaturday".match(/.[a-z]+/g),
62 masks: {
63 LT: "hh:mm",
64 LTS: "hh:mm:ss",
65 L: "DD/MM/YYYY",
66 LL: "D MMMM YYYY",
67 LLL: "D MMMM YYYY hh:mm",
68 LLLL: "DDDD, D MMMM YYYY hh:mm"
69 }
70 }
71 }
72 , masks = Date.masks = {
73 "iso": "UTC:YYYY-MM-DD[T]hh:mm:ss[Z]"
74 }
75
76
77 Date.makeStr = makeStr
78 function makeStr(mask, utc) {
79 var get = "d.get" + (utc ? "UTC" : "")
80 , setA = "a.setTime(+d+((4-(" + get + map.w + "))*864e5))"
81 return (utc ? mask.slice(4) : mask).replace(maskRe, function(match, quote, text, MD, single, pad, esc) {
82 var str = (
83 esc ? escape(esc).replace(/%u/g, "\\u").replace(/%/g, "\\x") :
84 quote ? text :
85 MD == "Y" ? get + "FullYear()" :
86 MD ? "l.names[" + get + (MD == "M" ? "Month" : "Day" ) + "()+" + (match == "DDD" ? 24 : MD == "D" ? 31 : match == "MMM" ? 0 : 12) + "]" :
87 match == "u" ? "(d/1000)>>>0" :
88 match == "U" ? "+d" :
89 match == "Q" ? "((" + get + "Month()/3)|0)+1" :
90 match == "A" ? "l[" + get + map.h + ">11?'pm':'am']" :
91 match == "o" ? setA + ",a" + get.slice(1) + "FullYear()" :
92 single == "Z" ? "(t=o)?(t<0?((t=-t),'-'):'+')+(t<600?'0':'')+(0|(t/60))" + (pad ? "" : "+':'") + "+((t%=60)>9?t:'0'+t):'Z'" :
93 single == "W" ? "Math.ceil(((" + setA + "-a.s" + get.slice(3) + "Month(0,1))/864e5+1)/7)" :
94 get + map[single || match]
95 )
96 return quote || esc ? str : '"+(' + (
97 match == "SS" ? "(t=" + str + ")>9?t>99?t:'0'+t:'00'+t" :
98 pad && single != "Z" ? "(t=" + str + ")>9?t:'0'+t" :
99 str
100 ) + ')+"'
101 })
102 }
103
104 Date$prototype.date = function(_mask, _zone) {
105 var offset, undef
106 , date = this
107 , locale = locales[date._locale || Date._locale || "en"] || locales.en
108 , mask = locale.masks && locale.masks[_mask] || masks[_mask] || _mask || masks.iso
109 , zone = _zone == undef ? date._tz || Date._tz : _zone
110 , utc = mask.slice(0, 4) == "UTC:"
111 if (zone != undef && !utc) {
112 offset = 60 * zone
113 tmp1.setTime(+date + offset * 6e4)
114 utc = mask = "UTC:" + mask
115 } else {
116 offset = utc ? 0 : -date.getTimezoneOffset()
117 tmp1.setTime(+date)
118 }
119 return isNaN(+date) ? "" + date : (
120 fns[mask] || (fns[mask] = Function("d,a,o,l", 'var t;return "' + makeStr(mask, utc) + '"')))(
121 tmp1,
122 tmp2,
123 offset,
124 locale
125 )
126 }
127
128 addFn("add", function(amount, _unit, mask) {
129 var date = this
130 , unit = aliases[_unit] || _unit
131 if (unit == "M" || unit == "Y" && (amount *= 12)) {
132 unit = date.getUTCDate()
133 date.setUTCMonth(date.getUTCMonth() + amount)
134 if (unit > (unit = date.getUTCDate())) {
135 date.add(-unit, "D")
136 }
137 } else if (amount) {
138 date.setTime(date.getTime() + (amount * (units[unit] || 1)))
139 }
140 return mask ? date.date(mask) : date
141 })
142
143 addFn("startOf", function(_unit, mask) {
144 var date = this
145 , unit = aliases[_unit] || _unit
146 if (unit == "Y") {
147 date.setUTCMonth(0, 1)
148 unit = "D"
149 } else if (unit == "M") {
150 date.setUTCDate(1)
151 unit = "D"
152 }
153 date.setTime(date - (date % (units[unit] || 1)))
154 return mask ? date.date(mask) : date
155 })
156
157 addFn("endOf", function(unit, mask) {
158 return this.startOf(unit).add(1, unit).add(-1, "S", mask)
159 })
160
161 addFn("since", function(from, _unit) {
162 var diff
163 , date = this
164 , unit = aliases[_unit] || _unit
165 if (typeof from == "string") {
166 from = aliases[from] ? (tmp2.setTime(+date), tmp2.startOf(from)) : from.date()
167 }
168 if (units[unit]) {
169 diff = (date - from) / units[unit]
170 } else {
171 diff = date.since("month", "S") - from.since("month", "S")
172 if (diff) {
173 tmp1.setTime(+date)
174 diff /= units.D * tmp1.endOf("M").getUTCDate()
175 }
176 diff += 12 * (date.getUTCFullYear() - from.getUTCFullYear()) + date.getUTCMonth() - from.getUTCMonth()
177 if (unit == "Y") {
178 diff /= 12
179 }
180 }
181
182 return diff
183 })
184
185 //*/
186
187
188 /*
189 * // In Chrome Date.parse("01.02.2001") is Jan
190 * num = +date || Date.parse(date) || ""+date;
191 */
192
193 String$prototype.date = function(mask, zoneOut, zoneIn) {
194 var undef, date, match, year, month
195 , str = this
196 if (isNaN(+str)) {
197 if (match = str.match(dateRe)) {
198 // Big endian date, starting with the year, eg. 2011-01-31
199 // Middle endian date, starting with the month, eg. 01/31/2011
200 // Little endian date, starting with the day, eg. 31.01.2011
201 year = match[1] > 99 ? 1 : 3
202 month = Date.middleEndian ? 4 - year : 2
203 date = new Date(match[year], match[month] - 1, match[6 - month - year])
204 } else {
205 date = new Date()
206 }
207
208 // Time
209 match = str.match(timeRe) || [0, 0, 0]
210 date.setHours(
211 match[6] && match[1] < 12 ? +match[1] + 12 :
212 match[5] && match[1] == 12 ? 0 : match[1],
213 match[2], match[3]|0, (1000 * match[4])|0
214 )
215
216 // Timezone
217 if (match[7]) {
218 zoneIn = (match[8]|0) + ((match[9]|0)/(match[8]<0?-60:60))
219 }
220
221 if (zoneIn != undef) {
222 date.setTime(date - (60 * zoneIn + date.getTimezoneOffset()) * 60000)
223 }
224 return mask ? date.date(mask, zoneOut) : date
225 }
226 return (+str).date(mask, zoneOut, zoneIn)
227 }
228
229 Number$prototype.date = function(mask, zoneOut, zoneIn) {
230 var date
231 , num = this
232 if (num < 4294967296) num *= 1000
233 date = new Date(
234 zoneIn != date ?
235 tmp1.setTime(num) - (60 * zoneIn + tmp1.getTimezoneOffset()) * 60000 :
236 num
237 )
238
239 return mask ? date.date(mask, zoneOut) : date
240 }
241
242 function addFn(method, fn) {
243 Date$prototype[method] = fn
244 String$prototype[method] = Number$prototype[method] = function(a, b, c) {
245 return this.date()[method](a, b, c)
246 }
247 }
248
249 function makeSetter(method) {
250 Date[method] = Date$prototype[method] = function(value, mask) {
251 var date = this
252 date["_" + method] = value
253 return mask ? date.date(mask) : date
254 }
255 }
256
257 makeSetter("tz")
258 makeSetter("locale")
259}(Date, "prototype")
260!function(exports) {
261 var pointerCache = {}
262 , hasOwn = pointerCache.hasOwnProperty
263
264 exports.clone = clone
265 exports.mergePatch = mergePatch
266 exports.isObject = isObject
267
268 /**
269 * JSON Merge Patch
270 * @see https://tools.ietf.org/html/rfc7396
271 */
272
273 function mergePatch(target, patch, changed, previous, pointer) {
274 var undef, key, oldVal, val, len, nextPointer
275 if (isObject(patch)) {
276 if (!pointer) {
277 pointer = ""
278 }
279 if (!isObject(target)) {
280 target = {}
281 }
282 for (key in patch) if (
283 undef !== (oldVal = target[key], val = patch[key]) &&
284 hasOwn.call(patch, key) &&
285 (
286 undef == val ?
287 undef !== oldVal && delete target[key] :
288 target[key] !== val
289 )
290 ) {
291 nextPointer = pointer + "/" + key.replace(/~/g, "~0").replace(/\//g, "~1")
292 len = changed && isObject(target[key]) && changed.length
293 if (undef != val) {
294 target[key] = mergePatch(target[key], val, changed, previous, nextPointer)
295 }
296 if (len === false || changed && len != changed.length) {
297 changed.push(nextPointer)
298 if (previous && !isObject(oldVal)) {
299 previous[nextPointer] = oldVal
300 }
301 }
302 }
303 } else {
304 if (changed && isObject(target)) {
305 val = {}
306 for (key in target) if (hasOwn.call(target, key)) {
307 val[key] = null
308 }
309 mergePatch(target, val, changed, previous, pointer)
310 }
311 target = patch
312 }
313 return target
314 }
315
316 function clone(obj) {
317 var temp, key
318 if (obj && typeof obj == "object") {
319 // new Date().constructor() returns a string
320 temp = obj instanceof Date ? new Date(+obj) :
321 obj instanceof RegExp ? RegExp(obj.source, (""+obj).split("/").pop()) :
322 obj.constructor()
323 for (key in obj) if (hasOwn.call(obj, key)) {
324 temp[key] = clone(obj[key])
325 }
326 obj = temp
327 }
328 return obj
329 }
330
331 function isObject(obj) {
332 return !!obj && obj.constructor === Object
333 }
334
335// `this` refers to the `window` in browser and to the `exports` in Node.js.
336}(this.JSON || this)
337!function(F) {
338 // Time to live - Run *onTimeout* if Function not called on time
339 F.ttl = function(ms, onTimeout, scope) {
340 var fn = this
341 , tick = setTimeout(function() {
342 ms = 0
343 if (onTimeout) onTimeout()
344 }, ms)
345
346 return function() {
347 clearTimeout(tick)
348 if (ms) fn.apply(scope, arguments)
349 }
350 }
351
352 // Run Function one time after last call
353 F.once = function(ms, scope) {
354 var tick, args
355 , fn = this
356 return function() {
357 clearTimeout(tick)
358 args = arguments
359 tick = setTimeout(function() {
360 fn.apply(scope, args)
361 }, ms)
362 }
363 }
364
365 // Maximum call rate for Function
366 // leading edge, trailing edge
367 F.rate = function(ms, last_call, _scope) {
368 var tick, args
369 , fn = this
370 , scope = _scope
371 , next = 0
372 return function() {
373 var now = Date.now()
374 clearTimeout(tick)
375 if (_scope === void 0) scope = this
376 if (now >= next) {
377 next = now + ms
378 fn.apply(scope, arguments)
379 } else if (last_call) {
380 args = arguments
381 tick = setTimeout(function() {
382 fn.apply(scope, args)
383 }, next - now)
384 }
385 }
386 }
387}(Function.prototype)
388!function(exports, Object) {
389 var undef
390 , P = "prototype"
391 , A = Array[P]
392 , F = Function[P]
393 , S = String[P]
394 , N = Number[P]
395 , slice = F.call.bind(A.slice)
396 , fns = {}
397 , hasOwn = fns.hasOwnProperty
398 , fnRe = /('|")(?:\\?.)*?\1|\/(?:\\?.)+?\/[gim]*|\b(?:false|in|new|null|this|true|typeof|void)\b|\.\w+|\w+:/g
399 , formatRe = /{(?!\\)((?:("|')(?:\\?.)*?\2|[^}])*?)}/g
400 , numbersRe = /-?\d+\.?\d*/g
401 , wordRe = /\b[a-z_$][\w$]*/ig
402 , unescapeRe = /{\\/g
403
404
405 exports.Fn = Fn
406 Fn.hold = hold
407 Fn.wait = wait
408
409
410 // Function extensions
411 // -------------------
412
413 F.extend = function() {
414 var arg
415 , fn = this
416 , i = 0
417
418 function wrapper() {
419 return fn.apply(this, arguments)
420 }
421
422 for (wrapper[P] = Object.create(fn[P]); arg = arguments[i++]; ) {
423 Object.assign(wrapper[P], arg)
424 }
425 wrapper[P].constructor = wrapper
426 return wrapper
427 }
428
429
430 // Non-standard
431 Object.each = function(obj, fn, scope, key) {
432 if (obj) for (key in obj) {
433 hasOwn.call(obj, key) && fn.call(scope, obj[key], key, obj)
434 }
435 }
436
437 // Chrome54, FF47, Edge14, Safari10.1
438 Object.values = function(obj) {
439 return Object.keys(obj || {}).map(function(e) {
440 return obj[e]
441 })
442 }
443
444 // Non-standard
445 // IE<9 bug: [1,2].splice(0).join("") == "" but should be "12"
446 A.remove = arrayRemove
447 function arrayRemove() {
448 var arr = this
449 , len = arr.length
450 , o = slice(arguments)
451 , lastId = -1
452
453 for (; len--; ) if (~o.indexOf(arr[len])) {
454 arr.splice(lastId = len, 1)
455 }
456 return lastId
457 }
458
459 A.each = A.forEach
460 // uniq
461 // first item preserved
462 A.uniq = function() {
463 for (var a = this, i = a.length; i--; ) {
464 if (a.indexOf(a[i]) !== i) a.splice(i, 1)
465 }
466 return a
467 }
468
469 A.pushUniq = function(item) {
470 return this.indexOf(item) < 0 && this.push(item)
471 }
472
473 // THANKS: Oliver Steele - Functional Javascript [http://www.osteele.com/sources/javascript/functional/]
474 function Fn(expr /*, scope, mask1, ..maskN */) {
475 var args = []
476 , arr = expr.match(/[^"']+?->|.+$/g)
477 , scope = slice(arguments, 1)
478 , key = scope.length + ":" + expr
479 , fn = fns[key]
480
481 if (!fn) {
482 fn = expr.replace(fnRe, "").match(wordRe) || []
483 for (; arr.length > 1; ) {
484 expr = arr.pop()
485 args = arr.pop().match(/\w+/g) || []
486 arrayRemove.apply(fn, args)
487 if (arr.length) {
488 arr.push("function(" + args + "){return(" + expr + ")}" + (scope[0] ? ".bind(this)" : ""))
489 }
490 }
491 expr = "return(" + expr + ")"
492
493 if (scope[0]) {
494 arr = Object.keys(scope).map(Fn("a->'__'+a"))
495 arr[0] = "this"
496 expr = (
497 fn[0] ?
498 "var " + fn.uniq().join("='',") + "='';" :
499 ""
500 ) + "with(" + arr.join(")with(") + "){" + expr + "}"
501 args = arr.slice(1).concat(args)
502 }
503
504 fn = fns[key] = Function(args, expr)
505 }
506
507 return scope.length ? fn.bind.apply(fn, scope) : fn
508 }
509
510 Fn.keys = function(str) {
511 var i, tmp
512 , arr = []
513 , match = str.match(formatRe)
514 if (match) {
515 for (i = match.length; i--; ) {
516 if (tmp = match[i].replace(fnRe, "").match(wordRe)) {
517 arr.push.apply(arr, tmp)
518 }
519 }
520 }
521 return arr.uniq()
522 }
523
524 S.format = function() {
525 var args = A.slice.call(arguments)
526 args.unshift(0)
527 return this.replace(formatRe, function(_, arg) {
528 args[0] = arg
529 return Fn.apply(null, args)()
530 }).replace(unescapeRe, "{")
531 }
532
533 N.format = function(data) {
534 return "" + this
535 }
536
537 S.safe = function() {
538 return this
539 .replace(/&/g, "&amp;")
540 .replace(/</g, "&lt;")
541 .replace(/>/g, "&gt;")
542 .replace(/\"/g, "&quot;")
543 }
544
545 S.capitalize = function() {
546 return this.charAt(0).toUpperCase() + this.slice(1)
547 }
548
549 S.camelCase = function() {
550 return this.replace(/[ _-]+([a-z])/g, function(_, a) {
551 return a.toUpperCase()
552 })
553 }
554
555 S.lower = S.toLowerCase
556 S.upper = S.toUpperCase
557
558 N.step = function(a, add) {
559 var x = ("" + a).split(".")
560 , steps = this / a
561 , n = ~~(steps + ((steps < 0 ? -1 : 1) * (add == undef ? .5 : add === 1 && steps == (steps|0) ? 0 : +add))) * a
562 return "" + (1 in x ? n.toFixed(x[1].length) : n)
563 }
564
565 S.step = function(a, add) {
566 return this.replace(numbersRe, function(num) {
567 return (+num).step(a, add)
568 })
569 }
570
571 N.scale = words([1000, 1000, 1000], ["","k","M","G"], {"default": "{n}{u}"})
572
573 S.scale = function() {
574 return this.replace(numbersRe, function(num) {
575 return (+num).scale()
576 })
577 }
578
579 S.pick = N.pick = function() {
580 var val = this + "="
581 for (var s, a = arguments, i = 0, len = a.length; i < len;) {
582 s = a[i++]
583 if (s.indexOf(val) == 0) {
584 s = s.slice(val.length)
585 i = len
586 }
587 }
588 return s.replace("#", this)
589 }
590
591 S.plural = N.plural = function() {
592 // Plural-Forms: nplurals=2; plural=n != 1;
593 // http://www.gnu.org/software/gettext/manual/html_mono/gettext.html#Plural-forms
594 return arguments[ +Fn("n->" + (String.plural || "n!=1"))( parseFloat(this) ) ].replace("#", this)
595 }
596
597 A.pluck = function(name) {
598 for (var arr = this, i = arr.length, out = []; i--; ) {
599 out[i] = arr[i][name]
600 }
601 return out
602 }
603
604 function words(steps, units, strings, overflow) {
605 return function(input) {
606 var n = +(arguments.length ? input : this)
607 , i = 0
608 , s = strings || {"default": "{n} {u}{s}"}
609
610 for (; n>=steps[i]; ) {
611 n /= steps[i++]
612 }
613 if (i == steps.length && overflow) {
614 return overflow(this)
615 }
616 i = units[i]
617 return (s[n < 2 ? i : i + "s"] || s["default"]).format({n: n, u: i, s: n < 2 ? "" : "s"})
618 }
619 }
620 Fn.words = words
621
622 function wait(fn) {
623 var pending = 1
624 function resume() {
625 if (!--pending && fn) fn.call(this)
626 }
627 resume.wait = function() {
628 pending++
629 return resume
630 }
631 return resume
632 }
633
634 function hold(ignore) {
635 var k
636 , obj = this
637 , hooks = []
638 , hooked = []
639 , _resume = wait(resume)
640 ignore = ignore || obj.syncMethods || []
641
642 for (k in obj) if (typeof obj[k] == "function" && ignore.indexOf(k) == -1) !function(k) {
643 hooked.push(k, hasOwn.call(obj, k) && obj[k])
644 obj[k] = function() {
645 hooks.push(k, arguments)
646 return obj
647 }
648 }(k)
649
650 /**
651 * `wait` is already in hooked array,
652 * so override hooked method
653 * that will be cleared on resume.
654 */
655 obj.wait = _resume.wait
656
657 return _resume
658
659 function resume() {
660 for (var v, scope = obj, i = hooked.length; i--; i--) {
661 if (hooked[i]) obj[hooked[i-1]] = hooked[i]
662 else delete obj[hooked[i-1]]
663 }
664 // i == -1 from previous loop
665 for (; v = hooks[++i]; ) {
666 scope = scope[v].apply(scope, hooks[++i]) || scope
667 }
668 hooks = hooked = null
669 }
670 }
671
672}(this, Object)
673!function(exports) {
674 var empty = []
675
676 exports.Emitter = EventEmitter
677 exports.asEmitter = asEmitter
678
679 function EventEmitter() {}
680
681 function asEmitter(obj) {
682 obj.on = on
683 obj.off = off
684 obj.one = one
685 obj.emit = emit
686 obj.listen = listen
687 obj.unlisten = unlisten
688 }
689 asEmitter(EventEmitter.prototype)
690
691 function on(type, fn, scope, _origin) {
692 var emitter = this === exports ? empty : this
693 , events = emitter._e || (emitter._e = Object.create(null))
694 if (type && fn) {
695 if (typeof fn === "string") fn = emit.bind(null, fn)
696 emit.call(emitter, "newListener", type, fn, scope, _origin)
697 ;(events[type] || (events[type] = [])).unshift(scope, _origin, fn)
698 }
699 return emitter
700 }
701
702 function off(type, fn, scope) {
703 var i, args
704 , emitter = this === exports ? empty : this
705 , events = emitter._e && emitter._e[type]
706 if (events) {
707 for (i = events.length - 2; i > 0; i -= 3) {
708 if ((events[i + 1] === fn || events[i] === fn) && events[i - 1] == scope) {
709 args = events.splice(i - 1, 3)
710 emit.call(emitter, "removeListener", type, args[2], args[0], args[1])
711 if (fn) break
712 }
713 }
714 }
715 return emitter
716 }
717
718 function one(type, fn, scope) {
719 var emitter = this === exports ? empty : this
720 function remove() {
721 emitter.off(type, fn, scope).off(type, remove, scope)
722 }
723 return emitter.on(type, remove, scope).on(type, fn, scope)
724 }
725
726 // emitNext
727 // emitLate
728
729 function emit(type) {
730 var args, i
731 , emitter = this === exports ? empty : this
732 , _e = emitter._e
733 , arr = _e ? (_e[type] || empty).concat(_e["*"] || empty) : empty
734 _e = 0
735 if (i = arr.length) {
736 for (args = arr.slice.call(arguments, 1); i--; ) {
737 arr[i--].apply(arr[--i] || emitter, args)
738 _e++
739 }
740 }
741 return _e
742 }
743
744 function listen(emitter, ev, fn, scope, _origin) {
745 if (emitter) {
746 emitter.on(ev, fn, scope)
747 ;(this._l || (this._l = [])).push([emitter, ev, fn, scope, _origin])
748 }
749 return this
750 }
751
752 function unlisten(key) {
753 var a, i
754 , listening = this._l
755 if (listening) for (i = listening.length; i--; ) {
756 a = listening[i]
757 if (key === "*" || a.indexOf(key) > -1) {
758 listening.splice(i, 1)
759 a[0].off(a[1], a[2], a[3])
760 }
761 }
762 return this
763 }
764
765// `this` refers to the `window` in browser and to the `exports` in Node.js.
766}(this.Event || this)
767/* litejs.com/MIT-LICENSE.txt */
768
769
770
771!function(window, document, history, location) {
772 var cb, base, lastRoute, iframe, tick, last
773 , cleanRe = /^[#\/\!]+|[\s\/]+$/g
774
775 // The JScript engine used in IE doesn't recognize vertical tabulation character
776 // http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
777 // oldIE = "\v" == "v"
778 //
779 // The documentMode is an IE only property, supported in IE8+.
780 //
781 // Starting in Internet Explorer 9 standards mode, Internet Explorer 10 standards mode,
782 // and win8_appname_long apps, you cannot identify the browser as Internet Explorer
783 // by testing for the equivalence of the vertical tab (\v) and the "v".
784 // In earlier versions, the expression "\v" === "v" returns true.
785 // In Internet Explorer 9 standards mode, Internet Explorer 10 standards mode,
786 // and win8_appname_long apps, the expression returns false.
787 , ie6_7 = !+"\v1" && (document.documentMode | 0) < 8
788
789 function getUrl(_loc) {
790 var url
791 /*** PUSH ***/
792 if (base) {
793 url = location.pathname.slice(base.length)
794 } else {
795 /**/
796 // bug in Firefox where location.hash is decoded
797 // bug in Safari where location.pathname is decoded
798
799 // var hash = location.href.split('#')[1] || '';
800 // https://bugs.webkit.org/show_bug.cgi?id=30225
801 // https://github.com/documentcloud/backbone/pull/967
802 url = (_loc || location).href.split("#")[1] || ""
803 /*** PUSH ***/
804 }
805 /**/
806 return url.replace(cleanRe, "")
807 }
808
809 function setUrl(url, replace) {
810 /*** PUSH ***/
811 if (base) {
812 history[replace ? "replaceState" : "pushState"](null, null, base + url)
813 } else {
814 /**/
815 location[replace ? "replace" : "assign"]("#" + url)
816 // Opening and closing the iframe tricks IE7 and earlier
817 // to push a history entry on hash-tag change.
818 if (iframe && getUrl() !== getUrl(iframe.location) ) {
819 iframe.location[replace ? "replace" : iframe.document.open().close(), "assign"]("#" + url)
820 }
821 /*** PUSH ***/
822 }
823 /**/
824 checkUrl()
825 }
826
827 function checkUrl() {
828 if (lastRoute != (lastRoute = getUrl()) && cb) {
829 cb(lastRoute)
830 }
831 }
832
833 history.getUrl = getUrl
834 history.setUrl = setUrl
835
836 history.start = function(_cb) {
837 cb = _cb
838 /*** PUSH ***/
839 // Chrome5, Firefox4, IE10, Safari5, Opera11.50
840 var url
841 , _base = document.documentElement.getElementsByTagName("base")[0]
842 if (_base) _base = _base.href.replace(/.*:\/\/[^/]*|[^\/]*$/g, "")
843 if (_base && !history.pushState) {
844 url = location.pathname.slice(_base.length)
845 if (url) {
846 location.replace(_base + "#" + url)
847 }
848 }
849 if (_base && history.pushState) {
850 base = _base
851
852 url = location.href.split("#")[1]
853 if (url && !getUrl()) {
854 setUrl(url, 1)
855 }
856
857 // Chrome and Safari emit a popstate event on page load, Firefox doesn't.
858 // Firing popstate after onload is as designed.
859 //
860 // See the discussion on https://bugs.webkit.org/show_bug.cgi?id=41372,
861 // https://code.google.com/p/chromium/issues/detail?id=63040
862 // and the change to the HTML5 spec that was made:
863 // http://html5.org/tools/web-apps-tracker?from=5345&to=5346.
864 window.onpopstate = checkUrl
865 } else
866 /**/
867 if ("onhashchange" in window && !ie6_7) {
868 // There are onhashchange in IE7 but its not get emitted
869 //
870 // Basic support:
871 // Chrome 5.0, Firefox 3.6, IE 8, Opera 10.6, Safari 5.0
872 window.onhashchange = checkUrl
873 } else {
874 if (ie6_7 && !iframe) {
875 // IE<9 encounters the Mixed Content warning when the URI javascript: is used.
876 // IE5/6 additionally encounters the Mixed Content warning when the URI about:blank is used.
877 // src="//:"
878 iframe = document.body.appendChild(document.createElement('<iframe class="hide" tabindex="-1">')).contentWindow
879 }
880 clearInterval(tick)
881 tick = setInterval(function(){
882 var cur = getUrl()
883 if (iframe && last === cur) cur = getUrl(iframe.location)
884 if (last !== cur) {
885 last = cur
886 iframe ? setUrl(cur) : checkUrl()
887 }
888 }, 60)
889 }
890 checkUrl()
891 }
892}(this, document, history, location)
893/* litejs.com/MIT-LICENSE.txt */
894
895
896
897!function(exports) {
898 var fn, lastView, lastParams, lastStr, lastUrl, syncResume
899 , capture = 1
900 , fnStr = ""
901 , reStr = ""
902 , views = View.views = {}
903 , paramCb = {}
904 , hasOwn = views.hasOwnProperty
905 , escapeRe = /[.*+?^=!:${}()|\[\]\/\\]/g
906 , parseRe = /\{([\w%.]+?)\}|.[^{\\]*?/g
907
908 exports.View = View
909
910 function View(route, el, parent) {
911 var view = views[route]
912 if (view) {
913 if (el) {
914 view.el = el
915 view.parent = parent && View(parent)
916 }
917 return view
918 }
919 view = this
920 if (!(view instanceof View)) return new View(route, el, parent)
921 views[view.route = route] = view
922 view.el = el
923 view.parent = parent && View(parent)
924
925 if (route.charAt(0) != "#") {
926 var params = "m[" + (view.seq = capture++) + "]?("
927 , _re = route.replace(parseRe, function(_, key) {
928 return key ?
929 (params += "o['" + key + "']=m[" + (capture++) + "],") && "([^/]+?)" :
930 _.replace(escapeRe, "\\$&")
931 })
932
933 fnStr += params + "'" + route + "'):"
934 reStr += (reStr ? "|(" : "(") + _re + ")"
935 fn = 0
936 }
937 }
938
939 View.prototype = {
940 show: function(_params) {
941 var parent
942 , params = lastParams = _params || {}
943 , view = lastView = this
944 , tmp = params._v || view
945 , close = view.isOpen && view
946
947 View.active = view.route
948
949 for (; tmp; tmp = parent) {
950 syncResume = params._v = tmp
951 tmp.emit("ping", params)
952 View.emit("ping", params, tmp)
953 syncResume = null
954 if (lastParams != params) return
955 if (parent = tmp.parent) {
956 if (parent.child && parent.child != tmp) {
957 close = parent.child
958 }
959 parent.child = tmp
960 }
961 if (!tmp.el) {
962 if (tmp.file) {
963 xhr.load(
964 tmp.file
965 .replace(/^|,/g, "$&" + (View.base || ""))
966 .split(","),
967 view.wait()
968 )
969 tmp.file = null
970 } else {
971 View("404").show(Object.assign({}, params))
972 }
973 return
974 }
975 }
976
977 for (tmp in params) if (tmp.charAt(0) != "_") {
978 if (syncResume = hasOwn.call(paramCb, tmp) && paramCb[tmp] || paramCb["*"]) {
979 syncResume.call(view, params[tmp], tmp, params)
980 syncResume = null
981 }
982 }
983
984 bubbleDown(params, close)
985 },
986 wait: function() {
987 var params = lastParams
988 params._p = 1 + (params._p | 0)
989 return function() {
990 if (--params._p || lastParams != params || syncResume) return
991 if (params._d) {
992 bubbleDown(params)
993 } else if (params._v) {
994 lastView.show(params)
995 }
996 }
997 }
998 }
999
1000 function bubbleDown(params, close) {
1001 var tmp
1002 , view = params._v
1003 , parent = view && view.parent
1004 if (!view || params._p && /{/.test(view.route)) {
1005 return closeView(close)
1006 }
1007 if (parent && !view.isOpen || view === close) {
1008 closeView(close, view)
1009 El.scope(
1010 view.isOpen = view.el.cloneNode(true),
1011 El.scope(tmp = parent.isOpen || parent.el)
1012 )
1013 El.append(tmp, view.isOpen)
1014 El.render(view.isOpen)
1015 parent.emit("openChild", view, close)
1016 view.emit("open", params)
1017 View.emit("open", params, view)
1018 if (view.kb) El.addKb(view.kb)
1019 close = null
1020 }
1021 if (params._d = params._v = view.child) {
1022 bubbleDown(params, close)
1023 }
1024 if (lastView == view) {
1025 view.emit("show", params)
1026 View.emit("show", params, view)
1027 blur()
1028 }
1029 }
1030
1031 function closeView(view, open) {
1032 if (view && view.isOpen) {
1033 view.parent.emit("closeChild", view, open)
1034 closeView(view.child)
1035 El.kill(view.isOpen)
1036 view.isOpen = null
1037 if (view.kb) El.rmKb(view.kb)
1038 view.emit("close")
1039 }
1040 }
1041
1042 Event.asEmitter(View)
1043 Event.asEmitter(View.prototype)
1044
1045 View.base = "view/"
1046 View.home = "home"
1047
1048 View.get = get
1049 function get(url, params) {
1050 if (!fn) {
1051 fn = Function(
1052 "var r=/^\\/?(?:" + reStr + ")[\\/\\s]*$/;" +
1053 "return function(i,o,d){var m=r.exec(i);return m!==null?(" + fnStr + "d):d}"
1054 )()
1055 }
1056 return View(fn(url || View.home, params || {}, "404"))
1057 }
1058
1059 View.show = function(url, _params) {
1060 if (url === true) {
1061 url = lastUrl
1062 lastUrl = 0
1063 }
1064 var params = _params || {}
1065 , view = get(url, params)
1066 if (!view.isOpen || lastUrl != url) {
1067 params._u = lastUrl = url
1068 view.show(El.data.route = params)
1069 }
1070 }
1071
1072 View.param = function(name, cb, re) {
1073 [].concat(name).forEach(function(n) {
1074 paramCb[n] = cb
1075 })
1076 }
1077
1078 View.def = function(str) {
1079 for (var match, re = /(\S+) (\S+)/g; match = re.exec(str);) {
1080 match[1].split(",").map(function(view) {
1081 view = View(defMap(view, lastStr))
1082 view.file = (view.file ? view.file + "," : "") +
1083 match[2].split(",").map(function(file) {
1084 return views[file] ? views[file].file : defMap(file, lastStr)
1085 })
1086 })
1087 }
1088 }
1089
1090 View.blur = blur
1091 function blur() {
1092 // When a View completes, blur focused link
1093 // IE8 can throw an exception for document.activeElement.
1094 try {
1095 var el = document.activeElement
1096 , tag = el && el.tagName
1097 if (tag === "A" || tag === "BUTTON") el.blur()
1098 } catch(e) {}
1099 }
1100
1101 View.url = defMap
1102 function defMap(str, _last) {
1103 var chr = str.charAt(0)
1104 , slice = str.slice(1)
1105 , last = _last || lastUrl
1106 return (
1107 chr === "+" ? last + slice :
1108 chr === "%" ? ((chr = last.lastIndexOf(slice.charAt(0))), (chr > 0 ? last.slice(0, chr) : last)) + slice :
1109 (lastStr = str)
1110 )
1111 }
1112
1113}(this)
1114/* litejs.com/MIT-LICENSE.txt */
1115
1116
1117
1118!function(window, document, Object, Event, protoStr) {
1119 var currentLang, styleNode
1120 , seq = 0
1121 , elCache = El.cache = {}
1122 , wrapProto = []
1123 , slice = wrapProto.slice
1124 , hasOwn = elCache.hasOwnProperty
1125 , body = document.body
1126 , root = document.documentElement
1127 , txtAttr = El.T = "textContent" in body ? "textContent" : "innerText"
1128 , templateRe = /^([ \t]*)(@?)((?:("|')(?:\\?.)*?\4|[-\w:.#[\]=])*)[ \t]*(([\])}]?).*?([[({]?))$/gm
1129 , renderRe = /[;\s]*(\w+)(?:\s*(:?):((?:(["'\/])(?:\\?.)*?\3|[^;])*))?/g
1130 , splitRe = /[,\s]+/
1131 , bindings = El.bindings = {
1132 attr: setAttr,
1133 css: El.css = acceptMany(function(el, key, val) {
1134 el.style[key.camelCase()] = "" + val || ""
1135 }),
1136 "class": El.cls = acceptMany(function(el, name, fn) {
1137 el && (arguments.length < 3 || fn ? addClass : rmClass)(el, name)
1138 }),
1139 data: function(el, key, val) {
1140 setAttr(el, "data-" + key, val)
1141 },
1142 html: function(el, html) {
1143 el.innerHTML = html
1144 },
1145 ref: function(el, name) {
1146 this[name] = el
1147 },
1148 txt: El.txt = function(el, txt) {
1149 // In Safari 2.x, innerText results an empty string
1150 // when style.display=="none" or node is not in dom
1151 //
1152 // innerText is implemented in IE4, textContent in IE9
1153 // Opera 9-10 have Node.text
1154
1155 if (el[txtAttr] !== txt) el[txtAttr] = txt
1156 },
1157 val: function(el, txt) {
1158 valFn(el, txt)
1159 },
1160 "with": function(el, map) {
1161 var scope = elScope(el, this)
1162 Object.assign(scope, map)
1163 if (scope !== this) {
1164 render(el)
1165 return true
1166 }
1167 }
1168 }
1169 , bindMatch = []
1170 , scopeData = El.data = {
1171 _: i18n,
1172 _b: bindings,
1173 El: El,
1174 history: history,
1175 View: View
1176 }
1177 , addClass = El.addClass = acceptMany(_addClass)
1178 , rmClass = El.rmClass = acceptMany(_rmClass)
1179
1180 /*** ie8 ***/
1181
1182 // JScript engine in IE<9 does not recognize vertical tabulation character
1183 , ie678 = !+"\v1"
1184 , ie67 = ie678 && (document.documentMode | 0) < 8
1185
1186 , matches = El.matches = body.matches ?
1187 function(el, sel) {
1188 return el.matches(sel)
1189 } :
1190 function(el, sel) {
1191 return !!selectorFn(sel)(el)
1192 }
1193 , closest = El.closest = body.closest ?
1194 function(el, sel) {
1195 return (el.closest ? el : el.parentNode).closest(sel)
1196 } :
1197 function(el, sel) {
1198 return walk("parentNode", 1, el, sel)
1199 }
1200
1201
1202 , selectorRe = /([.#:[])([-\w]+)(?:\((.+?)\)|([~^$*|]?)=(("|')(?:\\?.)*?\6|[-\w]+))?]?/g
1203 , selectorLastRe = /([~\s>+]*)(?:("|')(?:\\?.)*?\2|\(.+?\)|[^\s+>])+$/
1204 , selectorSplitRe = /\s*,\s*(?=(?:[^'"()]|"(?:\\?.)*?"|'(?:\\?.)*?'|\(.+?\))+$)/
1205 , selectorCache = {}
1206 , selectorMap = {
1207 "first-child": "(a=_.parentNode)&&a.firstChild==_",
1208 "last-child": "(a=_.parentNode)&&a.lastChild==_",
1209 ".": "~_.className.split(/\\s+/).indexOf(a)",
1210 "#": "_.id==a",
1211 "^": "!a.indexOf(v)",
1212 "|": "a.split('-')[0]==v",
1213 "$": "a.slice(-v.length)==v",
1214 "~": "~a.split(/\\s+/).indexOf(v)",
1215 "*": "~a.indexOf(v)"
1216 }
1217
1218 function selectorFn(str) {
1219 // jshint evil:true
1220 return selectorCache[str] ||
1221 (selectorCache[str] = Function("m,c", "return function(_,v,a,b){return " +
1222 str.split(selectorSplitRe).map(function(sel) {
1223 var relation, from
1224 , rules = ["_&&_.nodeType==1"]
1225 , parentSel = sel.replace(selectorLastRe, function(_, _rel, a, start) {
1226 from = start + _rel.length
1227 relation = _rel.trim()
1228 return ""
1229 })
1230 , tag = sel.slice(from).replace(selectorRe, function(_, op, key, subSel, fn, val, quotation) {
1231 rules.push(
1232 "((v='" +
1233 (subSel || (quotation ? val.slice(1, -1) : val) || "").replace(/'/g, "\\'") +
1234 "'),(a='" + key + "'),1)"
1235 ,
1236 selectorMap[op == ":" ? key : op] ||
1237 "(a=_.getAttribute(a))" +
1238 (fn ? "&&" + selectorMap[fn] : val ? "==v" : "")
1239 )
1240 return ""
1241 })
1242
1243 if (tag && tag != "*") rules[0] += "&&_.tagName=='" + tag.toUpperCase() + "'"
1244 if (parentSel) rules.push("(v='" + parentSel + "')", selectorMap[relation + relation])
1245 return rules.join("&&")
1246 }).join("||") + "}"
1247 )(matches, closest))
1248 }
1249
1250 function walk(next, first, el, sel, nextFn) {
1251 var out = []
1252 if (typeof sel !== "function") sel = selectorFn(sel)
1253 for (; el; el = el[next] || nextFn && nextFn(el)) if (sel(el)) {
1254 if (first) return el
1255 out.push(el)
1256 }
1257 return first ? null : out
1258 }
1259
1260 function find(node, sel, first) {
1261 return walk("firstChild", first, node.firstChild, sel, function(el) {
1262 var next = el.nextSibling
1263 while (!next && ((el = el.parentNode) !== node)) next = el.nextSibling
1264 return next
1265 })
1266 }
1267
1268 // Note: querySelector in IE8 supports only CSS 2.1 selectors
1269 if (!ie678 && body.querySelector) {
1270 El.find = function(el, sel) {
1271 return el.querySelector(sel)
1272 }
1273 El.findAll = function(el, sel) {
1274 return new ElWrap(el.querySelectorAll(sel))
1275 }
1276 } else {
1277 El.find = function(el, sel) {
1278 return find(el, sel, true)
1279 }
1280 El.findAll = function(el, sel) {
1281 return new ElWrap(find(el, sel))
1282 }
1283 }
1284
1285 /*/
1286 El.matches = function(el, sel) {
1287 return el.matches(sel)
1288 }
1289 El.closest = function(el, sel) {
1290 return (el.closest ? el : el.parentNode).closest(sel)
1291 }
1292 El.find = function(el, sel) {
1293 return el.querySelector(sel)
1294 }
1295 El.findAll = function(el, sel) {
1296 return new ElWrap(el.querySelectorAll(sel))
1297 }
1298 /**/
1299
1300 /**
1301 * Turns CSS selector like syntax to DOM Node
1302 * @returns {Node}
1303 *
1304 * @example
1305 * El("input#12.nice[type=checkbox]:checked:disabled[data-lang=en].class")
1306 * <input id="12" class="nice class" type="checkbox" checked="checked" disabled="disabled" data-lang="en">
1307 */
1308
1309 window.El = El
1310
1311 function El(name) {
1312 if (typeof name != "string") {
1313 return new ElWrap(name)
1314 }
1315 var el, pres
1316 , pre = {}
1317 name = name.replace(selectorRe, function(_, op, key, _sub, fn, val, quotation) {
1318 pres = 1
1319 val = quotation ? val.slice(1, -1) : val || key
1320 pre[op =
1321 op == "." ?
1322 (fn = "~", "class") :
1323 op == "#" ?
1324 "id" :
1325 key
1326 ] = fn && pre[op] ?
1327 fn == "^" ? val + pre[op] :
1328 pre[op] + (fn == "~" ? " " : "") + val :
1329 val
1330 return ""
1331 }) || "div"
1332
1333 // NOTE: IE-s cloneNode consolidates the two text nodes together as one
1334 // http://brooknovak.wordpress.com/2009/08/23/ies-clonenode-doesnt-actually-clone/
1335 el = (elCache[name] || (elCache[name] = document.createElement(name))).cloneNode(true)
1336
1337 if (pres) {
1338 setAttr(el, pre)
1339 }
1340
1341 return el
1342 }
1343
1344 function ElWrap(nodes) {
1345 var wrap = this
1346 , i = nodes.length
1347 /**
1348 * 1. Extended array size will not updated
1349 * when array elements set directly in Android 2.2.
1350 */
1351 if (i) {
1352 wrap.length = i /* 1 */
1353 for (; i--; ) {
1354 wrap[i] = nodes[i]
1355 }
1356 } else if (i == null) {
1357 wrap.length = 1 /* 1 */
1358 wrap[0] = nodes
1359 }
1360 }
1361
1362 ElWrap[protoStr] = wrapProto
1363
1364 wrapProto.append = function(el) {
1365 var elWrap = this
1366 if (elWrap._childId != void 0) {
1367 append(elWrap[elWrap._childId], el)
1368 } else {
1369 elWrap.push(el)
1370 }
1371 return elWrap
1372 }
1373
1374 wrapProto.cloneNode = function(deep) {
1375 var clone = new ElWrap(this.map(function(el) {
1376 return el.cloneNode(deep)
1377 }))
1378 clone._childId = this._childId
1379 return clone
1380 }
1381
1382
1383 El.attr = function(el, key, val) {
1384 return arguments.length < 3 && key.constructor != Object ? getAttr(el, key) : setAttr(el, key, val)
1385 }
1386
1387 function getAttr(el, key) {
1388 return el && el.getAttribute && el.getAttribute(key)
1389 }
1390
1391 function setAttr(el, key, val) {
1392 var current
1393
1394 if (key && key.constructor == Object) {
1395 for (current in key) {
1396 setAttr(el, current, key[current])
1397 }
1398 return
1399 }
1400
1401 /* Accept namespaced arguments
1402 var namespaces = {
1403 xlink: "http://www.w3.org/1999/xlink",
1404 svg: "http://www.w3.org/2000/svg"
1405 }
1406
1407 current = key.split("|")
1408 if (current[1]) {
1409 el.setAttributeNS(namespaces[current[0]], current[1], val)
1410 return
1411 }
1412 */
1413
1414 current = el.getAttribute(key)
1415
1416 // Note: IE5-7 doesn't set styles and removes events when you try to set them.
1417 //
1418 // in IE6, a label with a for attribute linked to a select list
1419 // will cause a re-selection of the first option instead of just giving focus.
1420 // http://webbugtrack.blogspot.com/2007/09/bug-116-for-attribute-woes-in-ie6.html
1421
1422 // there are bug in IE<9 where changed 'name' param not accepted on form submit
1423 // IE8 and below support document.createElement('<P>')
1424 //
1425 // http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
1426 // http://msdn.microsoft.com/en-us/library/ms536614(VS.85).aspx
1427
1428 /*** ie8 ***/
1429 // istanbul ignore next: IE fix
1430 if (ie67 && (key == "id" || key == "name" || key == "checked")) {
1431 el.mergeAttributes(document.createElement('<INPUT ' + key + '="' + val + '">'), false)
1432 } else
1433 /**/
1434 if (key == "class") {
1435 addClass(el, val)
1436 } else if (val || val === 0) {
1437 if (current != val) {
1438 el.setAttribute(key, val)
1439 }
1440 } else if (current) {
1441 el.removeAttribute(key)
1442 }
1443 }
1444
1445 El.val = valFn
1446 function valFn(el, val) {
1447 var input, step, key, value
1448 , i = 0
1449 , type = el.type
1450 , opts = el.options
1451 , checkbox = type === "checkbox" || type === "radio"
1452
1453 if (el.tagName === "FORM") {
1454 opts = {}
1455
1456 // Disabled controls do not receive focus,
1457 // are skipped in tabbing navigation, cannot be successfully posted.
1458 //
1459 // Read-only elements receive focus but cannot be modified by the user,
1460 // are included in tabbing navigation, are successfully posted.
1461 //
1462 // Read-only checkboxes can be changed by the user
1463
1464 for (; input = el.elements[i++]; ) if (!input.disabled && (key = input.name || input.id)) {
1465 value = valFn(input)
1466 if (value !== void 0) {
1467 step = opts
1468 key.replace(/\[(.*?)\]/g, function(_, _key, offset) {
1469 if (step == opts) key = key.slice(0, offset)
1470 step = step[key] || (step[key] = _key && +_key != _key ? {} : [])
1471 key = _key
1472 })
1473 step[key || step.length] = value
1474 }
1475 }
1476
1477 return opts
1478 }
1479
1480 if (arguments.length > 1) {
1481 if (opts) {
1482 value = (Array.isArray(val) ? val : [ val ]).map(String)
1483 for (; input = opts[i++]; ) {
1484 input.selected = value.indexOf(input.value) > -1
1485 }
1486 } else {
1487 checkbox ? (el.checked = !!val) : (el.value = val)
1488 }
1489 return
1490 }
1491
1492 if (opts) {
1493 if (type === "select-multiple") {
1494 for (val = []; input = opts[i++]; ) {
1495 if (input.selected && !input.disabled) {
1496 val.push(input.valObject || input.value)
1497 }
1498 }
1499 return val
1500 }
1501 // IE8 throws error when accessing to options[-1]
1502 value = el.selectedIndex
1503 el = value > -1 && opts[value] || el
1504 }
1505
1506 return checkbox && !el.checked ?
1507 (type === "radio" ? void 0 : null) :
1508 el.valObject || el.value
1509 }
1510
1511 function append(el, child, before) {
1512 if (!el.nodeType) {
1513 return el.append ? el.append(child, before) : el
1514 }
1515 var fragment
1516 , i = 0
1517 , tmp = typeof child
1518 if (child) {
1519 if (tmp == "string" || tmp == "number") child = document.createTextNode(child)
1520 else if ( !("nodeType" in child) && "length" in child ) {
1521 // document.createDocumentFragment is unsupported in IE5.5
1522 // fragment = "createDocumentFragment" in document ? document.createDocumentFragment() : El("div")
1523 for (
1524 tmp = child.length
1525 , fragment = document.createDocumentFragment();
1526 i < tmp; ) append(fragment, child[i++])
1527 child = fragment
1528 }
1529
1530 if (child.nodeType) {
1531 tmp = el.insertBefore ? el : el[el.length - 1]
1532 if (i = getAttr(tmp, "data-child")) {
1533 before = find(tmp, Fn("v->n->n.nodeType===8&&n.nodeValue==v")(i), 1) || tmp
1534 tmp = before.parentNode
1535 // TODO:2016-07-05:lauri:handle numeric befores
1536 }
1537 tmp.insertBefore(child,
1538 (before === true ? tmp.firstChild :
1539 typeof before == "number" ? tmp.childNodes[
1540 before < 0 ? tmp.childNodes.length - before - 2 : before
1541 ] : before) || null
1542 )
1543 }
1544 }
1545 return el
1546 }
1547
1548 function acceptMany(fn) {
1549 return function f(el, name, val, delay) {
1550 if (typeof name === "string" && name !== "") {
1551 if (delay > 0) return setTimeout(f, delay, el, name, val)
1552 var names = name.split(splitRe)
1553 , i = 0
1554 , len = names.length
1555
1556 if (arguments.length < 3) {
1557 if (len > 1) {
1558 for (; i < len; ) fn(el, names[i++])
1559 } else {
1560 fn(el, name)
1561 }
1562 } else if (len > 1) {
1563 /*
1564 if (Array.isArray(val)) {
1565 for (; i < len; ) fn(el, names[i], val[i++])
1566 } else {
1567 for (; i < len; ) fn(el, names[i++], val)
1568 }
1569 /*/
1570 for (; i < len; ) {
1571 fn(el, names[i++], Array.isArray(val) ? val[i - 1] : val)
1572 }
1573 //*/
1574 } else {
1575 fn(el, name, val)
1576 }
1577 }
1578 }
1579 }
1580
1581 // setAttribute("class") is broken in IE7
1582 // className is object in SVGElements
1583
1584 El.hasClass = hasClass
1585 function hasClass(el, name) {
1586 var current = el.className || ""
1587
1588 if (typeof current !== "string") {
1589 current = el.getAttribute("class") || ""
1590 }
1591
1592 return !!current && current.split(splitRe).indexOf(name) > -1
1593 }
1594
1595 function _addClass(el, name) {
1596 var current = el.className || ""
1597 , useAttr = typeof current !== "string"
1598
1599 if (useAttr) {
1600 current = el.getAttribute("class") || ""
1601 }
1602
1603 if (current) {
1604 name = current.split(splitRe).indexOf(name) > -1 ? current : current + " " + name
1605 }
1606
1607 if (current != name) {
1608 if (useAttr) {
1609 el.setAttribute("class", name)
1610 } else {
1611 el.className = name
1612 }
1613 }
1614 }
1615
1616 function _rmClass(el, name) {
1617 var current = el.className || ""
1618 , useAttr = typeof current != "string"
1619
1620 if (useAttr) {
1621 current = el.getAttribute("class") || ""
1622 }
1623
1624 if (current) {
1625 name = (" " + current + " ").replace(" " + name + " ", " ").trim()
1626 if (current != name) {
1627 if (useAttr) {
1628 el.setAttribute("class", name)
1629 } else {
1630 el.className = name
1631 }
1632 }
1633 }
1634 }
1635
1636 // The addEventListener is supported in Internet Explorer from version 9.
1637 // https://developer.mozilla.org/en-US/docs/Web/Reference/Events/wheel
1638 // - IE8 always prevents the default of the mousewheel event.
1639
1640 var wheelDiff = 120
1641 , addEv = "addEventListener"
1642 , remEv = "removeEventListener"
1643 , prefix = window[addEv] ? "" : (addEv = "attachEvent", remEv = "detachEvent", "on")
1644 , fixEv = Event.fixEv = {
1645 wheel:
1646 "onwheel" in document ? "wheel" : // Modern browsers
1647 "onmousewheel" in document ? "mousewheel" : // Webkit and IE
1648 "DOMMouseScroll" // older Firefox
1649 }
1650 , fixFn = Event.fixFn = {
1651 wheel: function(el, _fn) {
1652 return function(e) {
1653 var delta = (e.wheelDelta || -e.detail || -e.deltaY) / wheelDiff
1654 if (delta) {
1655 if (delta < 1 && delta > -1) {
1656 var diff = (delta < 0 ? -1 : 1)/delta
1657 delta *= diff
1658 wheelDiff /= diff
1659 }
1660 //TODO: fix event
1661 // e.deltaY =
1662 // e.deltaX = - 1/40 * e.wheelDeltaX|0
1663 // e.target = e.target || e.srcElement
1664 _fn.call(el, e, delta)
1665 }
1666 }
1667 }
1668 }
1669
1670 var emitter = new Event.Emitter
1671
1672 function addEvent(el, ev, _fn) {
1673 var fn = fixFn[ev] && fixFn[ev](el, _fn) || _fn
1674 , fix = prefix ? function() {
1675 var e = window.event
1676 if (e) {
1677 e.target = e.srcElement
1678 e.preventDefault = preventDefault
1679 e.stopPropagation = stopPropagation
1680 }
1681 fn.call(el, e)
1682 } : fn
1683
1684 el[addEv](prefix + (fixEv[ev] || ev), fix, false)
1685
1686 emitter.on.call(el, ev, fix, el, _fn)
1687 }
1688
1689 function rmEvent(el, ev, fn) {
1690 var evs = el._e && el._e[ev]
1691 , id = evs && evs.indexOf(fn)
1692 if (id > -1) {
1693 el[remEv](prefix + (fixEv[ev] || ev), evs[id + 1])
1694 evs.splice(id - 1, 3)
1695 }
1696 }
1697
1698 function preventDefault() {
1699 this.returnValue = false
1700 }
1701 function stopPropagation() {
1702 this.cancelBubble = this.cancel = true
1703 }
1704
1705 Event.stop = function(e) {
1706 if (e.preventDefault) {
1707 e.stopPropagation()
1708 e.preventDefault()
1709 }
1710 return false
1711 }
1712
1713 El.on = acceptMany(addEvent)
1714 El.off = acceptMany(rmEvent)
1715
1716 El.one = function(el, ev, fn) {
1717 function remove() {
1718 rmEvent(el, ev, fn)
1719 rmEvent(el, ev, remove)
1720 }
1721 addEvent(el, ev, fn)
1722 addEvent(el, ev, remove)
1723 return el
1724 }
1725
1726 El.emit = function(el, ev) {
1727 emitter.emit.apply(el, slice.call(arguments, 1))
1728 }
1729
1730 function empty(el) {
1731 for (var node; node = el.firstChild; ) {
1732 kill(node)
1733 }
1734 return el
1735 }
1736
1737 function kill(el) {
1738 var id
1739 if (el) {
1740 if (el._e) {
1741 emitter.emit.call(el, "kill")
1742 for (id in el._e) rmEvent(el, id)
1743 }
1744 if (el.parentNode) {
1745 el.parentNode.removeChild(el)
1746 }
1747 if (el.nodeType != 1) {
1748 return el.kill && el.kill()
1749 }
1750 empty(el)
1751 if (id = el._scope) {
1752 delete elScope[id]
1753 }
1754 if (el.valObject) {
1755 el.valObject = null
1756 }
1757 }
1758 }
1759
1760 function elScope(node, parent, fb) {
1761 return elScope[node._scope] ||
1762 fb ||
1763 (parent ?
1764 (((fb = elScope[node._scope = ++seq] = Object.create(parent))._super = parent), fb) :
1765 closestScope(node)
1766 ) ||
1767 scopeData
1768
1769 }
1770
1771 function closestScope(node) {
1772 for (; node = node.parentNode; ) {
1773 if (node._scope) return elScope[node._scope]
1774 }
1775 }
1776
1777 function render(node, scope) {
1778 var bind, fn
1779 , i = 0
1780
1781 if (node.nodeType != 1) {
1782 node.render ? node.render(scope) : node
1783 return
1784 }
1785
1786 scope = elScope(node, 0, scope)
1787
1788 if (bind = getAttr(node, "data-bind")) {
1789 scope._m = bindMatch
1790 scope._t = bind
1791 // i18n(bind, lang).format(scope)
1792 // document.documentElement.lang
1793 // document.getElementsByTagName('html')[0].getAttribute('lang')
1794
1795 fn = "data b s r->data&&(" + bind.replace(renderRe, function(match, name, op, args) {
1796 scope._m[i] = match
1797 var fn = bindings[name]
1798 return (
1799 (op == ":" || fn && hasOwn.call(fn, "once")) ?
1800 "s(this,'data-bind',data._t=data._t.replace(data._m[" + (i++)+ "],''))||" :
1801 ""
1802 ) + (
1803 fn ?
1804 "b['" + name + "'].call(data,this" + (fn.raw ? ",'" + args + "'" : args ? "," + args : "") :
1805 "s(this,'" + name + "'," + args
1806 ) + ")||"
1807 }) + "r)"
1808
1809 try {
1810 if (Fn(fn, node, scope)(scope, bindings, setAttr)) {
1811 return
1812 }
1813 } catch (e) {
1814 /*** debug ***//*
1815 e.message += "\nBINDING: " + bind
1816 console.error(e, node)
1817 /**/
1818 if (window.onerror) {
1819 window.onerror(e.message, e.fileName, e.lineNumber)
1820 }
1821 }
1822 }
1823
1824 for (bind = node.firstChild; bind; bind = fn) {
1825 fn = bind.nextSibling
1826 render(bind, scope)
1827 }
1828 /*** ie8 ***/
1829 if (ie678 && node.nodeName == "SELECT") {
1830 node.parentNode.insertBefore(node, node)
1831 }
1832 /**/
1833 }
1834
1835 El.empty = empty
1836 El.kill = kill
1837 El.render = render
1838
1839 Object.each(El, function(fn, key) {
1840 if (!wrapProto[key]) {
1841 wrapProto[key] = function wrap() {
1842 var i = 0
1843 , self = this
1844 , len = self.length
1845 , arr = slice.call(arguments)
1846 arr.unshift(1)
1847 for (; i < len; ) {
1848 arr[0] = self[i++]
1849 fn.apply(null, arr)
1850 }
1851 return self
1852 }
1853 }
1854 })
1855
1856 El.append = append
1857 El.scope = elScope
1858
1859 function parseTemplate(str) {
1860 var parent = El("div")
1861 , stack = [-1]
1862 , parentStack = []
1863
1864 function work(all, indent, plugin, name, q, text, mapEnd, mapStart, offset) {
1865 if (offset && all === indent) return
1866
1867 for (q = indent.length; q <= stack[0]; ) {
1868 if (parent.plugin) {
1869 parent.plugin.done()
1870 }
1871 parent = parentStack.pop()
1872 stack.shift()
1873 }
1874
1875 if (parent._r) {
1876 parent.txt += all + "\n"
1877 } else if (plugin || mapStart && (name = "map")) {
1878 if (El.plugins[name]) {
1879 parentStack.push(parent)
1880 stack.unshift(q)
1881 parent = (new El.plugins[name](parent, text, mapEnd ? "" : ";")).el
1882 } else {
1883 append(parent, all)
1884 }
1885 } else if (mapEnd) {
1886 appendBind(parent, text, "")
1887 } else {
1888 if (name) {
1889 parentStack.push(parent)
1890 stack.unshift(q)
1891 q = El(name, 0, 1)
1892 append(parent, q)
1893 parent = q
1894 }
1895 if (text) {
1896 q = text.charAt(0)
1897 name = text.slice(1)
1898 if (q == ">") {
1899 (indent + " " + name).replace(templateRe, work)
1900 } else if (q == "|" || q == "\\") {
1901 append(parent, name) // + "\n")
1902 } else if (q != "/") {
1903 if (q != "&") {
1904 name = (parent.tagName == "INPUT" ? "val" : "txt")
1905 + ":_('" + text.replace(/'/g, "\\'") + "').format(data)"
1906 }
1907 appendBind(parent, name, ";")
1908 }
1909 }
1910 }
1911 }
1912 str.replace(templateRe, work)
1913 work("", "")
1914 }
1915
1916 function appendBind(el, val, sep) {
1917 var current = getAttr(el, "data-bind")
1918 setAttr(el, "data-bind", (current ? current + sep + val : val))
1919 }
1920
1921 function plugin(parent, name) {
1922 var t = this
1923 t.name = name
1924 t.parent = parent
1925 t.el = El("div")
1926 t.el.plugin = t
1927 }
1928
1929 plugin[protoStr] = {
1930 _done: function() {
1931 var el, childId
1932 , t = this
1933 , childNodes = t.el.childNodes
1934 , i = childNodes.length
1935
1936 for (; i--; ) {
1937 el = childNodes[i]
1938 if (el._childKey) {
1939 childId = i
1940 setAttr(el, "data-child", el._childKey)
1941 break
1942 }
1943 }
1944
1945 if (childNodes[1]) {
1946 el = new ElWrap(childNodes)
1947 el._childId = childId
1948 } else {
1949 el = childNodes[0]
1950 }
1951
1952 t.el.plugin = t.el = t.parent = null
1953 return el
1954 },
1955 done: function() {
1956 var t = this
1957 , parent = t.parent
1958 elCache[t.name] = t._done()
1959 return parent
1960 }
1961 }
1962
1963 function js(parent, params, attr1) {
1964 var t = this
1965 // Raw text mode
1966 t._r = t.parent = parent
1967 t.txt = ""
1968 t.plugin = t.el = t
1969 t.params = params
1970 t.a = attr1
1971 }
1972
1973 js[protoStr].done = Fn("Function(this.txt)()")
1974
1975 El.plugins = {
1976 binding: js.extend({
1977 done: function() {
1978 Object.assign(bindings, Function("return({" + this.txt + "})")())
1979 }
1980 }),
1981 child: plugin.extend({
1982 done: function() {
1983 var key = "@child-" + (++seq)
1984 , root = this.parent
1985 for (; (root.parentNode.parentNode || key).nodeType == 1; ) {
1986 root = root.parentNode
1987 }
1988 root._childKey = key
1989 append(this.parent, document.createComment(key))
1990 }
1991 }),
1992 css: js.extend({
1993 done: Fn("xhr.css(this.txt)")
1994 }),
1995 def: js.extend({
1996 done: Fn("View.def(this.params||this.txt)")
1997 }),
1998 each: js.extend({
1999 done: function() {
2000 var txt = this.txt
2001
2002 JSON.parse(this.params)
2003 .each(function(val) {
2004 if (!val || val.constructor != Object) {
2005 val = { item: val }
2006 }
2007 parseTemplate(txt.format(val))
2008 })
2009 }
2010 }),
2011 el: plugin,
2012 js: js,
2013 map: js.extend({
2014 done: function() {
2015 var self = this
2016 , txt = (self.params + self.txt).replace(/\n+/g, "")
2017 appendBind(
2018 self.parent,
2019 self.a ? txt.slice(1) : txt,
2020 self.a
2021 )
2022 }
2023 }),
2024 template: plugin,
2025 view: plugin.extend({
2026 done: function() {
2027 var fn
2028 , t = this
2029 , arr = t.name.split(splitRe)
2030 , bind = getAttr(t.el, "data-bind")
2031 , view = View(arr[0], t._done(), arr[1], arr[2])
2032 if (bind) {
2033 fn = bind.replace(renderRe, function(match, name, op, args) {
2034 return "(this['" + name + "']" + (
2035 typeof view[name] == "function" ?
2036 "(" + (args || "") + ")" :
2037 "=" + args
2038 ) + "),"
2039 }) + "1"
2040 Fn(fn, view, scopeData)()
2041 }
2042 }
2043 }),
2044 "view-link": plugin.extend({
2045 done: function() {
2046 var t = this
2047 , arr = t.name.split(splitRe)
2048 View(arr[0], null, arr[2])
2049 .on("ping", function(opts) {
2050 View.show(arr[1].format(opts))
2051 })
2052 }
2053 })
2054 }
2055
2056 xhr.view = xhr.tpl = El.tpl = parseTemplate
2057 xhr.css = function(str) {
2058 if (!styleNode) {
2059 // Safari and IE6-8 requires dynamically created
2060 // <style> elements to be inserted into the <head>
2061 append(document.getElementsByTagName("head")[0], styleNode = El("style"))
2062 }
2063 if (styleNode.styleSheet) styleNode.styleSheet.cssText += str
2064 else append(styleNode, str)
2065 }
2066
2067 El.scrollLeft = scrollLeft
2068 function scrollLeft() {
2069 return window.pageXOffset || root.scrollLeft || body.scrollLeft || 0
2070 }
2071
2072 El.scrollTop = scrollTop
2073 function scrollTop() {
2074 return window.pageYOffset || root.scrollTop || body.scrollTop || 0
2075 }
2076
2077 El.mouse = function(e) {
2078 if (e.changedTouches) e = e.changedTouches[0]
2079 return {
2080 left: e.pageX || e.clientX + scrollLeft(),
2081 top: e.pageY || e.clientY + scrollTop()
2082 }
2083 }
2084
2085 /*** kb ***/
2086 var kbMaps = []
2087 , kbKeys = {
2088 8: "backspace", 9: "tab",
2089 13: "enter", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
2090 20: "caps", 27: "esc",
2091 33: "pgup", 34: "pgdown",
2092 35: "end", 36: "home",
2093 37: "left", 38: "up", 39: "right", 40: "down",
2094 45: "ins", 46: "del",
2095 91: "cmd",
2096 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6",
2097 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11", 123: "f12"
2098 }
2099 , kbMod = El.kbMod = /^(Mac|iP)/.test(navigator.platform) ? "metaKey" : "ctrlKey"
2100
2101 function kbRun(e, code, chr) {
2102 var fn, map
2103 , i = 0
2104 , el = e.target || e.srcElement
2105 , input = /INPUT|TEXTAREA|SELECT/i.test((el.nodeType == 3 ? el.parentNode : el).tagName)
2106
2107 for (; map = kbMaps[i++]; ) {
2108 if (!input || map.input) {
2109 fn = map[code] ||
2110 map[chr] ||
2111 map.num && code > 47 && code < 58 && (chr|=0, map.num) ||
2112 map.all
2113 }
2114 if (fn || !map.bubble) break
2115 }
2116 if (fn) {
2117 typeof fn === "string" ? View.emit(fn, e, chr, el) : fn(e, chr, el)
2118 }
2119 }
2120
2121 function kbDown(e) {
2122 if (kbMaps[0]) {
2123 var c = e.keyCode || e.which
2124 , numpad = c > 95 && c < 106
2125 , code = numpad ? c - 48 : c
2126 , key = kbKeys[code] || String.fromCharCode(code).toLowerCase() || code
2127
2128 // Otherwise IE backspace navigates back
2129 if (code == 8 && kbMaps[0].backspace) {
2130 Event.stop(e)
2131 }
2132 kbRun(e, code, key)
2133 if (e.shiftKey && code != 16) kbRun(e, code, "shift+" + key)
2134 /**
2135 * people in Poland use Right Alt+S to type in Ś.
2136 * Right Alt+S is mapped internally to Ctrl+Alt+S.
2137 * https://medium.engineering/the-curious-case-of-disappearing-polish-s-fa398313d4df
2138 */
2139 if (e.altKey) {
2140 if (code != 18) kbRun(e, code, "alt+" + key)
2141 } else if (code != 17) {
2142 if (e.ctrlKey) kbRun(e, code, "ctrl+" + key)
2143 if (e[kbMod] && code != 91) kbRun(e, code, "mod+" + key)
2144 }
2145 }
2146 }
2147
2148 El.addKb = kbMaps.unshift.bind(kbMaps)
2149 El.rmKb = function(map) {
2150 var i = kbMaps.indexOf(map||kbMaps[0])
2151 if (i > -1) kbMaps.splice(i, 1)
2152 }
2153
2154 addEvent(document, "keydown", kbDown)
2155 /**/
2156
2157
2158 /*** responsive ***/
2159 var lastSize, lastOrient
2160 , breakpoints = {
2161 sm: 0,
2162 md: 601,
2163 lg: 1025
2164 }
2165 , setBreakpointsRated = function() {
2166 setBreakpoints()
2167 }.rate(100, true)
2168
2169 function setBreakpoints(_breakpoints) {
2170 // document.documentElement.clientWidth is 0 in IE5
2171 var key, next
2172 , width = root.offsetWidth
2173 , map = breakpoints = _breakpoints || breakpoints
2174
2175 for (key in map) {
2176 if (map[key] > width) break
2177 next = key
2178 }
2179
2180 if ( next != lastSize ) {
2181 _rmClass(root, lastSize)
2182 _addClass(root, lastSize = next)
2183 }
2184
2185 next = width > root.offsetHeight ? "landscape" : "portrait"
2186
2187 if ( next != lastOrient) {
2188 _rmClass(root, lastOrient)
2189 _addClass(root, lastOrient = next)
2190 }
2191
2192 if (next = window.View) next.emit("resize")
2193 }
2194 El.setBreakpoints = setBreakpoints
2195
2196 setBreakpointsRated()
2197
2198 addEvent(window, "resize", setBreakpointsRated)
2199 addEvent(window, "orientationchange", setBreakpointsRated)
2200 addEvent(window, "load", setBreakpointsRated)
2201 /**/
2202
2203
2204 /*** i18n ***/
2205 function i18n(text, lang) {
2206 lang = i18n[i18nGet(lang) || currentLang]
2207 return (
2208 lang[text] ||
2209 typeof text === "string" && lang[text = text.slice(text.indexOf(":") + 1) || text] ||
2210 text || ""
2211 )
2212 }
2213 El.i18n = i18n
2214
2215 function i18nGet(lang) {
2216 return lang && (
2217 i18n[lang = ("" + lang).toLowerCase()] ||
2218 i18n[lang = lang.split("-")[0]]
2219 ) && lang
2220 }
2221
2222 function i18nUse(lang) {
2223 lang = i18nGet(lang)
2224 if (lang && currentLang != lang) {
2225 i18n[currentLang = i18n.current = lang] = i18n[currentLang] || {}
2226 }
2227 return currentLang
2228 }
2229
2230 function i18nAdd(lang, texts) {
2231 if (i18n.list.indexOf(lang) == -1) i18n.list.push(lang)
2232 Object.assign(i18n[lang] || (i18n[lang] = {}), texts)
2233 if (!currentLang) i18nUse(lang)
2234 }
2235
2236 i18n.list = []
2237 i18n.get = i18nGet
2238 i18n.use = i18nUse
2239 i18n.add = i18nAdd
2240 i18n.def = function(map, key) {
2241 for (key in map) {
2242 i18nAdd(key, map)
2243 }
2244 }
2245 // navigator.userLanguage for IE, navigator.language for others
2246 // var lang = navigator.language || navigator.userLanguage;
2247 // i18nUse("en")
2248 /**/
2249
2250}(window, document, Object, Event, "prototype")
2251/* litejs.com/MIT-LICENSE.txt */
2252
2253
2254
2255!function(bindings) {
2256 var hasOwn = Object.prototype.hasOwnProperty
2257 , slice = Array.prototype.slice
2258
2259 bindingEvery.once =
2260 emitForm.once =
2261 bindingFn.once =
2262 bindingOn.once =
2263 bindingsEach.raw = bindingsEach.once =
2264 true
2265
2266 bindings.every = bindingEvery
2267 function bindingEvery(el, list, attrName) {
2268 var len = 0
2269 , data = this
2270 , parent = el.parentNode
2271 , comm = document.createComment("every " + (list.name || list.length))
2272
2273 parent.replaceChild(comm, el)
2274
2275 if (list) {
2276 if (typeof list === "string") {
2277 data.model.on("change:" + list, render)
2278 render()
2279 } else if (list.eachLive) {
2280 list.eachLive(add, remove)
2281 } else {
2282 comm.render = render
2283 render()
2284 }
2285 }
2286 return true
2287
2288 function render() {
2289 for (; len; len--) {
2290 El.kill(comm.previousSibling)
2291 }
2292 Object.each(typeof list === "string" ? data.model.get(list) : list, add)
2293 }
2294
2295 function add(item, i) {
2296 len++
2297 var up
2298 , clone = el.cloneNode(true)
2299 , scope = El.scope(clone, data)
2300 scope.i = i
2301 scope[attrName || "item"] = item
2302 El.append(parent, clone, comm)
2303 El.render(clone, scope)
2304 if (typeof item.on === "function") {
2305 item.on("change", up = El.render.bind(clone, clone))
2306 El.on(clone, "kill", function() {
2307 item.off("change", up)
2308 })
2309 }
2310 }
2311
2312 function remove(pos) {
2313 for (var el = comm, i = pos + 1; i--; ) {
2314 el = el.previousSibling
2315 }
2316 El.kill(el)
2317 }
2318 }
2319
2320 bindings.fn = bindingFn
2321 function bindingFn(el, fn) {
2322 return fn.apply(el, slice.call(arguments, 3))
2323 }
2324
2325 bindings["if"] = bindingsIf
2326 function bindingsIf(el, enabled) {
2327 var parent = el.parentNode
2328 , scope = this
2329 if (enabled) {
2330 parent || el._ifComm && el._ifComm.parentNode.replaceChild(el, el._ifComm)
2331 } else {
2332 if (parent) {
2333 if (!el._ifComm) {
2334 El.on(el, "kill", El.kill.bind(el, el._ifComm = document.createComment("if")))
2335 el._ifComm.render = function() {
2336 El.render(el, scope)
2337 }
2338 }
2339 parent.replaceChild(el._ifComm, el)
2340 }
2341 return true
2342 }
2343 }
2344
2345 bindings.is = function bindingIs(node, model, path, list, state) {
2346 var i, match, val
2347 , scope = this
2348 if (typeof model === "string") {
2349 state = list
2350 list = path
2351 path = model
2352 model = scope.model
2353 }
2354 if (model && path) {
2355 match = val = state || model.get(path)
2356 if (list) {
2357 if (!Array.isArray(list)) {
2358 list = list.split(",")
2359 }
2360 i = list.length & -2
2361
2362 for (; i > -1; i -= 2) {
2363 if (i == 0 || list[i - 1] == "" + val || +list[i - 1] <= val) {
2364 match = list[i]
2365 break
2366 }
2367 }
2368 }
2369 El.rmClass(node, scope["_is-" + path])
2370 El.addClass(node, scope["_is-" + path] = match && "is-" + match)
2371 }
2372 }
2373
2374 bindings.on = bindingOn
2375 function bindingOn(el, ev, fn, a1, a2, a3, a4, a5) {
2376 El.on(el, ev, typeof fn == "string" ? function(e) {
2377 View.emit(fn, e, el, a1, a2, a3, a4, a5)
2378 } : fn)
2379 }
2380
2381 bindings.emitForm = emitForm
2382 function emitForm(el, ev, a1, a2, a3, a4) {
2383 El.on(el, "submit", function(e) {
2384 var data = El.val(el)
2385 View.emit(ev, e, data, a1, a2, a3, a4)
2386 return Event.stop(e)
2387 })
2388 }
2389
2390 function getChilds(node) {
2391 var child
2392 , childs = node._childs
2393 if (!childs) {
2394 for (node._childs = childs = []; child = node.firstChild;) {
2395 childs.push(child);
2396 node.removeChild(child)
2397 }
2398 }
2399 return childs
2400 }
2401
2402 bindings.each = bindingsEach
2403
2404 function bindingsEach(el, expr) {
2405 var node = el
2406 , child = getChilds(node)[0]
2407 , match = /^\s*(\w+) in (\w*)(.*)/.exec(expr)
2408 , fn = "with(data){var out=[],loop={i:0,offset:0},_1,_2=" + match[2]
2409 + match[3].replace(/ (limit|offset):\s*(\d+)/ig, ";loop.$1=$2")
2410 + ";if(_2)for(_1 in _2)if(hasOwn.call(_2,_1)&&!(loop.offset&&loop.offset--)){"
2411 + "loop.i++;"
2412 + "if(loop.limit&&loop.i-loop.offset>loop.limit)break;"
2413 + "var clone=el.cloneNode(true)"
2414 + ",scope=El.scope(clone,data);"
2415 + "scope.loopKey=loop.key=_1;"
2416 + "scope.loop=loop;"
2417 + "scope." + match[1] + "=_2[_1];"
2418 + "out.push(clone);"
2419 + "};return out}"
2420
2421 var childs = Function("hasOwn,el,data", fn)(hasOwn, child, this)
2422
2423 El.append(El.empty(node), childs)
2424 El.render(node)
2425 return node
2426 }
2427
2428 bindings.focus = function(el) {
2429 el.focus()
2430 }
2431
2432 bindings.href = function(el, url) {
2433 if (url) {
2434 var chr = url.charAt(0)
2435 el.href = chr === "+" || chr === "%" ? "#" + View.url(url) : url
2436 }
2437 }
2438}(El.bindings)
2439/* litejs.com/MIT-LICENSE.txt */
2440
2441
2442
2443El.bindings.list = function(node, list, extra, val) {
2444 var child = node._child
2445 , data = this
2446 , extraLen = 0
2447
2448 if (!child) {
2449 child = node._child = node.removeChild(node.firstChild)
2450 }
2451
2452 if (!list || node._list == list) return
2453
2454 if (node._list) clear()
2455
2456 node._list = data.list = list
2457
2458 El.on(node, "kill", clear)
2459
2460 El.addClass(node, "loading")
2461
2462 if (extra) {
2463 extra.each(clone)
2464 extraLen = extra.length
2465 }
2466
2467 list
2468 .each(clone)
2469 .on("add", clone).on("remove", remove)
2470 .then(function() {
2471 if (val !== void 0 && El.val(node) !== val) {
2472 if (!this.get(val)) {
2473 clone({id:val,name:val}, extraLen)
2474 extraLen++
2475 }
2476 El.val(node, val)
2477 }
2478 El.rmClass(node, "loading")
2479 })
2480
2481 // Do not render childs when list initialized
2482 return true
2483
2484 function clone(item, pos) {
2485 var clone = child.cloneNode(true)
2486 , scope = El.scope(clone, data)
2487 scope.item = item.data || item || {id:item,name:item}
2488 scope.model = item
2489 scope.pos = pos
2490 function up() {
2491 El.render(clone, scope)
2492 }
2493 if (item.on) {
2494 item.on("change", up)
2495 El.on(clone, "kill", function(){
2496 item.off("change", up)
2497 })
2498 }
2499 El.append(node, clone, extraLen + pos)
2500 return El.render(clone, scope)
2501 }
2502
2503 function remove(item, pos) {
2504 El.kill(node.childNodes[extraLen + pos])
2505 }
2506
2507 function clear() {
2508 var list = node._list
2509 El.empty(node)
2510 if (list) {
2511 node._list = null
2512 list.off("add", clone).off("remove", remove)
2513 }
2514 }
2515}
\No newline at end of file