다른 명령
편집 요약 없음 |
편집 요약 없음 |
||
| 2번째 줄: | 2번째 줄: | ||
/** | /** | ||
* | * Aggressive autofocus for Citizen search | ||
* - Remembers user intent even during page load | |||
* - Focuses input the moment it becomes available & visible | |||
* - | |||
* - | |||
*/ | */ | ||
(function () { | (function () { | ||
const TOGGLE_SELECTOR = '#citizen-search-details > summary.citizen-dropdown-summary'; | const TOGGLE_SELECTOR = | ||
'#citizen-search-details > summary.citizen-dropdown-summary'; | |||
const INPUT_SELECTOR = '#searchInput'; | const INPUT_SELECTOR = '#searchInput'; | ||
function | let wantFocus = false; | ||
let observer = null; | |||
let retryTimer = null; | |||
function canFocus(input) { | |||
if (!input) return false; | |||
if (input.disabled) return false; | |||
const rect = input.getBoundingClientRect(); | |||
return rect.width > 0 && rect.height > 0; | |||
} | |||
function tryFocus() { | |||
if (!wantFocus) return; | |||
const input = document.querySelector(INPUT_SELECTOR); | const input = document.querySelector(INPUT_SELECTOR); | ||
if (!input) return | if (!canFocus(input)) return; | ||
input.focus({ preventScroll: true }); | input.focus({ preventScroll: true }); | ||
input.click(); | input.click(); | ||
if (document.activeElement === input) { | |||
cleanup(); | |||
} | |||
} | } | ||
function | function cleanup() { | ||
wantFocus = false; | |||
if ( | if (observer) observer.disconnect(); | ||
observer = null; | |||
if (retryTimer) clearInterval(retryTimer); | |||
retryTimer = null; | |||
} | } | ||
function startWatching() { | |||
// 1) DOM 변화 감시 | |||
if (!observer) { | |||
observer = new MutationObserver(tryFocus); | |||
observer.observe(document.body, { | |||
childList: true, | |||
subtree: true, | |||
attributes: true, | |||
}); | |||
} | |||
// 2) 혹시 Mutation이 안 잡히는 케이스 대비 폴링 | |||
if (!retryTimer) { | |||
retryTimer = setInterval(tryFocus, 50); | |||
} | |||
} | |||
} | |||
} | |||
function onSearchIntent() { | |||
wantFocus = true; | |||
tryFocus(); // 즉시 한 번 | |||
startWatching(); // 안 되면 끝까지 쫓아감 | |||
} | |||
// 🔑 진짜 중요한 부분: "유저 제스처"에서 intent만 기록 | |||
['touchstart', 'touchend', 'mousedown', 'click'].forEach((evt) => { | |||
document.addEventListener( | |||
evt, | |||
function (e) { | |||
if (e.target.closest(TOGGLE_SELECTOR)) { | |||
onSearchIntent(); | |||
} | } | ||
}, | |||
true | |||
); | |||
}); | |||
})(); | })(); | ||
2026년 1월 17일 (토) 18:49 판
/* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */
/**
* Aggressive autofocus for Citizen search
* - Remembers user intent even during page load
* - Focuses input the moment it becomes available & visible
*/
(function () {
const TOGGLE_SELECTOR =
'#citizen-search-details > summary.citizen-dropdown-summary';
const INPUT_SELECTOR = '#searchInput';
let wantFocus = false;
let observer = null;
let retryTimer = null;
function canFocus(input) {
if (!input) return false;
if (input.disabled) return false;
const rect = input.getBoundingClientRect();
return rect.width > 0 && rect.height > 0;
}
function tryFocus() {
if (!wantFocus) return;
const input = document.querySelector(INPUT_SELECTOR);
if (!canFocus(input)) return;
input.focus({ preventScroll: true });
input.click();
if (document.activeElement === input) {
cleanup();
}
}
function cleanup() {
wantFocus = false;
if (observer) observer.disconnect();
observer = null;
if (retryTimer) clearInterval(retryTimer);
retryTimer = null;
}
function startWatching() {
// 1) DOM 변화 감시
if (!observer) {
observer = new MutationObserver(tryFocus);
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
});
}
// 2) 혹시 Mutation이 안 잡히는 케이스 대비 폴링
if (!retryTimer) {
retryTimer = setInterval(tryFocus, 50);
}
}
function onSearchIntent() {
wantFocus = true;
tryFocus(); // 즉시 한 번
startWatching(); // 안 되면 끝까지 쫓아감
}
// 🔑 진짜 중요한 부분: "유저 제스처"에서 intent만 기록
['touchstart', 'touchend', 'mousedown', 'click'].forEach((evt) => {
document.addEventListener(
evt,
function (e) {
if (e.target.closest(TOGGLE_SELECTOR)) {
onSearchIntent();
}
},
true
);
});
})();