mui-sass 0.4.2 → 0.4.7

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
  SHA1:
3
- metadata.gz: 3f47ba598013f481e02209323035f2b303241f1a
4
- data.tar.gz: ff59616b87976e183c4d138eaf4cad95fe1dfce5
3
+ metadata.gz: a2050f12dddeda8e3aef97f97647c8b68fb34404
4
+ data.tar.gz: 44f610c26efabbfcb61d9a9905a44c0852e0f2f9
5
5
  SHA512:
6
- metadata.gz: d6539d5ac8a3d0af8b8f64ed66b5c29c397eb4194a89471cd067d0a4e8ca759cafb1cf5632e2caefe416095e1d398012aff8f3bf492880181264ecadc3c11edc
7
- data.tar.gz: b8cb42a20da6d239c73a602f4a3874d7b91dc2518705003de835c756e2fe5d223e17bacb0bc03c2d984e5fd32cd8b6f97ab716cb620488d34f846736190a5260
6
+ metadata.gz: 24bb2735dfa831635f9cddc1fc6ca9e6a123472cd52907cc8303371087fab6812bea871d88d17d34b3450d0598867736a4822e2d00bc6052c2591907dd08519c
7
+ data.tar.gz: 469bd855a4955bd3d67bbf289b68efd11d4c8c29da22b85338b3a1c14d2d76d0bf8f806f893672f4e29a8e8376b20fc39f21337d0e7b9f3ac1e093b9689a18d4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.4.7 (2016-03-02)
2
+
3
+ - Update assets to match upstream version
4
+
5
+ Framework version: MUI v0.4.7
6
+
1
7
  ## 0.4.2 (2016-02-05)
2
8
 
3
9
  - Update assets to match upstream version
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  `mui-sass` is a Sass-powered version of MUI framework for your applications. It works with Ruby on Rails, Compass, Sprockets, etc.
9
9
 
10
- `mui-sass` allows to include MUI framework CSS and JavaScript components. HTML Email, React, WebComponents and Design Files are not included.
10
+ `mui-sass` allows to include MUI framework Sass and JavaScript components. React, Angular, HTML Email, WebComponents are not included.
11
11
 
12
12
  ## Installation
13
13
 
@@ -89,31 +89,38 @@ You can also import individual Sass components.
89
89
  First you need to include core components:
90
90
 
91
91
  ```scss
92
- @import 'mui/normalize-3.0.2';
92
+ // Normalizer
93
+ @import "mui/normalize-3.0.3";
94
+ // Core variables and mixins
93
95
  @import 'mui/colors';
94
96
  @import 'mui/variables';
95
97
  @import 'mui/mixins';
98
+ // CSS Reboot
99
+ @import "mui/reboot";
96
100
  ```
97
101
 
98
102
  Then include desired Sass component:
99
103
 
100
104
  ```scss
101
- @import 'mui/appbar';
102
- @import 'mui/buttons';
103
- @import 'mui/dividers';
104
- @import 'mui/dropdowns';
105
- @import 'mui/forms';
106
- @import 'mui/grid';
107
- @import 'mui/helpers';
108
- @import 'mui/layout';
109
- @import 'mui/overlay';
110
- @import 'mui/panel';
111
- @import 'mui/ripple';
112
- @import 'mui/scaffolding';
113
- @import 'mui/semantic-markup';
114
- @import 'mui/tables';
115
- @import 'mui/tabs';
116
- @import 'mui/typography';
105
+ // Components
106
+ @import "mui/appbar";
107
+ @import "mui/buttons";
108
+ @import "mui/checkbox-and-radio";
109
+ @import "mui/containers";
110
+ @import "mui/divider";
111
+ @import "mui/dropdown";
112
+ @import "mui/form";
113
+ @import "mui/grid";
114
+ @import "mui/panel";
115
+ @import "mui/select";
116
+ @import "mui/table";
117
+ @import "mui/tabs";
118
+ @import "mui/textfield";
119
+ // Miscellaneous
120
+ @import "mui/helpers";
121
+ @import "mui/overlay";
122
+ @import "mui/ripple";
123
+ @import "mui/typography";
117
124
  ```
118
125
 
119
126
  ### Variables
@@ -129,7 +136,7 @@ $mui-base-font-size: 16px !default;
129
136
 
130
137
  ## Versioning
131
138
 
132
- MUI for Sass follows the upstream version of MUI framework. But last version number may be ahead, in case there is a need to release project specific changes.
139
+ MUI for Sass follows the upstream version of MUI framework, but last version number may be ahead, in case there is a need to release project specific changes. Some upstream versions may be skipped if they include no Sass/JavaScript related changes.
133
140
 
134
141
  Please always refer to the [CHANGELOG](https://github.com/rubysamurai/mui-sass/blob/master/CHANGELOG.md) when upgrading.
135
142
 
@@ -1,5 +1,5 @@
1
1
  module Mui
2
2
  module Sass
3
- VERSION = '0.4.2'
3
+ VERSION = '0.4.7'
4
4
  end
5
5
  end
@@ -13,12 +13,12 @@
13
13
 
14
14
  // load dependencies
15
15
  var jqLite = require('src/js/lib/jqLite'),
16
- textfield = require('src/js/forms/textfield'),
17
- select = require('src/js/forms/select'),
18
- ripple = require('src/js/ripple'),
19
- dropdowns = require('src/js/dropdowns'),
16
+ dropdown = require('src/js/dropdown'),
17
+ overlay = require('src/js/overlay'),
18
+ ripple = require('src/js/ripple'),
19
+ select = require('src/js/select'),
20
20
  tabs = require('src/js/tabs'),
21
- overlay = require('src/js/overlay');
21
+ textfield = require('src/js/textfield');
22
22
 
23
23
  // expose api
24
24
  win.mui = {
@@ -31,12 +31,12 @@
31
31
  textfield.initListeners();
32
32
  select.initListeners();
33
33
  ripple.initListeners();
34
- dropdowns.initListeners();
34
+ dropdown.initListeners();
35
35
  tabs.initListeners();
36
36
  });
37
37
  })(window);
38
38
 
