PageSourceSearch

https://www.sdm.go.kr/lib/accessibility/modal/modal.js?v=2023120601

js sdm.go.kr collected 2026-10-02 05:06:52 UTC 9,095 bytes, 189 lines download raw bytes

1$( document ).ready(function() {
2    const popupBtnAll = document.querySelectorAll('[aria-haspopup="dialog"]');
3    if (popupBtnAll) {
4    let currentTarget, focusEl = [], popupDepth = 0, popupDimmed, keyEscapeEvt, KeyEvtEl;
5    const _$this = this,
6    popupAll = document.querySelectorAll('[role="dialog"]'),
7    popupCloseBtnAll = document.querySelectorAll('[popup-close]');
8    // ESC 누름 감지
9    const keyEvent = {
10        get keyEscape() {
11        return this._state;
12        },
13        set keyEscape(state) {
14        this._state = state;
15        if (state) escKeyEvt(KeyEvtEl, keyEscapeEvt);
16        },
17    };
18    keyEvent;
19    // popup dimmed 생성
20    const createdDimmed = () => {
21        const createDiv = document.createElement('div');
22        createDiv.classList.add('popup-dimmed');
23        document.querySelector('body').appendChild(createDiv);
24    };
25    // popup dimmed click 시 팝업 닫기
26    const dimmedClick = (e) => {
27        if (e.target.classList.contains('wrap-layer-popup')) {
28        popupCloseAll();
29        keyEvent.keyEscape = false;
30        }
31    };
32    // popup open
33    const popupOpen = (e) => {
34        currentTarget = e.target.tagName;
35        currentTarget === 'BUTTON' || currentTarget === 'A' ? currentTarget = e.target : currentTarget = e.target.closest('button') || e.target.closest('a');
36        
37        popupDimmed = document.querySelectorAll('.popup-dimmed');
38        if (popupDimmed.length === 0) createdDimmed();
39
40        popupAll.forEach((popupEl) => {
41        if (popupEl.getAttribute('data-popup') === currentTarget.getAttribute('data-popup')) {
42            popupDepth += 1; // popup depth 저장
43            focusEl.splice((popupDepth - 1), 0, currentTarget); // popup focus Element 저장
44            popupEl.classList.add('popup-open'); // open class add
45            popupEl.setAttribute('popup-depth', popupDepth); // popup depth 설정
46
47            // dimmed click 이벤트 할당
48            popupEl.removeEventListener('click', dimmedClick);
49            popupEl.addEventListener('click', dimmedClick);
50
51            document.body.classList.add('scroll-lock'); // popup scroll lock
52            popupEl.querySelector('.wrap-layer-popup-title').focus(); // popup 오픈 시 타이틀에 포커스
53
54            // shift+tab 또는 <- 화살표 키 키보드 동작 시 팝업 밖으로 포커스 이동 방지 이벤트 할당
55            popupEl.querySelector('.wrap-layer-popup-title').removeEventListener('keydown', titleKeyDown);
56            popupEl.querySelector('.wrap-layer-popup-title').addEventListener('keydown', titleKeyDown);
57            
58            // popup 위 팝업 케이스 dimmed 수정
59            if (popupDepth > 1) document.querySelector(`[popup-depth='${popupDepth - 1}']`).classList.add('prev-popup');
60
61            KeyEvtEl = popupEl; // ESC 키 동작을 위한 현재 활성화 된 popup element 저장
62        };
63        });
64    };
65    // popup close
66    const popupClose = (e) => {
67        // 키보드 이벤트 ESC 일 경우 currentTarget 설정
68        if (e.key == 'Escape' || e.key == 'Esc') currentTarget = KeyEvtEl.querySelector('.btn-layer-close');
69        // 일반적인 클릭, 키보드 이벤트 일 경우 currentTarget 설정
70        else {
71        currentTarget = e.target.tagName;
72        currentTarget === 'BUTTON' || currentTarget === 'A' ? currentTarget = e.target : currentTarget = e.target.closest('button') || e.target.closest('a');
73        let popupId = currentTarget.getAttribute('popup-close');
74        if (currentTarget.getAttribute('popup-close-all') === 'true') return popupCloseAll();
75        if (currentTarget.getAttribute('popup-confirm')) confirmEvt[popupId]();
76        else if (currentTarget.getAttribute('popup-cancel')) cancelEvt[popupId]();
77        }
78        popupAll.forEach((popupEl) => {
79        if (popupEl.getAttribute('data-popup') === currentTarget.getAttribute('popup-close')) {
80            popupEl.classList.remove('popup-open');
81            // 저장된 focus element 가 있을 때
82            if (focusEl.length > 0) {
83            focusEl[popupDepth - 1].focus(); // focus 상태 재설정
84            focusEl.splice((popupDepth - 1), 1); // popup focus Element 삭제
85            popupDepth -= 1; // popup depth 재설정
86            KeyEvtEl = document.querySelector(`.wrap-layer-popup[popup-depth='${popupDepth}']`); // ESC 키 동작을 위한 현재 활성화 된 popup element 저장
87            }
87 else { // 저장된 focus element 가 없을 때
88            document.body.setAttribute('tabindex', '0');
89            document.body.focus();
90            KeyEvtEl = null;
91            }
92        };
93        });
94        // 오픈 된 popup이 있는 지 확인
95        const openPopups = document.querySelectorAll(`.popup-open`);
96        if (openPopups.length === 0) popupCloseAll('none');
97        else if (openPopups.length > 0) { // 오픈된 popup이 있을 경우 popup dimmed 수정
98        const getPopupValue = currentTarget.getAttribute('popup-close') || currentTarget.getAttribute('data-popup');
99        const getPopupDepth = Number(document.querySelector(`.wrap-layer-popup[data-popup='${getPopupValue}']`).getAttribute('popup-depth'));
100        document.querySelector(`.wrap-layer-popup[popup-depth='${getPopupDepth - 1}']`).classList.remove('prev-popup');
101        document.querySelector(`.wrap-layer-popup[data-popup='${getPopupValue}']`).removeAttribute('popup-depth');
102        };
103    };
104    // popup close All
105    const popupCloseAll = (focusActionNone) => {
106        // dimmed 삭제
107        const popupDimmed = document.querySelector('.popup-dimmed');
108        popupDimmed.style.opacity = 0;
109        popupDimmed.addEventListener('transitionend', function() {
110        if (popupDimmed.parentNode !== null) popupDimmed.parentNode.removeChild(popupDimmed);
111        });
112        // popup depth 설정 삭제
113        popupAll.forEach((popupEl) => {
114        popupEl.classList.remove('prev-popup');
115        popupEl.removeAttribute('popup-depth');
116        });
117        // scroll lock 해지
118        document.body.classList.remove('scroll-lock');
119        // popupClose Event 통해서 focus 설정이 되지 않았을 경우 (popupCloseAll 단독 실행일 경우)
120        if (focusActionNone !== 'none') {
121        if (focusEl.length > 0) focusEl[0].focus();  // 저장된 focus element 가 있을 때
122        else { // 저장된 focus element 가 없을 때
123            document.body.setAttribute('tabindex', '0');
124            document.body.focus();
125        };
126        focusEl = []; // focus reset
127        }
128        popupAll.forEach((popupEl) => popupEl.classList.remove('popup-open')); // open class 삭제
129        popupDepth = 0; // popup depth reset
130        KeyEvtEl = null; // KeyEvtEl reset
131    };
132
133    // ESC 키보드 이벤트
134    const escKeyEvt = (El, e) => {
135        const openPopups = document.querySelectorAll(`.popup-open`);
136        // 팝업 열린 상태에서 키보드 ESC 키 이벤트 실행 
137        if (openPopups.length > 0) popupClose(e);
138    };
139    // popup 닫기 키보드 이벤트
140    const closeBtnKeyDown = (e) => {
141        if ((e.key == 'Tab' && !e.shiftKey) || e.key == 'ArrowRight') {
142        e.preventDefault();
143        popupAll.forEach((popupEl) => {
144            if (popupEl.getAttribute('data-popup') === e.target.getAttribute('popup-close')) {
145                popupEl.querySelector('.wrap-layer-popup-title').focus();
146            };
147        });
148        };
149    };
150    // popup title 키보드 이벤트
151    const titleKeyDown = (e) => {
152        if ((e.key == 'Tab' && e.shiftKey) || e.key == 'ArrowLeft') {
153        e.preventDefault();
154        popupAll.forEach((popupEl) => {
155            if (popupEl.getAttribute('data-popup') === e.target.closest('.wrap-layer-popup').getAttribute('data-popup')) {
156            popupEl.querySelector('.btn-layer-close').focus();
157            };
158        });
159        };
160    };
161
162    // 키보드 ESC 키 누름 감지 이벤트
163    const escKeyDown = (e) => {
164        if (e.key == 'Escape' || e.key == 'Esc') {
165        keyEscapeEvt = e;
166        keyEvent.keyEscape = true;
167        };
168    };
169
170    // 클릭/키보드 팝업 이벤트 제거/할당
171    // 팝업 열기
172    popupBtnAll.forEach((popupBtn) => {
173        popupBtn.removeEventListener('click', popupOpen);
174        popupBtn.addEventListener('click', popupOpen);
175    });
176    // 팝업 닫기 
177    popupCloseBtnAll.forEach((popupCloseBtn) => {
178        popupCloseBtn.removeEventListener('click', popupClose);
179        popupCloseBtn.addEventListener('click', popupClose);
180        if (popupCloseBtn.classList.contains('btn-layer-close')) {
181        popupCloseBtn.removeEventListener('keydown', closeBtnKeyDown);
182        popupCloseBtn.addEventListener('keydown', closeBtnKeyDown);
183        }
184    });
185    // ESC 키로 팝업 닫기
186    window.removeEventListener('keydown', escKeyDown);
187    window.addEventListener('keydown', escKeyDown);
188    }
189});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.