(function ($) {
"use strict";
const SEPARATORS = { comma: ",", dot: ".", space: " ", underline: "_" };
function formatWithSeparator(num, separator) {
const str = num.toString();
if (!separator) return str;
const negative = str.charAt(0) === "-";
const body = negative ? str.slice(1) : str;
if (body.length < 4) return str;
return (negative ? "-" : "") + body.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
}
function runCounter(counter, target, start, duration, separator) {
const startTime = performance.now();
function tick(time) {
const progress = Math.min((time - startTime) / duration, 1);
const current = Math.floor(start + (target - start) * progress);
counter.textContent = formatWithSeparator(current, separator);
if (progress < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
}
function runOdometer(counter, target, duration, separator) {
const targetInt = Math.floor(Math.abs(target));
const targetStr = targetInt.toString();
const negative = target < 0;
counter.innerHTML = "";
counter.classList.add("eel-cnt-odometer-wrap");
if (negative) {
const s = document.createElement("span");
s.className = "eel-cnt-odometer-sep";
s.textContent = "-";
counter.appendChild(s);
}
const animEls = [];
let digitIndex = 0;
for (let i = 0; i < targetStr.length; i++) {
const posFromRight = targetStr.length - i;
if (i > 0 && separator && posFromRight % 3 === 0) {
const sep = document.createElement("span");
sep.className = "eel-cnt-odometer-sep";
sep.textContent = separator;
counter.appendChild(sep);
}
const col = document.createElement("span");
col.className = "eel-cnt-odometer-digit";
const roll = document.createElement("span");
roll.className = "eel-cnt-odometer-roll";
const spins = 2 + digitIndex;
let html = "";
for (let s = 0; s < spins; s++) {
for (let n = 0; n <= 9; n++) {
html += '' + n + '';
}
}
html += '' + targetStr.charAt(i) + '';
roll.innerHTML = html;
roll.style.transform = "translateY(0)";
col.appendChild(roll);
counter.appendChild(col);
animEls.push({ roll: roll, spins: spins });
digitIndex++;
}
requestAnimationFrame(function () {
requestAnimationFrame(function () {
animEls.forEach(function (item) {
item.roll.style.transition = "transform " + duration + "ms cubic-bezier(.22,.85,.34,1)";
item.roll.style.transform = "translateY(-" + (item.spins * 10) + "em)";
});
});
});
}
function eelRunCounter($scope) {
const counters = $scope.find(".eel-counter");
if (!counters.length) return;
const observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (!entry.isIntersecting) return;
const counter = entry.target;
observer.unobserve(counter);
const target = parseInt(counter.dataset.count, 10) || 0;
const start = parseInt(counter.dataset.start, 10) || 0;
const duration = parseInt(counter.dataset.duration, 10) || 1000;
const format = counter.dataset.format || "default";
const animation = counter.dataset.animation || "counter";
const separator = SEPARATORS[format] || "";
if (animation === "odometer") {
runOdometer(counter, target, duration, separator);
} else {
runCounter(counter, target, start, duration, separator);
}
});
}, { threshold: 0.2 });
counters.each(function () {
observer.observe(this);
});
}
$(window).on("elementor/frontend/init", function () {
elementorFrontend.hooks.addAction("frontend/element_ready/widget", function ($scope) {
if ($scope.find(".eel-counter").length) {
eelRunCounter($scope);
}
});
});
})(jQuery);