luda 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 332762981bbececb534aa9ffd50d693cbc0e2d23442283d706df8361b8d2d7c7
4
- data.tar.gz: c6b1c0eab4314bc0cdff63b4c00a43d124d4529af42e3905eb18afcb22d0c175
3
+ metadata.gz: 7f7c78629dde4c8baf8e2786f200d5f01657c95413eb7b130653c51ff089a423
4
+ data.tar.gz: 4bb9d353a9b8d588eb717f6e74912436cf443173e880c88d587a629801b74517
5
5
  SHA512:
6
- metadata.gz: 43175cfccf52ef5da8980c6279b3fbb358eda458a8ecf9be0b713a22419acf240e5c754cccf86f91db6e6ed6a9820847468f7489d7a489921a62526dc712581d
7
- data.tar.gz: 2c71e1d2478ccd87655be6bb2c061c53ae0eab2e97a8b8b91f1e3bdd4fbce98c9bac2eb839d0df8369b1a19d481a7773ee5729fbc53c6f424639ee02f883513b
6
+ metadata.gz: be87d163b042369346fd8c74d6d06741b03698a1656d36da20b85c3ddc75cead7808a3a3d08925aeea6c1bf06c1611fea3be92e30591d276f04fd5f383ee801b
7
+ data.tar.gz: aa5ae4a50161eae53beea0d3f1b01f0933e7a9f828d786f985366384922d3d50a0ba20fcc2af25f47235dfa8a42f69fc3e09704e4d10f7cd99ec9f0f7164d382
data/README.md CHANGED
@@ -1,18 +1,33 @@
1
- <img src="https://github.com/oatw/luda/blob/master/site/assets/img/logo-horizontal-full.svg" alt="logo" width="300" height="134"/>
1
+ # Luda
2
2
 
3
- __A lightweight and responsive UI framework for modern web development.__
3
+ **Luda is a library helps to build cross-framework UI components.**
4
4
 
