PageSourceSearch

https://zippykind.com/assets/v2/node-waves/waves.js?ver=1.0

js zippykind.com collected 2026-10-01 23:53:34 UTC 18,135 bytes, 582 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.