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.