5
- Know more about Luda at the [official site](https://oatw.github.io/luda).
6
- Communicate with Luda's contributers in the [gitter chatroom](https://gitter.im/oatw/luda).
5
+ Luda takes part in the process after templates parsed and leaves the parsing
6
+ work like data binding and custom tag packaging to your faviroute frameworks.
7
+ In this way, you can package reusable Luda components with utmost flexibility,
8
+ no matter in a front-end framework or a back-end framework.
9
+
10
+ Know more about Luda at the **[official site](https://oatw.github.io/luda)**.
11
+ Play with the **[live demos](https://codepen.io/collection/nmBYVv)** at codepen.
7
12
 
8
13
  ## Key Features
9
14
 
10
- - Lightweight - No dependency. Includes multiple themes, each theme is only ~25KB after gziped.
11
- - Modular - Supports modular imports in asset management tools.
12
- - Rhythmical - Built-in baseline grid, column grid, modular type scale and more...
13
- - Automatic - Based on Mutation Observer API, components' lifecycles are handled automatically.
15
+ - Automatic component lifecycle handling.
16
+ - Automatic component dom searching and cache management.
17
+ - Automatic proxy creating for accessing components safely.
18
+ - Native attributes and events for component communication.
19
+ - Mixins for component code reusing.
20
+ - Built-in UI components for saving your time.
21
+
22
+ ## How Luda Component Works
23
+
24
+ ### Component Class Execution Process
25
+
26
+ ![component class execution process](https://raw.githubusercontent.com/oatw/luda/master/site/assets/img/execution.png)
27
+
28
+ ### Component Instance Lifecycle
14
29
 
15
- _Before version 1.0.0, only the default theme is released, more themes will be released after version 1.0.0._
30
+ ![component instance lifecycle](https://raw.githubusercontent.com/oatw/luda/master/site/assets/img/lifecycle.png)
16
31
 
17
32
  ## Getting Started
18
33
 
@@ -51,4 +66,4 @@ please read this [changelog](https://github.com/oatw/luda/blob/master/CHANGELOG.
51
66
  ## Copyright and License
52
67
 
53
68
  Copyright [Oatw](https://github.com/oatw) under the
54
- [MIT license](https://github.com/oatw/luda/blob/master/LICENSE).
69
+ [MIT license](https://github.com/oatw/luda/blob/master/LICENSE).
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Luda degradation script 0.3.0 | https://oatw.github.io/luda
2
+ * Luda degradation script 0.3.1 | https://oatw.github.io/luda
3
3
  * Copyright 2019 Oatw | https://oatw.blog
4
4
  * MIT license | http://opensource.org/licenses/MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Luda degradation script 0.3.0 | https://oatw.github.io/luda
2
+ * Luda degradation script 0.3.1 | https://oatw.github.io/luda
3
3
  * Copyright 2019 Oatw | https://oatw.blog
4
4
  * MIT license | http://opensource.org/licenses/MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Luda 0.3.0 | https://oatw.github.io/luda
2
+ * Luda 0.3.1 | https://oatw.github.io/luda
3
3
  * Copyright 2019 Oatw | https://oatw.blog
4
4
  * MIT license | http://opensource.org/licenses/MIT
5
5
  */
@@ -343,6 +343,30 @@
343
343
  return `${str[0].toLowerCase()}${str.slice(1).replace(pattern$1, replacer$1)}`;
344
344
  }
345
345
 
346
+ function arrayEqual(a, b, compareOrder) {
347
+ if (!(a && b)) {
348
+ return false;
349
+ }
350
+ if (a === b) {
351
+ return true;
352
+ }
353
+ if (a.length !== b.length) {
354
+ return false;
355
+ }
356
+ if (a.length === 0) {
357
+ return true;
358
+ }
359
+ if (compareOrder) {
360
+ return a.every(function(it, index) {
361
+ return it === b[index];
362
+ });
363
+ } else {
364
+ return !a.some(function(it) {
365
+ return !b.includes(it);
366
+ });
367
+ }
368
+ }
369
+
346
370
  var guid;
347
371
 
348
372
  guid = 0;
@@ -351,17 +375,29 @@
351
375
  return guid += 1;
352
376
  }
353
377
 
354
- function pluck(arr, prop, deep) {
378
+ function pluck(arr, prop, deep, filter) {
355
379
  var plucked;
356
380
  plucked = [];
381
+ if (!Type.isArray(arr)) {
382
+ arr = [arr];
383
+ }
357
384
  arr.forEach(function(item) {
358
385
  var results, val;
359
386
  val = item[prop];
360
387
  results = [];
361
- while (val !== null) {
362
- plucked.push(val);
363
- if (!deep) {
364
- break;
388
+ while (val != null) {
389
+ if (filter) {
390
+ if (filter(val)) {
391
+ plucked.push(val);
392
+ if (!deep) {
393
+ break;
394
+ }
395
+ }
396
+ } else {
397
+ plucked.push(val);
398
+ if (!deep) {
399
+ break;
400
+ }
365
401
  }
366
402
  results.push(val = val[prop]);
367
403
  }
@@ -379,11 +415,12 @@
379
415
  });
380
416
  }
381
417
 
382
- ['isString', 'isFunction', 'isArray', 'isObject', 'isBool', 'isNumeric', 'isDecimalism', 'isElement'].forEach(function(key) {
418
+ ['isString', 'isFunction', 'isArray', 'isObject', 'isBool', 'isNumeric', 'isElement'].forEach(function(key) {
383
419
  return luda$1.extend(key, Type[key]);
384
420
  });
385
421
 
386
422
  luda$1.extend({
423
+ arrayEqual: arrayEqual,
387
424
  camelCase: camelCase,
388
425
  dashCase: dashCase,
389
426
  guid: guid$1,
@@ -704,22 +741,15 @@
704
741
 
705
742
  luda$1.include({
706
743
  parent: function(comparator) {
707
- var parents;
708
- if (!comparator) {
709
- return luda$1(unique(pluck(this.els, 'parentNode')));
744
+ var plucked;
745
+ if (comparator) {
746
+ plucked = pluck(this.els, 'parentElement', false, function(p) {
747
+ return collect([p], comparator).length;
748
+ });
749
+ } else {
750
+ plucked = pluck(this.els, 'parentNode');
710
751
  }
711
- parents = [];
712
- this.els.forEach(function(el) {
713
- var matched, parent;
714
- while (parent = el.parentNode) {
715
- matched = collect([parent], comparator)[0];
716
- if (matched) {
717
- return parents.push(matched);
718
- }
719
- el = parent;
720
- }
721
- });
722
- return luda$1(unique(parents));
752
+ return luda$1(unique(plucked));
723
753
  }
724
754
  });
725
755
 
@@ -851,6 +881,9 @@
851
881
  }
852
882
  });
853
883
  return attrNodes.forEach(function(el) {
884
+ if (!Type.isElement(el)) {
885
+ return;
886
+ }
854
887
  if (matches(el, disAutoSelector)) {
855
888
  return;
856
889
  }
@@ -928,12 +961,18 @@
928
961
  }, 'LUDA ');
929
962
 
930
963
  function eventPath(event) {
964
+ var path;
931
965
  if (event.composedPath) {
932
966
  return event.composedPath();
933
967
  } else if (event.path) {
934
968
  return event.path;
935
969
  } else {
936
- return [event.target].concat(pluck([event.target], 'parentNode', true));
970
+ path = [event.target];
971
+ path = path.concat(pluck(path, 'parentNode', true));
972
+ if (document.contains(event.target)) {
973
+ path.push(window);
974
+ }
975
+ return path;
937
976
  }
938
977
  }
939
978
 
@@ -1535,7 +1574,7 @@
1535
1574
  });
1536
1575
  };
1537
1576
 
1538
- var config$1, createObserver, cur, executeMutations, findSameMutation, nodesEqual, runAttrCallbacks, runDomCallbacks, stopWatch, watch;
1577
+ var config$1, createObserver, cur, executeMutations, findSameMutation, nodesEqual, runAttrCallbacks, runNodeCallbacks, stopWatch, watch;
1539
1578
 
1540
1579
  config$1 = {
1541
1580
  childList: true,
@@ -1555,23 +1594,23 @@
1555
1594
  }
1556
1595
  };
1557
1596
 
1558
- runDomCallbacks = function(type, mutation, watches, nestable) {
1597
+ runNodeCallbacks = function(type, mutation, watches, nestable) {
1559
1598
  var C, ins, mu, nodes;
1560
1599
  ins = mutation.ins;
1561
1600
  C = ins.constructor;
1562
1601
  mu = mutation.mu;
1563
1602
  nodes = Array.from(mu[`${type}Nodes`]);
1564
- return watches.dom.forEach(function(dom) {
1603
+ return watches.node.forEach(function(node) {
1565
1604
  var els;
1566
1605
  els = [];
1567
1606
  nodes.forEach(function(n) {
1568
- return els = els.concat(findAll(dom.selector, n));
1607
+ return els = els.concat(findAll(node.selector, n));
1569
1608
  });
1570
1609
  if (!els.length) {
1571
1610
  return;
1572
1611
  }
1573
1612
  !nestable && (els = unnested(ins, unique(els)));
1574
- return els.length && dom.callbacks.forEach(function(callback) {
1613
+ return els.length && node.callbacks.forEach(function(callback) {
1575
1614
  var ctx;
1576
1615
  ctx = cur(ins, callback, els);
1577
1616
  if (callback !== C.prototype.cleanTraversal) {
@@ -1590,16 +1629,19 @@
1590
1629
  name = mu.attributeName;
1591
1630
  target = mu.target;
1592
1631
  oldVal = mu.oldValue;
1593
- return name && watches.attr.forEach(function(attr) {
1594
- if (name !== attr.name) {
1632
+ if (!(name && Type.isElement(target))) {
1633
+ return;
1634
+ }
1635
+ if (!nestable && !unnested(ins, [target]).length) {
1636
+ return;
1637
+ }
1638
+ return watches.attr.forEach(function(attr) {
1639
+ if (!attr.name.includes(name)) {
1595
1640
  return;
1596
1641
  }
1597
1642
  if (!matches(target, attr.selector)) {
1598
1643
  return;
1599
1644
  }
1600
- if (!nestable && !unnested(ins, [target]).length) {
1601
- return;
1602
- }
1603
1645
  return attr.callbacks.forEach(function(callback) {
1604
1646
  var ctx;
1605
1647
  ctx = cur(ins, callback, target);
@@ -1611,25 +1653,14 @@
1611
1653
 
1612
1654
  executeMutations = function(C, mutations, nestable) {
1613
1655
  return mutations.forEach(function(mutation) {
1614
- runDomCallbacks('added', mutation, C.watches, nestable);
1615
- runDomCallbacks('removed', mutation, C.watches, nestable);
1656
+ runNodeCallbacks('added', mutation, C.watches, nestable);
1657
+ runNodeCallbacks('removed', mutation, C.watches, nestable);
1616
1658
  return runAttrCallbacks(mutation, C.watches, nestable);
1617
1659
  });
1618
1660
  };
1619
1661
 
1620
1662
  nodesEqual = function(nodesOne, nodesTwo) {
1621
- var itemsOne, itemsTwo;
1622
- if (nodesOne.length !== nodesTwo.length) {
1623
- return false;
1624
- }
1625
- if (nodesOne.length === 0 && nodesTwo.length === 0) {
1626
- return true;
1627
- }
1628
- itemsOne = Array.from(nodesOne);
1629
- itemsTwo = Array.from(nodesTwo);
1630
- return !itemsOne.some(function(node, index) {
1631
- return node !== itemsTwo[index];
1632
- });
1663
+ return arrayEqual(Array.from(nodesOne), Array.from(nodesTwo), true);
1633
1664
  };
1634
1665
 
1635
1666
  findSameMutation = function(mutations, mu) {
@@ -1705,7 +1736,7 @@
1705
1736
  if (!C.watches) {
1706
1737
  conf = C.helpers.watch.call(C.prototype);
1707
1738
  C.watches = {
1708
- dom: (conf.dom || []).map(function(d) {
1739
+ node: (conf.node || []).map(function(d) {
1709
1740
  return {
1710
1741
  selector: Type.isFunction(d[0]) ? '*' : d[0],
1711
1742
  callbacks: Type.isFunction(d[0]) ? d : d.slice(1)
@@ -1713,7 +1744,7 @@
1713
1744
  }),
1714
1745
  attr: (conf.attr || []).map(function(a) {
1715
1746
  return {
1716
- name: a[0],
1747
+ name: splitValues(a[0]),
1717
1748
  selector: Type.isFunction(a[1]) ? '*' : a[1],
1718
1749
  callbacks: Type.isFunction(a[1]) ? a.slice(1) : a.slice(2)
1719
1750
  };
@@ -1772,14 +1803,14 @@
1772
1803
  C.helpers.watch = function() {
1773
1804
  var watches;
1774
1805
  watches = definedWatch.call(this);
1775
- watches.dom || (watches.dom = []);
1776
- watches.dom.unshift([proto.cleanTraversal]);
1806
+ watches.node || (watches.node = []);
1807
+ watches.node.unshift([proto.cleanTraversal]);
1777
1808
  return watches;
1778
1809
  };
1779
1810
  } else {
1780
1811
  C.helpers.watch = function() {
1781
1812
  return {
1782
- dom: [[proto.cleanTraversal]]
1813
+ node: [[proto.cleanTraversal]]
1783
1814
  };
1784
1815
  };
1785
1816
  }
@@ -2004,7 +2035,7 @@
2004
2035
  var factory$1;
2005
2036
 
2006
2037
  luda$1.extend('component', factory$1 = function(name, root) {
2007
- var Component;
2038
+ var Component, occupied;
2008
2039
  Component = (function() {
2009
2040
  class Component extends Base$1 {}
2010
2041
  Component.id = camelCase(`Component${(name ? '-' + name : '_' + guid$1())}`);
@@ -2030,10 +2061,11 @@
2030
2061
  return Component;
2031
2062
 
2032
2063
  }).call(this);
2064
+ occupied = name && name in luda$1;
2033
2065
  if (name) {
2034
2066
  luda$1.extend(name, createProxy(Component));
2035
2067
  }
2036
- luda$1.ready(function() {
2068
+ !occupied && luda$1.ready(function() {
2037
2069
  if (Type.isDocument(Component.root)) {
2038
2070
  Component.create(Component.root);
2039
2071
  }
@@ -2363,7 +2395,7 @@
2363
2395
  return this.els[0] && getValue(this.els[0]);
2364
2396
  }
2365
2397
  this.els.forEach(function(el) {
2366
- var val;
2398
+ var hasSelected, options, val;
2367
2399
  if (el.tagName === 'SELECT') {
2368
2400
  if (Type.isArray(value)) {
2369
2401
  val = value;
@@ -2372,16 +2404,24 @@
2372
2404
  } else {
2373
2405
  val = [value];
2374
2406
  }
2375
- return [].forEach.call(el.options, function(option) {
2407
+ hasSelected = false;
2408
+ options = Array.from(el.options);
2409
+ options.forEach(function(o) {
2376
2410
  var selected;
2377
- selected = val.includes(readValue(option.value));
2378
- luda$1(option).attr('selected', selected ? '' : null);
2379
- return option.selected = selected;
2411
+ selected = val.includes(readValue(o.value));
2412
+ o.selected = selected;
2413
+ return hasSelected || (hasSelected = selected);
2414
+ });
2415
+ if (!hasSelected) {
2416
+ el.selectedIndex = -1;
2417
+ }
2418
+ return options.forEach(function(o) {
2419
+ return luda$1(o).attr('selected', o.selected ? '' : null);
2380
2420
  });
2381
2421
  } else {
2382
2422
  val = value === null ? '' : parseValue(value);
2383
- luda$1(el).attr('value', val);
2384
- return el.value = val;
2423
+ el.value = val;
2424
+ return luda$1(el).attr('value', val);
2385
2425
  }
2386
2426
  });
2387
2427
  return this;
@@ -2526,7 +2566,7 @@
2526
2566
  argReverse = [].reverse.apply(arguments);
2527
2567
  handler = function(selector) {
2528
2568
  var els;
2529
- els = luda$1(selector).els.slice().reverse();
2569
+ els = luda$1(selector).els.reverse();
2530
2570
  return luda$1(els).insertAfter(self);
2531
2571
  };
2532
2572
  [].forEach.call(argReverse, handler);
@@ -2795,20 +2835,6 @@
2795
2835
  }
2796
2836
  });
2797
2837
 
2798
- luda$1.include({
2799
- matches: function(selector) {
2800
- if (!this.els.length) {
2801
- return false;
2802
- }
2803
- if (!selector) {
2804
- return false;
2805
- }
2806
- return this.els.some(function(el) {
2807
- return matches(el, selector);
2808
- });
2809
- }
2810
- });
2811
-
2812
2838
  var Mixin;
2813
2839
 
2814
2840
  var Mixin$1 = Mixin = class Mixin {
@@ -3054,26 +3080,42 @@
3054
3080
  });
3055
3081
 
3056
3082
  luda$1.include({
3057
- next: function(comparator, _all) {
3058
- return luda$1(collect(unique(pluck(this.els, 'nextElementSibling', _all)), comparator));
3083
+ nextAll: function(comparator) {
3084
+ var plucked;
3085
+ plucked = pluck(this.els, 'nextElementSibling', true);
3086
+ return luda$1(collect(unique(plucked), comparator));
3059
3087
  }
3060
3088
  });
3061
3089
 
3062
3090
  luda$1.include({
3063
- nextAll: function(comparator) {
3064
- return this.next(comparator, true);
3091
+ next: function(comparator) {
3092
+ var filter;
3093
+ if (comparator) {
3094
+ filter = function(n) {
3095
+ return collect([n], comparator).length;
3096
+ };
3097
+ }
3098
+ return luda$1(unique(pluck(this.els, 'nextElementSibling', false, filter)));
3065
3099
  }
3066
3100
  });
3067
3101
 
3068
3102
  luda$1.include({
3069
- prev: function(comparator, _al) {
3070
- return luda$1(collect(unique(pluck(this.els, 'previousElementSibling', _al)), comparator));
3103
+ prevAll: function(comparator) {
3104
+ var plucked;
3105
+ plucked = pluck(this.els, 'previousElementSibling', true);
3106
+ return luda$1(collect(unique(plucked), comparator));
3071
3107
  }
3072
3108
  });
3073
3109
 
3074
3110
  luda$1.include({
3075
- prevAll: function(comparator) {
3076
- return this.prev(comparator, true);
3111
+ prev: function(comparator) {
3112
+ var filter;
3113
+ if (comparator) {
3114
+ filter = function(p) {
3115
+ return collect([p], comparator).length;
3116
+ };
3117
+ }
3118
+ return luda$1(unique(pluck(this.els, 'previousElementSibling', false, filter)));
3077
3119
  }
3078
3120
  });
3079
3121
 
@@ -3099,22 +3141,23 @@
3099
3141
  // data:
3100
3142
  // disable:
3101
3143
  // tabIndex: string # required
3144
+ disableTargetProp: function() {
3145
+ var ref;
3146
+ return ((ref = this.attr) != null ? ref.disable : void 0) || 'disabled';
3147
+ },
3102
3148
  disableCreate: function() {
3103
- var dataAttr, ref, rootEl, tabIndex;
3104
- rootEl = this.root.els[0];
3105
- tabIndex = rootEl.tabIndex;
3149
+ var dataAttr, tabIndex;
3150
+ tabIndex = this.root.prop('tabIndex');
3106
3151
  dataAttr = this.data.disable.tabIndex;
3107
3152
  if (!this.root.hasData(dataAttr)) {
3108
3153
  this.root.data(dataAttr, tabIndex);
3109
3154
  }
3110
- rootEl.tabIndex = -1;
3111
- return rootEl[((ref = this.attr) != null ? ref.disable : void 0) || 'disabled'] = true;
3155
+ return this.root.prop('tabIndex', -1).prop(this.disableTargetProp(), true);
3112
3156
  },
3113
3157
  disableDestroy: function() {
3114
- var ref, rootEl;
3115
- rootEl = this.root.els[0];
3116
- rootEl.tabIndex = this.root.data(this.data.disable.tabIndex);
3117
- return rootEl[((ref = this.attr) != null ? ref.disable : void 0) || 'disabled'] = false;
3158
+ var tabIndex;
3159
+ tabIndex = this.root.data(this.data.disable.tabIndex);
3160
+ return this.root.prop('tabIndex', tabIndex).prop(this.disableTargetProp(), false);
3118
3161
  }
3119
3162
  });
3120
3163
 
@@ -3134,15 +3177,17 @@
3134
3177
  });
3135
3178
 
3136
3179
  luda.component('enter', document).protect({
3137
- data: {
3138
- enable: 'enter'
3139
- },
3140
- selectors: ['input[type=checkbox]', 'input[type=radio]', '[tabindex]'],
3180
+ selectors: ['input[type=checkbox]', 'input[type=radio]', '[tabindex]']
3181
+ }).protect({
3182
+ disabled: function() {
3183
+ return this.html.data('enter') === false;
3184
+ }
3185
+ }).protect({
3141
3186
  trigger: function(e) {
3142
- if (this.html.data(this.data.enable) === false) {
3187
+ if (this.disabled()) {
3143
3188
  return;
3144
3189
  }
3145
- if (!luda(e.target).matches(this.selectors.join(','))) {
3190
+ if (!luda(e.target).is(this.selectors.join(','))) {
3146
3191
  return;
3147
3192
  }
3148
3193
  e.preventDefault();
@@ -3162,18 +3207,17 @@
3162
3207
  cls: {
3163
3208
  focus: 'focus'
3164
3209
  },
3165
- data: {
3166
- enable: 'focus'
3167
- },
3168
3210
  selector: {
3169
3211
  focused: '.focus',
3170
3212
  always: ['select', 'textarea', ':not(.btn-check):not(.btn-radio):not(.btn-file) > input:not([type=button]):not([type=submit]):not([type=reset])', '[contenteditable]', '[contenteditable=true]'],
3171
3213
  nested: ['select', '[contenteditable]', '[contenteditable=true]'],
3172
3214
  touch: 'input[type=range]'
3173
- },
3215
+ }
3216
+ }).protect({
3174
3217
  disabled: function() {
3175
- return this.html.data(this.data.enable) === false;
3176
- },
3218
+ return this.html.data('focus') === false;
3219
+ }
3220
+ }).protect({
3177
3221
  addClass: function(node) {
3178
3222
  if (this.disabled()) {
3179
3223
  return;
@@ -3198,12 +3242,12 @@
3198
3242
  (evt = this.evtTriggeredFocus) && delete this.evtTriggeredFocus;
3199
3243
  if (evt && /key/.test(evt)) {
3200
3244
  target = node;
3201
- } else if (luda(node).matches(this.selector.always.join(','))) {
3245
+ } else if (luda(node).is(this.selector.always.join(','))) {
3202
3246
  target = node;
3203
- } else if (luda(node).matches(this.selector.nested.join(' *,'))) {
3247
+ } else if (luda(node).is(this.selector.nested.join(' *,'))) {
3204
3248
  parent = this.selector.nested.join(',');
3205
3249
  e.eventPath().some(function(el) {
3206
- return luda(el).matches(parent) && (target = el);
3250
+ return luda(el).is(parent) && (target = el);
3207
3251
  });
3208
3252
  }
3209
3253
  return this.addClass(target);
@@ -3279,10 +3323,12 @@
3279
3323
  });
3280
3324
 
3281
3325
  luda.component('tabulate', document).protect({
3282
- selector: 'input[type=radio]:not([disabled])',
3283
- data: {
3284
- tabulate: 'tabulate'
3285
- },
3326
+ selector: 'input[type=radio]:not([disabled])'
3327
+ }).protect({
3328
+ disabled: function() {
3329
+ return this.html.data('tabulate') === false;
3330
+ }
3331
+ }).protect({
3286
3332
  findSiblings: function(radio) {
3287
3333
  var index, name, radios, selector;
3288
3334
  selector = this.selector;
@@ -3300,7 +3346,7 @@
3300
3346
  },
3301
3347
  trigger: function(e) {
3302
3348
  var next, prev;
3303
- if (this.html.data(this.data.tabulate) === false) {
3349
+ if (this.disabled()) {
3304
3350
  return;
3305
3351
  }
3306
3352
  if (e.shiftKey) {
@@ -3345,6 +3391,38 @@
3345
3391
  // selector:
3346
3392
  // toggleable:
3347
3393
  // target: string # optional
3394
+ toggleableActive: function() {
3395
+ return this.root.hasClass(this.cls.toggleable.active);
3396
+ },
3397
+ toggleableTriggerable: function(e) {
3398
+ var evtPath, index, ref, ref1, toggleAttr, trigger;
3399
+ if (this.toggleableTransitioning()) {
3400
+ return;
3401
+ }
3402
+ if (/key/.test(e.type)) {
3403
+ return true;
3404
+ }
3405
+ if (!this.root.els[0].contains(e.target)) {
3406
+ return true;
3407
+ }
3408
+ trigger = (ref = this.default) != null ? (ref1 = ref.toggleable) != null ? ref1.trigger : void 0 : void 0;
3409
+ toggleAttr = this.data.toggleable.trigger;
3410
+ if (!toggleAttr) {
3411
+ return trigger;
3412
+ }
3413
+ evtPath = e.eventPath();
3414
+ index = evtPath.indexOf(this.root.els[0]) + 1;
3415
+ evtPath.slice(0, index).some(function(el) {
3416
+ var ins;
3417
+ ins = luda(el);
3418
+ if (!ins.hasData(toggleAttr)) {
3419
+ return;
3420
+ }
3421
+ trigger = ins.data(toggleAttr) !== false;
3422
+ return true;
3423
+ });
3424
+ return trigger;
3425
+ },
3348
3426
  toggleableActivate: function() {
3349
3427
  var evt;
3350
3428
  if (this.toggleableActive()) {
@@ -3394,41 +3472,9 @@
3394
3472
  return this.toggleableActivate();
3395
3473
  }
3396
3474
  },
3397
- toggleableActive: function() {
3398
- return this.root.hasClass(this.cls.toggleable.active);
3399
- },
3400
3475
  toggleableTransitioning: function() {
3401
3476
  return 'toggleableActivating' in this || 'toggleableDeactivating' in this;
3402
3477
  },
3403
- toggleableTriggerable: function(e) {
3404
- var evtPath, index, ref, ref1, toggleAttr, trigger;
3405
- if (this.toggleableTransitioning()) {
3406
- return;
3407
- }
3408
- if (/key/.test(e.type)) {
3409
- return true;
3410
- }
3411
- if (!this.root.els[0].contains(e.target)) {
3412
- return true;
3413
- }
3414
- trigger = (ref = this.default) != null ? (ref1 = ref.toggleable) != null ? ref1.trigger : void 0 : void 0;
3415
- toggleAttr = this.data.toggleable.trigger;
3416
- if (!toggleAttr) {
3417
- return trigger;
3418
- }
3419
- evtPath = e.eventPath();
3420
- index = evtPath.indexOf(this.root.els[0]) + 1;
3421
- evtPath.slice(0, index).some(function(el) {
3422
- var ins;
3423
- ins = luda(el);
3424
- if (!ins.hasData(toggleAttr)) {
3425
- return;
3426
- }
3427
- trigger = ins.data(toggleAttr) !== false;
3428
- return true;
3429
- });
3430
- return trigger;
3431
- },
3432
3478
  toggleableFocusOpener: function(e) {
3433
3479
  var ins;
3434
3480
  if (this.toggleableActive()) {
@@ -3645,38 +3691,57 @@
3645
3691
  file: 'input[type=file]',
3646
3692
  simulator: 'input:not([type=file])'
3647
3693
  },
3694
+ evt: {
3695
+ changed: 'luda:fmFile:changed'
3696
+ },
3648
3697
  splitor: ' '
3649
3698
  }).protect({
3699
+ placeholder: function() {
3700
+ return this.file.attr('placeholder');
3701
+ },
3702
+ value: function() {
3703
+ return this.file.attr('value');
3704
+ },
3705
+ multiple: function() {
3706
+ return this.file.prop('multiple');
3707
+ }
3708
+ }).protect({
3709
+ files: function() {
3710
+ return Array.from(this.file.prop('files'));
3711
+ },
3650
3712
  insertSimulator: function() {
3651
- var simulator;
3652
3713
  if (this.simulator.length) {
3653
3714
  return;
3654
3715
  }
3655
- simulator = luda('<input>');
3656
- simulator.els[0].tabIndex = -1;
3657
- return simulator.insertAfter(this.file);
3716
+ return luda('<input>').prop('tabIndex', -1).attr('placeholder', this.placeholder()).insertAfter(this.file);
3658
3717
  },
3659
- updatePlaceholder: function() {
3660
- var placeholder;
3661
- if (!(placeholder = this.file.attr('placeholder'))) {
3662
- return;
3663
- }
3664
- return this.simulator.attr('placeholder', placeholder);
3665
- },
3666
- updateValue: function() {
3718
+ updateSimulatorValue: function() {
3667
3719
  var value, values;
3668
- values = Array.from(this.file.els[0].files).map(function(f) {
3720
+ values = this.files().map(function(f) {
3669
3721
  return f.name;
3670
3722
  });
3671
- value = values.join(this.splitor) || this.file.attr('value') || '';
3672
- return this.simulator.attr('value', value);
3723
+ value = values.join(this.splitor) || this.value() || '';
3724
+ return this.simulator.val(value);
3725
+ },
3726
+ updateValue: function() {
3727
+ var oldFile, val;
3728
+ this.updateSimulatorValue();
3729
+ oldFile = this.selectedFile;
3730
+ this.selectedFile = this.files();
3731
+ if (!oldFile || luda.arrayEqual(this.selectedFile, oldFile)) {
3732
+ return;
3733
+ }
3734
+ val = this.multiple() ? this.selectedFile : this.selectedFile[0];
3735
+ return this.file.trigger(this.evt.changed, val);
3673
3736
  },
3674
3737
  tryReset: function(target, oldVal) {
3675
- if (this.file.attr('value') !== '') {
3738
+ if (this.value() !== '') {
3676
3739
  return;
3677
3740
  }
3678
- this.file.els[0].value = '';
3679
- return this.file.attr('value', oldVal);
3741
+ if (oldVal === '') {
3742
+ return;
3743
+ }
3744
+ return this.file.prop('value', '').attr('value', oldVal || '');
3680
3745
  }
3681
3746
  }).help({
3682
3747
  find: function() {
@@ -3692,7 +3757,6 @@
3692
3757
  },
3693
3758
  create: function() {
3694
3759
  this.insertSimulator();
3695
- this.updatePlaceholder();
3696
3760
  return this.updateValue();
3697
3761
  },
3698
3762
  listen: function() {
@@ -3710,15 +3774,27 @@
3710
3774
  data: {
3711
3775
  default: 'data-fm-select_default-selected',
3712
3776
  defaultMarked: 'data-fm-select_default-marked'
3777
+ },
3778
+ evt: {
3779
+ changed: 'luda:fmSelect:changed'
3780
+ }
3781
+ }).protect({
3782
+ placeholder: function() {
3783
+ return this.select.attr('placeholder');
3784
+ },
3785
+ multiple: function() {
3786
+ return this.select.prop('multiple');
3787
+ },
3788
+ options: function() {
3789
+ return Array.from(this.select.prop('options'));
3713
3790
  }
3714
3791
  }).protect({
3715
3792
  tryEmpty: function() {
3716
- var select, selected;
3717
- select = this.select.els[0];
3718
- selected = Array.from(select.options).some(function(o) {
3793
+ var selected;
3794
+ selected = this.options().some(function(o) {
3719
3795
  return luda(o).hasAttr('selected');
3720
3796
  });
3721
- return !selected && (select.selectedIndex = -1);
3797
+ return !selected && this.select.prop('selectedIndex', -1);
3722
3798
  },
3723
3799
  markSelected: function(markDefault) {
3724
3800
  markDefault = markDefault === true;
@@ -3728,7 +3804,7 @@
3728
3804
  if (markDefault) {
3729
3805
  this.root.data(this.data.defaultMarked, '');
3730
3806
  }
3731
- return Array.from(this.select.els[0].options).forEach((o) => {
3807
+ return this.options().forEach((o) => {
3732
3808
  var option, val;
3733
3809
  option = luda(o);
3734
3810
  if (markDefault) {
@@ -3740,39 +3816,48 @@
3740
3816
  }
3741
3817
  });
3742
3818
  },
3743
- initSimulator: function() {
3744
- var simulator;
3745
- if (this.select.els[0].multiple) {
3819
+ toggleSimulator: function() {
3820
+ if (this.multiple()) {
3746
3821
  return this.simulator.remove();
3747
3822
  }
3748
3823
  if (this.simulator.length) {
3749
3824
  return;
3750
3825
  }
3751
- simulator = luda('<input>');
3752
- simulator.els[0].tabIndex = -1;
3753
- simulator.insertAfter(this.select);
3754
- this.updatePlaceholder();
3755
- return this.updateValue();
3826
+ return luda('<input>').prop('tabIndex', -1).attr('placeholder', this.placeholder()).insertAfter(this.select);
3756
3827
  },
3757
- updatePlaceholder: function() {
3758
- if (this.select.els[0].multiple) {
3828
+ updateSimulatorValue: function() {
3829
+ var selected, val;
3830
+ if (this.multiple()) {
3759
3831
  return;
3760
3832
  }
3761
- return this.simulator.attr('placeholder', this.select.attr('placeholder'));
3833
+ selected = this.options()[this.select.prop('selectedIndex')];
3834
+ val = selected ? luda(selected).text() : '';
3835
+ return this.simulator.val(val);
3762
3836
  },
3763
3837
  updateValue: function() {
3764
- var select, selected, val;
3765
- select = this.select.els[0];
3766
- if (select.multiple) {
3838
+ var oldVal, selected, val;
3839
+ this.updateSimulatorValue();
3840
+ oldVal = this.selectedVal;
3841
+ val = this.select.val();
3842
+ this.selectedVal = luda.isArray(val) ? val : [val];
3843
+ if (!oldVal || luda.arrayEqual(this.selectedVal, oldVal)) {
3767
3844
  return;
3768
3845
  }
3769
- selected = select.options[select.selectedIndex];
3770
- val = selected ? luda(selected).text() : '';
3771
- return this.simulator.attr('value', val);
3846
+ if (this.multiple()) {
3847
+ selected = this.options().filter(function(o) {
3848
+ return o.selected;
3849
+ });
3850
+ } else {
3851
+ selected = this.options()[this.select.prop('selectedIndex')];
3852
+ }
3853
+ return this.select.trigger(this.evt.changed, {
3854
+ value: val,
3855
+ selected: selected
3856
+ });
3772
3857
  },
3773
3858
  reset: function() {
3774
- this.select.els[0].selectedIndex = -1;
3775
- Array.from(this.select.els[0].options).forEach((o) => {
3859
+ this.select.prop('selectedIndex', -1);
3860
+ this.options().forEach((o) => {
3776
3861
  return o.selected = luda(o).hasData(this.data.default);
3777
3862
  });
3778
3863
  return this.markSelected();
@@ -3787,12 +3872,13 @@
3787
3872
  create: function() {
3788
3873
  this.tryEmpty();
3789
3874
  this.markSelected(true);
3790
- return this.initSimulator();
3875
+ this.toggleSimulator();
3876
+ return this.updateValue();
3791
3877
  },
3792
3878
  watch: function() {
3793
3879
  return {
3794
- dom: [[this.selector.options, this.tryEmpty, this.updateValue]],
3795
- attr: [['selected', this.selector.options, this.updateValue], ['multiple', this.selector.select, this.initSimulator]]
3880
+ node: [[this.selector.options, this.tryEmpty, this.updateValue]],
3881
+ attr: [['selected', this.selector.options, this.tryEmpty, this.updateValue], ['multiple', this.selector.select, this.toggleSimulator, this.updateValue]]
3796
3882
  };
3797
3883
  },
3798
3884
  listen: function() {
@@ -3832,6 +3918,30 @@
3832
3918
  // indicators: string # required
3833
3919
  // prevCtrl: string # optional
3834
3920
  // nextCtrl: string # optional
3921
+ tabableActiveIndex: function() {
3922
+ var index, ref, ref1;
3923
+ index = ((ref = this.default) != null ? (ref1 = ref.tabable) != null ? ref1.activeIndex : void 0 : void 0) || 0;
3924
+ this.tabableTargets.els.some((it, i) => {
3925
+ if (!luda(it).hasClass(this.cls.tabable.active)) {
3926
+ return false;
3927
+ }
3928
+ index = i;
3929
+ return true;
3930
+ });
3931
+ return index;
3932
+ },
3933
+ tabableWrapable: function() {
3934
+ var ref, ref1, wrapAttr, wrapable;
3935
+ wrapAttr = this.data.tabable.wrap;
3936
+ if (!wrapAttr) {
3937
+ return false;
3938
+ }
3939
+ wrapable = this.root.data(wrapAttr);
3940
+ if (wrapable === false) {
3941
+ return false;
3942
+ }
3943
+ return (ref = this.default) != null ? (ref1 = ref.tabable) != null ? ref1.wrap : void 0 : void 0;
3944
+ },
3835
3945
  tabableActivate: function(index) {
3836
3946
  var direction;
3837
3947
  if (!luda.isNumeric(index)) {
@@ -3923,30 +4033,6 @@
3923
4033
  this.tabableSetDirectionCtrlsState();
3924
4034
  return true;
3925
4035
  },
3926
- tabableActiveIndex: function() {
3927
- var index, ref, ref1;
3928
- index = ((ref = this.default) != null ? (ref1 = ref.tabable) != null ? ref1.activeIndex : void 0 : void 0) || 0;
3929
- this.tabableTargets.els.some((it, i) => {
3930
- if (!luda(it).hasClass(this.cls.tabable.active)) {
3931
- return false;
3932
- }
3933
- index = i;
3934
- return true;
3935
- });
3936
- return index;
3937
- },
3938
- tabableWrapable: function() {
3939
- var ref, ref1, wrapAttr, wrapable;
3940
- wrapAttr = this.data.tabable.wrap;
3941
- if (!wrapAttr) {
3942
- return false;
3943
- }
3944
- wrapable = this.root.data(wrapAttr);
3945
- if (wrapable === false) {
3946
- return false;
3947
- }
3948
- return (ref = this.default) != null ? (ref1 = ref.tabable) != null ? ref1.wrap : void 0 : void 0;
3949
- },
3950
4036
  tabableTransitioning: function() {
3951
4037
  return 'tabableActivating' in this || 'tabableDeactivating' in this;
3952
4038
  },
@@ -4051,7 +4137,7 @@
4051
4137
  wrapAttr && attr.push([wrapAttr, this.tabableSetDirectionControlState]);
4052
4138
  return {
4053
4139
  attr: attr,
4054
- dom: [[this.selector.tabable.targets, this.tabableLayout], [this.selector.tabable.indicators, this.tabableSetIndicatorsState]]
4140
+ node: [[this.selector.tabable.targets, this.tabableLayout], [this.selector.tabable.indicators, this.tabableSetIndicatorsState]]
4055
4141
  };
4056
4142
  },
4057
4143
  tabableListen: function() {
@@ -4106,6 +4192,15 @@
4106
4192
  nextCtrl: '.carousel-next'
4107
4193
  }
4108
4194
  }
4195
+ }).protect({
4196
+ interval: function() {
4197
+ var duration;
4198
+ duration = this.root.data(this.data.interval);
4199
+ if (duration === false) {
4200
+ return false;
4201
+ }
4202
+ return Math.abs(parseInt(duration, 10)) || this.default.interval;
4203
+ }
4109
4204
  }).include(luda.mixin('tabable').alias({
4110
4205
  activate: 'tabableActivate',
4111
4206
  next: 'tabableNext',
@@ -4144,17 +4239,26 @@
4144
4239
  return this.intervaling = setTimeout(handler, this.nextInterval);
4145
4240
  }
4146
4241
  }).protect(luda.mixin('tabable').all()).protect({
4147
- interval: function() {
4148
- var duration;
4149
- duration = this.root.data(this.data.interval);
4150
- if (duration === false) {
4151
- return false;
4152
- }
4153
- return Math.abs(parseInt(duration, 10)) || this.default.interval;
4242
+ togglePath: function(path, action) {
4243
+ var targets;
4244
+ targets = path.filter((el) => {
4245
+ return this.con.contains(el);
4246
+ });
4247
+ return this.con.create(targets).forEach(function(ins) {
4248
+ return ins[action]();
4249
+ });
4250
+ },
4251
+ pauseOnEvt: function(e) {
4252
+ return this.togglePath(e.eventPath(), 'pause');
4154
4253
  },
4155
- touchendPlay: function() {
4254
+ playOnEvt: function(e) {
4255
+ return this.togglePath(e.eventPath(), 'play');
4256
+ },
4257
+ playOnTouchend: function(e) {
4258
+ var path;
4259
+ path = e.eventPath();
4156
4260
  return setTimeout(() => {
4157
- return this.play();
4261
+ return this.togglePath(path, 'play');
4158
4262
  });
4159
4263
  }
4160
4264
  }).help({
@@ -4176,7 +4280,7 @@
4176
4280
  return watches;
4177
4281
  },
4178
4282
  listen: function() {
4179
- return this.tabableListen().concat([['swipeleft', this.tabableNextOnEvent], ['swiperight', this.tabablePrevOnEvent], ['touchstart mouseover', this.pause], ['mouseout', this.play], ['touchend', this.touchendPlay]]);
4283
+ return this.tabableListen().concat([['swipeleft', this.tabableNextOnEvent], ['swiperight', this.tabablePrevOnEvent], ['touchstart mouseover', this.pauseOnEvt], ['mouseout', this.playOnEvt], ['touchend', this.playOnTouchend]]);
4180
4284
  }
4181
4285
  });
4182
4286
 
@@ -4282,6 +4386,12 @@
4282
4386
  }
4283
4387
  });
4284
4388
  },
4389
+ create: function() {
4390
+ return this.toggleableCreate();
4391
+ },
4392
+ destroy: function() {
4393
+ return this.toggleableDestroy();
4394
+ },
4285
4395
  listen: function() {
4286
4396
  var self;
4287
4397
  self = this;
@@ -4328,12 +4438,15 @@
4328
4438
  data: {
4329
4439
  label: 'fm-dropdown-label'
4330
4440
  },
4441
+ evt: {
4442
+ changed: 'luda:fmDropdown:changed'
4443
+ },
4331
4444
  splitor: ' '
4332
4445
  }).protect({
4333
- disableSimulator: function() {
4446
+ initSimulator: function() {
4334
4447
  return this.simulator.data('auto', false).attr('readonly', '');
4335
4448
  },
4336
- updateValue: function() {
4449
+ updateSimulatorValue: function() {
4337
4450
  var values;
4338
4451
  values = [];
4339
4452
  this.options.els.forEach((input, index) => {
@@ -4341,13 +4454,31 @@
4341
4454
  if (!input.checked) {
4342
4455
  return;
4343
4456
  }
4344
- label = luda(this.labels.els[index]);
4457
+ label = this.labels.eq(index);
4345
4458
  value = label.data(this.data.label) || label.text();
4346
4459
  if (value && !values.includes(value)) {
4347
4460
  return values.push(value);
4348
4461
  }
4349
4462
  });
4350
- return this.simulator.attr('value', values.join(this.splitor));
4463
+ return this.simulator.val(values.join(this.splitor));
4464
+ },
4465
+ updateValue: function() {
4466
+ var checked, oldVal;
4467
+ this.updateSimulatorValue();
4468
+ oldVal = this.selectedVal;
4469
+ checked = this.options.els.filter(function(input) {
4470
+ return input.checked;
4471
+ });
4472
+ this.selectedVal = checked.map(function(input) {
4473
+ return luda(input).val();
4474
+ });
4475
+ if (!oldVal || luda.arrayEqual(this.selectedVal, oldVal)) {
4476
+ return;
4477
+ }
4478
+ return this.root.trigger(this.evt.changed, {
4479
+ value: this.selectedVal,
4480
+ selected: checked
4481
+ });
4351
4482
  },
4352
4483
  triggerClick: function() {
4353
4484
  return this.simulator.trigger('click');
@@ -4361,13 +4492,13 @@
4361
4492
  };
4362
4493
  },
4363
4494
  create: function() {
4364
- this.disableSimulator();
4495
+ this.initSimulator();
4365
4496
  return this.updateValue();
4366
4497
  },
4367
4498
  watch: function() {
4368
4499
  return {
4369
- dom: [[this.selector.options, this.updateValue]],
4370
- attr: [['checked', this.selector.options, this.updateValue]]
4500
+ node: [[this.selector.options, this.updateValue]],
4501
+ attr: [['checked', this.selector.options, this.updateValue], ['type', this.selector.options, this.updateValue]]
4371
4502
  };
4372
4503
  },
4373
4504
  listen: function() {