다른 명령
편집 요약 없음 |
편집 요약 없음 |
||
| (같은 사용자의 중간 판 4개는 보이지 않습니다) | |||
| 1번째 줄: | 1번째 줄: | ||
/* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */ | /* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */ | ||
/ | /*Autofocus on when clicking search button*/ | ||
(function () { | (function () { | ||
const | const DETAILS_ID = 'citizen-search-details'; | ||
const | const TOGGLE_SEL = '#citizen-search-details > summary.citizen-dropdown-summary'; | ||
const REAL_INPUT_ID = 'searchInput'; | |||
function | function ensureProxy() { | ||
let p = document.getElementById('mw-search-proxy'); | |||
if ( | if (p) return p; | ||
p = document.createElement('input'); | |||
p.id = 'mw-search-proxy'; | |||
p.type = 'search'; | |||
p.autocomplete = 'off'; | |||
p.setAttribute('aria-hidden', 'true'); | |||
// | // "안 보이지만" 포커스는 가능한 상태로 (display:none / visibility:hidden 쓰면 포커스 자체가 막힘) | ||
p.style.position = 'fixed'; | |||
p.style.left = '-9999px'; | |||
p.style.top = '0'; | |||
p.style.width = '1px'; | |||
p.style.height = '1px'; | |||
p.style.opacity = '0'; | |||
p.style.pointerEvents = 'none'; | |||
document.documentElement.appendChild(p); | |||
return p; | |||
} | } | ||
function | function focusRealSoon() { | ||
const details = document.getElementById(DETAILS_ID); | |||
if ( | const real = document.getElementById(REAL_INPUT_ID); | ||
if (!details || !real) return; | |||
// | // 열기 보장 | ||
if (!details.open) details.open = true; | |||
// 레이아웃 한 번 강제 (iOS에 은근 도움 됨) | |||
void real.offsetHeight; | |||
// 키보드가 이미 떠있으면 real focus가 더 잘 붙는 편 | |||
real.focus({ preventScroll: true }); | |||
real.click(); | |||
} | |||
} | |||
function onToggleGesture(e) { | |||
const hit = e.target.closest(TOGGLE_SEL); | |||
if (!hit) return; | |||
// 1) 유저 제스처 안에서 "input focus"를 먼저 한 번 만들어줌 | |||
const proxy = ensureProxy(); | |||
try { | |||
proxy.focus({ preventScroll: true }); | |||
proxy.click(); | |||
} catch (_) {} | |||
// | // 2) 같은 제스처 안에서 real focus도 바로 시도 | ||
focusRealSoon(); | |||
// 3) 그래도 Citizen이 애니메이션/상태 적용을 늦게 하면 다음 프레임에 한 번 더 | |||
requestAnimationFrame(() => { | |||
focusRealSoon(); | |||
// proxy는 필요 없으니 정리 | |||
try { proxy.blur(); } catch (_) {} | |||
}); | |||
} | |||
// iOS에서 제일 잘 먹는 건 touchstart | |||
document.addEventListener('touchstart', onToggleGesture, { capture: true, passive: true }); | |||
document.addEventListener('click', onToggleGesture, true); | |||
})(); | })(); | ||
2026년 1월 17일 (토) 19:01 기준 최신판
/* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */
/*Autofocus on when clicking search button*/
(function () {
const DETAILS_ID = 'citizen-search-details';
const TOGGLE_SEL = '#citizen-search-details > summary.citizen-dropdown-summary';
const REAL_INPUT_ID = 'searchInput';
function ensureProxy() {
let p = document.getElementById('mw-search-proxy');
if (p) return p;
p = document.createElement('input');
p.id = 'mw-search-proxy';
p.type = 'search';
p.autocomplete = 'off';
p.setAttribute('aria-hidden', 'true');
// "안 보이지만" 포커스는 가능한 상태로 (display:none / visibility:hidden 쓰면 포커스 자체가 막힘)
p.style.position = 'fixed';
p.style.left = '-9999px';
p.style.top = '0';
p.style.width = '1px';
p.style.height = '1px';
p.style.opacity = '0';
p.style.pointerEvents = 'none';
document.documentElement.appendChild(p);
return p;
}
function focusRealSoon() {
const details = document.getElementById(DETAILS_ID);
const real = document.getElementById(REAL_INPUT_ID);
if (!details || !real) return;
// 열기 보장
if (!details.open) details.open = true;
// 레이아웃 한 번 강제 (iOS에 은근 도움 됨)
void real.offsetHeight;
// 키보드가 이미 떠있으면 real focus가 더 잘 붙는 편
real.focus({ preventScroll: true });
real.click();
}
function onToggleGesture(e) {
const hit = e.target.closest(TOGGLE_SEL);
if (!hit) return;
// 1) 유저 제스처 안에서 "input focus"를 먼저 한 번 만들어줌
const proxy = ensureProxy();
try {
proxy.focus({ preventScroll: true });
proxy.click();
} catch (_) {}
// 2) 같은 제스처 안에서 real focus도 바로 시도
focusRealSoon();
// 3) 그래도 Citizen이 애니메이션/상태 적용을 늦게 하면 다음 프레임에 한 번 더
requestAnimationFrame(() => {
focusRealSoon();
// proxy는 필요 없으니 정리
try { proxy.blur(); } catch (_) {}
});
}
// iOS에서 제일 잘 먹는 건 touchstart
document.addEventListener('touchstart', onToggleGesture, { capture: true, passive: true });
document.addEventListener('click', onToggleGesture, true);
})();