PageSourceSearch

https://kebun4dmu.com/js/new/main.js?v=1790436670

js kebun4dmu.com collected 2026-10-10 00:52:22 UTC 24,583 bytes, 664 lines download raw bytes

1var loading = '<div class="content-loader-wrap"><div class="loader"></div></div>';
2
3function esc(s) {
4    return String(s || '')
5        .replace(/&/g, '&amp;').replace(/</g, '&lt;')
6        .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
7}
8
9function jtApiOk(res) {
10    return !!(res && res.error && res.error.code === 200);
11}
12
13function jtPost(url, body) {
14    return fetch(url, {
15        method: 'POST',
16        credentials: 'same-origin',
17        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
18        body: JSON.stringify(body || {})
19    });
20}
21
22function jtPostJson(url, body) {
23    return jtPost(url, body).then(function (r) { return r.json(); });
24}
25
26function jtLooksLikeInjection(value) {
27    var s = String(value || '');
28    if (!s) return false;
29    if (/<[a-zA-Z\/!?]/.test(s)) return true;
30    if (/\bon[a-z]+\s*=/i.test(s)) return true;
31    if (/javascript\s*:/i.test(s)) return true;
32    if (/['"]\s*(or|and)\s+/i.test(s)) return true;
33    if (/\b(union\s+select|insert\s+into|drop\s+table|update\s+\w+\s+set|delete\s+from|sleep\s*\(|benchmark\s*\()/i.test(s)) return true;
34    if (/--|\/\*|\*\//.test(s)) return true;
35    if (/[;\\]/.test(s)) return true;
36    return false;
37}
38
39function jtIsAllowedWallet(value) {
40    return /^[A-Za-z0-9]{8,128}$/.test(String(value || ''));
41}
42
43function jtIsAllowedTxid(value) {
44    return /^[A-Za-z0-9]{8,128}$/.test(String(value || ''));
45}
46
47// Offset tetap (bukan tracking live ke elemen) supaya toast kira-kira sejajar
48// area search bar (#gsSearchWrap di header.php), bukan nempel di pojok kiri-atas viewport.
49var TOAST_OFFSET = { x: 0, y: 110 };
50
51function toast(message, code) {
52    if (typeof Toastify === 'undefined') return;
53    code = code === undefined ? 200 : code;
54    Toastify({
55        text: message,
56        duration: 3000,
57        gravity: 'top',
58        position: 'left',
59        offset: TOAST_OFFSET,
60        close: false,
61        stopOnFocus: false,
62        className: code === 200 ? 'toast-success' : 'toast-error'
63    }).showToast();
64}
65
66function toastAction(message, code, buttonText, buttonId) {
67    if (typeof Toastify === 'undefined') return;
68    code = code === undefined ? 200 : code;
69
70    var node = document.createElement('div');
71    node.className = 'toast-action-content';
72    var span = document.createElement('span');
73    span.textContent = message;
74    node.appendChild(span);
75
76    if (buttonText) {
77        var btn = document.createElement('button');
78        btn.type = 'button';
79        btn.className = 'toast-action-btn';
80        if (buttonId) btn.id = buttonId;
81        btn.textContent = buttonText;
82        node.appendChild(btn);
83    }
84
85    Toastify({
86        node: node,
87        duration: 5000,
88        gravity: 'top',
89        position: 'left',
90        offset: TOAST_OFFSET,
91        close: false,
92        stopOnFocus: false,
93        className: code === 200 ? 'toast-success' : 'toast-error'
94    }).showToast();
95}
96
97// 3 nominal terakhir dipakai bersama di semua form jumlah (deposit/withdraw).
98var TX_RECENT_AMOUNT_KEY = 'tx_recent_amount';
99var TX_RECENT_AMOUNT_LEGACY_KEYS = [
100    'tx_recent_amount_pgw',
101    'tx_recent_amount_bank',
102    'tx_recent_amount_crypto',
103    'tx_recent_amount_wd',
104    'tx_recent_amount_wd_crypto'
105];
106var txRecentAmountInstances = [];
107
108function txRecentAmountsReadList() {
109    var seen = {};
110    var list = [];
111    function addFrom(key) {
112        try {
113            var raw = JSON.parse(sessionStorage.getItem(key) || '[]');
114            if (!Array.isArray(raw)) return;
115            raw.forEach(function (v) {
116                var n = parseInt(v, 10);
117                if (!n || n <= 0 || seen[n]) return;
118                seen[n] = true;
119                list.push(n);
120            });
121        } catch (e) {}
122    }
123    addFrom(TX_RECENT_AMOUNT_KEY);
124    TX_RECENT_AMOUNT_LEGACY_KEYS.forEach(addFrom);
125    return list.slice(0, 3);
126}
127
128function txRecentAmountsBroadcast() {
129    txRecentAmountInstances = txRecentAmountInstances.filter(function (inst) {
130        return inst.container && document.body.contains(inst.container);
131    });
132    txRecentAmountInstances.forEach(function (inst) { inst.render(); });
133}
134
135function txRecentAmounts(storageKey, input, container) {
136    if (!input || !container) return { save: function () {} };
137
138    function render() {
139        var list = txRecentAmountsReadList();
140        container.innerHTML = '';
141        if (!list.length) {
142            container.style.display = 'none';
143            return;
144        }
145        list.forEach(function (val) {
146            var btn = document.createElement('button');
147            btn.type = 'button';
148            btn.className = 'tx-recent-amount-btn';
149            btn.textContent = Number(val).toLocaleString('en-US');
150            btn.addEventListener('click', function () {
151                input.value = Number(val).toLocaleString('en-US');
152                input.dispatchEvent(new Event('input', { bubbles: true }));
153            });
154            container.appendChild(btn);
155        });
156        container.style.display = '';
157    }
158
159    function save(rawValue) {
160        var val = parseInt(String(rawValue).replace(/[^0-9]/g, ''), 10);
161        if (!val || val <= 0) return;
162        var list = txRecentAmountsReadList().filter(function (v) { return v !== val; });
163        list.unshift(val);
164        try { sessionStorage.setItem(TX_RECENT_AMOUNT_KEY, JSON.stringify(list.slice(0, 3))); } catch (e) {}
165        txRecentAmountsBroadcast();
166    }
167
168    txRecentAmountInstances.push({ container: container, render: render });
169    render();
170    return { save: save };
171}
172
173// ?dev=1 di URL manapun mengaktifkan dev mode utk sisa sesi browser — disimpan di
174// sessionStorage krn URL bar SPA ini selalu di-normalize (query string custom hilang
175// tiap navigasi), jadi tidak bisa diandalkan buat nyimpen flag lintas halaman.
176(function () {
177    var params = new URLSearchParams(location.search);
178    if (params.has('dev')) {
179        sessionStorage.setItem('jt_dev_mode', params.get('dev') === '1' ? '1' : '0');
180    }
181})();
182
183// Nunggu link CSS async (media="print") selesai load, biar konten AJAX gak nyalip CSS-nya di koneksi lambat.
184function waitForCss(ids) {
185    var pending = ids
186        .map(function (id) { return document.getElementById(id); })
187        .filter(function (link) { return link && link.media === 'print'; });
188    if (!pending.length) return Promise.resolve();
189    return Promise.all(pending.map(function (link) {
190        return new Promise(function (resolve) {
191            link.addEventListener('load', resolve, { once: true });
192            link.addEventListener('error', resolve, { once: true });
193        });
194    }));
195}
196
197var ASYNC_CSS_IDS = ['css-home-sections', 'css-bootstrap-icons', 'css-splide', 'css-toastify', 'css-game'];
198
199function jtAssetVer() {
200    var el = document.querySelector('link[href*="/css/new/layout.css"]');
201    if (!el) return '1';
202    var m = String(el.href).match(/[?&]v=([^&]+)/);
203    return m ? decodeURIComponent(m[1]) : '1';
204}
205
206function ensureStylesheet(id, href) {
207    var existing = document.getElementById(id);
208    if (existing) {
209        if (existing.media === 'print') existing.media = 'all';
210        return Promise.resolve();
211    }
212    return new Promise(function (resolve) {
213        var link = document.createElement('link');
214        link.id = id;
215        link.rel = 'stylesheet';
216        link.href = href;
217        link.onload = function () { resolve(); };
218        link.onerror = function () { resolve(); };
219        document.head.appendChild(link);
220    });
221}
222
223function ensureGameCss() {
224    return ensureStylesheet('css-game', '/css/new/game.min.css?v=' + jtAssetVer());
225}
226
227function needsGameCss(url) {
228    return /(?:^|[?&/])game\.php(?:\?|$)/.test(String(url || ''));
229}
230
231var _splidePromise = null;
232/** Splide CSS tetap di shell; hanya JS di-load on-demand. Prefetch segera di bawah. */
233function ensureSplide() {
234    if (typeof Splide !== 'undefined') {
235        return waitForCss(['css-splide']);
236    }
237    if (_splidePromise) return _splidePromise;
238    var ver = jtAssetVer();
239    _splidePromise = waitForCss(['css-splide']).then(function () {
240        return new Promise(function (resolve, reject) {
241            var s = document.createElement('script');
242            s.src = '/js/new/vendor/splide.min.js?v=' + ver;
243            s.onload = function () { resolve(); };
244            s.onerror = function () {
245                _splidePromise = null;
246                reject(new Error('splide load failed'));
247            };
248            document.head.appendChild(s);
249        });
250    });
251    return _splidePromise;
252}
253// Mulai unduh Splide JS segera (paralllel dgn sisa parse), sebelum DOMContentLoaded mount.
254ensureSplide().catch(function () {});
255
256function ajaxLoad(url, target) {
257    var fullUrl = '/new' + url;
258    if (sessionStorage.getItem('jt_dev_mode') === '1') {
259        fullUrl += (fullUrl.indexOf('?') !== -1 ? '&' : '?') + 'dev=1';
260    }
261    var cssPrep = needsGameCss(url) ? ensureGameCss() : Promise.resolve();
262    $.ajax({
263        url: fullUrl,
264        headers: { 'X-Requested-With': 'XMLHttpRequest' },
265        success: function(r) {
266            cssPrep
267                .then(function () { return waitForCss(ASYNC_CSS_IDS); })
268                .then(function () { $(target).html(r); });
269        }
270    });
271}
272
273var _prevNavBeforeOverlay = '';
274
275function _restoreNavActive(navKey) {
276    $('.lobby-menu, .desktop-nav-link').removeClass('active');
277    if (navKey) $('[data-nav="' + navKey + '"]').addClass('active');
278}
279
280function showProviders(contentType, menuEl) {
281    if (menuEl === undefined) menuEl = null;
282    if ($('#providerOverlay').length) {
283        var current = $('#providerOverlay').attr('data-content');
284        $('#providerBackdrop, #providerOverlay').remove();
285        if (current === contentType) { _restoreNavActive(_prevNavBeforeOverlay); return; }
286    } else {
287        _prevNavBeforeOverlay = $('.desktop-nav-link.active').attr('data-nav') ||
288                                $('#lobbyMenuWrap .lobby-menu.active').attr('data-nav') || '';
289    }
290    if (menuEl) {
291        $('.lobby-menu, .desktop-nav-link').removeClass('active');
292        $(menuEl).addClass('active');
293    }
294    $.ajax({
295        url: '/new/' + 'provider' + '.php?' + 'content=' + contentType,
296        headers: { 'X-Requested-With': 'XMLHttpRequest' },
297        success: function(html) {
298            $('body').append(html);
299            positionProviderOverlay();
300        }
301    });
302}
303
304function setBackdropPos(bd, topPx) {
305    var docH = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
306    bd.style.top    = topPx + 'px';
307    bd.style.height = Math.max(docH - topPx, window.innerHeight) + 'px';
308}
309
310function positionProviderOverlay() {
311    var ov = document.getElementById('providerOverlay');
312    var bd = document.getElementById('providerBackdrop');
313    if (!ov) return;
314
315    var isDesktop = window.innerWidth >= 768;
316
317    if (isDesktop) {
318        var desktopNav  = document.querySelector('.desktop-mainnav');
319        var navRect     = desktopNav ? desktopNav.getBoundingClientRect() : null;
320        var linksEl     = desktopNav ? desktopNav.querySelector('.ms-auto') : null;
321        var linksRect   = linksEl ? linksEl.getBoundingClientRect() : navRect;
322        var scrollW     = linksEl ? linksEl.scrollWidth : 0;
323        var clientW     = linksEl ? linksEl.clientWidth  : 0;
324        var rightRef    = linksRect
325            ? (scrollW <= clientW
326                ? Math.min(linksRect.left + scrollW, window.innerWidth)
327                : Math.min(linksRect.right, window.innerWidth))
328            : window.innerWidth;
329        var navBottom = navRect ? navRect.bottom : 116;
330        ov.style.top = (window.scrollY + navBottom) + 'px';
331        ov.style.setProperty('--nav-left',  (linksRect ? linksRect.left : 0) + 'px');
332        ov.style.setProperty('--nav-right', Math.max(0, window.innerWidth - rightRef) + 'px');
333        if (bd) setBackdropPos(bd, window.scrollY + navBottom);
334    } else {
335        var lobby = document.getElementById('lobbyMenuWrap');
336        var lobbyBottom = lobby ? lobby.getBoundingClientRect().bottom : 0;
337        ov.style.top = (window.scrollY + lobbyBottom) + 'px';
338        ov.style.removeProperty('--nav-left');
339        ov.style.removeProperty('--nav-right');
340        if (bd) setBackdropPos(bd, window.scrollY + lobbyBottom);
341    }
342
343    var contentType = ov.getAttribute('data-content');
344    if (contentType) {
345        $('.lobby-menu, .desktop-nav-link').removeClass('active');
346        var selector = isDesktop
347            ? '.desktop-nav-link[data-nav="' + contentType + '"]'
348            : '#lobbyMenuWrap .lobby-menu[data-nav="' + contentType + '"]';
349        $(selector).addClass('active');
350    }
351}
352
353function searchGames(value) {
354    var searchInput = document.getElementById('gameSearchInput');
355    if (searchInput) searchInput.value = value;
356    if (typeof filterGames    === 'function') { filterGames(value);    return; }
357    if (typeof applyAllFilters === 'function') { applyAllFilters(value); return; }
358    if (typeof applyCatFilter  === 'function') { applyCatFilter(value);  return; }
359}
360
361/* ── Global game search overlay ──────────────────────────────── */
362var _gsTimer = null;
363
364function globalSearch(val) {
365    clearTimeout(_gsTimer);
366    var drop = document.getElementById('gsDropdown');
367    if (!drop) return;
368    if (!val || val.length < 2) { drop.style.display = 'none'; return; }
369    if (typeof jtLooksLikeInjection === 'function' && jtLooksLikeInjection(val)) {
370        drop.style.display = '';
371        drop.innerHTML = '<div class="gs-empty">Tidak ditemukan</div>';
372        return;
373    }
374
375    _gsTimer = setTimeout(function () {
376        drop.style.display = '';
377        drop.innerHTML = '<div class="gs-loading"><div class="loader"></div></div>';
378        jtPostJson('/api/front/game/search', { q: val })
379            .then(function (res) {
380                if (res.error && res.error.code === 200) { _gsRender(res.data || {}); }
381                else { drop.style.display = 'none'; }
382            })
383            .catch(function () { drop.style.display = 'none'; });
384    }, 300);
385}
386
387function _gsRender(data) {
388    var drop    = document.getElementById('gsDropdown');
389    var games   = data.games   || [];
390    var pasaran = data.pasaran || [];
391    if (!games.length && !pasaran.length) {
392        drop.innerHTML = '<div class="gs-empty">Tidak ditemukan</div>';
393        return;
394    }
395    var html = '';
396    if (games.length) {
397        html += '<div class="gs-section">Games</div><div class="gs-grid">';
398        games.forEach(function (g) {
399            html += '<div class="gs-item" data-token="' + esc(g.token) + '" onclick="gsLaunch(this)">' +
400                '<div class="gs-img-box">' +
401                '<img src="' + esc(g.image_url) + '" data-provider="' + esc(g.provider_id) + '" loading="lazy" onerror="gsImgFallback(this)">' +
402                '<div class="gs-img-placeholder"><i class="bi bi-controller"></i></div>' +
403                '</div>' +
404                '</div>';
405        });
406        html += '</div>';
407    }
408    if (pasaran.length) {
409        html += '<div class="gs-section">Pasaran Togel</div>';
410        pasaran.forEach(function (p) {
411            var target;
412            if (String(p.status) === '1') {
413                var marketCode = (p.nameid || '') + '-' + (p.periode || '');
414                target = "content('/togel-detail.php?market=" + encodeURIComponent(marketCode) + "','#content')";
415            } else {
416                target = "content('/togel.php','#content')";
417            }
418            html += '<div class="gs-pasaran-item" onclick="gsClose();' + target + '">' +
419                '<span class="gs-pasaran-icon"><i class="bi bi-ticket-perforated"></i></span>' +
420                '<span class="gs-pasaran-name">' + esc(p.name) + '</span>' +
421                '<i class="bi bi-chevron-right gs-pasaran-arrow"></i></div>';
422        });
423    }
424    drop.innerHTML = html;
425}
426
427// Fallback sementara per-provider (mg/hb) — hapus setelah gambar provider lengkap.
428var PROVIDER_FALLBACK_IMG = {
429    mg: function (src) { return src.replace(/(\.[^./?#]+)(\?.*)?$/, '_icon_square_250x250_en$1$2'); },
430    hb: function (src) { return src.replace('/images/', '/images/circle/'); }
431};
432function tryProviderImgFallback(img) {
433    var fn = PROVIDER_FALLBACK_IMG[img.dataset.provider];
434    if (!fn || img.dataset.triedProviderFallback === '1') return false;
435    img.dataset.triedProviderFallback = '1';
436    var alt = fn(img.src);
437    if (alt === img.src) return false;
438    img.src = alt;
439    return true;
440}
441
442// Retry-once: strip prefix "/new/" dari src gambar game kalau masih 404 — dipakai
443// game.php, home.php, dan gsImgFallback di bawah (dulu 3 salinan terpisah).
444function retryImgWithoutNewPrefix(img) {
445    if (!img.dataset.triedAlt && img.src.indexOf('/new/') !== -1) {
446        img.dataset.triedAlt = '1';
447        img.src = img.src.replace('/new/', '/');
448        return true;
449    }
450    return false;
451}
452
453// dipakai game.php via onerror="gameImgFallback(this)" — retry gagal = biarkan icon broken bawaan browser
454function gameImgFallback(img) {
455    if (tryProviderImgFallback(img)) return;
456    if (!retryImgWithoutNewPrefix(img)) img.onerror = null;
457}
458
459function gameImgLoaded(img) {
460    if (img.dataset.triedAlt === '1') {
461        var card = img.closest('.game-card');
462        if (card) card.classList.add('game-card--alt');
463    }
464}
465
466// dipakai home.php — retry gagal = tampilkan placeholder via class is-broken
467function markBrokenGameImage(img) {
468    var box = img.closest('.game-card-img-box');
469    if (box) box.classList.add('is-broken');
470}
471
472function retryGameImageWithoutNew(img) {
473    return retryImgWithoutNewPrefix(img);
474}
475
476function initHomeGameImageFallback(root) {
477    var scope = root || document;
478    scope.querySelectorAll('.js-game-image').forEach(function(img) {
479        if (img.dataset.fallbackBound === '1') return;
480        img.dataset.fallbackBound = '1';
481        img.addEventListener('error', function() {
482            if (tryProviderImgFallback(img)) return;
483            if (!retryGameImageWithoutNew(img)) markBrokenGameImage(img);
484        });
485        if (img.complete && img.naturalWidth === 0 && !tryProviderImgFallback(img) && !retryGameImageWithoutNew(img)) {
486            markBrokenGameImage(img);
487        }
488    });
489}
490
491function gsImgFallback(img) {
492    if (tryProviderImgFallback(img)) return;
493    if (!retryImgWithoutNewPrefix(img)) {
494        img.onerror = null;
495        var box = img.closest('.gs-img-box');
496        if (box) box.classList.add('is-broken');
497    }
498}
499
500function gsLaunch(el) {
501    var token = el.getAttribute('data-token');
502    gsClose();
503    launchGame(token, 1200, 800);
504}
505
506function gsClose() {
507    var drop = document.getElementById('gsDropdown');
508    if (drop) drop.style.display = 'none';
509    var inp  = document.getElementById('gameSearchInput');
510    if (inp) inp.value = '';
511}
512
513document.addEventListener('click', function (e) {
514    if (!e.target.closest || !e.target.closest('#gsSearchWrap')) gsClose();
515});
516
517function launchGame(token, w, h) {
518    if (window.JT_LOGGED_IN === false) {
519        sessionStorage.setItem('jt_pending_action', JSON.stringify({type: 'game', token: token, w: w||1200, h: h||800}));
520        if (typeof scrollToLoginForm === 'function') {
521            scrollToLoginForm();
522        } else {
523            window.location.href = '/new/index.php';
524        }
525        return;
526    }
527    var url = '/new/launch/' + token;
528    var standalone = window.navigator.standalone === true ||
529                     window.matchMedia('(display-mode: standalone)').matches;
530    var isMobile = window.innerWidth < 768;
531    var popup = isMobile ? null : window.open('about:blank', '_blank',
532        standalone ? '' : 'width=' + (w||1200) + ',height=' + (h||800) + ',top=0,left=0,resizable=yes,scrollbars=yes');
533    jtPost(url, { check: 1 }).then(function(res) {
534        if (res.ok) {
535            if (popup) { popup.location.href = url; } else { window.location.href = url; }
536        } else if (popup) {
537            popup.close();
538        }
539    }).catch(function() {
540        if (popup) popup.close();
541    });
542}
543
544function copyGameLink(token, btnEl) {
545    if (window.JT_LOGGED_IN === false) {
546        if (typeof scrollToLoginForm === 'function') scrollToLoginForm();
547        return;
548    }
549    if (btnEl) btnEl.disabled = true;
550    jtPostJson('/api/front/game/launch-url', { token: token })
551        .then(function (res) {
552            if (res.error && res.error.code === 200 && res.data && res.data.url) {
553                copyTextToClipboard(res.data.url);
554                toast('Link game disalin', 200);
555            } else {
556                toast((res.error && res.error.message) || 'Gagal mengambil link game', (res.error && res.error.code) || 500);
557            }
558        })
559        .catch(function () {
560            toast('Gagal mengambil link game', 500);
561        })
562        .finally(function () {
563            if (btnEl) btnEl.disabled = false;
564        });
565}
566
567function copyTextToClipboard(text) {
568    if (navigator.clipboard && navigator.clipboard.writeText) {
569        navigator.clipboard.writeText(text).catch(function () { copyTextFallback(text); });
570    } else {
571        copyTextFallback(text);
572    }
573}
574
575function copyTextFallback(text) {
576    var tmp = document.createElement('textarea');
577    tmp.value = text;
578    tmp.style.position = 'fixed';
579    tmp.style.opacity = '0';
580    document.body.appendChild(tmp);
581    tmp.select();
582    try { document.execCommand('copy'); } catch (e) {}
583    document.body.removeChild(tmp);
584}
585
586function content(path, element, menuEl, skipUrlUpdate) {
587    if (element === undefined) element = '#content';
588    if (menuEl  === undefined) menuEl  = null;
589
590    // Clear game-page filter functions so globalSearch uses overlay on the new page
591    ['filterGames', 'applyAllFilters', 'applyCatFilter'].forEach(function (fn) {
592        if (typeof window[fn] !== 'undefined') window[fn] = undefined;
593    });
594
595    var offcanvasEl   = document.getElementById('offcanvasExample');
596    var offcanvasInst = typeof bootstrap !== 'undefined'
597        ? bootstrap.Offcanvas.getInstance(offcanvasEl)
598        : null;
599    // Bootstrap mengunci scroll body selama animasi hide (~300ms), jadi
600    // scrollIntoView di bawah akan diabaikan kalau offcanvas baru saja dibuka.
601    // Tunda scroll sampai offcanvas benar-benar tertutup.
602    var offcanvasWasOpen = !!(offcanvasEl && offcanvasEl.classList.contains('show'));
603    if (offcanvasInst) offcanvasInst.hide();
604
605    $('#providerBackdrop, #providerOverlay').remove();
606    gsClose();
607
608    $(element).html(loading);
609    $('.lobby-menu, .desktop-nav-link').removeClass('active');
610    if (menuEl) $(menuEl).addClass('active');
611
612    // Prefetch game.css paralel dgn AJAX (bukan tunggu response dulu).
613    if (needsGameCss(path)) ensureGameCss();
614
615    ajaxLoad(path, element);
616
617    if (!skipUrlUpdate && (element === '#content' || element === '#menu-content') && typeof jtUpdateBrowserUrl === 'function') {
618        jtUpdateBrowserUrl(path, false);
619    }
620    
621    function jtScrollToContent() {
622        document.getElementById("content").scrollIntoView({ behavior: "smooth" });
623    }
624    // auto-scroll ke #content
625    // if (offcanvasWasOpen && offcanvasEl) {
626    //     offcanvasEl.addEventListener('hidden.bs.offcanvas', function _h() {
627    //         offcanvasEl.removeEventListener('hidden.bs.offcanvas', _h);
628    //         jtScrollToContent();
629    //     });
630    // } else {
631    //     jtScrollToContent();
632    // }
633}
634
635function modal(path) {
636    $('#providerBackdrop, #providerOverlay').remove();
637    $('#modal-content').html(loading);
638    var modalEl = document.getElementById('modal');
639    modalEl.classList.toggle('modal-tx', path.indexOf('transaksi.php') !== -1);
640    bootstrap.Modal.getOrCreateInstance(modalEl).show();
641    ajaxLoad(path, '#modal-content');
642}
643
644function openCms(key) {
645    if (!/^[a-z]+$/.test(key || '')) return;
646    modal('/' + 'cms' + '.php?' + 'content=' + encodeURIComponent(key));
647}
648
649function openPage(name, menuEl) {
650    var game = { sport: 1, sabung: 1 };
651    if (name === 'home' || name === 'promosi' || name === 'event') {
652        content('/' + name + '.php', '#content', menuEl);
653        return;
654    }
655    if (!game[name]) return;
656    content('/' + 'game' + '.php?' + 'content=' + name, '#content', menuEl);
657}
658
659function openRegister(mode) {
660    var mobile = mode === 'mobile' || (mode !== 'desktop' && window.matchMedia('(max-width: 768px)').matches);
661    content('/' + (mobile ? 'mregister' : 'register') + '.php', '#content');
662}
663
664window.addEventListener('resize', positionProviderOverlay);

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.