// noinspection JSUnusedGlobalSymbols window.addEventListener('error', (event) => { alert(`오류가 발생했어요!\n메시지: ${event.message}\n위치: ${event.filename}:${event.lineno}`); }); function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } let lastFocusedElement = null; document.addEventListener('DOMContentLoaded', () => { // 1. 감시할 대상 요소 const targetNode = document.getElementById('explode'); // 2. 대상 요소가 DOM에 존재할 때만 옵저버 실행 if (targetNode) { const observer = new MutationObserver(async (mutations) => { for (const mutation of mutations) { // style 속성이 변경되었을 때 (display: block/none 등) if (mutation.type === 'attributes' && mutation.attributeName === 'style') { const $explode = $('#explode'); // 화면에 보이는 상태가 되었는지 확인 if ($explode.is(':visible')) { lastFocusedElement = document.activeElement; await sleep(1000); // 1. 포커스 할 타겟 요소 동적 탐색 let $focusTarget = $explode.find('button').first(); // 우선순위 1: button if ($focusTarget.length === 0) { // 우선순위 2: 다른 포커스 가능한 요소 (input, a, select 등) $focusTarget = $explode.find('input, a[href], select, textarea, [tabindex]:not([tabindex="-1"])').first(); } if ($focusTarget.length === 0) { // 우선순위 3: 포커스할 하위 요소가 아예 없으면 팝업 창 자체에 강제 포커스 $explode.attr('tabindex', '-1'); $focusTarget = $explode; } // 2. 타겟에 최초 포커스 $focusTarget.focus(); } else { // 닫혔을 때: 찌꺼기 이벤트 지우기 (메모리 누수 방지) $explode.off('keydown'); } } } }); // 3. 옵저버 감시 시작 (속성(attributes) 변화만 감시) observer.observe(targetNode, { attributes: true }); } }); //자리수 채우기 Number.prototype.fill = function (fix) { let len = String(this).length; if (len >= fix) { return this; } let spec = '0000'; while (fix > String(spec).length) { spec += '0000'; } return spec.substring(0, (fix - len)) + this; }; Date.prototype.date = function (fmt) { if (!this.valueOf()) return ''; if (!fmt) fmt = 'yyyy-MM-dd HH:mm:ss'; let weekName = ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일']; let d = this; return fmt.replace(/(yyyy|yy|MM|dd|E|HH|hh|mm|ss|a\/p)/gi, function ($1) { switch ($1) { case 'yyyy': return d.getFullYear(); case 'yy': return (d.getFullYear() % 1000).fill(2); case 'MM': return (d.getMonth() + 1).fill(2); case 'dd': return d.getDate().fill(2); case 'E': return weekName[d.getDay()]; case 'HH': return d.getHours().fill(2); case 'hh': return ((d = d.getHours() % 12) ? d : 12).fill(2); case 'mm': return d.getMinutes().fill(2); case 'ss': return d.getSeconds().fill(2); case 'a/p': return d.getHours() < 12 ? '오전' : '오후'; default: return $1; } }); }; function changeDate(dt) { if (!dt) return ''; try { return dt.date(); } catch (e) { return dt; } } $(function () { // placeholder 지원 안하는 브라우저는 js로 처리 $('input, textarea').placeholder(); $('.numonly').on('keypress', function (e) { let key = window.event ? window.event.keyCode : e.which; if (!(key > 47 && key < 58) && !(key > 95 && key < 106) && !(key === 8 || key === 9 || key === 37 || key === 39 || key === 46)) { e.preventDefault; } }).on('keyup', function () { $(this).val($(this).val().replace(/[^0-9]/g, '')); }); wtypeCheck(true); }); //각 영역 변경 function change(id) { $('div.body-container').hide(); $('#' + id).show(); $('html,body').scrollTop(0); stepOn(id); changeFooter(); } function stepOn(id) { let no = 0; switch (id) { case 'notice' : no = 0; break; case 'company' : $('#noticeAgreementYn').attr('checked', true); no = 1; break; case 'agreement': no = 1; break; case 'sub-notice-agreement' : no = 1; break; case 'question' : no = 1; break; case 'residence': no = 1; break; case 'private' : $('#noticeAgreementYn').attr('checked', true); $('#agreementYn').attr('checked', true); no = 2; break; case 'confirm' : no = 3; break; case 'apply' : no = 3; break; case 'result' : no = 4; break; } for (let i = 0; i <= 4; i++) { if (i > no) $('.step li').eq(i).removeClass('on'); else if (i === no) $('.step li').eq(i).addClass('on'); } } function changeFooter() { if ($(window).height() > $('body').height() + 60) { $('#footer').css({ 'position': 'fixed', 'bottom': 0, 'margin-top': 0 }); } else { $('#footer').css({ 'position': 'relative', 'margin-top': '50px' }); } } //쿠키저장 function setCookie(name, value, expireMinute) { let todayDate = new Date(); todayDate.setTime(todayDate.getTime() + (expireMinute * 60 * 1000)); document.cookie = name + '=' + escape(value) + '; path=/; expires=' + todayDate.toGMTString() + ';'; } //쿠키값읽어오기 function getCookie(name) { let arg = name + '='; let alen = arg.length; let clen = document.cookie.length; let i = 0; while (i < clen) { let j = i + alen; if (document.cookie.substring(i, j) === arg) return getCookieVal(j); i = document.cookie.indexOf(' ', i) + 1; if (i === 0) break; } return null; } //쿠키값읽어오기 function getCookieVal(offset) { let endstr = document.cookie.indexOf(';', offset); if (endstr === -1) endstr = document.cookie.length; return unescape(document.cookie.substring(offset, endstr)); } //쿠키삭제 // noinspection JSUnusedGlobalSymbols function deleteCookie(name) { let expireDate = new Date(); expireDate.setDate(expireDate.getDate() - 1); if ('' !== getCookie(name)) { document.cookie = name + '=' + ';expires=' + expireDate.toGMTString() + ';path=/'; } } // noinspection JSUnusedGlobalSymbols function closePopupToday() { if ($('#popupAlwaysYn').is(':checked')) { let minute = 24 * 60; setCookie('POPUP', 'Y', minute); showPopup('N'); } } function showPopup(yn) { if (yn === 'N') $('#popupAlways').hide(); else $('#popupAlways').show(); } let isMobile = false; function wtypeCheck(flag) { let filter = 'win16|win32|win64|mac|macintel'; isMobile = false; if (navigator.platform) { isMobile = filter.indexOf(navigator.platform.toLowerCase()) < 0; } if (flag) { // 처음부터 감춰 두고 권장 브라우저가 아닐 때만 보이는 안내(data-browser-check)는 showBrowserGuide 가 맡는다 — 여기서는 옛 꼴 안내만 const legacyGuide = $('.browser-guide').not('[data-browser-check]'); if (isMobile) { $('.wtype-pc').hide(); $('.wtype-mobile').show(); legacyGuide.hide(); } else { $('.wtype-pc').show(); $('.wtype-mobile').hide(); let browser = getBrowserType(); if (!(browser === 'IE11' || browser === 'Chrome' || browser === 'Safari')) { legacyGuide.show(); } else legacyGuide.hide(); } } } /* * 권장 브라우저인가 — 안내 문구 «Chrome · Edge · Safari 최신»(범주 10-29). 오래된 브라우저에서도 이 함수는 돌아야 하므로 ES5 로만 쓴다. * 크롬 엔진 브라우저(웨일 · 삼성 인터넷 · 앱 안 브라우저 등)는 크롬과 같게, iOS 는 모든 브라우저가 Safari 엔진이라 Safari 와 같게 본다. * «최신» 은 판 번호 대신 기능으로 본다 — structuredClone(Chrome · Edge 98, Safari 15.4 — 2022년 3월부터)이 없으면 오래된 판 */ function isRecommendedBrowser() { var ua = navigator.userAgent; if (typeof window.structuredClone !== 'function') return false; if (/iPhone|iPad|iPod/.test(ua) || (/Macintosh/.test(ua) && navigator.maxTouchPoints > 1)) return true; // Firefox · IE · 크롬 엔진 이전의 Edge(UA 에 Chrome 도 들어 있다) if (/Firefox\/|Trident\/|MSIE |Edge\/\d/.test(ua)) return false; if (/Chrome\/\d/.test(ua)) return true; return /Safari\//.test(ua) && /Version\/\d/.test(ua); } /* * 메인의 «※ Chrome · Edge · Safari 최신 브라우저를 …» 안내(.browser-guide[data-browser-check], 처음엔 hidden) — 권장 브라우저가 아닐 때만 보인다. * 안내 바로 뒤에서 부른다(DOM 준비를 기다리면 그사이 잠깐 보였다 사라진다) */ function showBrowserGuide() { var guides = document.querySelectorAll('.browser-guide[data-browser-check]'); var hide = isRecommendedBrowser(); for (var i = 0; i < guides.length; i++) guides[i].hidden = hide; } function getBrowserType() { let _ua = navigator.userAgent; //IE 11,10,9,8 let trident = _ua.match(/Trident\/(\d.\d)/i); if (trident !== null) { if (trident[1] === '7.0') return 'IE' + 11; if (trident[1] === '6.0') return 'IE' + 10; if (trident[1] === '5.0') return 'IE' + 9; if (trident[1] === '4.0') return 'IE' + 8; } //IE 7... if (navigator.appName === 'Microsoft Internet Explorer') return 'IE' + 7; //other let agt = _ua.toLowerCase(); if (agt.indexOf('chrome') !== -1) return 'Chrome'; if (agt.indexOf('opera') !== -1) return 'Opera'; if (agt.indexOf('staroffice') !== -1) return 'Star Office'; if (agt.indexOf('webtv') !== -1) return 'WebTV'; if (agt.indexOf('beonex') !== -1) return 'Beonex'; if (agt.indexOf('chimera') !== -1) return 'Chimera'; if (agt.indexOf('netpositive') !== -1) return 'NetPositive'; if (agt.indexOf('phoenix') !== -1) return 'Phoenix'; if (agt.indexOf('firefox') !== -1) return 'Firefox'; if (agt.indexOf('safari') !== -1) return 'Safari'; if (agt.indexOf('skipstone') !== -1) return 'SkipStone'; if (agt.indexOf('netscape') !== -1) return 'Netscape'; if (agt.indexOf('mozilla/5.0') !== -1) return 'Mozilla'; } function applyLink() { wtypeCheck(false); } // 본인인증 호출 function privateCall() { let windowW = 430; let windowH = 590; // 지금 브라우저 창의 가운데 — 모니터가 여럿이거나 1920 보다 넓으면 화면 기준 계산이 아래 · 옆으로 밀렸다 (QA-191) // 새 창 바깥은 테두리 · 주소 줄만큼 커서(웨일 실측 +16 · +87) 그 반을 뺀다 let left = Math.round(window.screenX + (window.outerWidth - windowW - 16) / 2); let top = Math.round(window.screenY + (window.outerHeight - windowH - 87) / 2); window.open( '', 'auth_popup', `width=${windowW},height=${windowH},scrollbar=yes,left=${left},top=${top},screenX=${left},screenY=${top}`, ); let form = document.privateForm; form.target = 'auth_popup'; form.submit(); } function btnColorChange(obj, id) { if (obj.checked) { $('#' + id + ' .bk').addClass('activationColor'); } else { $('#' + id + ' .bk').removeClass('activationColor'); } } function businessNumberView(n) { if (!n) return ''; // 숫자만 남기기 const onlyNum = String(n).replace(/[^0-9]/g, ''); // 10자리가 아니면 하이픈 없이 숫자만 반환 if (onlyNum.length !== 10) return onlyNum; // 정규식으로 그룹을 나눠서 하이픈 추가 return onlyNum.replace(/(\d{3})(\d{2})(\d{5})/, '$1-$2-$3'); } //번호 출력 - 4자리 단위 데시 구분 function mobileView(n) { let reg = /(^[+-]?\d+)(\d{4})/; let len = n.length; let i = 0; while (reg.test(n)) { if ((i > 0 && (len <= 10))) { reg = /(^[+-]?\d+)(\d{3})/; } n = n.replace(reg, '$1' + '-' + '$2'); i++; } return n; } function birthdayView(n) { let reg = /(\d{4})(\d{2})(\d{2})/; n = n.replace(reg, '$1-$2-$3'); return n; } function moneyView(money) { return money.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') + '원'; } function dateView(date) { return `${date.substring(0, 4)}년 ${date.substring(4, 6)}월 ${date.substring(6, 8)}일`; } function dateTimeView(dt) { return `${dt.substring(0, 4)}년 ${dt.substring(4, 6)}월 ${dt.substring(6, 8)}일 ${dt.substring(8, 10)}:${dt.substring(10, 12)}`; } function goWaitConfirm() { location.href = '/'; } function goLanding() { location.href = '/landing/index.do'; } function copyToClipboard() { let copyText = $('#cyberAccountNo'); copyText.select(); document.execCommand('Copy'); $('#cyber_account_no').focus(); } function multiDeposit(type) { $('.js-depositSite').addClass('blind'); if (type) { const types = type.split(';'); for (let i = 0; i < types.length; i++) { const type = types[i]; const typeItems = type.split('-'); if ($.isArray(typeItems) && typeItems.length > 0) { let groupName = typeItems[0].replace(/\s/gi, ''); if (MULTI_GROUP_NAME) { groupName = MULTI_GROUP_NAME[groupName] ? MULTI_GROUP_NAME[groupName] : groupName; } if ($('#' + groupName)) { $('#deposit' + groupName).removeClass('blind'); } } } } } function showYn(yn) { return yn === 'Y' ? '예' : yn === 'N' ? '아니오' : yn.includes(';') ? yn.replaceAll(';', ', ') : yn; } // otherAreaName 이 없으면 N 을 '기타'로 보여 준다 function showResidentialAreaName(yn, residentialAreaName, otherAreaName) { if (residentialAreaName) { return yn === 'Y' ? residentialAreaName : (otherAreaName || '기타'); } else { return yn === 'Y' ? '예' : yn === 'N' ? '아니오' : yn; } } // 법인 신청이면 법인 정보를 이름표 붙은 줄(법인명 · 대표자 · 개업연월일 · 사업자등록번호)로 주소 줄 위에 두고, // 주소 줄은 «사업장 소재지», 이름 줄은 «담당자» 로 부른다. 다시 조회하면 앞서 넣은 줄을 지우고 새로 넣는다 (QA-150) function showCompanyResultRows(info) { const addressRow = $('#result-address').closest('dl'); addressRow.siblings('.company-result-row').remove(); if (!info.companyYn || 'Y' !== info.companyYn.toUpperCase()) { $('#result-name').siblings('dt').text('이름'); addressRow.children('dt').text('주소'); return; } $('#result-name').siblings('dt').text('담당자'); addressRow.children('dt').text('사업장 소재지'); const companyDate = String(info.companyDate || '').replace(/^(\d{4})(\d{2})(\d{2})$/, '$1-$2-$3'); const rows = [ ['법인명', info.companyName], ['대표자', info.companyCeo], ['개업연월일', companyDate], ['사업자등록번호', businessNumberView(info.businessNumber)], ]; for (const [title, value] of rows) { addressRow.before( $('