diff --git a/resources/views/controls/index.blade.php b/resources/views/controls/index.blade.php index 7862da2d..117e4779 100644 --- a/resources/views/controls/index.blade.php +++ b/resources/views/controls/index.blade.php @@ -90,6 +90,7 @@ class="table data-table striped row-hover cell-border" data-rownum="false" data-check="false" data-check-style="1" + data-search="true" > @@ -180,92 +181,142 @@ class="table data-table striped row-hover cell-border" - + // --- 2) lit la valeur dans l'URL + const params = new URLSearchParams(location.search); + const searchValue = params.get('search') || ''; + + // --- 3) applique à l'API table (filtrage effectif) + const applyToAPI = (val) => { + const tableEl = document.getElementById('controls'); + const api = tableEl ? Metro.getPlugin(tableEl, 'table') : null; + if (api && typeof api.search === 'function') { + api.search(val); + return true; + } + return false; + }; + + // --- 4) pose la valeur dans l'input quand il existe (et quand il est recréé) + function setSearchInputWhenReady(val, timeoutMs = 3000) { + if (!val) return; + + const trySet = () => { + const input = $('.table-search-block input'); + if (!input) return false; + if (input.value !== val) { + input.value = val; + input.dispatchEvent(new Event('input', { bubbles: true })); + input.dispatchEvent(new Event('change', { bubbles: true })); + } + return true; + }; + + if (trySet()) return; + + // a) quelques frames + let tries = 0, maxTries = 20; + const raf = () => { + if (trySet()) return; + if (++tries >= maxTries) return; + requestAnimationFrame(raf); + }; + requestAnimationFrame(raf); + + // b) garde-fou si l’input apparaît plus tard (reconstruction Metro) + const mo = new MutationObserver(() => { + if (trySet()) mo.disconnect(); + }); + mo.observe(document.body, { childList: true, subtree: true }); + setTimeout(() => mo.disconnect(), timeoutMs); + } + + // --- 5) exécution au chargement + if (searchValue) { + // filtre la table côté API (immédiat ou dès que prêt) + if (!applyToAPI(searchValue)) { + requestAnimationFrame(() => applyToAPI(searchValue)); + } + // force l’affichage dans l’input dès qu’il existe + setSearchInputWhenReady(searchValue); + } + + + // ================================================================== + // --- Bind: ne PAS utiliser e.isTrusted (Metro déclenche un change programmatique) + const bindChange = (id, key, coerce = v => v) => { + const el = document.getElementById(id); + if (!el) return; + el.addEventListener('change', () => { + if (!ready) return; // on ignore les changements pendant l'init + const newVal = coerce(el.value); + navigateWithAll({ [key]: newVal }); + }, false); + }; + + bindChange('domain', 'domain', v => String(v)); + bindChange('clause', 'clause', v => String(v).trim()); + bindChange('scope', 'scope', v => String(v).trim()); + bindChange('cur_period', 'period', v => String(v)); + + // Radios status (OK de garder le flag ready) + const bindStatus = (id, value) => { + const el = document.getElementById(id); + if (!el) return; + el.addEventListener('change', () => { + if (!ready) return; + navigateWithAll({ status: String(value) }); + }, false); + }; + bindStatus('status0', 0); + bindStatus('status1', 1); + bindStatus('status2', 2); +}, false); + @endsection