PageSourceSearch

https://broadbandswitch.uk/assets/js/stat-delight.js

js broadbandswitch.uk collected 2026-10-04 08:38:36 UTC 2,966 bytes, 70 lines download raw bytes

1/* BroadbandSwitch.uk honest delight layer.
2   1) Counts up real numeric hero stats when they scroll into view.
3   2) Fires a small emoji burst when the USER submits the postcode form.
4   Both respect prefers-reduced-motion.  No fake social proof, ever. */
5(function () {
6  'use strict';
7  var reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
8
9  /* 1. Count-up on real stats */
10  function countUp(el) {
11    var raw = el.getAttribute('data-count-base');
12    var target = parseInt(raw, 10);
13    if (!target || reduced) return;
14    var small = el.querySelector('small');
15    var suffix = small ? small.outerHTML : '';
16    var start = null, dur = 900;
17    function step(ts) {
18      if (!start) start = ts;
19      var p = Math.min((ts - start) / dur, 1);
20      var eased = 1 - Math.pow(1 - p, 3);
21      el.innerHTML = Math.round(target * eased).toLocaleString('en-GB') + suffix;
22      if (p < 1) requestAnimationFrame(step);
23    }
24    requestAnimationFrame(step);
25  }
26  var nums = document.querySelectorAll('.live-stat-num[data-count-base]');
27  if ('IntersectionObserver' in window && nums.length) {
28    var seen = new WeakSet();
29    var io = new IntersectionObserver(function (entries) {
30      entries.forEach(function (e) {
31        if (e.isIntersecting && !seen.has(e.target)) {
32          seen.add(e.target);
33          countUp(e.target);
34          io.unobserve(e.target);
35        }
36      });
37    }, { threshold: 0.6 });
38    nums.forEach(function (n) { io.observe(n); });
39  }
40
41  /* 2. Emoji burst on the user's own action (postcode submit) */
42  function burst(x, y) {
43    if (reduced) return;
44    var emojis = ['🎉', '⚡', '💷', '📶', '✨'];
45    for (var i = 0; i < 7; i++) {
46      var s = document.createElement('span');
47      s.textContent = emojis[i % emojis.length];
48      s.style.cssText = 'position:fixed;left:' + x + 'px;top:' + y + 'px;' +
49        'font-size:18px;pointer-events:none;z-index:9999;transition:transform .8s cubic-bezier(.2,.8,.3,1),opacity .8s;opacity:1;will-change:transform,opacity;';
50      document.body.appendChild(s);
51      (function (el, idx) {
52        requestAnimationFrame(function () {
53          var dx = (Math.random() - 0.5) * 160;
54          var dy = -60 - Math.random() * 90;
55          el.style.transform = 'translate(' + dx + 'px,' + dy + 'px) rotate(' + ((Math.random() - 0.5) * 60) + 'deg)';
56          el.style.opacity = '0';
57        });
58        setTimeout(function () { el.remove(); }, 850);
59      })(s, i);
60    }
61  }
62  document.addEventListener('submit', function (ev) {
63    var form = ev.target;
64    if (form && form.querySelector && form.querySelector('input[placeholder*="postcode" i], input[name*="postcode" i]')) {
65      var btn = form.querySelector('button[type="submit"], button');
66      var r = (btn || form).getBoundingClientRect();
67      burst(r.left + r.width / 2, r.top);
68    }
69  }, true);
70})();

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.