1class AbtCounter extends HTMLElement { 2 duration = 1500; 3 4 startValue = 0; 5 startTimestamp = null; 6 options = { 7 root: null, 8 rootMargin: "0px", 9 threshold: 1.0, 10 }; 11 12 constructor() { 13 super(); 14 15 const observer = new IntersectionObserver(this.isIntersecting.bind(this), this.options); 16 17 observer.observe(this); 18 } 19 20 isIntersecting(entries, observer) { 21 entries.forEach((entry) => { 22 if (entry.isIntersecting) { 23 let element = entry.target; 24 25 if (element.classList.contains('intersecting') || !element.dataset.target) return; 26 27 const match = element.dataset.target.match(/(.*)\s(.*)/); 28 29 if (!match) return; 30 31 element.dataset.target = match[1]; 32 element.classList.add('intersecting'); 33 34 this.createElements(match); 35 36 window.requestAnimationFrame(this.playAnimation.bind(this)); 37 38 observer.unobserve(this); 39 } 40 }); 41 } 42 43 createElements(match) { 44 this.innerHTML = ''; 45 46 const number = document.createElement('span'); 47 48 number.classList.add('number'); 49 number.innerHTML = this.startValue; 50 51 this.appendChild(number); 52 this.numberElement = number; 53 54 const unit = document.createElement('span'); 55 56 unit.classList.add('unit'); 57 unit.innerHTML = match[2]; 58 59 this.appendChild(unit); 60 } 61 62 playAnimation(timestamp) { 63 if (!this.startTimestamp) this.startTimestamp = timestamp; 64 65 const progress = Math.min((timestamp - this.startTimestamp) / this.duration, 1); 66 let target, text; 67 68 if (this.dataset.target && this.dataset.target.indexOf(',') !== -1) { 69 target = parseFloat(this.dataset.target.replace(',', '.')); 70 text = (progress * (target - this.startValue) + this.startValue).toFixed(1); 71 72 this.numberElement.innerHTML = document.documentElement.lang.startsWith('de') 73 ? text.replace('.', ',') 74 : text; 75 } else { 76 target = parseInt(this.dataset.target); 77 text = Math.floor(progress * (target - this.startValue) + this.startValue); 78 79 this.numberElement.innerHTML = text; 80 } 81 82 if (progress < target) { 83 window.requestAnimationFrame(this.playAnimation.bind(this)); 84 } else { 85 this.numberElement.innerHTML = target; 86 window.cancelAnimationFrame(this.playAnimation.bind(this)); 87 } 88 } 89 90 91} 92 93customElements.define('abt-counter', AbtCounter);
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.