다른 명령
편집 요약 없음 |
편집 요약 없음 |
||
| 1번째 줄: | 1번째 줄: | ||
/* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */ | /* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */ | ||
(function () { | (function () { | ||
const DETAILS_ID = 'citizen-search-details'; | const DETAILS_ID = 'citizen-search-details'; | ||
| 11번째 줄: | 6번째 줄: | ||
const INPUT_ID = 'searchInput'; | const INPUT_ID = 'searchInput'; | ||
function | // 화면에 디버그 패널 띄우기 (모바일에서도 보이게) | ||
function panel() { | |||
let el = document.getElementById('nova-search-debug'); | |||
if (el) return el; | |||
el = document.createElement('div'); | |||
el.id = 'nova-search-debug'; | |||
el.style.cssText = | |||
'position:fixed;left:8px;right:8px;bottom:8px;z-index:999999;' + | |||
'padding:10px;border-radius:12px;background:rgba(0,0,0,.85);' + | |||
'color:#fff;font:12px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Arial;' + | |||
'white-space:pre-wrap;max-height:40vh;overflow:auto;'; | |||
el.textContent = '[search debug] ready\n'; | |||
document.documentElement.appendChild(el); | |||
return el; | |||
} | |||
function log(msg) { | |||
const el = panel(); | |||
const t = new Date().toISOString().slice(11, 19); | |||
el.textContent += `${t} ${msg}\n`; | |||
el.scrollTop = el.scrollHeight; | |||
} | |||
function state(tag) { | |||
const details = document.getElementById(DETAILS_ID); | |||
const input = document.getElementById(INPUT_ID); | |||
const open = details ? !!details.open : null; | |||
const inputExists = !!input; | |||
let vis = null, dis = null, rect = null, ae = null; | |||
if (input) { | |||
const r = input.getBoundingClientRect(); | |||
rect = `${Math.round(r.width)}x${Math.round(r.height)}`; | |||
dis = !!input.disabled; | |||
vis = !!(r.width > 0 && r.height > 0); | |||
} | |||
ae = document.activeElement ? (document.activeElement.id || document.activeElement.tagName) : null; | |||
log(`${tag} | details.open=${open} | input=${inputExists} vis=${vis} rect=${rect} disabled=${dis} | active=${ae}`); | |||
} | |||
function tryFocus(where) { | |||
const details = document.getElementById(DETAILS_ID); | const details = document.getElementById(DETAILS_ID); | ||
const input = document.getElementById(INPUT_ID); | const input = document.getElementById(INPUT_ID); | ||
state(`before focus (${where})`); | |||
// | if (!details) { log('NO details element'); return; } | ||
if (!input) { log('NO input element'); return; } | |||
// 열려있지 않으면 강제로 열기 | |||
if (!details.open) details.open = true; | if (!details.open) details.open = true; | ||
// | // iOS에서 가끔 필요: 레이아웃 동기화 | ||
void input.offsetHeight; | void input.offsetHeight; | ||
input.focus({ preventScroll: true }); | try { | ||
input.focus({ preventScroll: true }); | |||
input.click(); | |||
} catch (e) { | |||
log('focus threw: ' + e); | |||
} | |||
state(`after focus (${where})`); | |||
} | } | ||
// | // 1) 페이지 로드 자체 확인 | ||
log('Common.js loaded'); | |||
state('initial'); | |||
// 2) summary 탭 이벤트가 들어오는지 확인 (passive:false 중요) | |||
document.addEventListener( | document.addEventListener( | ||
'touchstart', | 'touchstart', | ||
function (e) { | function (e) { | ||
const | const hit = !!e.target.closest(TOGGLE_SEL); | ||
if (! | if (!hit) return; | ||
log('touchstart on toggle ✅ (intercept)'); | |||
e.preventDefault(); | e.preventDefault(); | ||
e.stopPropagation(); | e.stopPropagation(); | ||
tryFocus('touchstart'); | |||
}, | }, | ||
{ capture: true, passive: false } | { capture: true, passive: false } | ||
); | ); | ||
document.addEventListener( | document.addEventListener( | ||
'click', | 'click', | ||
function (e) { | function (e) { | ||
const | const hit = !!e.target.closest(TOGGLE_SEL); | ||
if (! | if (!hit) return; | ||
log('click on toggle ✅ (intercept)'); | |||
e.preventDefault(); | e.preventDefault(); | ||
e.stopPropagation(); | e.stopPropagation(); | ||
tryFocus('click'); | |||
}, | }, | ||
true | true | ||
); | ); | ||
// 3) details가 열리는 순간을 감시 (토글이 우리 코드 말고 다른 경로로 열릴 수도 있으니) | |||
const details = document.getElementById(DETAILS_ID); | |||
if (details) { | |||
const obs = new MutationObserver(() => state('details mutation')); | |||
obs.observe(details, { attributes: true, attributeFilter: ['open'] }); | |||
log('observing details[open]'); | |||
} else { | |||
log('details element not found at load time'); | |||
} | |||
})(); | })(); | ||
2026년 1월 17일 (토) 18:53 판
/* 이 자바스크립트 설정은 모든 문서, 모든 사용자에게 적용됩니다. */
(function () {
const DETAILS_ID = 'citizen-search-details';
const TOGGLE_SEL = '#citizen-search-details > summary.citizen-dropdown-summary';
const INPUT_ID = 'searchInput';
// 화면에 디버그 패널 띄우기 (모바일에서도 보이게)
function panel() {
let el = document.getElementById('nova-search-debug');
if (el) return el;
el = document.createElement('div');
el.id = 'nova-search-debug';
el.style.cssText =
'position:fixed;left:8px;right:8px;bottom:8px;z-index:999999;' +
'padding:10px;border-radius:12px;background:rgba(0,0,0,.85);' +
'color:#fff;font:12px/1.4 -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Arial;' +
'white-space:pre-wrap;max-height:40vh;overflow:auto;';
el.textContent = '[search debug] ready\n';
document.documentElement.appendChild(el);
return el;
}
function log(msg) {
const el = panel();
const t = new Date().toISOString().slice(11, 19);
el.textContent += `${t} ${msg}\n`;
el.scrollTop = el.scrollHeight;
}
function state(tag) {
const details = document.getElementById(DETAILS_ID);
const input = document.getElementById(INPUT_ID);
const open = details ? !!details.open : null;
const inputExists = !!input;
let vis = null, dis = null, rect = null, ae = null;
if (input) {
const r = input.getBoundingClientRect();
rect = `${Math.round(r.width)}x${Math.round(r.height)}`;
dis = !!input.disabled;
vis = !!(r.width > 0 && r.height > 0);
}
ae = document.activeElement ? (document.activeElement.id || document.activeElement.tagName) : null;
log(`${tag} | details.open=${open} | input=${inputExists} vis=${vis} rect=${rect} disabled=${dis} | active=${ae}`);
}
function tryFocus(where) {
const details = document.getElementById(DETAILS_ID);
const input = document.getElementById(INPUT_ID);
state(`before focus (${where})`);
if (!details) { log('NO details element'); return; }
if (!input) { log('NO input element'); return; }
// 열려있지 않으면 강제로 열기
if (!details.open) details.open = true;
// iOS에서 가끔 필요: 레이아웃 동기화
void input.offsetHeight;
try {
input.focus({ preventScroll: true });
input.click();
} catch (e) {
log('focus threw: ' + e);
}
state(`after focus (${where})`);
}
// 1) 페이지 로드 자체 확인
log('Common.js loaded');
state('initial');
// 2) summary 탭 이벤트가 들어오는지 확인 (passive:false 중요)
document.addEventListener(
'touchstart',
function (e) {
const hit = !!e.target.closest(TOGGLE_SEL);
if (!hit) return;
log('touchstart on toggle ✅ (intercept)');
e.preventDefault();
e.stopPropagation();
tryFocus('touchstart');
},
{ capture: true, passive: false }
);
document.addEventListener(
'click',
function (e) {
const hit = !!e.target.closest(TOGGLE_SEL);
if (!hit) return;
log('click on toggle ✅ (intercept)');
e.preventDefault();
e.stopPropagation();
tryFocus('click');
},
true
);
// 3) details가 열리는 순간을 감시 (토글이 우리 코드 말고 다른 경로로 열릴 수도 있으니)
const details = document.getElementById(DETAILS_ID);
if (details) {
const obs = new MutationObserver(() => state('details mutation'));
obs.observe(details, { attributes: true, attributeFilter: ['open'] });
log('observing details[open]');
} else {
log('details element not found at load time');
}
})();