material_design_lite-sass 1.0.2.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/lib/material_design_lite/sass/version.rb +1 -1
  4. data/vendor/assets/javascripts/material.js +2562 -2993
  5. data/vendor/assets/javascripts/material/button.js +114 -112
  6. data/vendor/assets/javascripts/material/checkbox.js +255 -260
  7. data/vendor/assets/javascripts/material/data-table.js +140 -124
  8. data/vendor/assets/javascripts/material/icon-toggle.js +239 -243
  9. data/vendor/assets/javascripts/material/layout.js +392 -388
  10. data/vendor/assets/javascripts/material/mdlComponentHandler.js +68 -27
  11. data/vendor/assets/javascripts/material/menu.js +430 -414
  12. data/vendor/assets/javascripts/material/progress.js +110 -97
  13. data/vendor/assets/javascripts/material/radio.js +244 -247
  14. data/vendor/assets/javascripts/material/ripple.js +220 -211
  15. data/vendor/assets/javascripts/material/slider.js +228 -228
  16. data/vendor/assets/javascripts/material/spinner.js +122 -119
  17. data/vendor/assets/javascripts/material/switch.js +246 -250
  18. data/vendor/assets/javascripts/material/tabs.js +129 -127
  19. data/vendor/assets/javascripts/material/textfield.js +221 -222
  20. data/vendor/assets/javascripts/material/tooltip.js +126 -122
  21. data/vendor/assets/stylesheets/material/_badge.scss +1 -1
  22. data/vendor/assets/stylesheets/material/_button.scss +15 -8
  23. data/vendor/assets/stylesheets/material/_card.scss +1 -1
  24. data/vendor/assets/stylesheets/material/_checkbox.scss +1 -1
  25. data/vendor/assets/stylesheets/material/_data-table.scss +5 -3
  26. data/vendor/assets/stylesheets/material/_functions.scss +16 -0
  27. data/vendor/assets/stylesheets/material/_grid.scss +11 -20
  28. data/vendor/assets/stylesheets/material/_layout.scss +7 -5
  29. data/vendor/assets/stylesheets/material/_menu.scss +4 -1
  30. data/vendor/assets/stylesheets/material/_radio.scss +1 -1
  31. data/vendor/assets/stylesheets/material/_slider.scss +1 -0
  32. data/vendor/assets/stylesheets/material/_switch.scss +1 -1
  33. data/vendor/assets/stylesheets/material/_tabs.scss +1 -1
  34. data/vendor/assets/stylesheets/material/_textfield.scss +15 -5
  35. data/vendor/assets/stylesheets/material/_tooltip.scss +2 -2
  36. data/vendor/assets/stylesheets/material/_variables.scss +18 -43
  37. data/vendor/assets/stylesheets/material/resets/_h5bp.scss +28 -21
  38. metadata +1 -1
