UNPKG

dxb-count-to

Version:

A vanilla JavaScript counter animation plugin with IntersectionObserver integration

1 lines 4.22 kB
!function(t){"use strict";class e{static DEFAULTS={from:0,to:0,speed:1e3,refreshInterval:100,decimals:0,formatter:null,seperator:"",onUpdate:null,onComplete:null,prefix:"",postfix:""};constructor(t,i={}){if(!(t instanceof HTMLElement))throw new Error("DXBCountTo requires an HTMLElement");this.element=t,this.element.hasAttribute("data-dxb-countto-initialized")||(this.element.setAttribute("data-dxb-countto-initialized","true"),this.options={...e.DEFAULTS,...this._dataOptions(),...i},this.observer=null,this.interval=null,this.isRunning=!1,this.options.formatter||(this.options.formatter=this._defaultFormatter.bind(this)),this._init(),this._setupObserver())}_init(){this.value=this.options.from,this.loops=Math.ceil(this.options.speed/this.options.refreshInterval),this.loopCount=0,this.increment=(this.options.to-this.options.from)/this.loops}_dataOptions(){const t={from:this._getDataAttribute("from","number"),to:this._getDataAttribute("to","number"),speed:this._getDataAttribute("speed","number"),refreshInterval:this._getDataAttribute("refresh-interval","number"),decimals:this._getDataAttribute("decimals","number"),seperator:this._getDataAttribute("seperator","string"),prefix:this._getDataAttribute("prefix","string"),postfix:this._getDataAttribute("postfix","string")};return Object.keys(t).forEach((e=>{void 0===t[e]&&delete t[e]})),t}_getDataAttribute(t,e){const i=this.element.dataset[t];if(void 0!==i)return"number"===e?parseFloat(i):i}_defaultFormatter(t){let e=t.toFixed(this.options.decimals);return this.options.seperator&&(e=e.replace(/\B(?=(\d{3})+(?!\d))/g,this.options.seperator)),this.options.prefix+e+this.options.postfix}_update(){this.value+=this.increment,this.loopCount++,this._render(),"function"==typeof this.options.onUpdate&&this.options.onUpdate.call(this.element,this.value),this.loopCount>=this.loops&&(clearInterval(this.interval),this.isRunning=!1,this.value=this.options.to,this._render(),"function"==typeof this.options.onComplete&&this.options.onComplete.call(this.element,this.value))}_render(){const t=this.options.formatter.call(this,this.value,this.options);this.element.textContent=t}_setupObserver(){this.observer=new IntersectionObserver((t=>{t.forEach((t=>{t.isIntersecting&&!this.isRunning&&this.start()}))}),{root:null,threshold:.1}),this.observer.observe(this.element),this._isElementInViewport(this.element)&&!this.isRunning&&this.start()}_isElementInViewport(t){const e=t.getBoundingClientRect();return e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.bottom>=0}restart(){this.stop(),this._init(),this.start()}start(){this.isRunning||(this.stop(),this._render(),this.isRunning=!0,this.interval=setInterval((()=>this._update()),this.options.refreshInterval))}stop(){this.interval&&(clearInterval(this.interval),this.isRunning=!1)}toggle(){this.isRunning?this.stop():this.start()}destroy(){this.stop(),this.observer&&(this.observer.disconnect(),this.observer=null),this.element.removeAttribute("data-dxb-countto-initialized")}static initAll(){const t=document.querySelectorAll(".az-counter .az-counter-inner:not([data-dxb-countto-initialized])"),i=document.querySelectorAll(".dxb-countto:not([data-dxb-countto-initialized])"),s=[];return t.forEach((t=>{s.push(new e(t))})),i.forEach((t=>{s.push(new e(t))})),s}}function i(t,i){if("string"==typeof t)t=document.querySelectorAll(t);else if(t instanceof HTMLElement)t=[t];else if(!(Array.isArray(t)||t instanceof NodeList))throw new Error("Invalid element selection");return Array.from(t).map((t=>new e(t,i)))}function s(){if(!window.MutationObserver)return;new MutationObserver((t=>{let i=!1;t.forEach((t=>{"childList"===t.type&&t.addedNodes.length&&t.addedNodes.forEach((t=>{1===t.nodeType&&t.classList&&(t.classList.contains("az-counter")||t.classList.contains("dxb-countto")||t.querySelector(".az-counter, .dxb-countto"))&&(i=!0)}))})),i&&setTimeout((()=>{e.initAll()}),50)})).observe(document.body,{childList:!0,subtree:!0})}t.DXBCountTo=e,t.createDXBCountTo=i,t.dxprBuilder&&(t.dxprBuilder.DXBCountTo=e,t.dxprBuilder.createDXBCountTo=i);"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{e.initAll(),s()})):(e.initAll(),s())}("undefined"!=typeof window?window:this);