From dfaf7c577b1ec76e84a5e5f5559e6a393248367e Mon Sep 17 00:00:00 2001 From: Huzaifa Inam Date: Sat, 22 Aug 2026 21:25:17 +0000 Subject: [PATCH] Add theme_3d_systems/static/src/js/widgets/widget_stats_counter.js --- .../src/js/widgets/widget_stats_counter.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 theme_3d_systems/static/src/js/widgets/widget_stats_counter.js diff --git a/theme_3d_systems/static/src/js/widgets/widget_stats_counter.js b/theme_3d_systems/static/src/js/widgets/widget_stats_counter.js new file mode 100644 index 0000000..4948f26 --- /dev/null +++ b/theme_3d_systems/static/src/js/widgets/widget_stats_counter.js @@ -0,0 +1,43 @@ +/** @odoo-module **/ + +import publicWidget from '@web/legacy/js/public/public_widget'; + +publicWidget.registry.ThemeStatsCounter = publicWidget.Widget.extend({ + selector: '.s_stats_matrix', + + start: function () { + this._super.apply(this, arguments); + + const counters = this.el.querySelectorAll('.stat-number'); + if (!counters.length) return; + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + counters.forEach((c) => this._animateCounter(c)); + observer.disconnect(); + } + }); + }, { threshold: 0.2 }); + + observer.observe(this.el); + }, + + _animateCounter: function (el) { + const target = parseFloat(el.dataset.target || el.textContent.replace(/[^0-9.]/g, '')); + const suffix = el.dataset.suffix || ''; + let current = 0; + const step = target / 40; + const timer = setInterval(() => { + current += step; + if (current >= target) { + el.textContent = (target % 1 === 0 ? target : target.toFixed(1)) + suffix; + clearInterval(timer); + } else { + el.textContent = (target % 1 === 0 ? Math.floor(current) : current.toFixed(1)) + suffix; + } + }, 30); + }, +}); + +export default publicWidget.registry.ThemeStatsCounter;