1/* 2Code of jquery.ripple.js rewritten on vanilla JS with AI. 3https://github.com/sus-happy/jquery.ripple.js 4 5CSS: 6 7.ripple-wrapper { 8 display: block; 9 position: absolute; 10 z-index: 1; 11 left: 0; 12 top: 0; 13 overflow: hidden; 14 pointer-events: none; 15} 16 17.ripple-effect { 18 display: block; 19 position: absolute; 20 left: 0; 21 top: 0; 22 width: 0; 23 height: 0; 24 border-radius: 50%; 25 background-color: rgba(255, 255, 255, 0.3); 26} 27 28Effect color can be provided by 'data-color' attribute. 29 30Usage: 31document.querySelectorAll('.btn').forEach(element => new Ripple(element)); 32*/ 33 34class Ripple { 35 constructor(target, options = {}) { 36 this.target = target; 37 this.vDuration = options.vDuration || 400; 38 this.hDuration = options.hDuration || 400; 39 this.timer = null; 40 41 this.init(); 42 } 43 44 wrapInner(element, wrapper) { 45 const content = element.innerHTML; 46 element.innerHTML = ''; 47 wrapper.innerHTML = content; 48 element.appendChild(wrapper); 49 } 50 51 init() { 52 if (getComputedStyle(this.target).position === 'static') { 53 this.target.style.position = 'relative'; 54 } 55 this.target.classList.add('ripple-initialized'); 56 57 const innerWrapper = document.createElement('span'); 58 innerWrapper.classList.add('ripple-inner'); 59 this.wrapInner(this.target, innerWrapper); 60 61 const rippleWrapper = document.createElement('span'); 62 rippleWrapper.classList.add('ripple-wrapper'); 63 64 const rippleEffect = document.createElement('span'); 65 rippleEffect.classList.add('ripple-effect'); 66 67 rippleWrapper.appendChild(rippleEffect); 68 this.target.appendChild(rippleWrapper); 69 70 this.rippleWrapper = rippleWrapper; 71 this.rippleEffect = rippleEffect; 72 73 this.rippleWrapper.style.borderTopLeftRadius = getComputedStyle(this.target).borderTopLeftRadius; 74 this.rippleWrapper.style.borderTopRightRadius = getComputedStyle(this.target).borderTopRightRadius; 75 this.rippleWrapper.style.borderBottomLeftRadius = getComputedStyle(this.target).borderBottomLeftRadius; 76 this.rippleWrapper.style.borderBottomRightRadius = getComputedStyle(this.target).borderBottomRightRadius; 77 78 const top = parseFloat(getComputedStyle(this.target).borderTopWidth) || 0; 79 const left = parseFloat(getComputedStyle(this.target).borderLeftWidth) || 0; 80 this.rippleWrapper.style.top = -top + 'px'; 81 this.rippleWrapper.style.left = -left + 'px'; 82 83 this.rippleEffect.style.backgroundColor = this.target.getAttribute('data-color'); 84 85 this.target.addEventListener('mousedown', this.view.bind(this)); 86 this.target.addEventListener('mouseup', this.hidden.bind(this)); 87 this.target.addEventListener('mouseleave', this.hidden.bind(this)); 88 } 89 90 view(e) { 91 if (this.timer) { 92 clearTimeout(this.timer); 93 } 94 95 const width = this.target.offsetWidth; 96 const height = this.target.offsetHeight; 97 this.rippleWrapper.style.width = width + 'px'; 98 this.rippleWrapper.style.height = height + 'px'; 99 this.rippleWrapper.style.opacity = '1'; 100 this.rippleWrapper.style.transition = 'none'; 101 102 const circleRatio = 2.8; 103 const size = Math.max(width, height); 104 const rect = this.target.getBoundingClientRect(); 105 const offsetX = e.clientX - rect.left; 106 const offsetY = e.clientY - rect.top; 107 this.rippleEffect.style.width = size + 'px'; 108 this.rippleEffect.style.height = size + 'px'; 109 this.rippleEffect.style.transform = 'scale3d(0, 0, 1)'; 110 this.rippleEffect.style.left = offsetX - size / 2 + 'px'; 111 this.rippleEffect.style.top = offsetY - size / 2 + 'px'; 112 this.rippleEffect.style.transition = 'none'; 113 114 setTimeout(() => { 115 this.rippleEffect.style.transition = `transform ${this.vDuration / 1000}s ease-out`; 116 this.rippleEffect.style.transform = `scale3d(${circleRatio}, ${circleRatio}, 1)`; 117 }, 1); 118 } 119 120 hidden() { 121 this.rippleWrapper.style.opacity = '0'; 122 this.rippleWrapper.style.transition = `opacity ${this.hDuration / 1000}s ease-out`; 123 124 this.timer = setTimeout(() => { 125 this.rippleWrapper.style.opacity = '1'; 126 this.rippleWrapper.style.transition = 'none'; 127 this.rippleEffect.style.transform = 'scale3d(0, 0, 1)';
128 this.rippleEffect.style.transition = 'none'; 129 }, this.vDuration); 130 } 131}
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.