@@ -15,230 +15,239 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- /**
19
- * Class constructor for Ripple MDL component.
20
- * Implements MDL component design pattern defined at:
21
- * https://github.com/jasonmayes/mdl-component-design-pattern
22
- * @param {HTMLElement} element The element that will be upgraded.
23
- */
24
- function MaterialRipple(element) {
18
+ (function() {
25
19
  'use strict';
26
20
 
27
- this.element_ = element;
28
-
29
- // Initialize instance.
30
- this.init();
31
- }
32
-
33
- /**
34
- * Store constants in one place so they can be updated easily.
35
- * @enum {string | number}
36
- * @private
37
- */
38
- MaterialRipple.prototype.Constant_ = {
39
- INITIAL_SCALE: 'scale(0.0001, 0.0001)',
40
- INITIAL_SIZE: '1px',
41
- INITIAL_OPACITY: '0.4',
42
- FINAL_OPACITY: '0',
43
- FINAL_SCALE: ''
44
- };
45
-
46
- /**
47
- * Store strings for class names defined by this component that are used in
48
- * JavaScript. This allows us to simply change it in one place should we
49
- * decide to modify at a later date.
50
- * @enum {string}
51
- * @private
52
- */
53
- MaterialRipple.prototype.CssClasses_ = {
54
- RIPPLE_CENTER: 'mdl-ripple--center',
55
- RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
56
- RIPPLE: 'mdl-ripple',
57
- IS_ANIMATING: 'is-animating',
58
- IS_VISIBLE: 'is-visible'
59
- };
21
+ /**
22
+ * Class constructor for Ripple MDL component.
23
+ * Implements MDL component design pattern defined at:
24
+ * https://github.com/jasonmayes/mdl-component-design-pattern
25
+ *
26
+ * @param {HTMLElement} element The element that will be upgraded.
27
+ */
28
+ var MaterialRipple = function MaterialRipple(element) {
29
+ this.element_ = element;
30
+
31
+ // Initialize instance.
32
+ this.init();
33
+ };
34
+ window.MaterialRipple = MaterialRipple;
35
+
36
+ /**
37
+ * Store constants in one place so they can be updated easily.
38
+ *
39
+ * @enum {String | Number}
40
+ * @private
41
+ */
42
+ MaterialRipple.prototype.Constant_ = {
43
+ INITIAL_SCALE: 'scale(0.0001, 0.0001)',
44
+ INITIAL_SIZE: '1px',
45
+ INITIAL_OPACITY: '0.4',
46
+ FINAL_OPACITY: '0',
47
+ FINAL_SCALE: ''
48
+ };
49
+
50
+ /**
51
+ * Store strings for class names defined by this component that are used in
52
+ * JavaScript. This allows us to simply change it in one place should we
53
+ * decide to modify at a later date.
54
+ *
55
+ * @enum {String}
56
+ * @private
57
+ */
58
+ MaterialRipple.prototype.CssClasses_ = {
59
+ RIPPLE_CENTER: 'mdl-ripple--center',
60
+ RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
61
+ RIPPLE: 'mdl-ripple',
62
+ IS_ANIMATING: 'is-animating',
63
+ IS_VISIBLE: 'is-visible'
64
+ };
65
+
66
+ /**
67
+ * Handle mouse / finger down on element.
68
+ *
69
+ * @param {Event} event The event that fired.
70
+ * @private
71
+ */
72
+ MaterialRipple.prototype.downHandler_ = function(event) {
73
+ if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) {
74
+ var rect = this.element_.getBoundingClientRect();
75
+ this.boundHeight = rect.height;
76
+ this.boundWidth = rect.width;
77
+ this.rippleSize_ = Math.sqrt(rect.width * rect.width +
78
+ rect.height * rect.height) * 2 + 2;
79
+ this.rippleElement_.style.width = this.rippleSize_ + 'px';
80
+ this.rippleElement_.style.height = this.rippleSize_ + 'px';
81
+ }
60
82
 
61
- /**
62
- * Handle mouse / finger down on element.
63
- * @param {Event} event The event that fired.
64
- * @private
65
- */
66
- MaterialRipple.prototype.downHandler_ = function(event) {
67
- 'use strict';
83
+ this.rippleElement_.classList.add(this.CssClasses_.IS_VISIBLE);
68
84
 
69
- if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) {
70
- var rect = this.element_.getBoundingClientRect();
71
- this.boundHeight = rect.height;
72
- this.boundWidth = rect.width;
73
- this.rippleSize_ = Math.sqrt(rect.width * rect.width +
74
- rect.height * rect.height) * 2 + 2;
75
- this.rippleElement_.style.width = this.rippleSize_ + 'px';
76
- this.rippleElement_.style.height = this.rippleSize_ + 'px';
77
- }
78
-
79
- this.rippleElement_.classList.add(this.CssClasses_.IS_VISIBLE);
80
-
81
- if (event.type === 'mousedown' && this.ignoringMouseDown_) {
82
- this.ignoringMouseDown_ = false;
83
- } else {
84
- if (event.type === 'touchstart') {
85
- this.ignoringMouseDown_ = true;
86
- }
87
- var frameCount = this.getFrameCount();
88
- if (frameCount > 0) {
89
- return;
90
- }
91
- this.setFrameCount(1);
92
- var bound = event.currentTarget.getBoundingClientRect();
93
- var x;
94
- var y;
95
- // Check if we are handling a keyboard click.
96
- if (event.clientX === 0 && event.clientY === 0) {
97
- x = Math.round(bound.width / 2);
98
- y = Math.round(bound.height / 2);
85
+ if (event.type === 'mousedown' && this.ignoringMouseDown_) {
86
+ this.ignoringMouseDown_ = false;
99
87
  } else {
100
- var clientX = event.clientX ? event.clientX : event.touches[0].clientX;
101
- var clientY = event.clientY ? event.clientY : event.touches[0].clientY;
102
- x = Math.round(clientX - bound.left);
103
- y = Math.round(clientY - bound.top);
88
+ if (event.type === 'touchstart') {
89
+ this.ignoringMouseDown_ = true;
90
+ }
91
+ var frameCount = this.getFrameCount();
92
+ if (frameCount > 0) {
93
+ return;
94
+ }
95
+ this.setFrameCount(1);
96
+ var bound = event.currentTarget.getBoundingClientRect();
97
+ var x;
98
+ var y;
99
+ // Check if we are handling a keyboard click.
100
+ if (event.clientX === 0 && event.clientY === 0) {
101
+ x = Math.round(bound.width / 2);
102
+ y = Math.round(bound.height / 2);
103
+ } else {
104
+ var clientX = event.clientX ? event.clientX : event.touches[0].clientX;
105
+ var clientY = event.clientY ? event.clientY : event.touches[0].clientY;
106
+ x = Math.round(clientX - bound.left);
107
+ y = Math.round(clientY - bound.top);
108
+ }
109
+ this.setRippleXY(x, y);
110
+ this.setRippleStyles(true);
111
+ window.requestAnimationFrame(this.animFrameHandler.bind(this));
104
112
  }
105
- this.setRippleXY(x, y);
106
- this.setRippleStyles(true);
107
- window.requestAnimationFrame(this.animFrameHandler.bind(this));
108
- }
109
- };
110
-
111
- /**
112
- * Handle mouse / finger up on element.
113
- * @param {Event} event The event that fired.
114
- * @private
115
- */
116
- MaterialRipple.prototype.upHandler_ = function(event) {
117
- 'use strict';
118
-
119
- // Don't fire for the artificial "mouseup" generated by a double-click.
120
- if (event && event.detail !== 2) {
121
- this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE);
122
- }
123
- };
124
-
125
- /**
126
- * Initialize element.
127
- */
128
- MaterialRipple.prototype.init = function() {
129
- 'use strict';
113
+ };
114
+
115
+ /**
116
+ * Handle mouse / finger up on element.
117
+ *
118
+ * @param {Event} event The event that fired.
119
+ * @private
120
+ */
121
+ MaterialRipple.prototype.upHandler_ = function(event) {
122
+ // Don't fire for the artificial "mouseup" generated by a double-click.
123
+ if (event && event.detail !== 2) {
124
+ this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE);
125
+ }
126
+ // Allow a repaint to occur before removing this class, so the animation
127
+ // shows for tap events, which seem to trigger a mouseup too soon after
128
+ // mousedown.
129
+ window.setTimeout(function() {
130
+ this.rippleElement_.classList.remove(this.CssClasses_.IS_VISIBLE);
131
+ }.bind(this), 0);
132
+ };
133
+
134
+ /**
135
+ * Initialize element.
136
+ */
137
+ MaterialRipple.prototype.init = function() {
138
+ if (this.element_) {
139
+ var recentering =
140
+ this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER);
141
+ if (!this.element_.classList.contains(
142
+ this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)) {
143
+ this.rippleElement_ = this.element_.querySelector('.' +
144
+ this.CssClasses_.RIPPLE);
145
+ this.frameCount_ = 0;
146
+ this.rippleSize_ = 0;
147
+ this.x_ = 0;
148
+ this.y_ = 0;
149
+
150
+ // Touch start produces a compat mouse down event, which would cause a
151
+ // second ripples. To avoid that, we use this property to ignore the first
152
+ // mouse down after a touch start.
153
+ this.ignoringMouseDown_ = false;
154
+
155
+ this.boundDownHandler = this.downHandler_.bind(this);
156
+ this.element_.addEventListener('mousedown',
157
+ this.boundDownHandler);
158
+ this.element_.addEventListener('touchstart',
159
+ this.boundDownHandler);
160
+
161
+ this.boundUpHandler = this.upHandler_.bind(this);
162
+ this.element_.addEventListener('mouseup', this.boundUpHandler);
163
+ this.element_.addEventListener('mouseleave', this.boundUpHandler);
164
+ this.element_.addEventListener('touchend', this.boundUpHandler);
165
+ this.element_.addEventListener('blur', this.boundUpHandler);
166
+
167
+ this.getFrameCount = function() {
168
+ return this.frameCount_;
169
+ };
170
+
171
+ this.setFrameCount = function(fC) {
172
+ this.frameCount_ = fC;
173
+ };
174
+
175
+ this.getRippleElement = function() {
176
+ return this.rippleElement_;
177
+ };
178
+
179
+ this.setRippleXY = function(newX, newY) {
180
+ this.x_ = newX;
181
+ this.y_ = newY;
182
+ };
183
+
184
+ this.setRippleStyles = function(start) {
185
+ if (this.rippleElement_ !== null) {
186
+ var transformString;
187
+ var scale;
188
+ var size;
189
+ var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)';
190
+
191
+ if (start) {
192
+ scale = this.Constant_.INITIAL_SCALE;
193
+ size = this.Constant_.INITIAL_SIZE;
194
+ } else {
195
+ scale = this.Constant_.FINAL_SCALE;
196
+ size = this.rippleSize_ + 'px';
197
+ if (recentering) {
198
+ offset = 'translate(' + this.boundWidth / 2 + 'px, ' +
199
+ this.boundHeight / 2 + 'px)';
200
+ }
201
+ }
130
202
 
131
- if (this.element_) {
132
- var recentering =
133
- this.element_.classList.contains(this.CssClasses_.RIPPLE_CENTER);
134
- if (!this.element_.classList.contains(
135
- this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS)) {
136
- this.rippleElement_ = this.element_.querySelector('.' +
137
- this.CssClasses_.RIPPLE);
138
- this.frameCount_ = 0;
139
- this.rippleSize_ = 0;
140
- this.x_ = 0;
141
- this.y_ = 0;
142
-
143
- // Touch start produces a compat mouse down event, which would cause a
144
- // second ripples. To avoid that, we use this property to ignore the first
145
- // mouse down after a touch start.
146
- this.ignoringMouseDown_ = false;
203
+ transformString = 'translate(-50%, -50%) ' + offset + scale;
147
204
 
148
- this.boundDownHandler = this.downHandler_.bind(this);
149
- this.element_.addEventListener('mousedown',
150
- this.boundDownHandler);
151
- this.element_.addEventListener('touchstart',
152
- this.boundDownHandler);
205
+ this.rippleElement_.style.webkitTransform = transformString;
206
+ this.rippleElement_.style.msTransform = transformString;
207
+ this.rippleElement_.style.transform = transformString;
153
208
 
154
- this.boundUpHandler = this.upHandler_.bind(this);
155
- this.element_.addEventListener('mouseup', this.boundUpHandler);
156
- this.element_.addEventListener('mouseleave', this.boundUpHandler);
157
- this.element_.addEventListener('touchend', this.boundUpHandler);
158
- this.element_.addEventListener('blur', this.boundUpHandler);
159
-
160
- this.getFrameCount = function() {
161
- return this.frameCount_;
162
- };
163
-
164
- this.setFrameCount = function(fC) {
165
- this.frameCount_ = fC;
166
- };
167
-
168
- this.getRippleElement = function() {
169
- return this.rippleElement_;
170
- };
171
-
172
- this.setRippleXY = function(newX, newY) {
173
- this.x_ = newX;
174
- this.y_ = newY;
175
- };
176
-
177
- this.setRippleStyles = function(start) {
178
- if (this.rippleElement_ !== null) {
179
- var transformString;
180
- var scale;
181
- var size;
182
- var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)';
183
-
184
- if (start) {
185
- scale = this.Constant_.INITIAL_SCALE;
186
- size = this.Constant_.INITIAL_SIZE;
187
- } else {
188
- scale = this.Constant_.FINAL_SCALE;
189
- size = this.rippleSize_ + 'px';
190
- if (recentering) {
191
- offset = 'translate(' + this.boundWidth / 2 + 'px, ' +
192
- this.boundHeight / 2 + 'px)';
209
+ if (start) {
210
+ this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING);
211
+ } else {
212
+ this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING);
193
213
  }
194
214
  }
215
+ };
195
216
 
196
- transformString = 'translate(-50%, -50%) ' + offset + scale;
197
-
198
- this.rippleElement_.style.webkitTransform = transformString;
199
- this.rippleElement_.style.msTransform = transformString;
200
- this.rippleElement_.style.transform = transformString;
201
-
202
- if (start) {
203
- this.rippleElement_.classList.remove(this.CssClasses_.IS_ANIMATING);
217
+ this.animFrameHandler = function() {
218
+ if (this.frameCount_-- > 0) {
219
+ window.requestAnimationFrame(this.animFrameHandler.bind(this));
204
220
  } else {
205
- this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING);
221
+ this.setRippleStyles(false);
206
222
  }
207
- }
208
- };
209
-
210
- this.animFrameHandler = function() {
211
- if (this.frameCount_-- > 0) {
212
- window.requestAnimationFrame(this.animFrameHandler.bind(this));
213
- } else {
214
- this.setRippleStyles(false);
215
- }
216
- };
223
+ };
224
+ }
217
225
  }