39
- },{"src/js/dropdowns":6,"src/js/forms/select":7,"src/js/forms/textfield":8,"src/js/lib/jqLite":9,"src/js/overlay":10,"src/js/ripple":11,"src/js/tabs":12}],2:[function(require,module,exports){
39
+ },{"src/js/dropdown":6,"src/js/lib/jqLite":7,"src/js/overlay":8,"src/js/ripple":9,"src/js/select":10,"src/js/tabs":11,"src/js/textfield":12}],2:[function(require,module,exports){
40
40
  /**
41
41
  * MUI config module
42
42
  * @module config
@@ -878,347 +878,287 @@ module.exports = {
878
878
  };
879
879
 
880
880
  },{"./lib/jqLite":4,"./lib/util":5}],7:[function(require,module,exports){
881
+ module.exports=require(4)
882
+ },{}],8:[function(require,module,exports){
881
883
  /**
882
- * MUI CSS/JS select module
883
- * @module forms/select
884
+ * MUI CSS/JS overlay module
885
+ * @module overlay
884
886
  */
885
887
 
886
888
  'use strict';
887
889
 
888
890
 
889
- var jqLite = require('../lib/jqLite'),
890
- util = require('../lib/util'),
891
- formlib = require('../lib/forms'),
892
- wrapperClass = 'mui-select',
893
- cssSelector = '.mui-select > select',
894
- menuClass = 'mui-select__menu',
895
- selectedClass = 'mui--is-selected',
896
- doc = document,
897
- win = window;
891
+ var util = require('./lib/util'),
892
+ jqLite = require('./lib/jqLite'),
893
+ overlayId = 'mui-overlay',
894
+ bodyClass = 'mui--overflow-hidden',
895
+ iosRegex = /(iPad|iPhone|iPod)/g;
898
896
 
899
897
 
900
898
  /**
901
- * Initialize select element.
902
- * @param {Element} selectEl - The select element.
899
+ * Turn overlay on/off.
900
+ * @param {string} action - Turn overlay "on"/"off".
901
+ * @param {object} [options]
902
+ * @config {boolean} [keyboard] - If true, close when escape key is pressed.
903
+ * @config {boolean} [static] - If false, close when backdrop is clicked.
904
+ * @config {Function} [onclose] - Callback function to execute on close
905
+ * @param {Element} [childElement] - Child element to add to overlay.
903
906
  */
904
- function initialize(selectEl) {
905
- // check flag
906
- if (selectEl._muiSelect === true) return;
907
- else selectEl._muiSelect = true;
907
+ function overlayFn(action) {
908
+ var overlayEl;
909
+
910
+ if (action === 'on') {
911
+ // extract arguments
912
+ var arg, options, childElement;
913
+
914
+ // pull options and childElement from arguments
915
+ for (var i=arguments.length - 1; i > 0; i--) {
916
+ arg = arguments[i];
908
917
 
909
- // use default behavior on touch devices
910
- if ('ontouchstart' in doc.documentElement) return;
918
+ if (jqLite.type(arg) === 'object') options = arg;
919
+ if (arg instanceof Element && arg.nodeType === 1) childElement = arg;
920
+ }
911
921
 
912
- // initialize element
913
- new Select(selectEl);
922
+ // option defaults
923
+ options = options || {};
924
+ if (options.keyboard === undefined) options.keyboard = true;
925
+ if (options.static === undefined) options.static = false;
926
+
927
+ // execute method
928
+ overlayEl = overlayOn(options, childElement);
929
+
930
+ } else if (action === 'off') {
931
+ overlayEl = overlayOff();
932
+
933
+ } else {
934
+ // raise error
935
+ util.raiseError("Expecting 'on' or 'off'");
936
+ }
937
+
938
+ return overlayEl;
914
939
  }
915
940
 
916
941
 
917
942
  /**
918
- * Creates a new Select object
919
- * @class
943
+ * Turn on overlay.
944
+ * @param {object} options - Overlay options.
945
+ * @param {Element} childElement - The child element.
920
946
  */
921
- function Select(selectEl) {
922
- // instance variables
923
- this.selectEl = selectEl;
924
- this.wrapperEl = selectEl.parentNode;
925
- this.useDefault = false; // currently unused but let's keep just in case
947
+ function overlayOn(options, childElement) {
948
+ var bodyEl = document.body,
949
+ overlayEl = document.getElementById(overlayId);
950
+
951
+ // add overlay
952
+ util.enableScrollLock();
953
+ //jqLite.addClass(bodyEl, bodyClass);
926
954
 
927
- // attach event handlers
928
- jqLite.on(selectEl, 'mousedown', util.callback(this, 'mousedownHandler'));
929
- jqLite.on(selectEl, 'focus', util.callback(this, 'focusHandler'));
930
- jqLite.on(selectEl, 'click', util.callback(this, 'clickHandler'));
931
-
932
- // make wrapper focusable and fix firefox bug
933
- this.wrapperEl.tabIndex = -1;
934
- var callbackFn = util.callback(this, 'wrapperFocusHandler');
935
- jqLite.on(this.wrapperEl, 'focus', callbackFn);
936
- }
955
+ if (!overlayEl) {
956
+ // create overlayEl
957
+ overlayEl = document.createElement('div');
958
+ overlayEl.setAttribute('id', overlayId);
959
+
960
+ // add child element
961
+ if (childElement) overlayEl.appendChild(childElement);
937
962
 
963
+ bodyEl.appendChild(overlayEl);
964
+
965
+ } else {
966
+ // remove existing children
967
+ while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
968
+
969
+ // add child element
970
+ if (childElement) overlayEl.appendChild(childElement);
971
+ }
938
972
 
939
- /**
940
- * Disable default dropdown on mousedown.
941
- * @param {Event} ev - The DOM event
942
- */
943
- Select.prototype.mousedownHandler = function(ev) {
944
- if (ev.button !== 0 || this.useDefault === true) return;
945
- ev.preventDefault();
973
+ // iOS bugfix
974
+ if (iosRegex.test(navigator.userAgent)) {
975
+ jqLite.css(overlayEl, 'cursor', 'pointer');
976
+ }
977
+
978
+ // handle options
979
+ if (options.keyboard) addKeyupHandler();
980
+ else removeKeyupHandler();
981
+
982
+ if (options.static) removeClickHandler(overlayEl);
983
+ else addClickHandler(overlayEl);
984
+
985
+ // attach options
986
+ overlayEl.muiOptions = options;
987
+
988
+ return overlayEl;
946
989
  }
947
990
 
948
991
 
949
992
  /**
950
- * Handle focus event on select element.
951
- * @param {Event} ev - The DOM event
993
+ * Turn off overlay.
952
994
  */
953
- Select.prototype.focusHandler = function(ev) {
954
- // check flag
955
- if (this.useDefault === true) return;
956
-
957
- var selectEl = this.selectEl,
958
- wrapperEl = this.wrapperEl,
959
- origIndex = selectEl.tabIndex,
960
- keydownFn = util.callback(this, 'keydownHandler');
995
+ function overlayOff() {
996
+ var overlayEl = document.getElementById(overlayId),
997
+ callbackFn;
961
998
 
962
- // attach keydown handler
963
- jqLite.on(doc, 'keydown', keydownFn);
999
+ if (overlayEl) {
1000
+ // remove children
1001
+ while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
964
1002
 
965
- // disable tabfocus once
966
- selectEl.tabIndex = -1;
967
- jqLite.one(wrapperEl, 'blur', function() {
968
- selectEl.tabIndex = origIndex;
969
- jqLite.off(doc, 'keydown', keydownFn);
970
- });
971
-
972
- // defer focus to parent
973
- wrapperEl.focus();
974
- }
1003
+ // remove overlay element
1004
+ overlayEl.parentNode.removeChild(overlayEl);
975
1005
 
1006
+ // callback reference
1007
+ callbackFn = overlayEl.muiOptions.onclose;
976
1008
 
977
- /**
978
- * Handle keydown events on doc
979
- **/
980
- Select.prototype.keydownHandler = function(ev) {
981
- // spacebar, down, up
982
- if (ev.keyCode === 32 || ev.keyCode === 38 || ev.keyCode === 40) {
983
- // prevent win scroll
984
- ev.preventDefault();
985
-
986
- if (this.selectEl.disabled !== true) this.renderMenu();
1009
+ // remove click handler
1010
+ removeClickHandler(overlayEl);
987
1011
  }
1012
+
1013
+ util.disableScrollLock();
1014
+
1015
+ // remove keyup handler
1016
+ removeKeyupHandler();
1017
+
1018
+ // execute callback
1019
+ if (callbackFn) callbackFn();
1020
+
1021
+ return overlayEl;
988
1022
  }
989
1023
 
990
1024
 
991
1025
  /**
992
- * Handle focus event on wrapper element.
1026
+ * Add keyup handler.
993
1027
  */
994
- Select.prototype.wrapperFocusHandler = function() {
995
- // firefox bugfix
996
- if (this.selectEl.disabled) return this.wrapperEl.blur();
1028
+ function addKeyupHandler() {
1029
+ jqLite.on(document, 'keyup', onKeyup);
997
1030
  }
998
1031
 
999
1032
 
1000
1033
  /**
1001
- * Handle click events on select element.
1002
- * @param {Event} ev - The DOM event
1034
+ * Remove keyup handler.
1003
1035
  */
1004
- Select.prototype.clickHandler = function(ev) {
1005
- // only left clicks
1006
- if (ev.button !== 0) return;
1007
- this.renderMenu();
1036
+ function removeKeyupHandler() {
1037
+ jqLite.off(document, 'keyup', onKeyup);
1008
1038
  }
1009
1039
 
1010
1040
 
1011
1041
  /**
1012
- * Render options dropdown.
1042
+ * Teardown overlay when escape key is pressed.
1013
1043
  */
1014
- Select.prototype.renderMenu = function() {
1015
- // check and reset flag
1016
- if (this.useDefault === true) return this.useDefault = false;
1017
-
1018
- new Menu(this.wrapperEl, this.selectEl);
1044
+ function onKeyup(ev) {
1045
+ if (ev.keyCode === 27) overlayOff();
1019
1046
  }
1020
1047
 
1021
1048
 
1022
1049
  /**
1023
- * Creates a new Menu
1024
- * @class
1050
+ * Add click handler.
1025
1051
  */
1026
- function Menu(wrapperEl, selectEl) {
1027
- // add scroll lock
1028
- util.enableScrollLock();
1029
-
1030
- // instance variables
1031
- this.origIndex = null;
1032
- this.currentIndex = null;
1033
- this.selectEl = selectEl;
1034
- this.menuEl = this._createMenuEl(wrapperEl, selectEl);
1035
- this.clickCallbackFn = util.callback(this, 'clickHandler');
1036
- this.keydownCallbackFn = util.callback(this, 'keydownHandler');
1037
- this.destroyCallbackFn = util.callback(this, 'destroy');
1038
-
1039
- // add to DOM
1040
- wrapperEl.appendChild(this.menuEl);
1041
- jqLite.scrollTop(this.menuEl, this.menuEl._muiScrollTop);
1042
-
1043
- // blur active element
1044
- setTimeout(function() {
1045
- // ie10 bugfix
1046
- if (doc.activeElement.nodeName.toLowerCase() !== "body") {
1047
- doc.activeElement.blur();
1048
- }
1049
- }, 0);
1052
+ function addClickHandler(overlayEl) {
1053
+ jqLite.on(overlayEl, 'click', onClick);
1054
+ }
1050
1055
 
1051
- // attach event handlers
1052
- jqLite.on(this.menuEl, 'click', this.clickCallbackFn);
1053
- jqLite.on(doc, 'keydown', this.keydownCallbackFn);
1054
- jqLite.on(win, 'resize', this.destroyCallbackFn);
1055
1056
 
1056
- // attach event handler after current event loop exits
1057
- var fn = this.destroyCallbackFn;
1058
- setTimeout(function() {jqLite.on(doc, 'click', fn);}, 0);
1057
+ /**
1058
+ * Remove click handler.
1059
+ */
1060
+ function removeClickHandler(overlayEl) {
1061
+ jqLite.off(overlayEl, 'click', onClick);
1059
1062
  }
1060
1063
 
1061
1064
 
1062
1065
  /**
1063
- * Create menu element
1064
- * @param {Element} selectEl - The select element
1066
+ * Teardown overlay when backdrop is clicked.
1065
1067
  */
1066
- Menu.prototype._createMenuEl = function(wrapperEl, selectEl) {
1067
- var menuEl = doc.createElement('div'),
1068
- optionEls = selectEl.children,
1069
- numOptions = optionEls.length,
1070
- selectedPos = 0,
1071
- optionEl,
1072
- itemEl,
1073
- i;
1074
-
1075
- menuEl.className = menuClass;
1076
-
1077
- // add options
1078
- for (i=0; i < numOptions; i++) {
1079
- optionEl = optionEls[i];
1080
-
1081
- itemEl = doc.createElement('div');
1082
- itemEl.textContent = optionEl.textContent;
1083
- itemEl._muiPos = i;
1084
-
1085
- if (optionEl.selected) {
1086
- itemEl.setAttribute('class', selectedClass);
1087
- selectedPos = i;
1088
- }
1089
-
1090
- menuEl.appendChild(itemEl);
1091
- }
1092
-
1093
- // save indices
1094
- this.origIndex = selectedPos;
1095
- this.currentIndex = selectedPos;
1096
-
1097
- // set position
1098
- var props = formlib.getMenuPositionalCSS(
1099
- wrapperEl,
1100
- numOptions,
1101
- selectedPos
1102
- );
1103
-
1104
- jqLite.css(menuEl, props);
1105
- menuEl._muiScrollTop = props.scrollTop;
1106
-
1107
- return menuEl;
1068
+ function onClick(ev) {
1069
+ if (ev.target.id === overlayId) overlayOff();
1108
1070
  }
1109
1071
 
1110
1072
 
1111
- /**
1112
- * Handle keydown events on doc element.
1113
- * @param {Event} ev - The DOM event
1114
- */
1115
- Menu.prototype.keydownHandler = function(ev) {
1116
- var keyCode = ev.keyCode;
1117
-
1118
- // tab
1119
- if (keyCode === 9) return this.destroy();
1120
-
1121
- // escape | up | down | enter
1122
- if (keyCode === 27 || keyCode === 40 || keyCode === 38 || keyCode === 13) {
1123
- ev.preventDefault();
1124
- }
1125
-
1126
- if (keyCode === 27) {
1127
- this.destroy();
1128
- } else if (keyCode === 40) {
1129
- this.increment();
1130
- } else if (keyCode === 38) {
1131
- this.decrement();
1132
- } else if (keyCode === 13) {
1133
- this.selectCurrent();
1134
- this.destroy();
1135
- }
1136
- }
1137
-
1073
+ /** Define module API */
1074
+ module.exports = overlayFn;
1138
1075
 
1076
+ },{"./lib/jqLite":4,"./lib/util":5}],9:[function(require,module,exports){
1139
1077
  /**
1140
- * Handle click events on menu element.
1141
- * @param {Event} ev - The DOM event
1078
+ * MUI CSS/JS ripple module
1079
+ * @module ripple
1142
1080
  */
1143
- Menu.prototype.clickHandler = function(ev) {
1144
- // don't allow events to bubble
1145
- ev.stopPropagation();
1146
-
1147
- var pos = ev.target._muiPos;
1148
1081
 
1149
- // ignore clicks on non-items
1150
- if (pos === undefined) return;
1082
+ 'use strict';
1151
1083
 
1152
- // select option
1153
- this.currentIndex = pos;
1154
- this.selectCurrent();
1155
1084
 
1156
- // destroy menu
1157
- this.destroy();
1158
- }
1085
+ var jqLite = require('./lib/jqLite'),
1086
+ util = require('./lib/util'),
1087
+ btnClass = 'mui-btn',
1088
+ btnFABClass = 'mui-btn--fab',
1089
+ rippleClass = 'mui-ripple-effect',
1090
+ animationName = 'mui-btn-inserted';
1159
1091
 
1160
1092
 
1161
1093
  /**
1162
- * Increment selected item
1094
+ * Add ripple effects to button element.
1095
+ * @param {Element} buttonEl - The button element.
1163
1096
  */
1164
- Menu.prototype.increment = function() {
1165
- if (this.currentIndex === this.menuEl.children.length - 1) return;
1097
+ function initialize(buttonEl) {
1098
+ // check flag
1099
+ if (buttonEl._muiRipple === true) return;
1100
+ else buttonEl._muiRipple = true;
1166
1101
 
1167
- var optionEls = this.menuEl.children;
1168
-
1169
- jqLite.removeClass(optionEls[this.currentIndex], selectedClass);
1170
- this.currentIndex += 1;
1171
- jqLite.addClass(optionEls[this.currentIndex], selectedClass);
1102
+ // exit if element is INPUT (doesn't support absolute positioned children)
1103
+ if (buttonEl.tagName === 'INPUT') return;
1104
+
1105
+ // attach event handler
1106
+ jqLite.on(buttonEl, 'touchstart', eventHandler);
1107
+ jqLite.on(buttonEl, 'mousedown', eventHandler);
1172
1108
  }
1173
1109
 
1174
1110
 
1175
1111
  /**
1176
- * Decrement selected item
1112
+ * Event handler
1113
+ * @param {Event} ev - The DOM event
1177
1114
  */
1178
- Menu.prototype.decrement = function() {
1179
- if (this.currentIndex === 0) return;
1180
-
1181
- var optionEls = this.menuEl.children;
1182
-
1183
- jqLite.removeClass(optionEls[this.currentIndex], selectedClass);
1184
- this.currentIndex -= 1;
1185
- jqLite.addClass(optionEls[this.currentIndex], selectedClass);
1186
- }
1115
+ function eventHandler(ev) {
1116
+ // only left clicks
1117
+ if (ev.button !== 0) return;
1187
1118
 
1119
+ var buttonEl = this;
1188
1120
 
1189
- /**
1190
- * Select current item
1191
- */
1192
- Menu.prototype.selectCurrent = function() {
1193
- if (this.currentIndex !== this.origIndex) {
1194
- var optionEls = this.selectEl.children;
1195
- optionEls[this.origIndex].selected = false;
1196
- optionEls[this.currentIndex].selected = true;
1121
+ // exit if button is disabled
1122
+ if (buttonEl.disabled === true) return;
1197
1123
 
1198
- // trigger change event
1199
- util.dispatchEvent(this.selectEl, 'change');
1124
+ // de-dupe touchstart and mousedown with 100msec flag
1125
+ if (buttonEl.touchFlag === true) {
1126
+ return;
1127
+ } else {
1128
+ buttonEl.touchFlag = true;
1129
+ setTimeout(function() {
1130
+ buttonEl.touchFlag = false;
1131
+ }, 100);
1200
1132
  }
1201
- }
1202
1133
 
1134
+ var rippleEl = document.createElement('div');
1135
+ rippleEl.className = rippleClass;
1203
1136
 
1204
- /**
1205
- * Destroy menu and detach event handlers
1206
- */
1207
- Menu.prototype.destroy = function() {
1208
- // remove element and focus element
1209
- var parentNode = this.menuEl.parentNode;
1210
- if (parentNode) parentNode.removeChild(this.menuEl);
1137
+ var offset = jqLite.offset(buttonEl),
1138
+ xPos = ev.pageX - offset.left,
1139
+ yPos = ev.pageY - offset.top,
1140
+ diameter,
1141
+ radius;
1211
1142
 
1212
- this.selectEl.focus();
1143
+ // get height
1144
+ if (jqLite.hasClass(buttonEl, btnFABClass)) diameter = offset.height / 2;
1145
+ else diameter = offset.height;
1213
1146
 
1214
- // remove scroll lock
1215
- util.disableScrollLock();
1147
+ radius = diameter / 2;
1148
+
1149
+ jqLite.css(rippleEl, {
1150
+ height: diameter + 'px',
1151
+ width: diameter + 'px',
1152
+ top: yPos - radius + 'px',
1153
+ left: xPos - radius + 'px'
1154
+ });
1216
1155
 
1217
- // remove event handlers
1218
- jqLite.off(this.menuEl, 'click', this.clickCallbackFn);
1219
- jqLite.off(doc, 'keydown', this.keydownCallbackFn);
1220
- jqLite.off(doc, 'click', this.destroyCallbackFn);
1221
- jqLite.off(win, 'resize', this.destroyCallbackFn);
1156
+ buttonEl.appendChild(rippleEl);
1157
+
1158
+ window.setTimeout(function() {
1159
+ var parentNode = rippleEl.parentNode;
1160
+ if (parentNode) parentNode.removeChild(rippleEl);
1161
+ }, 2000);
1222
1162
  }
1223
1163
 
1224
1164
 
@@ -1226,403 +1166,361 @@ Menu.prototype.destroy = function() {
1226
1166
  module.exports = {
1227
1167
  /** Initialize module listeners */
1228
1168
  initListeners: function() {
1169
+ var doc = document;
1170
+
1229
1171
  // markup elements available when method is called
1230
- var elList = doc.querySelectorAll(cssSelector);
1172
+ var elList = doc.getElementsByClassName(btnClass);
1231
1173
  for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1232
1174
 
1233
1175
  // listen for new elements
1234
1176
  util.onNodeInserted(function(el) {
1235
- if (el.tagName === 'SELECT' &&
1236
- jqLite.hasClass(el.parentNode, wrapperClass)) {
1237
- initialize(el);
1238
- }
1177
+ if (jqLite.hasClass(el, btnClass)) initialize(el);
1239
1178
  });
1240
1179
  }
1241
1180
  };
1242
1181
 
1243
- },{"../lib/forms":3,"../lib/jqLite":4,"../lib/util":5}],8:[function(require,module,exports){
1182
+ },{"./lib/jqLite":4,"./lib/util":5}],10:[function(require,module,exports){
1244
1183
  /**
1245
- * MUI CSS/JS form-control module
1246
- * @module forms/form-control
1184
+ * MUI CSS/JS select module
1185
+ * @module forms/select
1247
1186
  */
1248
1187
 
1249
1188
  'use strict';
1250
1189
 
1251
1190
 
1252
- var jqLite = require('../lib/jqLite'),
1253
- util = require('../lib/util'),
1254
- cssSelector = '.mui-textfield > input, .mui-textfield > textarea',
1255
- emptyClass = 'mui--is-empty',
1256
- notEmptyClass = 'mui--is-not-empty',
1257
- dirtyClass = 'mui--is-dirty',
1258
- floatingLabelClass = 'mui-textfield--float-label';
1191
+ var jqLite = require('./lib/jqLite'),
1192
+ util = require('./lib/util'),
1193
+ formlib = require('./lib/forms'),
1194
+ wrapperClass = 'mui-select',
1195
+ cssSelector = '.mui-select > select',
1196
+ menuClass = 'mui-select__menu',
1197
+ selectedClass = 'mui--is-selected',
1198
+ doc = document,
1199
+ win = window;
1259
1200
 
1260
1201
 
1261
1202
  /**
1262
- * Initialize input element.
1263
- * @param {Element} inputEl - The input element.
1203
+ * Initialize select element.
1204
+ * @param {Element} selectEl - The select element.
1264
1205
  */
1265
- function initialize(inputEl) {
1206
+ function initialize(selectEl) {
1266
1207
  // check flag
1267
- if (inputEl._muiTextfield === true) return;
1268
- else inputEl._muiTextfield = true;
1269
-
1270
- if (inputEl.value.length) jqLite.addClass(inputEl, notEmptyClass);
1271
- else jqLite.addClass(inputEl, emptyClass);
1208
+ if (selectEl._muiSelect === true) return;
1209
+ else selectEl._muiSelect = true;
1272
1210
 
1273
- jqLite.on(inputEl, 'input', inputHandler);
1211
+ // use default behavior on touch devices
1212
+ if ('ontouchstart' in doc.documentElement) return;
1274
1213
 
1275
- // add dirty class on focus
1276
- jqLite.on(inputEl, 'focus', function(){jqLite.addClass(this, dirtyClass);});
1214
+ // initialize element
1215
+ new Select(selectEl);
1277
1216
  }
1278
1217
 
1279
1218
 
1280
1219
  /**
1281
- * Handle input events.
1220
+ * Creates a new Select object
1221
+ * @class
1282
1222
  */
1283
- function inputHandler() {
1284
- var inputEl = this;
1285
-
1286
- if (inputEl.value.length) {
1287
- jqLite.removeClass(inputEl, emptyClass);
1288
- jqLite.addClass(inputEl, notEmptyClass);
1289
- } else {
1290
- jqLite.removeClass(inputEl, notEmptyClass);
1291
- jqLite.addClass(inputEl, emptyClass)
1292
- }
1223
+ function Select(selectEl) {
1224
+ // instance variables
1225
+ this.selectEl = selectEl;
1226
+ this.wrapperEl = selectEl.parentNode;
1227
+ this.useDefault = false; // currently unused but let's keep just in case
1293
1228
 
1294
- jqLite.addClass(inputEl, dirtyClass);
1295
- }
1296
-
1297
-
1298
- /** Define module API */
1299
- module.exports = {
1300
- /** Initialize input elements */
1301
- initialize: initialize,
1229
+ // attach event handlers
1230
+ jqLite.on(selectEl, 'mousedown', util.callback(this, 'mousedownHandler'));
1231
+ jqLite.on(selectEl, 'focus', util.callback(this, 'focusHandler'));
1232
+ jqLite.on(selectEl, 'click', util.callback(this, 'clickHandler'));
1302
1233
 
1303
- /** Initialize module listeners */
1304
- initListeners: function() {
1305
- var doc = document;
1306
-
1307
- // markup elements available when method is called
1308
- var elList = doc.querySelectorAll(cssSelector);
1309
- for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1234
+ // make wrapper focusable and fix firefox bug
1235
+ this.wrapperEl.tabIndex = -1;
1236
+ var callbackFn = util.callback(this, 'wrapperFocusHandler');
1237
+ jqLite.on(this.wrapperEl, 'focus', callbackFn);
1238
+ }
1310
1239
 
1311
- // listen for new elements
1312
- util.onNodeInserted(function(el) {
1313
- if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') initialize(el);
1314
- });
1315
1240
 
1316
- // add transition css for floating labels
1317
- setTimeout(function() {
1318
- var css = '.mui-textfield.mui-textfield--float-label > label {' + [
1319
- '-webkit-transition',
1320
- '-moz-transition',
1321
- '-o-transition',
1322
- 'transition',
1323
- ''
1324
- ].join(':all .15s ease-out;') + '}';
1325
-
1326
- util.loadStyle(css);
1327
- }, 150);
1328
-
1329
- // pointer-events shim for floating labels
1330
- if (util.supportsPointerEvents() === false) {
1331
- jqLite.on(document, 'click', function(ev) {
1332
- var targetEl = ev.target;
1241
+ /**
1242
+ * Disable default dropdown on mousedown.
1243
+ * @param {Event} ev - The DOM event
1244
+ */
1245
+ Select.prototype.mousedownHandler = function(ev) {
1246
+ if (ev.button !== 0 || this.useDefault === true) return;
1247
+ ev.preventDefault();
1248
+ }
1333
1249
 
1334
- if (targetEl.tagName === 'LABEL' &&
1335
- jqLite.hasClass(targetEl.parentNode, floatingLabelClass)) {
1336
- var inputEl = targetEl.previousElementSibling;
1337
- if (inputEl) inputEl.focus();
1338
- }
1339
- });
1340
- }
1341
- }
1342
- };
1343
1250
 
1344
- },{"../lib/jqLite":4,"../lib/util":5}],9:[function(require,module,exports){
1345
- module.exports=require(4)
1346
- },{}],10:[function(require,module,exports){
1347
1251
  /**
1348
- * MUI CSS/JS overlay module
1349
- * @module overlay
1252
+ * Handle focus event on select element.
1253
+ * @param {Event} ev - The DOM event
1350
1254
  */
1255
+ Select.prototype.focusHandler = function(ev) {
1256
+ // check flag
1257
+ if (this.useDefault === true) return;
1351
1258
 
1352
- 'use strict';
1259
+ var selectEl = this.selectEl,
1260
+ wrapperEl = this.wrapperEl,
1261
+ origIndex = selectEl.tabIndex,
1262
+ keydownFn = util.callback(this, 'keydownHandler');
1353
1263
 
1264
+ // attach keydown handler
1265
+ jqLite.on(doc, 'keydown', keydownFn);
1354
1266
 
1355
- var util = require('./lib/util'),
1356
- jqLite = require('./lib/jqLite'),
1357
- overlayId = 'mui-overlay',
1358
- bodyClass = 'mui--overflow-hidden',
1359
- iosRegex = /(iPad|iPhone|iPod)/g;
1267
+ // disable tabfocus once
1268
+ selectEl.tabIndex = -1;
1269
+ jqLite.one(wrapperEl, 'blur', function() {
1270
+ selectEl.tabIndex = origIndex;
1271
+ jqLite.off(doc, 'keydown', keydownFn);
1272
+ });
1273
+
1274
+ // defer focus to parent
1275
+ wrapperEl.focus();
1276
+ }
1360
1277
 
1361
1278
 
1362
1279
  /**
1363
- * Turn overlay on/off.
1364
- * @param {string} action - Turn overlay "on"/"off".
1365
- * @param {object} [options]
1366
- * @config {boolean} [keyboard] - If true, close when escape key is pressed.
1367
- * @config {boolean} [static] - If false, close when backdrop is clicked.
1368
- * @config {Function} [onclose] - Callback function to execute on close
1369
- * @param {Element} [childElement] - Child element to add to overlay.
1370
- */
1371
- function overlayFn(action) {
1372
- var overlayEl;
1373
-
1374
- if (action === 'on') {
1375
- // extract arguments
1376
- var arg, options, childElement;
1280
+ * Handle keydown events on doc
1281
+ **/
1282
+ Select.prototype.keydownHandler = function(ev) {
1283
+ // spacebar, down, up
1284
+ if (ev.keyCode === 32 || ev.keyCode === 38 || ev.keyCode === 40) {
1285
+ // prevent win scroll
1286
+ ev.preventDefault();
1377
1287
 
1378
- // pull options and childElement from arguments
1379
- for (var i=arguments.length - 1; i > 0; i--) {
1380
- arg = arguments[i];
1288
+ if (this.selectEl.disabled !== true) this.renderMenu();
1289
+ }
1290
+ }
1381
1291
 
1382
- if (jqLite.type(arg) === 'object') options = arg;
1383
- if (arg instanceof Element && arg.nodeType === 1) childElement = arg;
1384
- }
1385
1292
 
1386
- // option defaults
1387
- options = options || {};
1388
- if (options.keyboard === undefined) options.keyboard = true;
1389
- if (options.static === undefined) options.static = false;
1390
-
1391
- // execute method
1392
- overlayEl = overlayOn(options, childElement);
1393
-
1394
- } else if (action === 'off') {
1395
- overlayEl = overlayOff();
1293
+ /**
1294
+ * Handle focus event on wrapper element.
1295
+ */
1296
+ Select.prototype.wrapperFocusHandler = function() {
1297
+ // firefox bugfix
1298
+ if (this.selectEl.disabled) return this.wrapperEl.blur();
1299
+ }
1396
1300
 
1397
- } else {
1398
- // raise error
1399
- util.raiseError("Expecting 'on' or 'off'");
1400
- }
1401
1301
 
1402
- return overlayEl;
1302
+ /**
1303
+ * Handle click events on select element.
1304
+ * @param {Event} ev - The DOM event
1305
+ */
1306
+ Select.prototype.clickHandler = function(ev) {
1307
+ // only left clicks
1308
+ if (ev.button !== 0) return;
1309
+ this.renderMenu();
1403
1310
  }
1404
1311
 
1405
1312
 
1406
1313
  /**
1407
- * Turn on overlay.
1408
- * @param {object} options - Overlay options.
1409
- * @param {Element} childElement - The child element.
1314
+ * Render options dropdown.
1410
1315
  */
1411
- function overlayOn(options, childElement) {
1412
- var bodyEl = document.body,
1413
- overlayEl = document.getElementById(overlayId);
1414
-
1415
- // add overlay
1416
- util.enableScrollLock();
1417
- //jqLite.addClass(bodyEl, bodyClass);
1316
+ Select.prototype.renderMenu = function() {
1317
+ // check and reset flag
1318
+ if (this.useDefault === true) return this.useDefault = false;
1418
1319
 
1419
- if (!overlayEl) {
1420
- // create overlayEl
1421
- overlayEl = document.createElement('div');
1422
- overlayEl.setAttribute('id', overlayId);
1423
-
1424
- // add child element
1425
- if (childElement) overlayEl.appendChild(childElement);
1320
+ new Menu(this.wrapperEl, this.selectEl);
1321
+ }
1426
1322
 
1427
- bodyEl.appendChild(overlayEl);
1428
-
1429
- } else {
1430
- // remove existing children
1431
- while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
1432
-
1433
- // add child element
1434
- if (childElement) overlayEl.appendChild(childElement);
1435
- }
1436
1323
 
1437
- // iOS bugfix
1438
- if (iosRegex.test(navigator.userAgent)) {
1439
- jqLite.css(overlayEl, 'cursor', 'pointer');
1440
- }
1324
+ /**
1325
+ * Creates a new Menu
1326
+ * @class
1327
+ */
1328
+ function Menu(wrapperEl, selectEl) {
1329
+ // add scroll lock
1330
+ util.enableScrollLock();
1441
1331
 
1442
- // handle options
1443
- if (options.keyboard) addKeyupHandler();
1444
- else removeKeyupHandler();
1332
+ // instance variables
1333
+ this.origIndex = null;
1334
+ this.currentIndex = null;
1335
+ this.selectEl = selectEl;
1336
+ this.menuEl = this._createMenuEl(wrapperEl, selectEl);
1337
+ this.clickCallbackFn = util.callback(this, 'clickHandler');
1338
+ this.keydownCallbackFn = util.callback(this, 'keydownHandler');
1339
+ this.destroyCallbackFn = util.callback(this, 'destroy');
1445
1340
 
1446
- if (options.static) removeClickHandler(overlayEl);
1447
- else addClickHandler(overlayEl);
1341
+ // add to DOM
1342
+ wrapperEl.appendChild(this.menuEl);
1343
+ jqLite.scrollTop(this.menuEl, this.menuEl._muiScrollTop);
1448
1344
 
1449
- // attach options
1450
- overlayEl.muiOptions = options;
1345
+ // blur active element
1346
+ setTimeout(function() {
1347
+ // ie10 bugfix
1348
+ if (doc.activeElement.nodeName.toLowerCase() !== "body") {
1349
+ doc.activeElement.blur();
1350
+ }
1351
+ }, 0);
1451
1352
 
1452
- return overlayEl;
1353
+ // attach event handlers
1354
+ jqLite.on(this.menuEl, 'click', this.clickCallbackFn);
1355
+ jqLite.on(doc, 'keydown', this.keydownCallbackFn);
1356
+ jqLite.on(win, 'resize', this.destroyCallbackFn);
1357
+
1358
+ // attach event handler after current event loop exits
1359
+ var fn = this.destroyCallbackFn;
1360
+ setTimeout(function() {jqLite.on(doc, 'click', fn);}, 0);
1453
1361
  }
1454
1362
 
1455
1363
 
1456
1364
  /**
1457
- * Turn off overlay.
1365
+ * Create menu element
1366
+ * @param {Element} selectEl - The select element
1458
1367
  */
1459
- function overlayOff() {
1460
- var overlayEl = document.getElementById(overlayId),
1461
- callbackFn;
1368
+ Menu.prototype._createMenuEl = function(wrapperEl, selectEl) {
1369
+ var menuEl = doc.createElement('div'),
1370
+ optionEls = selectEl.children,
1371
+ numOptions = optionEls.length,
1372
+ selectedPos = 0,
1373
+ optionEl,
1374
+ itemEl,
1375
+ i;
1462
1376
 
1463
- if (overlayEl) {
1464
- // remove children
1465
- while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
1377
+ menuEl.className = menuClass;
1466
1378
 
1467
- // remove overlay element
1468
- overlayEl.parentNode.removeChild(overlayEl);
1379
+ // add options
1380
+ for (i=0; i < numOptions; i++) {
1381
+ optionEl = optionEls[i];
1469
1382
 
1470
- // callback reference
1471
- callbackFn = overlayEl.muiOptions.onclose;
1383
+ itemEl = doc.createElement('div');
1384
+ itemEl.textContent = optionEl.textContent;
1385
+ itemEl._muiPos = i;
1472
1386
 
1473
- // remove click handler
1474
- removeClickHandler(overlayEl);
1387
+ if (optionEl.selected) {
1388
+ itemEl.setAttribute('class', selectedClass);
1389
+ selectedPos = i;
1390
+ }
1391
+
1392
+ menuEl.appendChild(itemEl);
1475
1393
  }
1476
1394
 
1477
- util.disableScrollLock();
1395
+ // save indices
1396
+ this.origIndex = selectedPos;
1397
+ this.currentIndex = selectedPos;
1478
1398
 
1479
- // remove keyup handler
1480
- removeKeyupHandler();
1399
+ // set position
1400
+ var props = formlib.getMenuPositionalCSS(
1401
+ wrapperEl,
1402
+ numOptions,
1403
+ selectedPos
1404
+ );
1481
1405
 
1482
- // execute callback
1483
- if (callbackFn) callbackFn();
1406
+ jqLite.css(menuEl, props);
1407
+ menuEl._muiScrollTop = props.scrollTop;
1484
1408
 
1485
- return overlayEl;
1409
+ return menuEl;
1486
1410
  }
1487
1411
 
1488
1412
 
1489
1413
  /**
1490
- * Add keyup handler.
1414
+ * Handle keydown events on doc element.
1415
+ * @param {Event} ev - The DOM event
1491
1416
  */
1492
- function addKeyupHandler() {
1493
- jqLite.on(document, 'keyup', onKeyup);
1494
- }
1417
+ Menu.prototype.keydownHandler = function(ev) {
1418
+ var keyCode = ev.keyCode;
1495
1419
 
1420
+ // tab
1421
+ if (keyCode === 9) return this.destroy();
1422
+
1423
+ // escape | up | down | enter
1424
+ if (keyCode === 27 || keyCode === 40 || keyCode === 38 || keyCode === 13) {
1425
+ ev.preventDefault();
1426
+ }
1496
1427
 
1497
- /**
1498
- * Remove keyup handler.
1499
- */
1500
- function removeKeyupHandler() {
1501
- jqLite.off(document, 'keyup', onKeyup);
1428
+ if (keyCode === 27) {
1429
+ this.destroy();
1430
+ } else if (keyCode === 40) {
1431
+ this.increment();
1432
+ } else if (keyCode === 38) {
1433
+ this.decrement();
1434
+ } else if (keyCode === 13) {
1435
+ this.selectCurrent();
1436
+ this.destroy();
1437
+ }
1502
1438
  }
1503
1439
 
1504
1440
 
1505
1441
  /**
1506
- * Teardown overlay when escape key is pressed.
1442
+ * Handle click events on menu element.
1443
+ * @param {Event} ev - The DOM event
1507
1444
  */
1508
- function onKeyup(ev) {
1509
- if (ev.keyCode === 27) overlayOff();
1510
- }
1445
+ Menu.prototype.clickHandler = function(ev) {
1446
+ // don't allow events to bubble
1447
+ ev.stopPropagation();
1511
1448
 
1449
+ var pos = ev.target._muiPos;
1512
1450
 
1513
- /**
1514
- * Add click handler.
1515
- */
1516
- function addClickHandler(overlayEl) {
1517
- jqLite.on(overlayEl, 'click', onClick);
1518
- }
1451
+ // ignore clicks on non-items
1452
+ if (pos === undefined) return;
1519
1453
 
1454
+ // select option
1455
+ this.currentIndex = pos;
1456
+ this.selectCurrent();
1520
1457
 
1521
- /**
1522
- * Remove click handler.
1523
- */
1524
- function removeClickHandler(overlayEl) {
1525
- jqLite.off(overlayEl, 'click', onClick);
1458
+ // destroy menu
1459
+ this.destroy();
1526
1460
  }
1527
1461
 
1528
1462
 
1529
1463
  /**
1530
- * Teardown overlay when backdrop is clicked.
1464
+ * Increment selected item
1531
1465
  */
1532
- function onClick(ev) {
1533
- if (ev.target.id === overlayId) overlayOff();
1534
- }
1466
+ Menu.prototype.increment = function() {
1467
+ if (this.currentIndex === this.menuEl.children.length - 1) return;
1535
1468
 
1469
+ var optionEls = this.menuEl.children;
1470
+
1471
+ jqLite.removeClass(optionEls[this.currentIndex], selectedClass);
1472
+ this.currentIndex += 1;
1473
+ jqLite.addClass(optionEls[this.currentIndex], selectedClass);
1474
+ }
1536
1475
 
1537
- /** Define module API */
1538
- module.exports = overlayFn;
1539
1476
 
1540
- },{"./lib/jqLite":4,"./lib/util":5}],11:[function(require,module,exports){
1541
1477
  /**
1542
- * MUI CSS/JS ripple module
1543
- * @module ripple
1478
+ * Decrement selected item
1544
1479
  */
1480
+ Menu.prototype.decrement = function() {
1481
+ if (this.currentIndex === 0) return;
1545
1482
 
1546
- 'use strict';
1547
-
1483
+ var optionEls = this.menuEl.children;
1548
1484
 
1549
- var jqLite = require('./lib/jqLite'),
1550
- util = require('./lib/util'),
1551
- btnClass = 'mui-btn',
1552
- btnFABClass = 'mui-btn--fab',
1553
- rippleClass = 'mui-ripple-effect',
1554
- animationName = 'mui-btn-inserted';
1485
+ jqLite.removeClass(optionEls[this.currentIndex], selectedClass);
1486
+ this.currentIndex -= 1;
1487
+ jqLite.addClass(optionEls[this.currentIndex], selectedClass);
1488
+ }
1555
1489
 
1556
1490
 
1557
1491
  /**
1558
- * Add ripple effects to button element.
1559
- * @param {Element} buttonEl - The button element.
1492
+ * Select current item
1560
1493
  */
1561
- function initialize(buttonEl) {
1562
- // check flag
1563
- if (buttonEl._muiRipple === true) return;
1564
- else buttonEl._muiRipple = true;
1565
-
1566
- // exit if element is INPUT (doesn't support absolute positioned children)
1567
- if (buttonEl.tagName === 'INPUT') return;
1494
+ Menu.prototype.selectCurrent = function() {
1495
+ if (this.currentIndex !== this.origIndex) {
1496
+ var optionEls = this.selectEl.children;
1497
+ optionEls[this.origIndex].selected = false;
1498
+ optionEls[this.currentIndex].selected = true;
1568
1499
 
1569
- // attach event handler
1570
- jqLite.on(buttonEl, 'touchstart', eventHandler);
1571
- jqLite.on(buttonEl, 'mousedown', eventHandler);
1500
+ // trigger change event
1501
+ util.dispatchEvent(this.selectEl, 'change');
1502
+ }
1572
1503
  }
1573
1504
 
1574
1505
 
1575
1506
  /**
1576
- * Event handler
1577
- * @param {Event} ev - The DOM event
1507
+ * Destroy menu and detach event handlers
1578
1508
  */
1579
- function eventHandler(ev) {
1580
- // only left clicks
1581
- if (ev.button !== 0) return;
1582
-
1583
- var buttonEl = this;
1584
-
1585
- // exit if button is disabled
1586
- if (buttonEl.disabled === true) return;
1587
-
1588
- // de-dupe touchstart and mousedown with 100msec flag
1589
- if (buttonEl.touchFlag === true) {
1590
- return;
1591
- } else {
1592
- buttonEl.touchFlag = true;
1593
- setTimeout(function() {
1594
- buttonEl.touchFlag = false;
1595
- }, 100);
1596
- }
1597
-
1598
- var rippleEl = document.createElement('div');
1599
- rippleEl.className = rippleClass;
1600
-
1601
- var offset = jqLite.offset(buttonEl),
1602
- xPos = ev.pageX - offset.left,
1603
- yPos = ev.pageY - offset.top,
1604
- diameter,
1605
- radius;
1509
+ Menu.prototype.destroy = function() {
1510
+ // remove element and focus element
1511
+ var parentNode = this.menuEl.parentNode;
1512
+ if (parentNode) parentNode.removeChild(this.menuEl);
1606
1513
 
1607
- // get height
1608
- if (jqLite.hasClass(buttonEl, btnFABClass)) diameter = offset.height / 2;
1609
- else diameter = offset.height;
1514
+ this.selectEl.focus();
1610
1515
 
1611
- radius = diameter / 2;
1612
-
1613
- jqLite.css(rippleEl, {
1614
- height: diameter + 'px',
1615
- width: diameter + 'px',
1616
- top: yPos - radius + 'px',
1617
- left: xPos - radius + 'px'
1618
- });
1516
+ // remove scroll lock
1517
+ util.disableScrollLock();
1619
1518
 
1620
- buttonEl.appendChild(rippleEl);
1621
-
1622
- window.setTimeout(function() {
1623
- var parentNode = rippleEl.parentNode;
1624
- if (parentNode) parentNode.removeChild(rippleEl);
1625
- }, 2000);
1519
+ // remove event handlers
1520
+ jqLite.off(this.menuEl, 'click', this.clickCallbackFn);
1521
+ jqLite.off(doc, 'keydown', this.keydownCallbackFn);
1522
+ jqLite.off(doc, 'click', this.destroyCallbackFn);
1523
+ jqLite.off(win, 'resize', this.destroyCallbackFn);
1626
1524
  }
1627
1525
 
1628
1526
 
@@ -1630,20 +1528,21 @@ function eventHandler(ev) {
1630
1528
  module.exports = {
1631
1529
  /** Initialize module listeners */
1632
1530
  initListeners: function() {
1633
- var doc = document;
1634
-
1635
1531
  // markup elements available when method is called
1636
- var elList = doc.getElementsByClassName(btnClass);
1532
+ var elList = doc.querySelectorAll(cssSelector);
1637
1533
  for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1638
1534
 
1639
1535
  // listen for new elements
1640
1536
  util.onNodeInserted(function(el) {
1641
- if (jqLite.hasClass(el, btnClass)) initialize(el);
1537
+ if (el.tagName === 'SELECT' &&
1538
+ jqLite.hasClass(el.parentNode, wrapperClass)) {
1539
+ initialize(el);
1540
+ }
1642
1541
  });
1643
1542
  }
1644
1543
  };
1645
1544
 
1646
- },{"./lib/jqLite":4,"./lib/util":5}],12:[function(require,module,exports){
1545
+ },{"./lib/forms":3,"./lib/jqLite":4,"./lib/util":5}],11:[function(require,module,exports){
1647
1546
  /**
1648
1547
  * MUI CSS/JS tabs module
1649
1548
  * @module tabs
@@ -1804,4 +1703,106 @@ module.exports = {
1804
1703
  }
1805
1704
  };
1806
1705
 
1706
+ },{"./lib/jqLite":4,"./lib/util":5}],12:[function(require,module,exports){
1707
+ /**
1708
+ * MUI CSS/JS form-control module
1709
+ * @module forms/form-control
1710
+ */
1711
+
1712
+ 'use strict';
1713
+
1714
+
1715
+ var jqLite = require('./lib/jqLite'),
1716
+ util = require('./lib/util'),
1717
+ cssSelector = '.mui-textfield > input, .mui-textfield > textarea',
1718
+ emptyClass = 'mui--is-empty',
1719
+ notEmptyClass = 'mui--is-not-empty',
1720
+ dirtyClass = 'mui--is-dirty',
1721
+ floatingLabelClass = 'mui-textfield--float-label';
1722
+
1723
+
1724
+ /**
1725
+ * Initialize input element.
1726
+ * @param {Element} inputEl - The input element.
1727
+ */
1728
+ function initialize(inputEl) {
1729
+ // check flag
1730
+ if (inputEl._muiTextfield === true) return;
1731
+ else inputEl._muiTextfield = true;
1732
+
1733
+ if (inputEl.value.length) jqLite.addClass(inputEl, notEmptyClass);
1734
+ else jqLite.addClass(inputEl, emptyClass);
1735
+
1736
+ jqLite.on(inputEl, 'input', inputHandler);
1737
+ jqLite.on(inputEl, 'change', inputHandler);
1738
+
1739
+ // add dirty class on focus
1740
+ jqLite.on(inputEl, 'focus', function(){jqLite.addClass(this, dirtyClass);});
1741
+ }
1742
+
1743
+
1744
+ /**
1745
+ * Handle input events.
1746
+ */
1747
+ function inputHandler() {
1748
+ var inputEl = this;
1749
+
1750
+ if (inputEl.value.length) {
1751
+ jqLite.removeClass(inputEl, emptyClass);
1752
+ jqLite.addClass(inputEl, notEmptyClass);
1753
+ } else {
1754
+ jqLite.removeClass(inputEl, notEmptyClass);
1755
+ jqLite.addClass(inputEl, emptyClass)
1756
+ }
1757
+
1758
+ jqLite.addClass(inputEl, dirtyClass);
1759
+ }
1760
+
1761
+
1762
+ /** Define module API */
1763
+ module.exports = {
1764
+ /** Initialize input elements */
1765
+ initialize: initialize,
1766
+
1767
+ /** Initialize module listeners */
1768
+ initListeners: function() {
1769
+ var doc = document;
1770
+
1771
+ // markup elements available when method is called
1772
+ var elList = doc.querySelectorAll(cssSelector);
1773
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1774
+
1775
+ // listen for new elements
1776
+ util.onNodeInserted(function(el) {
1777
+ if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') initialize(el);
1778
+ });
1779
+
1780
+ // add transition css for floating labels
1781
+ setTimeout(function() {
1782
+ var css = '.mui-textfield.mui-textfield--float-label > label {' + [
1783
+ '-webkit-transition',
1784
+ '-moz-transition',
1785
+ '-o-transition',
1786
+ 'transition',
1787
+ ''
1788
+ ].join(':all .15s ease-out;') + '}';
1789
+
1790
+ util.loadStyle(css);
1791
+ }, 150);
1792
+
1793
+ // pointer-events shim for floating labels
1794
+ if (util.supportsPointerEvents() === false) {
1795
+ jqLite.on(document, 'click', function(ev) {
1796
+ var targetEl = ev.target;
1797
+
1798
+ if (targetEl.tagName === 'LABEL' &&
1799
+ jqLite.hasClass(targetEl.parentNode, floatingLabelClass)) {
1800
+ var inputEl = targetEl.previousElementSibling;
1801
+ if (inputEl) inputEl.focus();
1802
+ }
1803
+ });
1804
+ }
1805
+ }
1806
+ };
1807
+
1807
1808
  },{"./lib/jqLite":4,"./lib/util":5}]},{},[1])