1/** 2 * å¨åº«ã²ã¼ã¸ (stock-gauge) ã®ã¹ã¯ãã¼ã«ã¤ã³ã¢ãã¡ init 3 * 4 * å 㯠resources/views/components/stock-gauge.blade.php L196-327 ã® @once å scriptã 5 * å·®åãªãã¼ã (fragment swap) ã§æ°è¦ã«ã¼ãå ã®ã²ã¼ã¸ã«ã init ãèµ°ãããããå¤é¨ JS åã 6 * 7 * å ¬é API: 8 * - window.StockGauge.rescan(root?) â root ã¹ã³ã¼ãå ã®æª init ã²ã¼ã¸ã observe ã«ç»é² 9 * 10 * åªçå: 11 * - window.__STOCK_GAUGE_LOADED__ ã¬ã¼ãã§ module äºéãã¼ã鲿¢ 12 * - å gauge è¦ç´ ã« data-scroll-animate-init="1" ãã¼ã«ã¼ã§å observe ãã¹ããã 13 * 14 * ã¤ãã³ã: 15 * - document.addEventListener('top:gacha-list-updated') ã§ fragment swap å¾ã«åã¹ãã£ã³ 16 * 17 * Spec: docs/features/top-main-gacha-partial-reload/spec.md §3.D-3 18 */ 19(function () { 20 if (window.__STOCK_GAUGE_LOADED__) return; 21 window.__STOCK_GAUGE_LOADED__ = true; 22 23 var FIRE_DELAY_MS = 300; 24 var ANIMATION_DURATION_MS = 800; 25 var FALLBACK_MS = 1000; 26 27 // åä¸ã®å ±æ observer + fallbackTimers ã module ã¹ã³ã¼ãã«æã¤ 28 // (rescan æã«æ§ observer ã disconnect ãããæ° gauge ã ã追å observe ãã) 29 var observer = null; 30 var fallbackTimers = new WeakMap(); 31 32 function scaleFor(target) { 33 return Math.max(0, Math.min(1, target / 100)); 34 } 35 36 function applyImmediate(gauges) { 37 for (var i = 0; i < gauges.length; i++) { 38 var g = gauges[i]; 39 var target = parseFloat(g.getAttribute('data-percentage')) || 0; 40 var bar = g.querySelector('.stock-gauge-bar-fill'); 41 if (bar) { 42 bar.style.transformOrigin = 'left'; 43 bar.style.transform = 'scaleX(' + scaleFor(target) + ')'; 44 } 45 g.setAttribute('data-scroll-animate-init', '1'); 46 } 47 } 48 49 function animateGauge(g) { 50 var target = parseFloat(g.getAttribute('data-percentage')) || 0; 51 var bar = g.querySelector('.stock-gauge-bar-fill'); 52 if (!bar) return; 53 bar.style.transformOrigin = 'left'; 54 bar.classList.add('scroll-animating'); 55 requestAnimationFrame(function () { 56 requestAnimationFrame(function () { 57 bar.style.transform = 'scaleX(' + scaleFor(target) + ')'; 58 }); 59 }); 60 setTimeout(function () { 61 bar.classList.remove('scroll-animating'); 62 }, ANIMATION_DURATION_MS + 100); 63 } 64 65 function scheduleFire(g) { 66 if (g.getAttribute('data-scroll-animate-init') === '1') return; 67 g.setAttribute('data-scroll-animate-init', '1'); 68 var t = fallbackTimers.get(g); 69 if (t) { 70 clearTimeout(t); 71 fallbackTimers.delete(g); 72 } 73 if (observer) observer.unobserve(g); 74 setTimeout(function () { 75 animateGauge(g); 76 }, FIRE_DELAY_MS); 77 } 78 79 function ensureObserver() { 80 if (observer) return observer; 81 observer = new IntersectionObserver(function (entries) { 82 entries.forEach(function (entry) { 83 var g = entry.target; 84 if (g.getAttribute('data-scroll-animate-init') === '1') { 85 observer.unobserve(g); 86 return; 87 } 88 if (!entry.isIntersecting) { 89 var t = fallbackTimers.get(g); 90 if (t) { 91 clearTimeout(t); 92 fallbackTimers.delete(g); 93 } 94 return; 95 } 96 if (entry.intersectionRatio >= 0.8) { 97 scheduleFire(g); 98 } else if (!fallbackTimers.has(g)) { 99 fallbackTimers.set(g, setTimeout(function () { 100 fallbackTimers.delete(g); 101 scheduleFire(g); 102 }, FALLBACK_MS)); 103 } 104 }); 105 }, { threshold: [0.3, 0.8] }); 106 return observer; 107 } 108 109 function rescan(root) { 110 var scope = root || document; 111 var gauges = scope.querySelectorAll( 112 '.stock-gauge-container[data-scroll-animate="1"]:not([data-scroll-animate-init])' 113 ); 114 if (gauges.length === 0) return; 115 116 var prefersReduced = window.matchMedia 117 && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 118 var noObserver = !('IntersectionObserver' in window); 119 120 if (prefersReduced || noObserver) { 121 applyImmediate(gauges); 122 return; 123 } 124 125 var obs = ensureObserver(); 126 for (var j = 0; j < gauges.length; j++) { 127 obs.observe(gauges[j]); 128 } 129 } 130 131 // å ¬é API 132 window.StockGauge = { rescan: rescan }; 133 134 // åæãã¼ãæã®èªå init 135 if (document.readyState === 'loading') { 136 document.addEventListener('DOMContentLoaded', function () { rescan(); }); 137 } else { 138 rescan(); 139 } 140 141 // fragment swap å¾ã®åã¹ãã£ã³ 142 document.addEventListener('top:gacha-list-updated', function (e) { 143 var root = (e && e.detail && e.detail.container) ? e.detail.container : document; 144 rescan(root); 145 }); 146})();
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.