다른 명령
편집 요약 없음 |
편집 요약 없음 |
||
| 5번째 줄: | 5번째 줄: | ||
* Triggered when MobileFrontend search UI opens | * Triggered when MobileFrontend search UI opens | ||
* Improves UX by immediately opening the virtual keyboard | * Improves UX by immediately opening the virtual keyboard | ||
*/ | |||
/** | |||
* iOS-friendly autofocus for Citizen search | |||
* - Bind focus to the actual user gesture on the search toggle (summary) | |||
* - Use a couple rAFs to wait for the input to appear/expand | |||
*/ | */ | ||
(function () { | (function () { | ||
const TOGGLE_SELECTOR = '#citizen-search-details > summary.citizen-dropdown-summary'; | |||
const INPUT_SELECTOR = '#searchInput'; | |||
function focusInput() { | |||
const input = document.querySelector(INPUT_SELECTOR); | |||
if (!input) return false; | if (!input) return false; | ||
// | // If the toggle is still animating / collapsing, focus may fail. | ||
// preventScroll avoids weird jump on mobile. | |||
input.focus({ preventScroll: true }); | input.focus({ preventScroll: true }); | ||
// | // Some iOS versions are picky; a click can help trigger the keyboard. | ||
// (Harmless elsewhere.) | |||
input.click(); | input.click(); | ||
| 24번째 줄: | 31번째 줄: | ||
} | } | ||
// | function focusSoon() { | ||
// Try immediately first (best chance to count as user gesture) | |||
if (focusInput()) return; | |||
// Then wait 1-2 frames for Citizen to render/open the search card | |||
requestAnimationFrame(() => { | |||
if (focusInput()) return; | |||
requestAnimationFrame(() => focusInput()); | |||
}); | |||
} | |||
// Use capturing so we still get it even if other handlers stop propagation. | |||
document.addEventListener( | |||
'touchend', | |||
function (e) { | |||
if (e.target.closest(TOGGLE_SELECTOR)) focusSoon(); | |||
}, | |||
true | |||
); | |||
// Fallback for devices/browsers that don't fire touchend as expected | |||
document.addEventListener( | |||
'click', | |||
function (e) { | |||
if (e.target.closest(TOGGLE_SELECTOR)) focusSoon(); | |||
}, | |||
true | |||
); | |||
})(); | |||
/*general*/ | |||
(function () { | |||
document.addEventListener( | function focusSearch() { | ||
const input = | |||
document.querySelector('.citizen-search__input') || | |||
// 검색 버튼 | document.querySelector('#searchInput') || | ||
const isSearchButton = e.target.closest( | document.querySelector('input[type="search"]'); | ||
if (input) { | |||
input.focus({ preventScroll: true }); | |||
input.click(); | |||
} | |||
} | |||
// 검색 버튼/아이콘(스킨마다 다름)에서 이벤트로 잡기 | |||
document.addEventListener('click', function (e) { | |||
// Citizen/모바일에서 검색 토글 버튼 후보들 | |||
const isSearchButton = | |||
e.target.closest('.citizen-search__button, .mw-ui-icon-search, .search-toggle, a[title="Search"], button[title="Search"]'); | |||
if (!isSearchButton) return; | if (!isSearchButton) return; | ||
// | // 버튼 누른 "직후" 입력창이 생기므로 프레임 2번 정도만 양보 | ||
requestAnimationFrame(() => requestAnimationFrame(focusSearch)); | |||
}, true); | |||
requestAnimationFrame(() => | |||
})(); | })(); | ||
2026년 1월 17일 (토) 18:45 판
/* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */
/**
* Autofocus search input on mobile
* Triggered when MobileFrontend search UI opens
* Improves UX by immediately opening the virtual keyboard
*/
/**
* iOS-friendly autofocus for Citizen search
* - Bind focus to the actual user gesture on the search toggle (summary)
* - Use a couple rAFs to wait for the input to appear/expand
*/
(function () {
const TOGGLE_SELECTOR = '#citizen-search-details > summary.citizen-dropdown-summary';
const INPUT_SELECTOR = '#searchInput';
function focusInput() {
const input = document.querySelector(INPUT_SELECTOR);
if (!input) return false;
// If the toggle is still animating / collapsing, focus may fail.
// preventScroll avoids weird jump on mobile.
input.focus({ preventScroll: true });
// Some iOS versions are picky; a click can help trigger the keyboard.
// (Harmless elsewhere.)
input.click();
return document.activeElement === input;
}
function focusSoon() {
// Try immediately first (best chance to count as user gesture)
if (focusInput()) return;
// Then wait 1-2 frames for Citizen to render/open the search card
requestAnimationFrame(() => {
if (focusInput()) return;
requestAnimationFrame(() => focusInput());
});
}
// Use capturing so we still get it even if other handlers stop propagation.
document.addEventListener(
'touchend',
function (e) {
if (e.target.closest(TOGGLE_SELECTOR)) focusSoon();
},
true
);
// Fallback for devices/browsers that don't fire touchend as expected
document.addEventListener(
'click',
function (e) {
if (e.target.closest(TOGGLE_SELECTOR)) focusSoon();
},
true
);
})();
/*general*/
(function () {
function focusSearch() {
const input =
document.querySelector('.citizen-search__input') ||
document.querySelector('#searchInput') ||
document.querySelector('input[type="search"]');
if (input) {
input.focus({ preventScroll: true });
input.click();
}
}
// 검색 버튼/아이콘(스킨마다 다름)에서 이벤트로 잡기
document.addEventListener('click', function (e) {
// Citizen/모바일에서 검색 토글 버튼 후보들
const isSearchButton =
e.target.closest('.citizen-search__button, .mw-ui-icon-search, .search-toggle, a[title="Search"], button[title="Search"]');
if (!isSearchButton) return;
// 버튼 누른 "직후" 입력창이 생기므로 프레임 2번 정도만 양보
requestAnimationFrame(() => requestAnimationFrame(focusSearch));
}, true);
})();