|
|
|
|
@ -1,3 +1,12 @@
|
|
|
|
|
/* =========================================================================
|
|
|
|
|
* XIT Common JavaScript Library
|
|
|
|
|
* 중요도 순서: 1.환경설정 → 2.세션/보안 → 3.Ajax통신 → 4.공통유틸 → 5.UI컴포넌트
|
|
|
|
|
* ========================================================================= */
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* 1. ENVIRONMENT CONFIGURATION (최우선 - 시스템 기본 설정)
|
|
|
|
|
* ============================================================================= */
|
|
|
|
|
|
|
|
|
|
/* 컨택스트 패스 설정 로드 */
|
|
|
|
|
// 기본값 설정 (설정 로드 실패 시 사용)
|
|
|
|
|
var contextPath = '';
|
|
|
|
|
@ -7,7 +16,7 @@ var contextPath = '';
|
|
|
|
|
var scripts = document.getElementsByTagName('script');
|
|
|
|
|
var currentScript = scripts[scripts.length - 1];
|
|
|
|
|
var src = currentScript.src;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (src) {
|
|
|
|
|
// 스크립트 경로에서 컨택스트 패스 추출 (예: http://localhost:8080/context/resources/xit/xit-common.js)
|
|
|
|
|
var match = src.match(/^https?:\/\/[^\/]+([^\/]*?)\/resources\//);
|
|
|
|
|
@ -41,6 +50,218 @@ var loginUrl = '/login/login.do';
|
|
|
|
|
document.head.appendChild(script);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* 2. SESSION & SECURITY MANAGEMENT (세션 및 보안 관리)
|
|
|
|
|
* ============================================================================= */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 세션 만료 처리 함수 - 모든 팝업을 닫고 로그인 페이지로 이동
|
|
|
|
|
* 중요로직: 팝업 환경에서 세션 만료 시 현재 팝업이 아닌 최상위 창에서 로그인 페이지로 이동
|
|
|
|
|
*/
|
|
|
|
|
function handleSessionExpired() {
|
|
|
|
|
try {
|
|
|
|
|
console.log('[세션 만료] 처리 시작');
|
|
|
|
|
|
|
|
|
|
// 중요로직: 현재 창이 팝업인지 확인
|
|
|
|
|
var isPopup = !!(window.opener && !window.opener.closed);
|
|
|
|
|
console.log('[세션 만료] 현재 창 팝업 여부:', isPopup);
|
|
|
|
|
|
|
|
|
|
if (isPopup) {
|
|
|
|
|
// 팝업인 경우: 최상위 부모창 찾기
|
|
|
|
|
var topWindow = window;
|
|
|
|
|
var windowChain = [];
|
|
|
|
|
var currentWindow = window;
|
|
|
|
|
|
|
|
|
|
// 최상위 창까지 탐색
|
|
|
|
|
while (currentWindow && currentWindow.opener && !currentWindow.opener.closed) {
|
|
|
|
|
windowChain.push(currentWindow);
|
|
|
|
|
currentWindow = currentWindow.opener;
|
|
|
|
|
topWindow = currentWindow;
|
|
|
|
|
|
|
|
|
|
// 무한루프 방지 (최대 10단계)
|
|
|
|
|
if (windowChain.length > 10) {
|
|
|
|
|
console.warn('[세션 만료] 너무 많은 팝업 체인, 탐색 중단');
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('[세션 만료] 팝업 체인 길이:', windowChain.length);
|
|
|
|
|
console.log('[세션 만료] 최상위 창 찾음:', !!topWindow);
|
|
|
|
|
|
|
|
|
|
// 메시지 표시 (현재 팝업에서)
|
|
|
|
|
alert("세션이 종료되었습니다. 다시 로그인해주세요.");
|
|
|
|
|
|
|
|
|
|
// 최상위 창을 로그인 페이지로 이동
|
|
|
|
|
if (topWindow && !topWindow.closed) {
|
|
|
|
|
try {
|
|
|
|
|
topWindow.location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[세션 만료] 최상위 창 리다이렉트 성공');
|
|
|
|
|
} catch (redirectError) {
|
|
|
|
|
console.warn('[세션 만료] 최상위 창 리다이렉트 실패:', redirectError);
|
|
|
|
|
// 리다이렉트 실패 시 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 최상위 창이 닫혀있는 경우 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[세션 만료] 현재 창에서 리다이렉트');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 모든 팝업창 닫기 (약간의 지연 후)
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
try {
|
|
|
|
|
// 하위 팝업부터 상위 팝업 순서로 닫기
|
|
|
|
|
for (var i = 0; i < windowChain.length; i++) {
|
|
|
|
|
try {
|
|
|
|
|
var popupWindow = windowChain[i];
|
|
|
|
|
if (popupWindow && !popupWindow.closed) {
|
|
|
|
|
popupWindow.close();
|
|
|
|
|
console.log('[세션 만료] 팝업창 닫기 성공:', i + 1);
|
|
|
|
|
}
|
|
|
|
|
} catch (closeError) {
|
|
|
|
|
console.warn('[세션 만료] 팝업창 닫기 실패:', closeError);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
console.log('[세션 만료] 모든 팝업창 닫기 완료');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[세션 만료] 팝업창 일괄 닫기 실패:', e);
|
|
|
|
|
}
|
|
|
|
|
}, 300); // 리다이렉트 후 약간의 지연
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// 일반 페이지인 경우 기존 로직 사용
|
|
|
|
|
console.log('[세션 만료] 일반 페이지에서 처리');
|
|
|
|
|
redirectToLoginWithCloseAllPopups("세션이 종료되었습니다. 다시 로그인해주세요.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('[세션 만료] 전체 처리 중 오류:', e);
|
|
|
|
|
// 모든 처리가 실패한 경우 기본 처리
|
|
|
|
|
try {
|
|
|
|
|
alert("세션이 종료되었습니다. 다시 로그인해주세요.");
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
} catch (finalError) {
|
|
|
|
|
console.error('[세션 만료] 최종 처리도 실패:', finalError);
|
|
|
|
|
location.reload();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 모든 팝업을 닫고 메인페이지를 로그인 페이지로 이동시키는 함수
|
|
|
|
|
* 중요로직: 다중 팝업 구조에서 안전하게 모든 팝업을 닫고 최상위 창만 로그인 페이지로 이동
|
|
|
|
|
* @param {string} message - 사용자에게 표시할 메시지 (선택사항)
|
|
|
|
|
* @param {boolean} showAlert - alert 창 표시 여부 (기본값: true)
|
|
|
|
|
*/
|
|
|
|
|
function redirectToLoginWithCloseAllPopups(message, showAlert) {
|
|
|
|
|
try {
|
|
|
|
|
// 기본값 설정
|
|
|
|
|
if (showAlert === undefined) showAlert = true;
|
|
|
|
|
if (!message) message = "로그인 페이지로 이동합니다.";
|
|
|
|
|
|
|
|
|
|
// 메시지 표시
|
|
|
|
|
if (showAlert) {
|
|
|
|
|
alert(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 중요로직: 최상위 부모창 찾기 (다중 팝업 처리)
|
|
|
|
|
var topWindow = window;
|
|
|
|
|
var currentWindow = window;
|
|
|
|
|
|
|
|
|
|
// 현재 창부터 최상위까지의 모든 창 정보 수집
|
|
|
|
|
var windowChain = [];
|
|
|
|
|
while (currentWindow) {
|
|
|
|
|
windowChain.push({
|
|
|
|
|
window: currentWindow,
|
|
|
|
|
isPopup: !!(currentWindow.opener && !currentWindow.opener.closed)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (currentWindow.opener && !currentWindow.opener.closed) {
|
|
|
|
|
currentWindow = currentWindow.opener;
|
|
|
|
|
topWindow = currentWindow;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('[로그인 리다이렉트] 창 체인 정보:', windowChain.length + '개의 창 감지');
|
|
|
|
|
|
|
|
|
|
// 최상위 부모창을 로그인 페이지로 이동
|
|
|
|
|
if (topWindow && !topWindow.closed) {
|
|
|
|
|
try {
|
|
|
|
|
topWindow.location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[로그인 리다이렉트] 최상위 창 리다이렉트 성공');
|
|
|
|
|
} catch (redirectError) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 최상위 창 리다이렉트 실패:', redirectError);
|
|
|
|
|
// 리다이렉트 실패 시 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 최상위 창이 닫혀있는 경우 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[로그인 리다이렉트] 현재 창에서 리다이렉트');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 중요로직: 메인창 외에 모든 팝업창 종료
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
try {
|
|
|
|
|
var popupsToClose = windowChain.filter(function(item) {
|
|
|
|
|
return item.isPopup;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('[로그인 리다이렉트] 닫을 팝업 수:', popupsToClose.length);
|
|
|
|
|
|
|
|
|
|
// 수집된 모든 팝업창을 닫기 (하위창부터 상위창 순서)
|
|
|
|
|
for (var i = 0; i < popupsToClose.length; i++) {
|
|
|
|
|
try {
|
|
|
|
|
var popupWindow = popupsToClose[i].window;
|
|
|
|
|
if (popupWindow && !popupWindow.closed) {
|
|
|
|
|
popupWindow.close();
|
|
|
|
|
console.log('[로그인 리다이렉트] 팝업창 닫기 성공:', i + 1);
|
|
|
|
|
}
|
|
|
|
|
} catch (closeError) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 팝업창 닫기 실패:', closeError);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('[로그인 리다이렉트] 모든 팝업창 닫기 완료');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 팝업창 일괄 닫기 실패:', e);
|
|
|
|
|
// 기본 방식으로 현재 창 닫기 시도
|
|
|
|
|
if (window.opener && !window.opener.closed) {
|
|
|
|
|
try {
|
|
|
|
|
window.close();
|
|
|
|
|
} catch (fallbackError) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 기본 방식 팝업창 닫기도 실패:', fallbackError);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, 200); // 리다이렉트 후 약간의 지연을 두어 안정성 확보
|
|
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("[로그인 리다이렉트] 전체 처리 중 오류:", e);
|
|
|
|
|
// 모든 처리가 실패한 경우 현재 창에서 로그인 페이지로 이동
|
|
|
|
|
try {
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
} catch (finalError) {
|
|
|
|
|
console.error("[로그인 리다이렉트] 최종 리다이렉트도 실패:", finalError);
|
|
|
|
|
// 최후의 수단으로 새로고침
|
|
|
|
|
location.reload();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 로그아웃 함수 - 모든 팝업을 닫고 로그인 페이지로 이동
|
|
|
|
|
*/
|
|
|
|
|
function logout() {
|
|
|
|
|
redirectToLoginWithCloseAllPopups("로그아웃 되었습니다.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* 3. AJAX COMMUNICATION (Ajax 통신 관리)
|
|
|
|
|
* ============================================================================= */
|
|
|
|
|
|
|
|
|
|
/* jQuery Ajax 설정 */
|
|
|
|
|
$.ajaxSetup({
|
|
|
|
|
type:"POST",
|
|
|
|
|
@ -76,6 +297,9 @@ $(document).ajaxError( function( event, jqxhr, settings, exception ){
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/* Ajax Progress Block UI 설정 */
|
|
|
|
|
// Ajax 활성 요청 카운터 (동시 Ajax 요청 처리를 위함)
|
|
|
|
|
var activeAjaxCount = 0;
|
|
|
|
|
|
|
|
|
|
// Progress Block UI 초기화
|
|
|
|
|
$(document).ready(function() {
|
|
|
|
|
// Progress Block UI 생성
|
|
|
|
|
@ -87,9 +311,6 @@ $(document).ready(function() {
|
|
|
|
|
console.log('[Ajax Block UI] Ajax 카운터 초기화:', activeAjaxCount);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Ajax 활성 요청 카운터 (동시 Ajax 요청 처리를 위함)
|
|
|
|
|
var activeAjaxCount = 0;
|
|
|
|
|
|
|
|
|
|
// Ajax 시작 시 Progress Block UI 표시
|
|
|
|
|
$(document).ajaxSend(function(event, jqXHR, ajaxOptions) {
|
|
|
|
|
console.log('[Ajax Block UI] Ajax 시작:', ajaxOptions.url);
|
|
|
|
|
@ -178,45 +399,11 @@ function createProgressBlockUI() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* 4. COMMON UTILITIES (공통 유틸리티 함수들)
|
|
|
|
|
* ============================================================================= */
|
|
|
|
|
|
|
|
|
|
$(document).ready(function () {
|
|
|
|
|
$('.pop-x-btn, .modalclose').click(function() {
|
|
|
|
|
var tmp = $(this).parents().parents().parents()
|
|
|
|
|
if (tmp.attr('class') == 'modalz act') {
|
|
|
|
|
tmp.removeClass('act');
|
|
|
|
|
} else {
|
|
|
|
|
//tmp.removeClass('act');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 모달 닫기 이벤트를 설정하는 함수
|
|
|
|
|
* 모달 닫기 버튼 클릭 및 모달 외부 클릭 시 모달을 닫는 이벤트를 설정합니다.
|
|
|
|
|
* @param {string} modalId - 모달 요소의 ID (기본값: 'modal')
|
|
|
|
|
* @param {string} closeBtnSelector - 닫기 버튼의 선택자 (기본값: '.pop-x-btn, .modalclose')
|
|
|
|
|
*/
|
|
|
|
|
function initModalClose(modalId) {
|
|
|
|
|
// 기본값 설정
|
|
|
|
|
modalId = modalId || 'modal';
|
|
|
|
|
|
|
|
|
|
// '#' 접두사가 없는 경우 추가
|
|
|
|
|
if (!modalId.startsWith('#')) {
|
|
|
|
|
modalId = '#' + modalId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 모달 외부 클릭 시 닫기 (dim 영역 클릭 시)
|
|
|
|
|
$(modalId + ' .dim').on('click', function() {
|
|
|
|
|
$(modalId).removeClass('act');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ESC 키 입력 시 모달 닫기
|
|
|
|
|
$(document).on('keydown', function(e) {
|
|
|
|
|
if (e.keyCode === 27 && $(modalId).hasClass('act')) { // ESC key
|
|
|
|
|
$(modalId).removeClass('act');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
/* 4.1 VALIDATION UTILITIES (검증 관련 함수들) */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* HTML 엔티티를 원래 문자로 변환하는 함수
|
|
|
|
|
@ -318,14 +505,14 @@ function unescapeHtml(input) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return unescaped;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 입력값이 배열인 경우 각 요소를 재귀적으로 처리
|
|
|
|
|
else if (Array.isArray(input)) {
|
|
|
|
|
// 배열의 각 요소에 대해 재귀적으로 unescapeHtml 함수 적용
|
|
|
|
|
return input.map(function(item) {
|
|
|
|
|
return unescapeHtml(item);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 입력값이 객체인 경우 각 속성을 재귀적으로 처리
|
|
|
|
|
else if (typeof input === 'object') {
|
|
|
|
|
// 객체의 복사본 생성
|
|
|
|
|
@ -339,13 +526,15 @@ function unescapeHtml(input) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 기타 타입(숫자, 불리언 등)은 그대로 반환
|
|
|
|
|
else {
|
|
|
|
|
return input;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 4.2 COLOR UTILITIES (색상 관련 함수들) */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* selectbox option에 data-color가 있을 때 자동으로 색상을 적용하는 함수
|
|
|
|
|
* @param {string|jQuery} selector - selectbox 선택자 또는 jQuery 객체
|
|
|
|
|
@ -398,210 +587,53 @@ function makeColorTransparent(color, opacity) {
|
|
|
|
|
return color;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 모든 팝업을 닫고 메인페이지를 로그인 페이지로 이동시키는 함수
|
|
|
|
|
* 중요로직: 다중 팝업 구조에서 안전하게 모든 팝업을 닫고 최상위 창만 로그인 페이지로 이동
|
|
|
|
|
* @param {string} message - 사용자에게 표시할 메시지 (선택사항)
|
|
|
|
|
* @param {boolean} showAlert - alert 창 표시 여부 (기본값: true)
|
|
|
|
|
*/
|
|
|
|
|
function redirectToLoginWithCloseAllPopups(message, showAlert) {
|
|
|
|
|
try {
|
|
|
|
|
// 기본값 설정
|
|
|
|
|
if (showAlert === undefined) showAlert = true;
|
|
|
|
|
if (!message) message = "로그인 페이지로 이동합니다.";
|
|
|
|
|
|
|
|
|
|
// 메시지 표시
|
|
|
|
|
if (showAlert) {
|
|
|
|
|
alert(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 중요로직: 최상위 부모창 찾기 (다중 팝업 처리)
|
|
|
|
|
var topWindow = window;
|
|
|
|
|
var currentWindow = window;
|
|
|
|
|
|
|
|
|
|
// 현재 창부터 최상위까지의 모든 창 정보 수집
|
|
|
|
|
var windowChain = [];
|
|
|
|
|
while (currentWindow) {
|
|
|
|
|
windowChain.push({
|
|
|
|
|
window: currentWindow,
|
|
|
|
|
isPopup: !!(currentWindow.opener && !currentWindow.opener.closed)
|
|
|
|
|
});
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* 5. UI COMPONENTS (UI 컴포넌트들)
|
|
|
|
|
* ============================================================================= */
|
|
|
|
|
|
|
|
|
|
if (currentWindow.opener && !currentWindow.opener.closed) {
|
|
|
|
|
currentWindow = currentWindow.opener;
|
|
|
|
|
topWindow = currentWindow;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* 5.1 MODAL UTILITIES (모달 관련 함수들) */
|
|
|
|
|
|
|
|
|
|
console.log('[로그인 리다이렉트] 창 체인 정보:', windowChain.length + '개의 창 감지');
|
|
|
|
|
|
|
|
|
|
// 최상위 부모창을 로그인 페이지로 이동
|
|
|
|
|
if (topWindow && !topWindow.closed) {
|
|
|
|
|
try {
|
|
|
|
|
topWindow.location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[로그인 리다이렉트] 최상위 창 리다이렉트 성공');
|
|
|
|
|
} catch (redirectError) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 최상위 창 리다이렉트 실패:', redirectError);
|
|
|
|
|
// 리다이렉트 실패 시 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
}
|
|
|
|
|
$(document).ready(function () {
|
|
|
|
|
$('.pop-x-btn, .modalclose').click(function() {
|
|
|
|
|
var tmp = $(this).parents().parents().parents()
|
|
|
|
|
if (tmp.attr('class') == 'modalz act') {
|
|
|
|
|
tmp.removeClass('act');
|
|
|
|
|
} else {
|
|
|
|
|
// 최상위 창이 닫혀있는 경우 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[로그인 리다이렉트] 현재 창에서 리다이렉트');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 중요로직: 메인창 외에 모든 팝업창 종료
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
try {
|
|
|
|
|
var popupsToClose = windowChain.filter(function(item) {
|
|
|
|
|
return item.isPopup;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('[로그인 리다이렉트] 닫을 팝업 수:', popupsToClose.length);
|
|
|
|
|
|
|
|
|
|
// 수집된 모든 팝업창을 닫기 (하위창부터 상위창 순서)
|
|
|
|
|
for (var i = 0; i < popupsToClose.length; i++) {
|
|
|
|
|
try {
|
|
|
|
|
var popupWindow = popupsToClose[i].window;
|
|
|
|
|
if (popupWindow && !popupWindow.closed) {
|
|
|
|
|
popupWindow.close();
|
|
|
|
|
console.log('[로그인 리다이렉트] 팝업창 닫기 성공:', i + 1);
|
|
|
|
|
}
|
|
|
|
|
} catch (closeError) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 팝업창 닫기 실패:', closeError);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('[로그인 리다이렉트] 모든 팝업창 닫기 완료');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 팝업창 일괄 닫기 실패:', e);
|
|
|
|
|
// 기본 방식으로 현재 창 닫기 시도
|
|
|
|
|
if (window.opener && !window.opener.closed) {
|
|
|
|
|
try {
|
|
|
|
|
window.close();
|
|
|
|
|
} catch (fallbackError) {
|
|
|
|
|
console.warn('[로그인 리다이렉트] 기본 방식 팝업창 닫기도 실패:', fallbackError);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, 200); // 리다이렉트 후 약간의 지연을 두어 안정성 확보
|
|
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("[로그인 리다이렉트] 전체 처리 중 오류:", e);
|
|
|
|
|
// 모든 처리가 실패한 경우 현재 창에서 로그인 페이지로 이동
|
|
|
|
|
try {
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
} catch (finalError) {
|
|
|
|
|
console.error("[로그인 리다이렉트] 최종 리다이렉트도 실패:", finalError);
|
|
|
|
|
// 최후의 수단으로 새로고침
|
|
|
|
|
location.reload();
|
|
|
|
|
//tmp.removeClass('act');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 로그아웃 함수 - 모든 팝업을 닫고 로그인 페이지로 이동
|
|
|
|
|
*/
|
|
|
|
|
function logout() {
|
|
|
|
|
redirectToLoginWithCloseAllPopups("로그아웃 되었습니다.");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 세션 만료 처리 함수 - 모든 팝업을 닫고 로그인 페이지로 이동
|
|
|
|
|
* 중요로직: 팝업 환경에서 세션 만료 시 현재 팝업이 아닌 최상위 창에서 로그인 페이지로 이동
|
|
|
|
|
* 모달 닫기 이벤트를 설정하는 함수
|
|
|
|
|
* 모달 닫기 버튼 클릭 및 모달 외부 클릭 시 모달을 닫는 이벤트를 설정합니다.
|
|
|
|
|
* @param {string} modalId - 모달 요소의 ID (기본값: 'modal')
|
|
|
|
|
* @param {string} closeBtnSelector - 닫기 버튼의 선택자 (기본값: '.pop-x-btn, .modalclose')
|
|
|
|
|
*/
|
|
|
|
|
function handleSessionExpired() {
|
|
|
|
|
try {
|
|
|
|
|
console.log('[세션 만료] 처리 시작');
|
|
|
|
|
|
|
|
|
|
// 중요로직: 현재 창이 팝업인지 확인
|
|
|
|
|
var isPopup = !!(window.opener && !window.opener.closed);
|
|
|
|
|
console.log('[세션 만료] 현재 창 팝업 여부:', isPopup);
|
|
|
|
|
|
|
|
|
|
if (isPopup) {
|
|
|
|
|
// 팝업인 경우: 최상위 부모창 찾기
|
|
|
|
|
var topWindow = window;
|
|
|
|
|
var windowChain = [];
|
|
|
|
|
var currentWindow = window;
|
|
|
|
|
|
|
|
|
|
// 최상위 창까지 탐색
|
|
|
|
|
while (currentWindow && currentWindow.opener && !currentWindow.opener.closed) {
|
|
|
|
|
windowChain.push(currentWindow);
|
|
|
|
|
currentWindow = currentWindow.opener;
|
|
|
|
|
topWindow = currentWindow;
|
|
|
|
|
|
|
|
|
|
// 무한루프 방지 (최대 10단계)
|
|
|
|
|
if (windowChain.length > 10) {
|
|
|
|
|
console.warn('[세션 만료] 너무 많은 팝업 체인, 탐색 중단');
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('[세션 만료] 팝업 체인 길이:', windowChain.length);
|
|
|
|
|
console.log('[세션 만료] 최상위 창 찾음:', !!topWindow);
|
|
|
|
|
|
|
|
|
|
// 메시지 표시 (현재 팝업에서)
|
|
|
|
|
alert("세션이 종료되었습니다. 다시 로그인해주세요.");
|
|
|
|
|
|
|
|
|
|
// 최상위 창을 로그인 페이지로 이동
|
|
|
|
|
if (topWindow && !topWindow.closed) {
|
|
|
|
|
try {
|
|
|
|
|
topWindow.location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[세션 만료] 최상위 창 리다이렉트 성공');
|
|
|
|
|
} catch (redirectError) {
|
|
|
|
|
console.warn('[세션 만료] 최상위 창 리다이렉트 실패:', redirectError);
|
|
|
|
|
// 리다이렉트 실패 시 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 최상위 창이 닫혀있는 경우 현재 창에서 이동
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
console.log('[세션 만료] 현재 창에서 리다이렉트');
|
|
|
|
|
}
|
|
|
|
|
function initModalClose(modalId) {
|
|
|
|
|
// 기본값 설정
|
|
|
|
|
modalId = modalId || 'modal';
|
|
|
|
|
|
|
|
|
|
// 모든 팝업창 닫기 (약간의 지연 후)
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
try {
|
|
|
|
|
// 하위 팝업부터 상위 팝업 순서로 닫기
|
|
|
|
|
for (var i = 0; i < windowChain.length; i++) {
|
|
|
|
|
try {
|
|
|
|
|
var popupWindow = windowChain[i];
|
|
|
|
|
if (popupWindow && !popupWindow.closed) {
|
|
|
|
|
popupWindow.close();
|
|
|
|
|
console.log('[세션 만료] 팝업창 닫기 성공:', i + 1);
|
|
|
|
|
}
|
|
|
|
|
} catch (closeError) {
|
|
|
|
|
console.warn('[세션 만료] 팝업창 닫기 실패:', closeError);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
console.log('[세션 만료] 모든 팝업창 닫기 완료');
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[세션 만료] 팝업창 일괄 닫기 실패:', e);
|
|
|
|
|
}
|
|
|
|
|
}, 300); // 리다이렉트 후 약간의 지연
|
|
|
|
|
// '#' 접두사가 없는 경우 추가
|
|
|
|
|
if (!modalId.startsWith('#')) {
|
|
|
|
|
modalId = '#' + modalId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// 일반 페이지인 경우 기존 로직 사용
|
|
|
|
|
console.log('[세션 만료] 일반 페이지에서 처리');
|
|
|
|
|
redirectToLoginWithCloseAllPopups("세션이 종료되었습니다. 다시 로그인해주세요.");
|
|
|
|
|
}
|
|
|
|
|
// 모달 외부 클릭 시 닫기 (dim 영역 클릭 시)
|
|
|
|
|
$(modalId + ' .dim').on('click', function() {
|
|
|
|
|
$(modalId).removeClass('act');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('[세션 만료] 전체 처리 중 오류:', e);
|
|
|
|
|
// 모든 처리가 실패한 경우 기본 처리
|
|
|
|
|
try {
|
|
|
|
|
alert("세션이 종료되었습니다. 다시 로그인해주세요.");
|
|
|
|
|
location.href = (contextPath || '') + loginUrl;
|
|
|
|
|
} catch (finalError) {
|
|
|
|
|
console.error('[세션 만료] 최종 처리도 실패:', finalError);
|
|
|
|
|
location.reload();
|
|
|
|
|
// ESC 키 입력 시 모달 닫기
|
|
|
|
|
$(document).on('keydown', function(e) {
|
|
|
|
|
if (e.keyCode === 27 && $(modalId).hasClass('act')) { // ESC key
|
|
|
|
|
$(modalId).removeClass('act');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 5.2 SELECTBOX INITIALIZATION (selectbox 자동 색상 적용) */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 페이지 로드 시 모든 selectbox에 자동 색상 적용
|
|
|
|
|
*/
|
|
|
|
|
@ -637,4 +669,4 @@ $(document).ready(function() {
|
|
|
|
|
childList: true,
|
|
|
|
|
subtree: true
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|