@materializecss/materialize 1.2.0 → 1.2.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 (82) hide show
  1. package/Gruntfile.js +722 -712
  2. package/LICENSE +21 -21
  3. package/README.md +91 -91
  4. package/dist/css/materialize.css +68 -135
  5. package/dist/css/materialize.min.css +12 -12
  6. package/dist/js/materialize.js +1112 -1112
  7. package/dist/js/materialize.min.js +6 -6
  8. package/extras/noUiSlider/nouislider.css +403 -403
  9. package/extras/noUiSlider/nouislider.js +2147 -2147
  10. package/js/anime.min.js +34 -34
  11. package/js/autocomplete.js +479 -479
  12. package/js/buttons.js +354 -354
  13. package/js/cards.js +40 -40
  14. package/js/carousel.js +732 -732
  15. package/js/cash.js +960 -960
  16. package/js/characterCounter.js +136 -136
  17. package/js/chips.js +486 -486
  18. package/js/collapsible.js +275 -275
  19. package/js/component.js +44 -44
  20. package/js/datepicker.js +983 -983
  21. package/js/dropdown.js +669 -669
  22. package/js/forms.js +285 -285
  23. package/js/global.js +428 -428
  24. package/js/materialbox.js +453 -453
  25. package/js/modal.js +382 -382
  26. package/js/parallax.js +138 -138
  27. package/js/pushpin.js +148 -148
  28. package/js/range.js +263 -263
  29. package/js/scrollspy.js +295 -295
  30. package/js/select.js +391 -391
  31. package/js/sidenav.js +583 -583
  32. package/js/slider.js +359 -359
  33. package/js/tabs.js +402 -402
  34. package/js/tapTarget.js +315 -315
  35. package/js/timepicker.js +712 -712
  36. package/js/toasts.js +325 -325
  37. package/js/tooltip.js +320 -320
  38. package/js/waves.js +614 -614
  39. package/package.json +87 -84
  40. package/sass/_style.scss +929 -929
  41. package/sass/components/_badges.scss +55 -55
  42. package/sass/components/_buttons.scss +322 -322
  43. package/sass/components/_cards.scss +195 -195
  44. package/sass/components/_carousel.scss +90 -90
  45. package/sass/components/_chips.scss +96 -96
  46. package/sass/components/_collapsible.scss +91 -91
  47. package/sass/components/_collection.scss +106 -106
  48. package/sass/components/_color-classes.scss +32 -32
  49. package/sass/components/_color-variables.scss +370 -370
  50. package/sass/components/_datepicker.scss +191 -191
  51. package/sass/components/_dropdown.scss +84 -84
  52. package/sass/components/_global.scss +646 -646
  53. package/sass/components/_grid.scss +158 -158
  54. package/sass/components/_icons-material-design.scss +5 -5
  55. package/sass/components/_materialbox.scss +42 -42
  56. package/sass/components/_modal.scss +97 -97
  57. package/sass/components/_navbar.scss +208 -208
  58. package/sass/components/_normalize.scss +447 -447
  59. package/sass/components/_preloader.scss +334 -334
  60. package/sass/components/_pulse.scss +34 -34
  61. package/sass/components/_sidenav.scss +214 -214
  62. package/sass/components/_slider.scss +91 -91
  63. package/sass/components/_table_of_contents.scss +33 -33
  64. package/sass/components/_tabs.scss +99 -99
  65. package/sass/components/_tapTarget.scss +103 -103
  66. package/sass/components/_timepicker.scss +199 -199
  67. package/sass/components/_toast.scss +58 -58
  68. package/sass/components/_tooltip.scss +32 -32
  69. package/sass/components/_transitions.scss +12 -12
  70. package/sass/components/_typography.scss +62 -62
  71. package/sass/components/_variables.scss +352 -352
  72. package/sass/components/_waves.scss +187 -187
  73. package/sass/components/forms/_checkboxes.scss +200 -200
  74. package/sass/components/forms/_file-input.scss +44 -44
  75. package/sass/components/forms/_forms.scss +22 -22
  76. package/sass/components/forms/_input-fields.scss +388 -388
  77. package/sass/components/forms/_radio-buttons.scss +115 -115
  78. package/sass/components/forms/_range.scss +161 -161
  79. package/sass/components/forms/_select.scss +199 -199
  80. package/sass/components/forms/_switches.scss +91 -91
  81. package/sass/ghpages-materialize.scss +7 -7
  82. package/sass/materialize.scss +42 -42
