material_design_lite-sass 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +11 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +108 -0
  9. data/Rakefile +4 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +7 -0
  12. data/lib/material_design_lite-sass.rb +46 -0
  13. data/lib/material_design_lite/sass/engine.rb +13 -0
  14. data/lib/material_design_lite/sass/version.rb +5 -0
  15. data/material_design_lite-sass.gemspec +28 -0
  16. data/vendor/assets/javascripts/material.js +3919 -0
  17. data/vendor/assets/javascripts/material/button.js +132 -0
  18. data/vendor/assets/javascripts/material/checkbox.js +265 -0
  19. data/vendor/assets/javascripts/material/data-table.js +149 -0
  20. data/vendor/assets/javascripts/material/icon-toggle.js +248 -0
  21. data/vendor/assets/javascripts/material/layout.js +434 -0
  22. data/vendor/assets/javascripts/material/mdlComponentHandler.js +346 -0
  23. data/vendor/assets/javascripts/material/menu.js +468 -0
  24. data/vendor/assets/javascripts/material/progress.js +116 -0
  25. data/vendor/assets/javascripts/material/rAF.js +38 -0
  26. data/vendor/assets/javascripts/material/radio.js +257 -0
  27. data/vendor/assets/javascripts/material/ripple.js +244 -0
  28. data/vendor/assets/javascripts/material/slider.js +252 -0
  29. data/vendor/assets/javascripts/material/spinner.js +140 -0
  30. data/vendor/assets/javascripts/material/switch.js +269 -0
  31. data/vendor/assets/javascripts/material/tabs.js +152 -0
  32. data/vendor/assets/javascripts/material/textfield.js +247 -0
  33. data/vendor/assets/javascripts/material/tooltip.js +146 -0
  34. data/vendor/assets/stylesheets/_material.scss +50 -0
  35. data/vendor/assets/stylesheets/material/_animation.scss +34 -0
  36. data/vendor/assets/stylesheets/material/_badge.scss +66 -0
  37. data/vendor/assets/stylesheets/material/_button.scss +298 -0
  38. data/vendor/assets/stylesheets/material/_card.scss +111 -0
  39. data/vendor/assets/stylesheets/material/_checkbox.scss +175 -0
  40. data/vendor/assets/stylesheets/material/_color-definitions.scss +599 -0
  41. data/vendor/assets/stylesheets/material/_data-table.scss +105 -0
  42. data/vendor/assets/stylesheets/material/_functions.scss +3 -0
  43. data/vendor/assets/stylesheets/material/_grid.scss +180 -0
  44. data/vendor/assets/stylesheets/material/_icon-toggle.scss +121 -0
  45. data/vendor/assets/stylesheets/material/_layout.scss +580 -0
  46. data/vendor/assets/stylesheets/material/_mega_footer.scss +309 -0
  47. data/vendor/assets/stylesheets/material/_menu.scss +193 -0
  48. data/vendor/assets/stylesheets/material/_mini_footer.scss +88 -0
  49. data/vendor/assets/stylesheets/material/_mixins.scss +268 -0
  50. data/vendor/assets/stylesheets/material/_palette.scss +2303 -0
  51. data/vendor/assets/stylesheets/material/_progress.scss +115 -0
  52. data/vendor/assets/stylesheets/material/_radio.scss +155 -0
  53. data/vendor/assets/stylesheets/material/_resets.scss +55 -0
  54. data/vendor/assets/stylesheets/material/_ripple.scss +42 -0
  55. data/vendor/assets/stylesheets/material/_shadow.scss +42 -0
  56. data/vendor/assets/stylesheets/material/_slider.scss +396 -0
  57. data/vendor/assets/stylesheets/material/_spinner.scss +248 -0
  58. data/vendor/assets/stylesheets/material/_switch.scss +199 -0
  59. data/vendor/assets/stylesheets/material/_tabs.scss +115 -0
  60. data/vendor/assets/stylesheets/material/_textfield.scss +190 -0
  61. data/vendor/assets/stylesheets/material/_tooltip.scss +66 -0
  62. data/vendor/assets/stylesheets/material/_typography.scss +297 -0
  63. data/vendor/assets/stylesheets/material/_variables.scss +572 -0
  64. data/vendor/assets/stylesheets/material/resets/_h5bp.scss +284 -0
  65. data/vendor/assets/stylesheets/material/resets/_mobile.scss +25 -0
  66. metadata +151 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * Class constructor for Progress 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 MaterialProgress(element) {
25
+ 'use strict';
26
+
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
+ MaterialProgress.prototype.Constant_ = {
39
+ };
40
+
41
+ /**
42
+ * Store strings for class names defined by this component that are used in
43
+ * JavaScript. This allows us to simply change it in one place should we
44
+ * decide to modify at a later date.
45
+ * @enum {string}
46
+ * @private
47
+ */
48
+ MaterialProgress.prototype.CssClasses_ = {
49
+ INDETERMINATE_CLASS: 'mdl-progress__indeterminate'
50
+ };
51
+
52
+ MaterialProgress.prototype.setProgress = function(p) {
53
+ 'use strict';
54
+
55
+ if (this.element_.classList.contains(this.CssClasses_.INDETERMINATE_CLASS)) {
56
+ return;
57
+ }
58
+
59
+ this.progressbar_.style.width = p + '%';
60
+ };
61
+
62
+ MaterialProgress.prototype.setBuffer = function(p) {
63
+ 'use strict';
64
+
65
+ this.bufferbar_.style.width = p + '%';
66
+ this.auxbar_.style.width = (100 - p) + '%';
67
+ };
68
+
69
+ /**
70
+ * Initialize element.
71
+ */
72
+ MaterialProgress.prototype.init = function() {
73
+ 'use strict';
74
+
75
+ if (this.element_) {
76
+ var el = document.createElement('div');
77
+ el.className = 'progressbar bar bar1';
78
+ this.element_.appendChild(el);
79
+ this.progressbar_ = el;
80
+
81
+ el = document.createElement('div');
82
+ el.className = 'bufferbar bar bar2';
83
+ this.element_.appendChild(el);
84
+ this.bufferbar_ = el;
85
+
86
+ el = document.createElement('div');
87
+ el.className = 'auxbar bar bar3';
88
+ this.element_.appendChild(el);
89
+ this.auxbar_ = el;
90
+
91
+ this.progressbar_.style.width = '0%';
92
+ this.bufferbar_.style.width = '100%';
93
+ this.auxbar_.style.width = '0%';
94
+
95
+ this.element_.classList.add('is-upgraded');
96
+ }
97
+ };
98
+
99
+ /*
100
+ * Downgrade the component
101
+ */
102
+ MaterialProgress.prototype.mdlDowngrade_ = function() {
103
+ 'use strict';
104
+ while (this.element_.firstChild) {
105
+ this.element_.removeChild(this.element_.firstChild);
106
+ }
107
+ };
108
+
109
+ // The component registers itself. It can assume componentHandler is available
110
+ // in the global scope.
111
+ componentHandler.register({
112
+ constructor: MaterialProgress,
113
+ classAsString: 'MaterialProgress',
114
+ cssClass: 'mdl-js-progress',
115
+ widget: true
116
+ });
@@ -0,0 +1,38 @@
1
+ // Source: https://github.com/darius/requestAnimationFrame/blob/master/requestAnimationFrame.js
2
+ // Adapted from https://gist.github.com/paulirish/1579671 which derived from
3
+ // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
4
+ // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
5
+
6
+ // requestAnimationFrame polyfill by Erik Möller.
7
+ // Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon
8
+
9
+ // MIT license
10
+
11
+ (function() {
12
+ 'use strict';
13
+
14
+ if (!Date.now) {
15
+ Date.now = function() { return new Date().getTime(); };
16
+ }
17
+
18
+ var vendors = ['webkit', 'moz'];
19
+ for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
20
+ var vp = vendors[i];
21
+ window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
22
+ window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame'] ||
23
+ window[vp + 'CancelRequestAnimationFrame']);
24
+ }
25
+
26
+ if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
27
+ var lastTime = 0;
28
+ window.requestAnimationFrame = function(callback) {
29
+ var now = Date.now();
30
+ var nextTime = Math.max(lastTime + 16, now);
31
+ return setTimeout(function() { callback(lastTime = nextTime); },
32
+ nextTime - now);
33
+ };
34
+ window.cancelAnimationFrame = clearTimeout;
35
+ }
36
+
37
+ })();
38
+
@@ -0,0 +1,257 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * Class constructor for Radio 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 MaterialRadio(element) {
25
+ 'use strict';
26
+
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
+ MaterialRadio.prototype.Constant_ = {
39
+ TINY_TIMEOUT: 0.001
40
+ };
41
+
42
+ /**
43
+ * Store strings for class names defined by this component that are used in
44
+ * JavaScript. This allows us to simply change it in one place should we
45
+ * decide to modify at a later date.
46
+ * @enum {string}
47
+ * @private
48
+ */
49
+ MaterialRadio.prototype.CssClasses_ = {
50
+ IS_FOCUSED: 'is-focused',
51
+ IS_DISABLED: 'is-disabled',
52
+ IS_CHECKED: 'is-checked',
53
+ IS_UPGRADED: 'is-upgraded',
54
+ JS_RADIO: 'mdl-js-radio',
55
+ RADIO_BTN: 'mdl-radio__button',
56
+ RADIO_OUTER_CIRCLE: 'mdl-radio__outer-circle',
57
+ RADIO_INNER_CIRCLE: 'mdl-radio__inner-circle',
58
+ RIPPLE_EFFECT: 'mdl-js-ripple-effect',
59
+ RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
60
+ RIPPLE_CONTAINER: 'mdl-radio__ripple-container',
61
+ RIPPLE_CENTER: 'mdl-ripple--center',
62
+ RIPPLE: 'mdl-ripple'
63
+ };
64
+
65
+ /**
66
+ * Handle change of state.
67
+ * @param {Event} event The event that fired.
68
+ * @private
69
+ */
70
+ MaterialRadio.prototype.onChange_ = function(event) {
71
+ 'use strict';
72
+
73
+ this.updateClasses_(this.btnElement_, this.element_);
74
+
75
+ // Since other radio buttons don't get change events, we need to look for
76
+ // them to update their classes.
77
+ var radios = document.getElementsByClassName(this.CssClasses_.JS_RADIO);
78
+ for (var i = 0; i < radios.length; i++) {
79
+ var button = radios[i].querySelector('.' + this.CssClasses_.RADIO_BTN);
80
+ // Different name == different group, so no point updating those.
81
+ if (button.getAttribute('name') === this.btnElement_.getAttribute('name')) {
82
+ this.updateClasses_(button, radios[i]);
83
+ }
84
+ }
85
+ };
86
+
87
+ /**
88
+ * Handle focus.
89
+ * @param {Event} event The event that fired.
90
+ * @private
91
+ */
92
+ MaterialRadio.prototype.onFocus_ = function(event) {
93
+ 'use strict';
94
+
95
+ this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
96
+ };
97
+
98
+ /**
99
+ * Handle lost focus.
100
+ * @param {Event} event The event that fired.
101
+ * @private
102
+ */
103
+ MaterialRadio.prototype.onBlur_ = function(event) {
104
+ 'use strict';
105
+
106
+ this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
107
+ };
108
+
109
+ /**
110
+ * Handle mouseup.
111
+ * @param {Event} event The event that fired.
112
+ * @private
113
+ */
114
+ MaterialRadio.prototype.onMouseup_ = function(event) {
115
+ 'use strict';
116
+
117
+ this.blur_();
118
+ };
119
+
120
+ /**
121
+ * Update classes.
122
+ * @param {HTMLElement} button The button whose classes we should update.
123
+ * @param {HTMLElement} label The label whose classes we should update.
124
+ * @private
125
+ */
126
+ MaterialRadio.prototype.updateClasses_ = function(button, label) {
127
+ 'use strict';
128
+
129
+ if (button.disabled) {
130
+ label.classList.add(this.CssClasses_.IS_DISABLED);
131
+ } else {
132
+ label.classList.remove(this.CssClasses_.IS_DISABLED);
133
+ }
134
+
135
+ if (button.checked) {
136
+ label.classList.add(this.CssClasses_.IS_CHECKED);
137
+ } else {
138
+ label.classList.remove(this.CssClasses_.IS_CHECKED);
139
+ }
140
+ };
141
+
142
+ /**
143
+ * Add blur.
144
+ * @private
145
+ */
146
+ MaterialRadio.prototype.blur_ = function(event) {
147
+ 'use strict';
148
+
149
+ // TODO: figure out why there's a focus event being fired after our blur,
150
+ // so that we can avoid this hack.
151
+ window.setTimeout(function() {
152
+ this.btnElement_.blur();
153
+ }.bind(this), this.Constant_.TINY_TIMEOUT);
154
+ };
155
+
156
+ // Public methods.
157
+
158
+ /**
159
+ * Disable radio.
160
+ * @public
161
+ */
162
+ MaterialRadio.prototype.disable = function() {
163
+ 'use strict';
164
+
165
+ this.btnElement_.disabled = true;
166
+ this.updateClasses_(this.btnElement_, this.element_);
167
+ };
168
+
169
+ /**
170
+ * Enable radio.
171
+ * @public
172
+ */
173
+ MaterialRadio.prototype.enable = function() {
174
+ 'use strict';
175
+
176
+ this.btnElement_.disabled = false;
177
+ this.updateClasses_(this.btnElement_, this.element_);
178
+ };
179
+
180
+ /**
181
+ * Check radio.
182
+ * @public
183
+ */
184
+ MaterialRadio.prototype.check = function() {
185
+ 'use strict';
186
+
187
+ this.btnElement_.checked = true;
188
+ this.updateClasses_(this.btnElement_, this.element_);
189
+ };
190
+
191
+ /**
192
+ * Uncheck radio.
193
+ * @public
194
+ */
195
+ MaterialRadio.prototype.uncheck = function() {
196
+ 'use strict';
197
+
198
+ this.btnElement_.checked = false;
199
+ this.updateClasses_(this.btnElement_, this.element_);
200
+ };
201
+
202
+ /**
203
+ * Initialize element.
204
+ */
205
+ MaterialRadio.prototype.init = function() {
206
+ 'use strict';
207
+
208
+ if (this.element_) {
209
+ this.btnElement_ = this.element_.querySelector('.' +
210
+ this.CssClasses_.RADIO_BTN);
211
+
212
+ var outerCircle = document.createElement('span');
213
+ outerCircle.classList.add(this.CssClasses_.RADIO_OUTER_CIRCLE);
214
+
215
+ var innerCircle = document.createElement('span');
216
+ innerCircle.classList.add(this.CssClasses_.RADIO_INNER_CIRCLE);
217
+
218
+ this.element_.appendChild(outerCircle);
219
+ this.element_.appendChild(innerCircle);
220
+
221
+ var rippleContainer;
222
+ if (this.element_.classList.contains(
223
+ this.CssClasses_.RIPPLE_EFFECT)) {
224
+ this.element_.classList.add(
225
+ this.CssClasses_.RIPPLE_IGNORE_EVENTS);
226
+ rippleContainer = document.createElement('span');
227
+ rippleContainer.classList.add(
228
+ this.CssClasses_.RIPPLE_CONTAINER);
229
+ rippleContainer.classList.add(this.CssClasses_.RIPPLE_EFFECT);
230
+ rippleContainer.classList.add(this.CssClasses_.RIPPLE_CENTER);
231
+ rippleContainer.addEventListener('mouseup', this.onMouseup_.bind(this));
232
+
233
+ var ripple = document.createElement('span');
234
+ ripple.classList.add(this.CssClasses_.RIPPLE);
235
+
236
+ rippleContainer.appendChild(ripple);
237
+ this.element_.appendChild(rippleContainer);
238
+ }
239
+
240
+ this.btnElement_.addEventListener('change', this.onChange_.bind(this));
241
+ this.btnElement_.addEventListener('focus', this.onFocus_.bind(this));
242
+ this.btnElement_.addEventListener('blur', this.onBlur_.bind(this));
243
+ this.element_.addEventListener('mouseup', this.onMouseup_.bind(this));
244
+
245
+ this.updateClasses_(this.btnElement_, this.element_);
246
+ this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
247
+ }
248
+ };
249
+
250
+ // The component registers itself. It can assume componentHandler is available
251
+ // in the global scope.
252
+ componentHandler.register({
253
+ constructor: MaterialRadio,
254
+ classAsString: 'MaterialRadio',
255
+ cssClass: 'mdl-js-radio',
256
+ widget: true
257
+ });
@@ -0,0 +1,244 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
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) {
25
+ 'use strict';
26
+
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
+ };
60
+
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';
68
+
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);
99
+ } 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);
104
+ }
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';
130
+
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;
147
+
148
+ this.boundDownHandler = this.downHandler_.bind(this);
149
+ this.element_.addEventListener('mousedown',
150
+ this.boundDownHandler);
151
+ this.element_.addEventListener('touchstart',
152
+ this.boundDownHandler);
153
+
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)';
193
+ }
194
+ }
195
+
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);
204
+ } else {
205
+ this.rippleElement_.classList.add(this.CssClasses_.IS_ANIMATING);
206
+ }
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
+ };
217
+ }
218
+ }
219
+ };
220
+
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
+ });