PageSourceSearch

https://rootscs.org/themes/contrib/material_base/js/mb-ripple.js?tjzkg5

js rootscs.org collected 2026-10-04 05:21:27 UTC 4,210 bytes, 131 lines download raw bytes

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.