material_design_lite-sass 1.0.2.1 → 1.0.3

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.
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
+ })();