luda 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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() {