218
- }
219
- };
226
+ };
227
+
228
+ /**
229
+ * Downgrade the component
230
+ *
231
+ * @private
232
+ */
233
+ MaterialRipple.prototype.mdlDowngrade_ = function() {
234
+ this.element_.removeEventListener('mousedown',
235
+ this.boundDownHandler);
236
+ this.element_.removeEventListener('touchstart',
237
+ this.boundDownHandler);
220
238
 
221
- /*
222
- * Downgrade the component
223
- */
224
- MaterialRipple.prototype.mdlDowngrade_ = function() {
225
- 'use strict';
226
- this.element_.removeEventListener('mousedown',
227
- this.boundDownHandler);
228
- this.element_.removeEventListener('touchstart',
229
- this.boundDownHandler);
230
-
231
- this.element_.removeEventListener('mouseup', this.boundUpHandler);
232
- this.element_.removeEventListener('mouseleave', this.boundUpHandler);
233
- this.element_.removeEventListener('touchend', this.boundUpHandler);
234
- this.element_.removeEventListener('blur', this.boundUpHandler);
235
- };
236
-
237
- // The component registers itself. It can assume componentHandler is available
238
- // in the global scope.
239
- componentHandler.register({
240
- constructor: MaterialRipple,
241
- classAsString: 'MaterialRipple',
242
- cssClass: 'mdl-js-ripple-effect',
243
- widget: false
244
- });
239
+ this.element_.removeEventListener('mouseup', this.boundUpHandler);
240
+ this.element_.removeEventListener('mouseleave', this.boundUpHandler);
241
+ this.element_.removeEventListener('touchend', this.boundUpHandler);
242
+ this.element_.removeEventListener('blur', this.boundUpHandler);
243
+ };
244
+
245
+ // The component registers itself. It can assume componentHandler is available
246
+ // in the global scope.
247
+ componentHandler.register({
248
+ constructor: MaterialRipple,
249
+ classAsString: 'MaterialRipple',
250
+ cssClass: 'mdl-js-ripple-effect',
251
+ widget: false
252
+ });
253
+ })();
@@ -15,238 +15,238 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
- /**
19
- * Class constructor for Slider MDL component.
20
- * Implements MDL component design pattern defined at:
21
- * https://github.com/jasonmayes/mdl-component-design-pattern
22
- * @param {HTMLElement} element The element that will be upgraded.
23
- */
24
- function MaterialSlider(element) {
18
+ (function() {
25
19
  'use strict';
26
20
 
27
- this.element_ = element;
28
- // Browser feature detection.
29
- this.isIE_ = window.navigator.msPointerEnabled;
30
- // Initialize instance.
31
- this.init();
32
- }
33
-
34
- /**
35
- * Store constants in one place so they can be updated easily.
36
- * @enum {string | number}
37
- * @private
38
- */
39
- MaterialSlider.prototype.Constant_ = {
40
- // None for now.
41
- };
42
-
43
- /**
44
- * Store strings for class names defined by this component that are used in
45
- * JavaScript. This allows us to simply change it in one place should we
46
- * decide to modify at a later date.
47
- * @enum {string}
48
- * @private
49
- */
50
- MaterialSlider.prototype.CssClasses_ = {
51
- IE_CONTAINER: 'mdl-slider__ie-container',
52
- SLIDER_CONTAINER: 'mdl-slider__container',
53
- BACKGROUND_FLEX: 'mdl-slider__background-flex',
54
- BACKGROUND_LOWER: 'mdl-slider__background-lower',
55
- BACKGROUND_UPPER: 'mdl-slider__background-upper',
56
- IS_LOWEST_VALUE: 'is-lowest-value',
57
- IS_UPGRADED: 'is-upgraded'
58
- };
59
-
60
- /**
61
- * Handle input on element.
62
- * @param {Event} event The event that fired.
63
- * @private
64
- */
65
- MaterialSlider.prototype.onInput_ = function(event) {
66
- 'use strict';
67
-
68
- this.updateValueStyles_();
69
- };
70
-
71
- /**
72
- * Handle change on element.
73
- * @param {Event} event The event that fired.
74
- * @private
75
- */
76
- MaterialSlider.prototype.onChange_ = function(event) {
77
- 'use strict';
78
-
79
- this.updateValueStyles_();
80
- };
81
-
82
- /**
83
- * Handle mouseup on element.
84
- * @param {Event} event The event that fired.
85
- * @private
86
- */
87
- MaterialSlider.prototype.onMouseUp_ = function(event) {
88
- 'use strict';
89
-
90
- event.target.blur();
91
- };
92
-
93
- /**
94
- * Handle mousedown on container element.
95
- * This handler is purpose is to not require the use to click
96
- * exactly on the 2px slider element, as FireFox seems to be very
97
- * strict about this.
98
- * @param {Event} event The event that fired.
99
- * @private
100
- */
101
- MaterialSlider.prototype.onContainerMouseDown_ = function(event) {
102
- 'use strict';
103
-
104
- // If this click is not on the parent element (but rather some child)
105
- // ignore. It may still bubble up.
106
- if (event.target !== this.element_.parentElement) {
107
- return;
108
- }
109
-
110
- // Discard the original event and create a new event that
111
- // is on the slider element.
112
- event.preventDefault();
113
- var newEvent = new MouseEvent('mousedown', {
114
- target: event.target,
115
- buttons: event.buttons,
116
- clientX: event.clientX,
117
- clientY: this.element_.getBoundingClientRect().y
118
- });
119
- this.element_.dispatchEvent(newEvent);
120
- };
121
-
122
- /**
123
- * Handle updating of values.
124
- * @param {Event} event The event that fired.
125
- * @private
126
- */
127
- MaterialSlider.prototype.updateValueStyles_ = function(event) {
128
- 'use strict';
129
-
130
- // Calculate and apply percentages to div structure behind slider.
131
- var fraction = (this.element_.value - this.element_.min) /
132
- (this.element_.max - this.element_.min);
133
-
134
- if (fraction === 0) {
135
- this.element_.classList.add(this.CssClasses_.IS_LOWEST_VALUE);
136
- } else {
137
- this.element_.classList.remove(this.CssClasses_.IS_LOWEST_VALUE);
138
- }
139
-
140
- if (!this.isIE_) {
141
- this.backgroundLower_.style.flex = fraction;
142
- this.backgroundLower_.style.webkitFlex = fraction;
143
- this.backgroundUpper_.style.flex = 1 - fraction;
144
- this.backgroundUpper_.style.webkitFlex = 1 - fraction;
145
- }
146
- };
147
-
148
- // Public methods.
149
-
150
- /**
151
- * Disable slider.
152
- * @public
153
- */
154
- MaterialSlider.prototype.disable = function() {
155
- 'use strict';
156
-
157
- this.element_.disabled = true;
158
- };
159
-
160
- /**
161
- * Enable slider.
162
- * @public
163
- */
164
- MaterialSlider.prototype.enable = function() {
165
- 'use strict';
166
-
167
- this.element_.disabled = false;
168
- };
169
-
170
- /**
171
- * Update slider value.
172
- * @param {Number} value The value to which to set the control (optional).
173
- * @public
174
- */
175
- MaterialSlider.prototype.change = function(value) {
176
- 'use strict';
177
-
178
- if (value) {
179
- this.element_.value = value;
180
- }
181
- this.updateValueStyles_();
182
- };
183
-
184
- /**
185
- * Initialize element.
186
- */
187
- MaterialSlider.prototype.init = function() {
188
- 'use strict';
21
+ /**
22
+ * Class constructor for Slider MDL component.
23
+ * Implements MDL component design pattern defined at:
24
+ * https://github.com/jasonmayes/mdl-component-design-pattern
25
+ *
26
+ * @param {HTMLElement} element The element that will be upgraded.
27
+ */
28
+ var MaterialSlider = function MaterialSlider(element) {
29
+ this.element_ = element;
30
+ // Browser feature detection.
31
+ this.isIE_ = window.navigator.msPointerEnabled;
32
+ // Initialize instance.
33
+ this.init();
34
+ };
35
+ window.MaterialSlider = MaterialSlider;
36
+
37
+ /**
38
+ * Store constants in one place so they can be updated easily.
39
+ *
40
+ * @enum {String | Number}
41
+ * @private
42
+ */
43
+ MaterialSlider.prototype.Constant_ = {
44
+ // None for now.
45
+ };
46
+
47
+ /**
48
+ * Store strings for class names defined by this component that are used in
49
+ * JavaScript. This allows us to simply change it in one place should we
50
+ * decide to modify at a later date.
51
+ *
52
+ * @enum {String}
53
+ * @private
54
+ */
55
+ MaterialSlider.prototype.CssClasses_ = {
56
+ IE_CONTAINER: 'mdl-slider__ie-container',
57
+ SLIDER_CONTAINER: 'mdl-slider__container',
58
+ BACKGROUND_FLEX: 'mdl-slider__background-flex',
59
+ BACKGROUND_LOWER: 'mdl-slider__background-lower',
60
+ BACKGROUND_UPPER: 'mdl-slider__background-upper',
61
+ IS_LOWEST_VALUE: 'is-lowest-value',
62
+ IS_UPGRADED: 'is-upgraded'
63
+ };
64
+
65
+ /**
66
+ * Handle input on element.
67
+ *
68
+ * @param {Event} event The event that fired.
69
+ * @private
70
+ */
71
+ MaterialSlider.prototype.onInput_ = function(event) {
72
+ this.updateValueStyles_();
73
+ };
74
+
75
+ /**
76
+ * Handle change on element.
77
+ *
78
+ * @param {Event} event The event that fired.
79
+ * @private
80
+ */
81
+ MaterialSlider.prototype.onChange_ = function(event) {
82
+ this.updateValueStyles_();
83
+ };
84
+
85
+ /**
86
+ * Handle mouseup on element.
87
+ *
88
+ * @param {Event} event The event that fired.
89
+ * @private
90
+ */
91
+ MaterialSlider.prototype.onMouseUp_ = function(event) {
92
+ event.target.blur();
93
+ };
94
+
95
+ /**
96
+ * Handle mousedown on container element.
97
+ * This handler is purpose is to not require the use to click
98
+ * exactly on the 2px slider element, as FireFox seems to be very
99
+ * strict about this.
100
+ *
101
+ * @param {Event} event The event that fired.
102
+ * @private
103
+ */
104
+ MaterialSlider.prototype.onContainerMouseDown_ = function(event) {
105
+ // If this click is not on the parent element (but rather some child)
106
+ // ignore. It may still bubble up.
107
+ if (event.target !== this.element_.parentElement) {
108
+ return;
109
+ }
189
110
 
190
- if (this.element_) {
191
- if (this.isIE_) {
192
- // Since we need to specify a very large height in IE due to
193
- // implementation limitations, we add a parent here that trims it down to
194
- // a reasonable size.
195
- var containerIE = document.createElement('div');
196
- containerIE.classList.add(this.CssClasses_.IE_CONTAINER);
197
- this.element_.parentElement.insertBefore(containerIE, this.element_);
198
- this.element_.parentElement.removeChild(this.element_);
199
- containerIE.appendChild(this.element_);
111
+ // Discard the original event and create a new event that
112
+ // is on the slider element.
113
+ event.preventDefault();
114
+ var newEvent = new MouseEvent('mousedown', {
115
+ target: event.target,
116
+ buttons: event.buttons,
117
+ clientX: event.clientX,
118
+ clientY: this.element_.getBoundingClientRect().y
119
+ });
120
+ this.element_.dispatchEvent(newEvent);
121
+ };
122
+
123
+ /**
124
+ * Handle updating of values.
125
+ *
126
+ * @param {Event} event The event that fired.
127
+ * @private
128
+ */
129
+ MaterialSlider.prototype.updateValueStyles_ = function(event) {
130
+ // Calculate and apply percentages to div structure behind slider.
131
+ var fraction = (this.element_.value - this.element_.min) /
132
+ (this.element_.max - this.element_.min);
133
+
134
+ if (fraction === 0) {
135
+ this.element_.classList.add(this.CssClasses_.IS_LOWEST_VALUE);
200
136
  } else {
201
- // For non-IE browsers, we need a div structure that sits behind the
202
- // slider and allows us to style the left and right sides of it with
203
- // different colors.
204
- var container = document.createElement('div');
205
- container.classList.add(this.CssClasses_.SLIDER_CONTAINER);
206
- this.element_.parentElement.insertBefore(container, this.element_);
207
- this.element_.parentElement.removeChild(this.element_);
208
- container.appendChild(this.element_);
209
- var backgroundFlex = document.createElement('div');
210
- backgroundFlex.classList.add(this.CssClasses_.BACKGROUND_FLEX);
211
- container.appendChild(backgroundFlex);
212
- this.backgroundLower_ = document.createElement('div');
213
- this.backgroundLower_.classList.add(this.CssClasses_.BACKGROUND_LOWER);
214
- backgroundFlex.appendChild(this.backgroundLower_);
215
- this.backgroundUpper_ = document.createElement('div');
216
- this.backgroundUpper_.classList.add(this.CssClasses_.BACKGROUND_UPPER);
217
- backgroundFlex.appendChild(this.backgroundUpper_);
137
+ this.element_.classList.remove(this.CssClasses_.IS_LOWEST_VALUE);
218
138
  }
219
139
 
220
- this.boundInputHandler = this.onInput_.bind(this);
221
- this.boundChangeHandler = this.onChange_.bind(this);
222
- this.boundMouseUpHandler = this.onMouseUp_.bind(this);
223
- this.boundContainerMouseDownHandler = this.onContainerMouseDown_.bind(this);
224
- this.element_.addEventListener('input', this.boundInputHandler);
225
- this.element_.addEventListener('change', this.boundChangeHandler);
226
- this.element_.addEventListener('mouseup', this.boundMouseUpHandler);
227
- this.element_.parentElement.addEventListener('mousedown', this.boundContainerMouseDownHandler);
228
-
140
+ if (!this.isIE_) {
141
+ this.backgroundLower_.style.flex = fraction;
142
+ this.backgroundLower_.style.webkitFlex = fraction;
143
+ this.backgroundUpper_.style.flex = 1 - fraction;
144
+ this.backgroundUpper_.style.webkitFlex = 1 - fraction;
145
+ }
146
+ };
147
+
148
+ // Public methods.
149
+
150
+ /**
151
+ * Disable slider.
152
+ *
153
+ * @public
154
+ */
155
+ MaterialSlider.prototype.disable = function() {
156
+ this.element_.disabled = true;
157
+ };
158
+
159
+ /**
160
+ * Enable slider.
161
+ *
162
+ * @public
163
+ */
164
+ MaterialSlider.prototype.enable = function() {
165
+
166
+ this.element_.disabled = false;
167
+ };
168
+
169
+ /**
170
+ * Update slider value.
171
+ *
172
+ * @param {Number} value The value to which to set the control (optional).
173
+ * @public
174
+ */
175
+ MaterialSlider.prototype.change = function(value) {
176
+
177
+ if (typeof value !== 'undefined') {
178
+ this.element_.value = value;
179
+ }
229
180
  this.updateValueStyles_();
230
- this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
231
- }
232
- };
233
-
234
- /*
235
- * Downgrade the component
236
- */
237
- MaterialSlider.prototype.mdlDowngrade_ = function() {
238
- 'use strict';
239
- this.element_.removeEventListener('input', this.boundInputHandler);
240
- this.element_.removeEventListener('change', this.boundChangeHandler);
241
- this.element_.removeEventListener('mouseup', this.boundMouseUpHandler);
242
- this.element_.parentElement.removeEventListener('mousedown', this.boundContainerMouseDownHandler);
243
- };
244
-
245
- // The component registers itself. It can assume componentHandler is available
246
- // in the global scope.
247
- componentHandler.register({
248
- constructor: MaterialSlider,
249
- classAsString: 'MaterialSlider',
250
- cssClass: 'mdl-js-slider',
251
- widget: true
252
- });
181
+ };
182
+
183
+ /**
184
+ * Initialize element.
185
+ */
186
+ MaterialSlider.prototype.init = function() {
187
+
188
+ if (this.element_) {
189
+ if (this.isIE_) {
190
+ // Since we need to specify a very large height in IE due to
191
+ // implementation limitations, we add a parent here that trims it down to
192
+ // a reasonable size.
193
+ var containerIE = document.createElement('div');
194
+ containerIE.classList.add(this.CssClasses_.IE_CONTAINER);
195
+ this.element_.parentElement.insertBefore(containerIE, this.element_);
196
+ this.element_.parentElement.removeChild(this.element_);
197
+ containerIE.appendChild(this.element_);
198
+ } else {
199
+ // For non-IE browsers, we need a div structure that sits behind the
200
+ // slider and allows us to style the left and right sides of it with
201
+ // different colors.
202
+ var container = document.createElement('div');
203
+ container.classList.add(this.CssClasses_.SLIDER_CONTAINER);
204
+ this.element_.parentElement.insertBefore(container, this.element_);
205
+ this.element_.parentElement.removeChild(this.element_);
206
+ container.appendChild(this.element_);
207
+ var backgroundFlex = document.createElement('div');
208
+ backgroundFlex.classList.add(this.CssClasses_.BACKGROUND_FLEX);
209
+ container.appendChild(backgroundFlex);
210
+ this.backgroundLower_ = document.createElement('div');
211
+ this.backgroundLower_.classList.add(this.CssClasses_.BACKGROUND_LOWER);
212
+ backgroundFlex.appendChild(this.backgroundLower_);
213
+ this.backgroundUpper_ = document.createElement('div');
214
+ this.backgroundUpper_.classList.add(this.CssClasses_.BACKGROUND_UPPER);
215
+ backgroundFlex.appendChild(this.backgroundUpper_);
216
+ }
217
+
218
+ this.boundInputHandler = this.onInput_.bind(this);
219
+ this.boundChangeHandler = this.onChange_.bind(this);
220
+ this.boundMouseUpHandler = this.onMouseUp_.bind(this);
221
+ this.boundContainerMouseDownHandler = this.onContainerMouseDown_.bind(this);
222
+ this.element_.addEventListener('input', this.boundInputHandler);
223
+ this.element_.addEventListener('change', this.boundChangeHandler);
224
+ this.element_.addEventListener('mouseup', this.boundMouseUpHandler);
225
+ this.element_.parentElement.addEventListener('mousedown', this.boundContainerMouseDownHandler);
226
+
227
+ this.updateValueStyles_();
228
+ this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
229
+ }
230
+ };
231
+
232
+ /**
233
+ * Downgrade the component
234
+ *
235
+ * @private
236
+ */
237
+ MaterialSlider.prototype.mdlDowngrade_ = function() {
238
+ this.element_.removeEventListener('input', this.boundInputHandler);
239
+ this.element_.removeEventListener('change', this.boundChangeHandler);
240
+ this.element_.removeEventListener('mouseup', this.boundMouseUpHandler);
241
+ this.element_.parentElement.removeEventListener('mousedown', this.boundContainerMouseDownHandler);
242
+ };
243
+
244
+ // The component registers itself. It can assume componentHandler is available
245
+ // in the global scope.
246
+ componentHandler.register({
247
+ constructor: MaterialSlider,
248
+ classAsString: 'MaterialSlider',
249
+ cssClass: 'mdl-js-slider',
250
+ widget: true
251
+ });
252
+ })();