package/js/waves.js CHANGED
@@ -1,615 +1,615 @@
1
- /*!
2
- * Waves v0.7.6
3
- * http://fian.my.id/Waves
4
- *
5
- * Copyright 2014-2018 Alfiana E. Sibuea and other contributors
6
- * Released under the MIT license
7
- * https://github.com/fians/Waves/blob/master/LICENSE
8
- */
9
-
10
- ;(function(window, factory) {
11
- 'use strict';
12
-
13
- // AMD. Register as an anonymous module. Wrap in function so we have access
14
- // to root via `this`.
15
- if (typeof define === 'function' && define.amd) {
16
- define([], function() {
17
- window.Waves = factory.call(window);
18
- document.addEventListener('DOMContentLoaded', function() {
19
- window.Waves.init();
20
- }, false);
21
- return window.Waves;
22
- });
23
- }
24
-
25
- // Node. Does not work with strict CommonJS, but only CommonJS-like
26
- // environments that support module.exports, like Node.
27
- else if (typeof exports === 'object') {
28
- module.exports = factory.call(window);
29
- }
30
-
31
- // Browser globals.
32
- else {
33
- window.Waves = factory.call(window);
34
- document.addEventListener('DOMContentLoaded', function() {
35
- window.Waves.init();
36
- }, false);
37
- }
38
- })(typeof global === 'object' ? global : this, function() {
39
- 'use strict';
40
-
41
- var Waves = Waves || {};
42
- var $$ = document.querySelectorAll.bind(document);
43
- var toString = Object.prototype.toString;
44
- var isTouchAvailable = 'ontouchstart' in window;
45
-
46
- /* Feature detection */
47
- var passiveIfSupported = false;
48
- try {
49
- window.addEventListener("test", null,
50
- Object.defineProperty({}, "passive", {
51
- get: function() { passiveIfSupported = { passive: false }; }
52
- }
53
- ));
54
- } catch(err) {}
55
-
56
- // Find exact position of element
57
- function isWindow(obj) {
58
- return obj !== null && obj === obj.window;
59
- }
60
-
61
- function getWindow(elem) {
62
- return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
63
- }
64
-
65
- function isObject(value) {
66
- var type = typeof value;
67
- return type === 'function' || type === 'object' && !!value;
68
- }
69
-
70
- function isDOMNode(obj) {
71
- return isObject(obj) && obj.nodeType > 0;
72
- }
73
-
74
- function getWavesElements(nodes) {
75
- var stringRepr = toString.call(nodes);
76
-
77
- if (stringRepr === '[object String]') {
78
- return $$(nodes);
79
- } else if (isObject(nodes) && /^\[object (Array|HTMLCollection|NodeList|Object)\]$/.test(stringRepr) && nodes.hasOwnProperty('length')) {
80
- return nodes;
81
- } else if (isDOMNode(nodes)) {
82
- return [nodes];
83
- }
84
-
85
- return [];
86
- }
87
-
88
- function offset(elem) {
89
- var docElem, win,
90
- box = { top: 0, left: 0 },
91
- doc = elem && elem.ownerDocument;
92
-
93
- docElem = doc.documentElement;
94
-
95
- if (typeof elem.getBoundingClientRect !== typeof undefined) {
96
- box = elem.getBoundingClientRect();
97
- }
98
- win = getWindow(doc);
99
- return {
100
- top: box.top + win.pageYOffset - docElem.clientTop,
101
- left: box.left + win.pageXOffset - docElem.clientLeft
102
- };
103
- }
104
-
105
- function convertStyle(styleObj) {
106
- var style = '';
107
-
108
- for (var prop in styleObj) {
109
- if (styleObj.hasOwnProperty(prop)) {
110
- style += (prop + ':' + styleObj[prop] + ';');
111
- }
112
- }
113
-
114
- return style;
115
- }
116
-
117
- var Effect = {
118
-
119
- // Effect duration
120
- duration: 750,
121
-
122
- // Effect delay (check for scroll before showing effect)
123
- delay: 200,
124
-
125
- show: function(e, element, velocity) {
126
-
127
- // Disable right click
128
- if (e.button === 2) {
129
- return false;
130
- }
131
-
132
- element = element || this;
133
-
134
- // Create ripple
135
- var ripple = document.createElement('div');
136
- ripple.className = 'waves-ripple waves-rippling';
137
- element.appendChild(ripple);
138
-
139
- // Get click coordinate and element width
140
- var pos = offset(element);
141
- var relativeY = 0;
142
- var relativeX = 0;
143
- // Support for touch devices
144
- if('touches' in e && e.touches.length) {
145
- relativeY = (e.touches[0].pageY - pos.top);
146
- relativeX = (e.touches[0].pageX - pos.left);
147
- }
148
- //Normal case
149
- else {
150
- relativeY = (e.pageY - pos.top);
151
- relativeX = (e.pageX - pos.left);
152
- }
153
- // Support for synthetic events
154
- relativeX = relativeX >= 0 ? relativeX : 0;
155
- relativeY = relativeY >= 0 ? relativeY : 0;
156
-
157
- var scale = 'scale(' + ((element.clientWidth / 100) * 3) + ')';
158
- var translate = 'translate(0,0)';
159
-
160
- if (velocity) {
161
- translate = 'translate(' + (velocity.x) + 'px, ' + (velocity.y) + 'px)';
162
- }
163
-
164
- // Attach data to element
165
- ripple.setAttribute('data-hold', Date.now());
166
- ripple.setAttribute('data-x', relativeX);
167
- ripple.setAttribute('data-y', relativeY);
168
- ripple.setAttribute('data-scale', scale);
169
- ripple.setAttribute('data-translate', translate);
170
-
171
- // Set ripple position
172
- var rippleStyle = {
173
- top: relativeY + 'px',
174
- left: relativeX + 'px'
175
- };
176
-
177
- ripple.classList.add('waves-notransition');
178
- ripple.setAttribute('style', convertStyle(rippleStyle));
179
- ripple.classList.remove('waves-notransition');
180
-
181
- // Scale the ripple
182
- rippleStyle['-webkit-transform'] = scale + ' ' + translate;
183
- rippleStyle['-moz-transform'] = scale + ' ' + translate;
184
- rippleStyle['-ms-transform'] = scale + ' ' + translate;
185
- rippleStyle['-o-transform'] = scale + ' ' + translate;
186
- rippleStyle.transform = scale + ' ' + translate;
187
- rippleStyle.opacity = '1';
188
-
189
- var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
190
- rippleStyle['-webkit-transition-duration'] = duration + 'ms';
191
- rippleStyle['-moz-transition-duration'] = duration + 'ms';
192
- rippleStyle['-o-transition-duration'] = duration + 'ms';
193
- rippleStyle['transition-duration'] = duration + 'ms';
194
-
195
- ripple.setAttribute('style', convertStyle(rippleStyle));
196
- },
197
-
198
- hide: function(e, element) {
199
- element = element || this;
200
-
201
- var ripples = element.getElementsByClassName('waves-rippling');
202
-
203
- for (var i = 0, len = ripples.length; i < len; i++) {
204
- removeRipple(e, element, ripples[i]);
205
- }
206
-
207
- if (isTouchAvailable) {
208
- element.removeEventListener('touchend', Effect.hide);
209
- element.removeEventListener('touchcancel', Effect.hide);
210
- }
211
-
212
- element.removeEventListener('mouseup', Effect.hide);
213
- element.removeEventListener('mouseleave', Effect.hide);
214
- }
215
- };
216
-
217
- /**
218
- * Collection of wrapper for HTML element that only have single tag
219
- * like <input> and <img>
220
- */
221
- var TagWrapper = {
222
-
223
- // Wrap <input> tag so it can perform the effect
224
- input: function(element) {
225
-
226
- var parent = element.parentNode;
227
-
228
- // If input already have parent just pass through
229
- if (parent.tagName.toLowerCase() === 'i' && parent.classList.contains('waves-effect')) {
230
- return;
231
- }
232
-
233
- // Put element class and style to the specified parent
234
- var wrapper = document.createElement('i');
235
- wrapper.className = element.className + ' waves-input-wrapper';
236
- element.className = 'waves-button-input';
237
-
238
- // Put element as child
239
- parent.replaceChild(wrapper, element);
240
- wrapper.appendChild(element);
241
-
242
- // Apply element color and background color to wrapper
243
- var elementStyle = window.getComputedStyle(element, null);
244
- var color = elementStyle.color;
245
- var backgroundColor = elementStyle.backgroundColor;
246
-
247
- wrapper.setAttribute('style', 'color:' + color + ';background:' + backgroundColor);
248
- element.setAttribute('style', 'background-color:rgba(0,0,0,0);');
249
-
250
- },
251
-
252
- // Wrap <img> tag so it can perform the effect
253
- img: function(element) {
254
-
255
- var parent = element.parentNode;
256
-
257
- // If input already have parent just pass through
258
- if (parent.tagName.toLowerCase() === 'i' && parent.classList.contains('waves-effect')) {
259
- return;
260
- }
261
-
262
- // Put element as child
263
- var wrapper = document.createElement('i');
264
- parent.replaceChild(wrapper, element);
265
- wrapper.appendChild(element);
266
-
267
- }
268
- };
269
-
270
- /**
271
- * Hide the effect and remove the ripple. Must be
272
- * a separate function to pass the JSLint...
273
- */
274
- function removeRipple(e, el, ripple) {
275
-
276
- // Check if the ripple still exist
277
- if (!ripple) {
278
- return;
279
- }
280
-
281
- ripple.classList.remove('waves-rippling');
282
-
283
- var relativeX = ripple.getAttribute('data-x');
284
- var relativeY = ripple.getAttribute('data-y');
285
- var scale = ripple.getAttribute('data-scale');
286
- var translate = ripple.getAttribute('data-translate');
287
-
288
- // Get delay beetween mousedown and mouse leave
289
- var diff = Date.now() - Number(ripple.getAttribute('data-hold'));
290
- var delay = 350 - diff;
291
-
292
- if (delay < 0) {
293
- delay = 0;
294
- }
295
-
296
- if (e.type === 'mousemove') {
297
- delay = 150;
298
- }
299
-
300
- // Fade out ripple after delay
301
- var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
302
-
303
- setTimeout(function() {
304
-
305
- var style = {
306
- top: relativeY + 'px',
307
- left: relativeX + 'px',
308
- opacity: '0',
309
-
310
- // Duration
311
- '-webkit-transition-duration': duration + 'ms',
312
- '-moz-transition-duration': duration + 'ms',
313
- '-o-transition-duration': duration + 'ms',
314
- 'transition-duration': duration + 'ms',
315
- '-webkit-transform': scale + ' ' + translate,
316
- '-moz-transform': scale + ' ' + translate,
317
- '-ms-transform': scale + ' ' + translate,
318
- '-o-transform': scale + ' ' + translate,
319
- 'transform': scale + ' ' + translate
320
- };
321
-
322
- ripple.setAttribute('style', convertStyle(style));
323
-
324
- setTimeout(function() {
325
- try {
326
- el.removeChild(ripple);
327
- } catch (e) {
328
- return false;
329
- }
330
- }, duration);
331
-
332
- }, delay);
333
- }
334
-
335
-
336
- /**
337
- * Disable mousedown event for 500ms during and after touch
338
- */
339
- var TouchHandler = {
340
-
341
- /* uses an integer rather than bool so there's no issues with
342
- * needing to clear timeouts if another touch event occurred
343
- * within the 500ms. Cannot mouseup between touchstart and
344
- * touchend, nor in the 500ms after touchend. */
345
- touches: 0,
346
-
347
- allowEvent: function(e) {
348
-
349
- var allow = true;
350
-
351
- if (/^(mousedown|mousemove)$/.test(e.type) && TouchHandler.touches) {
352
- allow = false;
353
- }
354
-
355
- return allow;
356
- },
357
- registerEvent: function(e) {
358
- var eType = e.type;
359
-
360
- if (eType === 'touchstart') {
361
-
362
- TouchHandler.touches += 1; // push
363
-
364
- } else if (/^(touchend|touchcancel)$/.test(eType)) {
365
-
366
- setTimeout(function() {
367
- if (TouchHandler.touches) {
368
- TouchHandler.touches -= 1; // pop after 500ms
369
- }
370
- }, 500);
371
-
372
- }
373
- }
374
- };
375
-
376
-
377
- /**
378
- * Delegated click handler for .waves-effect element.
379
- * returns null when .waves-effect element not in "click tree"
380
- */
381
- function getWavesEffectElement(e) {
382
-
383
- if (TouchHandler.allowEvent(e) === false) {
384
- return null;
385
- }
386
-
387
- var element = null;
388
- var target = e.target || e.srcElement;
389
-
390
- while (target.parentElement) {
391
- if ( (!(target instanceof SVGElement)) && target.classList.contains('waves-effect')) {
392
- element = target;
393
- break;
394
- }
395
- target = target.parentElement;
396
- }
397
-
398
- return element;
399
- }
400
-
401
- /**
402
- * Bubble the click and show effect if .waves-effect elem was found
403
- */
404
- function showEffect(e) {
405
-
406
- // Disable effect if element has "disabled" property on it
407
- // In some cases, the event is not triggered by the current element
408
- // if (e.target.getAttribute('disabled') !== null) {
409
- // return;
410
- // }
411
-
412
- var element = getWavesEffectElement(e);
413
-
414
- if (element !== null) {
415
-
416
- // Make it sure the element has either disabled property, disabled attribute or 'disabled' class
417
- if (element.disabled || element.getAttribute('disabled') || element.classList.contains('disabled')) {
418
- return;
419
- }
420
-
421
- TouchHandler.registerEvent(e);
422
-
423
- if (e.type === 'touchstart' && Effect.delay) {
424
-
425
- var hidden = false;
426
-
427
- var timer = setTimeout(function () {
428
- timer = null;
429
- Effect.show(e, element);
430
- }, Effect.delay);
431
-
432
- var hideEffect = function(hideEvent) {
433
-
434
- // if touch hasn't moved, and effect not yet started: start effect now
435
- if (timer) {
436
- clearTimeout(timer);
437
- timer = null;
438
- Effect.show(e, element);
439
- }
440
- if (!hidden) {
441
- hidden = true;
442
- Effect.hide(hideEvent, element);
443
- }
444
-
445
- removeListeners();
446
- };
447
-
448
- var touchMove = function(moveEvent) {
449
- if (timer) {
450
- clearTimeout(timer);
451
- timer = null;
452
- }
453
- hideEffect(moveEvent);
454
-
455
- removeListeners();
456
- };
457
-
458
- element.addEventListener('touchmove', touchMove, passiveIfSupported);
459
- element.addEventListener('touchend', hideEffect, passiveIfSupported);
460
- element.addEventListener('touchcancel', hideEffect, passiveIfSupported);
461
-
462
- var removeListeners = function() {
463
- element.removeEventListener('touchmove', touchMove);
464
- element.removeEventListener('touchend', hideEffect);
465
- element.removeEventListener('touchcancel', hideEffect);
466
- };
467
- } else {
468
-
469
- Effect.show(e, element);
470
-
471
- if (isTouchAvailable) {
472
- element.addEventListener('touchend', Effect.hide, passiveIfSupported);
473
- element.addEventListener('touchcancel', Effect.hide, passiveIfSupported);
474
- }
475
-
476
- element.addEventListener('mouseup', Effect.hide, passiveIfSupported);
477
- element.addEventListener('mouseleave', Effect.hide, passiveIfSupported);
478
- }
479
- }
480
- }
481
-
482
- Waves.init = function(options) {
483
- var body = document.body;
484
-
485
- options = options || {};
486
-
487
- if ('duration' in options) {
488
- Effect.duration = options.duration;
489
- }
490
-
491
- if ('delay' in options) {
492
- Effect.delay = options.delay;
493
- }
494
-
495
- if (isTouchAvailable) {
496
- body.addEventListener('touchstart', showEffect, passiveIfSupported);
497
- body.addEventListener('touchcancel', TouchHandler.registerEvent, passiveIfSupported);
498
- body.addEventListener('touchend', TouchHandler.registerEvent, passiveIfSupported);
499
- }
500
-
501
- body.addEventListener('mousedown', showEffect, passiveIfSupported);
502
- };
503
-
504
-
505
- /**
506
- * Attach Waves to dynamically loaded inputs, or add .waves-effect and other
507
- * waves classes to a set of elements. Set drag to true if the ripple mouseover
508
- * or skimming effect should be applied to the elements.
509
- */
510
- Waves.attach = function(elements, classes) {
511
-
512
- elements = getWavesElements(elements);
513
-
514
- if (toString.call(classes) === '[object Array]') {
515
- classes = classes.join(' ');
516
- }
517
-
518
- classes = classes ? ' ' + classes : '';
519
-
520
- var element, tagName;
521
-
522
- for (var i = 0, len = elements.length; i < len; i++) {
523
-
524
- element = elements[i];
525
- tagName = element.tagName.toLowerCase();
526
-
527
- if (['input', 'img'].indexOf(tagName) !== -1) {
528
- TagWrapper[tagName](element);
529
- element = element.parentElement;
530
- }
531
-
532
- if (element.className.indexOf('waves-effect') === -1) {
533
- element.className += ' waves-effect' + classes;
534
- }
535
- }
536
- };
537
-
538
-
539
- /**
540
- * Cause a ripple to appear in an element via code.
541
- */
542
- Waves.ripple = function(elements, options) {
543
- elements = getWavesElements(elements);
544
- var elementsLen = elements.length;
545
-
546
- options = options || {};
547
- options.wait = options.wait || 0;
548
- options.position = options.position || null; // default = centre of element
549
-
550
-
551
- if (elementsLen) {
552
- var element, pos, off, centre = {}, i = 0;
553
- var mousedown = {
554
- type: 'mousedown',
555
- button: 1
556
- };
557
- var hideRipple = function(mouseup, element) {
558
- return function() {
559
- Effect.hide(mouseup, element);
560
- };
561
- };
562
-
563
- for (; i < elementsLen; i++) {
564
- element = elements[i];
565
- pos = options.position || {
566
- x: element.clientWidth / 2,
567
- y: element.clientHeight / 2
568
- };
569
-
570
- off = offset(element);
571
- centre.x = off.left + pos.x;
572
- centre.y = off.top + pos.y;
573
-
574
- mousedown.pageX = centre.x;
575
- mousedown.pageY = centre.y;
576
-
577
- Effect.show(mousedown, element);
578
-
579
- if (options.wait >= 0 && options.wait !== null) {
580
- var mouseup = {
581
- type: 'mouseup',
582
- button: 1
583
- };
584
-
585
- setTimeout(hideRipple(mouseup, element), options.wait);
586
- }
587
- }
588
- }
589
- };
590
-
591
- /**
592
- * Remove all ripples from an element.
593
- */
594
- Waves.calm = function(elements) {
595
- elements = getWavesElements(elements);
596
- var mouseup = {
597
- type: 'mouseup',
598
- button: 1
599
- };
600
-
601
- for (var i = 0, len = elements.length; i < len; i++) {
602
- Effect.hide(mouseup, elements[i]);
603
- }
604
- };
605
-
606
- /**
607
- * Deprecated API fallback
608
- */
609
- Waves.displayEffect = function(options) {
610
- console.error('Waves.displayEffect() has been deprecated and will be removed in future version. Please use Waves.init() to initialize Waves effect');
611
- Waves.init(options);
612
- };
613
-
614
- return Waves;
1
+ /*!
2
+ * Waves v0.7.6
3
+ * http://fian.my.id/Waves
4
+ *
5
+ * Copyright 2014-2018 Alfiana E. Sibuea and other contributors
6
+ * Released under the MIT license
7
+ * https://github.com/fians/Waves/blob/master/LICENSE
8
+ */
9
+
10
+ ;(function(window, factory) {
11
+ 'use strict';
12
+
13
+ // AMD. Register as an anonymous module. Wrap in function so we have access
14
+ // to root via `this`.
15
+ if (typeof define === 'function' && define.amd) {
16
+ define([], function() {
17
+ window.Waves = factory.call(window);
18
+ document.addEventListener('DOMContentLoaded', function() {
19
+ window.Waves.init();
20
+ }, false);
21
+ return window.Waves;
22
+ });
23
+ }
24
+
25
+ // Node. Does not work with strict CommonJS, but only CommonJS-like
26
+ // environments that support module.exports, like Node.
27
+ else if (typeof exports === 'object') {
28
+ module.exports = factory.call(window);
29
+ }
30
+
31
+ // Browser globals.
32
+ else {
33
+ window.Waves = factory.call(window);
34
+ document.addEventListener('DOMContentLoaded', function() {
35
+ window.Waves.init();
36
+ }, false);
37
+ }
38
+ })(typeof global === 'object' ? global : this, function() {
39
+ 'use strict';
40
+
41
+ var Waves = Waves || {};
42
+ var $$ = document.querySelectorAll.bind(document);
43
+ var toString = Object.prototype.toString;
44
+ var isTouchAvailable = 'ontouchstart' in window;
45
+
46
+ /* Feature detection */
47
+ var passiveIfSupported = false;
48
+ try {
49
+ window.addEventListener("test", null,
50
+ Object.defineProperty({}, "passive", {
51
+ get: function() { passiveIfSupported = { passive: false }; }
52
+ }
53
+ ));
54
+ } catch(err) {}
55
+
56
+ // Find exact position of element
57
+ function isWindow(obj) {
58
+ return obj !== null && obj === obj.window;
59
+ }
60
+
61
+ function getWindow(elem) {
62
+ return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
63
+ }
64
+
65
+ function isObject(value) {
66
+ var type = typeof value;
67
+ return type === 'function' || type === 'object' && !!value;
68
+ }
69
+
70
+ function isDOMNode(obj) {
71
+ return isObject(obj) && obj.nodeType > 0;
72
+ }
73
+
74
+ function getWavesElements(nodes) {
75
+ var stringRepr = toString.call(nodes);
76
+
77
+ if (stringRepr === '[object String]') {
78
+ return $$(nodes);
79
+ } else if (isObject(nodes) && /^\[object (Array|HTMLCollection|NodeList|Object)\]$/.test(stringRepr) && nodes.hasOwnProperty('length')) {
80
+ return nodes;
81
+ } else if (isDOMNode(nodes)) {
82
+ return [nodes];
83
+ }
84
+
85
+ return [];
86
+ }
87
+
88
+ function offset(elem) {
89
+ var docElem, win,
90
+ box = { top: 0, left: 0 },
91
+ doc = elem && elem.ownerDocument;
92
+
93
+ docElem = doc.documentElement;
94
+
95
+ if (typeof elem.getBoundingClientRect !== typeof undefined) {
96
+ box = elem.getBoundingClientRect();
97
+ }
98
+ win = getWindow(doc);
99
+ return {
100
+ top: box.top + win.pageYOffset - docElem.clientTop,
101
+ left: box.left + win.pageXOffset - docElem.clientLeft
102
+ };
103
+ }
104
+
105
+ function convertStyle(styleObj) {
106
+ var style = '';
107
+
108
+ for (var prop in styleObj) {
109
+ if (styleObj.hasOwnProperty(prop)) {
110
+ style += (prop + ':' + styleObj[prop] + ';');
111
+ }
112
+ }
113
+
114
+ return style;
115
+ }
116
+
117
+ var Effect = {
118
+
119
+ // Effect duration
120
+ duration: 750,
121
+
122
+ // Effect delay (check for scroll before showing effect)
123
+ delay: 200,
124
+
125
+ show: function(e, element, velocity) {
126
+
127
+ // Disable right click
128
+ if (e.button === 2) {
129
+ return false;
130
+ }
131
+
132
+ element = element || this;
133
+
134
+ // Create ripple
135
+ var ripple = document.createElement('div');
136
+ ripple.className = 'waves-ripple waves-rippling';
137
+ element.appendChild(ripple);
138
+
139
+ // Get click coordinate and element width
140
+ var pos = offset(element);
141
+ var relativeY = 0;
142
+ var relativeX = 0;
143
+ // Support for touch devices
144
+ if('touches' in e && e.touches.length) {
145
+ relativeY = (e.touches[0].pageY - pos.top);
146
+ relativeX = (e.touches[0].pageX - pos.left);
147
+ }
148
+ //Normal case
149
+ else {
150
+ relativeY = (e.pageY - pos.top);
151
+ relativeX = (e.pageX - pos.left);
152
+ }
153
+ // Support for synthetic events
154
+ relativeX = relativeX >= 0 ? relativeX : 0;
155
+ relativeY = relativeY >= 0 ? relativeY : 0;
156
+
157
+ var scale = 'scale(' + ((element.clientWidth / 100) * 3) + ')';
158
+ var translate = 'translate(0,0)';
159
+
160
+ if (velocity) {
161
+ translate = 'translate(' + (velocity.x) + 'px, ' + (velocity.y) + 'px)';
162
+ }
163
+
164
+ // Attach data to element
165
+ ripple.setAttribute('data-hold', Date.now());
166
+ ripple.setAttribute('data-x', relativeX);
167
+ ripple.setAttribute('data-y', relativeY);
168
+ ripple.setAttribute('data-scale', scale);
169
+ ripple.setAttribute('data-translate', translate);
170
+
171
+ // Set ripple position
172
+ var rippleStyle = {
173
+ top: relativeY + 'px',
174
+ left: relativeX + 'px'
175
+ };
176
+
177
+ ripple.classList.add('waves-notransition');
178
+ ripple.setAttribute('style', convertStyle(rippleStyle));
179
+ ripple.classList.remove('waves-notransition');
180
+
181
+ // Scale the ripple
182
+ rippleStyle['-webkit-transform'] = scale + ' ' + translate;
183
+ rippleStyle['-moz-transform'] = scale + ' ' + translate;
184
+ rippleStyle['-ms-transform'] = scale + ' ' + translate;
185
+ rippleStyle['-o-transform'] = scale + ' ' + translate;
186
+ rippleStyle.transform = scale + ' ' + translate;
187
+ rippleStyle.opacity = '1';
188
+
189
+ var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
190
+ rippleStyle['-webkit-transition-duration'] = duration + 'ms';
191
+ rippleStyle['-moz-transition-duration'] = duration + 'ms';
192
+ rippleStyle['-o-transition-duration'] = duration + 'ms';
193
+ rippleStyle['transition-duration'] = duration + 'ms';
194
+
195
+ ripple.setAttribute('style', convertStyle(rippleStyle));
196
+ },
197
+
198
+ hide: function(e, element) {
199
+ element = element || this;
200
+
201
+ var ripples = element.getElementsByClassName('waves-rippling');
202
+
203
+ for (var i = 0, len = ripples.length; i < len; i++) {
204
+ removeRipple(e, element, ripples[i]);
205
+ }
206
+
207
+ if (isTouchAvailable) {
208
+ element.removeEventListener('touchend', Effect.hide);
209
+ element.removeEventListener('touchcancel', Effect.hide);
210
+ }
211
+
212
+ element.removeEventListener('mouseup', Effect.hide);
213
+ element.removeEventListener('mouseleave', Effect.hide);
214
+ }
215
+ };
216
+
217
+ /**
218
+ * Collection of wrapper for HTML element that only have single tag
219
+ * like <input> and <img>
220
+ */
221
+ var TagWrapper = {
222
+
223
+ // Wrap <input> tag so it can perform the effect
224
+ input: function(element) {
225
+
226
+ var parent = element.parentNode;
227
+
228
+ // If input already have parent just pass through
229
+ if (parent.tagName.toLowerCase() === 'i' && parent.classList.contains('waves-effect')) {
230
+ return;
231
+ }
232
+
233
+ // Put element class and style to the specified parent
234
+ var wrapper = document.createElement('i');
235
+ wrapper.className = element.className + ' waves-input-wrapper';
236
+ element.className = 'waves-button-input';
237
+
238
+ // Put element as child
239
+ parent.replaceChild(wrapper, element);
240
+ wrapper.appendChild(element);
241
+
242
+ // Apply element color and background color to wrapper
243
+ var elementStyle = window.getComputedStyle(element, null);
244
+ var color = elementStyle.color;
245
+ var backgroundColor = elementStyle.backgroundColor;
246
+
247
+ wrapper.setAttribute('style', 'color:' + color + ';background:' + backgroundColor);
248
+ element.setAttribute('style', 'background-color:rgba(0,0,0,0);');
249
+
250
+ },
251
+
252
+ // Wrap <img> tag so it can perform the effect
253
+ img: function(element) {
254
+
255
+ var parent = element.parentNode;
256
+
257
+ // If input already have parent just pass through
258
+ if (parent.tagName.toLowerCase() === 'i' && parent.classList.contains('waves-effect')) {
259
+ return;
260
+ }
261
+
262
+ // Put element as child
263
+ var wrapper = document.createElement('i');
264
+ parent.replaceChild(wrapper, element);
265
+ wrapper.appendChild(element);
266
+
267
+ }
268
+ };
269
+
270
+ /**
271
+ * Hide the effect and remove the ripple. Must be
272
+ * a separate function to pass the JSLint...
273
+ */
274
+ function removeRipple(e, el, ripple) {
275
+
276
+ // Check if the ripple still exist
277
+ if (!ripple) {
278
+ return;
279
+ }
280
+
281
+ ripple.classList.remove('waves-rippling');
282
+
283
+ var relativeX = ripple.getAttribute('data-x');
284
+ var relativeY = ripple.getAttribute('data-y');
285
+ var scale = ripple.getAttribute('data-scale');
286
+ var translate = ripple.getAttribute('data-translate');
287
+
288
+ // Get delay beetween mousedown and mouse leave
289
+ var diff = Date.now() - Number(ripple.getAttribute('data-hold'));
290
+ var delay = 350 - diff;
291
+
292
+ if (delay < 0) {
293
+ delay = 0;
294
+ }
295
+
296
+ if (e.type === 'mousemove') {
297
+ delay = 150;
298
+ }
299
+
300
+ // Fade out ripple after delay
301
+ var duration = e.type === 'mousemove' ? 2500 : Effect.duration;
302
+
303
+ setTimeout(function() {
304
+
305
+ var style = {
306
+ top: relativeY + 'px',
307
+ left: relativeX + 'px',
308
+ opacity: '0',
309
+
310
+ // Duration
311
+ '-webkit-transition-duration': duration + 'ms',
312
+ '-moz-transition-duration': duration + 'ms',
313
+ '-o-transition-duration': duration + 'ms',
314
+ 'transition-duration': duration + 'ms',
315
+ '-webkit-transform': scale + ' ' + translate,
316
+ '-moz-transform': scale + ' ' + translate,
317
+ '-ms-transform': scale + ' ' + translate,
318
+ '-o-transform': scale + ' ' + translate,
319
+ 'transform': scale + ' ' + translate
320
+ };
321
+
322
+ ripple.setAttribute('style', convertStyle(style));
323
+
324
+ setTimeout(function() {
325
+ try {
326
+ el.removeChild(ripple);
327
+ } catch (e) {
328
+ return false;
329
+ }
330
+ }, duration);
331
+
332
+ }, delay);
333
+ }
334
+
335
+
336
+ /**
337
+ * Disable mousedown event for 500ms during and after touch
338
+ */
339
+ var TouchHandler = {
340
+
341
+ /* uses an integer rather than bool so there's no issues with
342
+ * needing to clear timeouts if another touch event occurred
343
+ * within the 500ms. Cannot mouseup between touchstart and
344
+ * touchend, nor in the 500ms after touchend. */
345
+ touches: 0,
346
+
347
+ allowEvent: function(e) {
348
+
349
+ var allow = true;
350
+
351
+ if (/^(mousedown|mousemove)$/.test(e.type) && TouchHandler.touches) {
352
+ allow = false;
353
+ }
354
+
355
+ return allow;
356
+ },
357
+ registerEvent: function(e) {
358
+ var eType = e.type;
359
+
360
+ if (eType === 'touchstart') {
361
+
362
+ TouchHandler.touches += 1; // push
363
+
364
+ } else if (/^(touchend|touchcancel)$/.test(eType)) {
365
+
366
+ setTimeout(function() {
367
+ if (TouchHandler.touches) {
368
+ TouchHandler.touches -= 1; // pop after 500ms
369
+ }
370
+ }, 500);
371
+
372
+ }
373
+ }
374
+ };
375
+
376
+
377
+ /**
378
+ * Delegated click handler for .waves-effect element.
379
+ * returns null when .waves-effect element not in "click tree"
380
+ */
381
+ function getWavesEffectElement(e) {
382
+
383
+ if (TouchHandler.allowEvent(e) === false) {
384
+ return null;
385
+ }
386
+
387
+ var element = null;
388
+ var target = e.target || e.srcElement;
389
+
390
+ while (target.parentElement) {
391
+ if ( (!(target instanceof SVGElement)) && target.classList.contains('waves-effect')) {
392
+ element = target;
393
+ break;
394
+ }
395
+ target = target.parentElement;
396
+ }
397
+
398
+ return element;
399
+ }
400
+
401
+ /**
402
+ * Bubble the click and show effect if .waves-effect elem was found
403
+ */
404
+ function showEffect(e) {
405
+
406
+ // Disable effect if element has "disabled" property on it
407
+ // In some cases, the event is not triggered by the current element
408
+ // if (e.target.getAttribute('disabled') !== null) {
409
+ // return;
410
+ // }
411
+
412
+ var element = getWavesEffectElement(e);
413
+
414
+ if (element !== null) {
415
+
416
+ // Make it sure the element has either disabled property, disabled attribute or 'disabled' class
417
+ if (element.disabled || element.getAttribute('disabled') || element.classList.contains('disabled')) {
418
+ return;
419
+ }
420
+
421
+ TouchHandler.registerEvent(e);
422
+
423
+ if (e.type === 'touchstart' && Effect.delay) {
424
+
425
+ var hidden = false;
426
+
427
+ var timer = setTimeout(function () {
428
+ timer = null;
429
+ Effect.show(e, element);
430
+ }, Effect.delay);
431
+
432
+ var hideEffect = function(hideEvent) {
433
+
434
+ // if touch hasn't moved, and effect not yet started: start effect now
435
+ if (timer) {
436
+ clearTimeout(timer);
437
+ timer = null;
438
+ Effect.show(e, element);
439
+ }
440
+ if (!hidden) {
441
+ hidden = true;
442
+ Effect.hide(hideEvent, element);
443
+ }
444
+
445
+ removeListeners();
446
+ };
447
+
448
+ var touchMove = function(moveEvent) {
449
+ if (timer) {
450
+ clearTimeout(timer);
451
+ timer = null;
452
+ }
453
+ hideEffect(moveEvent);
454
+
455
+ removeListeners();
456
+ };
457
+
458
+ element.addEventListener('touchmove', touchMove, passiveIfSupported);
459
+ element.addEventListener('touchend', hideEffect, passiveIfSupported);
460
+ element.addEventListener('touchcancel', hideEffect, passiveIfSupported);
461
+
462
+ var removeListeners = function() {
463
+ element.removeEventListener('touchmove', touchMove);
464
+ element.removeEventListener('touchend', hideEffect);
465
+ element.removeEventListener('touchcancel', hideEffect);
466
+ };
467
+ } else {
468
+
469
+ Effect.show(e, element);
470
+
471
+ if (isTouchAvailable) {
472
+ element.addEventListener('touchend', Effect.hide, passiveIfSupported);
473
+ element.addEventListener('touchcancel', Effect.hide, passiveIfSupported);
474
+ }
475
+
476
+ element.addEventListener('mouseup', Effect.hide, passiveIfSupported);
477
+ element.addEventListener('mouseleave', Effect.hide, passiveIfSupported);
478
+ }
479
+ }
480
+ }
481
+
482
+ Waves.init = function(options) {
483
+ var body = document.body;
484
+
485
+ options = options || {};
486
+
487
+ if ('duration' in options) {
488
+ Effect.duration = options.duration;
489
+ }
490
+
491
+ if ('delay' in options) {
492
+ Effect.delay = options.delay;
493
+ }
494
+
495
+ if (isTouchAvailable) {
496
+ body.addEventListener('touchstart', showEffect, passiveIfSupported);
497
+ body.addEventListener('touchcancel', TouchHandler.registerEvent, passiveIfSupported);
498
+ body.addEventListener('touchend', TouchHandler.registerEvent, passiveIfSupported);
499
+ }
500
+
501
+ body.addEventListener('mousedown', showEffect, passiveIfSupported);
502
+ };
503
+
504
+
505
+ /**
506
+ * Attach Waves to dynamically loaded inputs, or add .waves-effect and other
507
+ * waves classes to a set of elements. Set drag to true if the ripple mouseover
508
+ * or skimming effect should be applied to the elements.
509
+ */
510
+ Waves.attach = function(elements, classes) {
511
+
512
+ elements = getWavesElements(elements);
513
+
514
+ if (toString.call(classes) === '[object Array]') {
515
+ classes = classes.join(' ');
516
+ }
517
+
518
+ classes = classes ? ' ' + classes : '';
519
+
520
+ var element, tagName;
521
+
522
+ for (var i = 0, len = elements.length; i < len; i++) {
523
+
524
+ element = elements[i];
525
+ tagName = element.tagName.toLowerCase();
526
+
527
+ if (['input', 'img'].indexOf(tagName) !== -1) {
528
+ TagWrapper[tagName](element);
529
+ element = element.parentElement;
530
+ }
531
+
532
+ if (element.className.indexOf('waves-effect') === -1) {
533
+ element.className += ' waves-effect' + classes;
534
+ }
535
+ }
536
+ };
537
+
538
+
539
+ /**
540
+ * Cause a ripple to appear in an element via code.
541
+ */
542
+ Waves.ripple = function(elements, options) {
543
+ elements = getWavesElements(elements);
544
+ var elementsLen = elements.length;
545
+
546
+ options = options || {};
547
+ options.wait = options.wait || 0;
548
+ options.position = options.position || null; // default = centre of element
549
+
550
+
551
+ if (elementsLen) {
552
+ var element, pos, off, centre = {}, i = 0;
553
+ var mousedown = {
554
+ type: 'mousedown',
555
+ button: 1
556
+ };
557
+ var hideRipple = function(mouseup, element) {
558
+ return function() {
559
+ Effect.hide(mouseup, element);
560
+ };
561
+ };
562
+
563
+ for (; i < elementsLen; i++) {
564
+ element = elements[i];
565
+ pos = options.position || {
566
+ x: element.clientWidth / 2,
567
+ y: element.clientHeight / 2
568
+ };
569
+
570
+ off = offset(element);
571
+ centre.x = off.left + pos.x;
572
+ centre.y = off.top + pos.y;
573
+
574
+ mousedown.pageX = centre.x;
575
+ mousedown.pageY = centre.y;
576
+
577
+ Effect.show(mousedown, element);
578
+
579
+ if (options.wait >= 0 && options.wait !== null) {
580
+ var mouseup = {
581
+ type: 'mouseup',
582
+ button: 1
583
+ };
584
+
585
+ setTimeout(hideRipple(mouseup, element), options.wait);
586
+ }
587
+ }
588
+ }
589
+ };
590
+
591
+ /**
592
+ * Remove all ripples from an element.
593
+ */
594
+ Waves.calm = function(elements) {
595
+ elements = getWavesElements(elements);
596
+ var mouseup = {
597
+ type: 'mouseup',
598
+ button: 1
599
+ };
600
+
601
+ for (var i = 0, len = elements.length; i < len; i++) {
602
+ Effect.hide(mouseup, elements[i]);
603
+ }
604
+ };
605
+
606
+ /**
607
+ * Deprecated API fallback
608
+ */
609
+ Waves.displayEffect = function(options) {
610
+ console.error('Waves.displayEffect() has been deprecated and will be removed in future version. Please use Waves.init() to initialize Waves effect');
611
+ Waves.init(options);
612
+ };
613
+
614
+ return Waves;
615
615
  });