Files
eapim-portal/src/main/resources/static/js/popup/custom-popups.js
T
Rinjae f79e528fec
eapim-portal CI / build (push) Has been cancelled
eapim-portal Test / test (push) Has been cancelled
이메일 인증 재발송 기능 제거 및 관련 코드 정리
- `emailResendPopup` 및 팝업 호출 로직 삭제
- `InquiryAdminNotifier` → `CommunityAdminNotifier`로 클래스 명칭 변경
- 제휴 신청 시 관리자 알림 로직 추가
2026-06-24 19:45:37 +09:00

733 lines
26 KiB
JavaScript

const customPopups = {
/**
* HTML 새니타이저 - 허용된 태그만 통과시키고 나머지는 제거
* XSS 방지를 위해 script, event handler 등 위험 요소를 제거합니다.
* @param {string} input - 새니타이즈할 문자열
* @returns {string} 새니타이즈된 HTML 문자열
*/
_sanitizeHtml: function (input) {
if (!input) return '';
var allowedTags = ['br', 'strong', 'b', 'em', 'i', 'span', 'p'];
var div = document.createElement('div');
div.innerHTML = input;
// script, style, iframe, object, embed, form 등 위험 요소 제거
var dangerousTags = div.querySelectorAll('script, style, iframe, object, embed, form, link, meta, base');
for (var i = dangerousTags.length - 1; i >= 0; i--) {
dangerousTags[i].parentNode.removeChild(dangerousTags[i]);
}
// 허용되지 않은 태그는 텍스트 노드로 대체
var allElements = div.querySelectorAll('*');
for (var j = allElements.length - 1; j >= 0; j--) {
var el = allElements[j];
if (allowedTags.indexOf(el.tagName.toLowerCase()) === -1) {
var textNode = document.createTextNode(el.textContent);
el.parentNode.replaceChild(textNode, el);
} else {
// 허용된 태그라도 모든 속성 제거 (on* 이벤트 핸들러 등 방지)
while (el.attributes.length > 0) {
el.removeAttribute(el.attributes[0].name);
}
}
}
return div.innerHTML;
},
/**
* 알림 팝업 표시
* @param {string} message - 알림 메시지
* @param {Function} callback - 확인 버튼 클릭 시 호출되는 콜백 (선택사항)
*/
showAlert: function (message, callback) {
// 메시지 설정 (XSS 방지를 위해 새니타이즈)
$('#customAlertMessage').html(customPopups._sanitizeHtml(message));
// 팝업 표시 (modal 구조 사용)
$('#customAlert').show();
setTimeout(function() {
$('#customAlertBackdrop').addClass('show');
$('#customAlertModal').addClass('show');
}, 10);
// Body 스크롤 방지
$('body').css('overflow', 'hidden');
// 확인 버튼에 포커스
setTimeout(function() {
$('#customAlertOkButton').focus();
}, 350);
// 확인 버튼 클릭 이벤트 (기존 이벤트 제거 후 재등록)
$('#customAlertOkButton').off('click').on('click', function () {
customPopups.hideAlert();
if (typeof callback === 'function') {
callback();
}
});
// 닫기 버튼 클릭 이벤트
$('#customAlertCloseButton').off('click').on('click', function () {
customPopups.hideAlert();
if (typeof callback === 'function') {
callback();
}
});
// Enter 키 이벤트
$(document).off('keydown.customAlert').on('keydown.customAlert', function (e) {
if (e.key === 'Enter') {
customPopups.hideAlert();
if (typeof callback === 'function') {
callback();
}
}
});
// Escape 키 이벤트
$(document).off('keydown.customAlertEsc').on('keydown.customAlertEsc', function (e) {
if (e.key === 'Escape') {
customPopups.hideAlert();
if (typeof callback === 'function') {
callback();
}
}
});
},
/**
* 알림 팝업 숨기기
*/
hideAlert: function () {
// Modal 숨김 애니메이션
$('#customAlertBackdrop').removeClass('show');
$('#customAlertModal').removeClass('show');
// 애니메이션 완료 후 숨김
setTimeout(function() {
$('#customAlert').hide();
}, 300);
// Body 스크롤 복원
$('body').css('overflow', '');
// 이벤트 리스너 제거
$('#customAlertOkButton').off('click');
$('#customAlertCloseButton').off('click');
$(document).off('keydown.customAlert');
$(document).off('keydown.customAlertEsc');
},
/**
* 비밀번호 입력 팝업 표시
* @param {Object} options - 팝업 옵션
* @param {string} options.title - 팝업 제목 (기본값: "비밀번호 입력")
* @param {string} options.message - 안내 메시지 (기본값: "계속하려면 비밀번호를 입력해주세요.")
* @param {Function} options.onConfirm - 확인 버튼 클릭 시 호출되는 콜백 (파라미터: password)
* @param {Function} options.onCancel - 취소 버튼 클릭 시 호출되는 콜백 (선택사항)
*/
showPasswordInput: function (options) {
options = options || {};
// 기본값 설정
const title = options.title || '비밀번호 입력';
const message = options.message || '계속하려면 비밀번호를 입력해주세요.';
const onConfirm = options.onConfirm;
const onCancel = options.onCancel;
// 팝업 내용 설정 (XSS 방지를 위해 새니타이즈)
$('#passwordPopupTitle').text(title);
$('#passwordPopupMessage').html(customPopups._sanitizeHtml(message));
// 입력 필드 및 에러 초기화
$('#passwordPopupInput').val('').removeClass('error');
$('#passwordPopupError').removeClass('show').text('');
// 팝업 표시 (modal 구조 사용)
$('#passwordInputPopup').show();
setTimeout(function() {
$('#passwordModalBackdrop').addClass('show');
$('#passwordModal').addClass('show');
}, 10);
// Body 스크롤 방지
$('body').css('overflow', 'hidden');
// 입력 필드에 포커스
setTimeout(function() {
$('#passwordPopupInput').focus();
}, 350);
// 확인 버튼 이벤트 (기존 이벤트 제거 후 재등록)
$('#passwordPopupConfirmButton').off('click').on('click', function () {
const password = $('#passwordPopupInput').val().trim();
if (!password) {
customPopups.showPasswordError('비밀번호를 입력해주세요.');
return;
}
if (typeof onConfirm === 'function') {
onConfirm(password);
}
});
// 취소 버튼 이벤트
$('#passwordPopupCancelButton').off('click').on('click', function () {
customPopups.hidePasswordInput();
if (typeof onCancel === 'function') {
onCancel();
}
});
// 닫기 버튼 이벤트
$('#passwordPopupCloseButton').off('click').on('click', function () {
customPopups.hidePasswordInput();
if (typeof onCancel === 'function') {
onCancel();
}
});
// Enter 키 이벤트
$('#passwordPopupInput').off('keypress').on('keypress', function (e) {
if (e.which === 13) {
$('#passwordPopupConfirmButton').click();
}
});
// 입력 시 에러 초기화
$('#passwordPopupInput').off('input').on('input', function () {
customPopups.clearPasswordError();
});
},
/**
* 비밀번호 입력 팝업 숨기기
*/
hidePasswordInput: function () {
// Modal 숨김 애니메이션
$('#passwordModalBackdrop').removeClass('show');
$('#passwordModal').removeClass('show');
// 애니메이션 완료 후 숨김
setTimeout(function() {
$('#passwordInputPopup').hide();
}, 300);
// Body 스크롤 복원
$('body').css('overflow', '');
// 입력 필드 초기화
$('#passwordPopupInput').val('').removeClass('error');
$('#passwordPopupError').removeClass('show').text('');
// 이벤트 리스너 제거
$('#passwordPopupConfirmButton').off('click');
$('#passwordPopupCancelButton').off('click');
$('#passwordPopupCloseButton').off('click');
$('#passwordPopupInput').off('keypress').off('input');
},
/**
* 비밀번호 입력 에러 메시지 표시
* @param {string} message - 에러 메시지
*/
showPasswordError: function (message) {
$('#passwordPopupError').text(message).addClass('show');
$('#passwordPopupInput').addClass('error');
},
/**
* 비밀번호 입력 에러 메시지 제거
*/
clearPasswordError: function () {
$('#passwordPopupError').removeClass('show');
$('#passwordPopupInput').removeClass('error');
},
/**
* 확인 팝업 표시
* @param {string} message - 확인 메시지
* @param {Function} callback - 버튼 클릭 시 호출되는 콜백 (파라미터: boolean - true는 확인, false는 취소)
*/
showConfirm: function (message, callback) {
// 메시지 설정 (XSS 방지를 위해 새니타이즈)
$('#customConfirmMessage').html(customPopups._sanitizeHtml(message));
// 팝업 표시 (modal 구조 사용)
$('#customConfirm').show();
setTimeout(function() {
$('#customConfirmBackdrop').addClass('show');
$('#customConfirmModal').addClass('show');
}, 10);
// Body 스크롤 방지
$('body').css('overflow', 'hidden');
// 확인 버튼에 포커스
setTimeout(function() {
$('#customConfirmYesButton').focus();
}, 350);
// 확인 버튼 클릭 이벤트 (기존 이벤트 제거 후 재등록)
$('#customConfirmYesButton').off('click').on('click', function () {
customPopups.hideConfirm();
if (typeof callback === 'function') {
callback(true);
}
});
// 취소 버튼 클릭 이벤트
$('#customConfirmNoButton').off('click').on('click', function () {
customPopups.hideConfirm();
if (typeof callback === 'function') {
callback(false);
}
});
// 닫기 버튼 클릭 이벤트
$('#customConfirmCloseButton').off('click').on('click', function () {
customPopups.hideConfirm();
if (typeof callback === 'function') {
callback(false);
}
});
// Enter 키 이벤트 (확인 버튼 실행)
$(document).off('keydown.customConfirm').on('keydown.customConfirm', function (e) {
if (e.key === 'Enter') {
customPopups.hideConfirm();
if (typeof callback === 'function') {
callback(true);
}
}
});
// Escape 키 이벤트 (취소)
$(document).off('keydown.customConfirmEsc').on('keydown.customConfirmEsc', function (e) {
if (e.key === 'Escape') {
customPopups.hideConfirm();
if (typeof callback === 'function') {
callback(false);
}
}
});
},
/**
* 확인 팝업 숨기기
*/
hideConfirm: function () {
// Modal 숨김 애니메이션
$('#customConfirmBackdrop').removeClass('show');
$('#customConfirmModal').removeClass('show');
// 애니메이션 완료 후 숨김
setTimeout(function() {
$('#customConfirm').hide();
}, 300);
// Body 스크롤 복원
$('body').css('overflow', '');
// 이벤트 리스너 제거
$('#customConfirmYesButton').off('click');
$('#customConfirmNoButton').off('click');
$('#customConfirmCloseButton').off('click');
$(document).off('keydown.customConfirm');
$(document).off('keydown.customConfirmEsc');
},
showEmailValidationPopup: function (message, onConvertCallback, onChangeEmailCallback) {
$('#emailValidationPopupMessage').html(customPopups._sanitizeHtml(message));
$('#emailValidationPopup').css('display', 'flex');
$('#emailConvertButton').one('click', function () {
$('#emailValidationPopup').hide();
if (onConvertCallback) onConvertCallback();
});
$('#emailChangeButton').one('click', function () {
$('#emailValidationPopup').hide();
if (onChangeEmailCallback) onChangeEmailCallback();
});
$('#emailValidationPopupCloseButton').one('click', function () {
$('#emailValidationPopup').hide();
});
},
/**
* 사용자 초대 팝업 표시
* @param {Object} options - 팝업 옵션
* @param {Function} options.onConfirm - 확인 버튼 클릭 시 호출되는 콜백 (파라미터: mobile, notifyConsent)
* @param {Function} options.onCancel - 취소 버튼 클릭 시 호출되는 콜백 (선택사항)
*/
showUserInvite: function (options) {
options = options || {};
const onConfirm = options.onConfirm;
const onCancel = options.onCancel;
// 입력 필드 및 에러 초기화
$('#userInviteMobileInput').val('').removeClass('error');
$('#userInviteNotifyConsent').prop('checked', false);
$('#userInvitePopupError').removeClass('show').text('');
// 팝업 표시 (modal 구조 사용)
$('#userInvitePopup').show();
setTimeout(function() {
$('#userInviteModalBackdrop').addClass('show');
$('#userInviteModal').addClass('show');
}, 10);
// Body 스크롤 방지
$('body').css('overflow', 'hidden');
// 입력 필드에 포커스
setTimeout(function() {
$('#userInviteMobileInput').focus();
}, 350);
// 확인 버튼 이벤트 (기존 이벤트 제거 후 재등록)
$('#userInvitePopupConfirmButton').off('click').on('click', function () {
const mobile = $('#userInviteMobileInput').val().trim();
const notifyConsent = $('#userInviteNotifyConsent').is(':checked');
// 휴대폰 번호 유효성 검사
if (!mobile) {
customPopups.showUserInviteError('휴대폰 번호를 입력해주세요.');
return;
}
// 휴대폰 번호 형식 검증 (하이픈 유무 모두 허용)
const mobilePattern = /^01[016-9]-?\d{3,4}-?\d{4}$/;
if (!mobilePattern.test(mobile)) {
customPopups.showUserInviteError('올바른 휴대폰 번호 형식이 아닙니다.');
return;
}
if (typeof onConfirm === 'function') {
onConfirm(mobile, notifyConsent);
}
});
// 취소 버튼 이벤트
$('#userInvitePopupCancelButton').off('click').on('click', function () {
customPopups.hideUserInvite();
if (typeof onCancel === 'function') {
onCancel();
}
});
// 닫기 버튼 이벤트
$('#userInvitePopupCloseButton').off('click').on('click', function () {
customPopups.hideUserInvite();
if (typeof onCancel === 'function') {
onCancel();
}
});
// Enter 키 이벤트
$('#userInviteMobileInput').off('keypress').on('keypress', function (e) {
if (e.which === 13) {
$('#userInvitePopupConfirmButton').click();
}
});
// 입력 시 에러 초기화
$('#userInviteMobileInput').off('input').on('input', function () {
customPopups.clearUserInviteError();
});
},
/**
* 사용자 초대 팝업 숨기기
*/
hideUserInvite: function () {
// Modal 숨김 애니메이션
$('#userInviteModalBackdrop').removeClass('show');
$('#userInviteModal').removeClass('show');
// 애니메이션 완료 후 숨김
setTimeout(function() {
$('#userInvitePopup').hide();
}, 300);
// Body 스크롤 복원
$('body').css('overflow', '');
// 입력 필드 초기화
$('#userInviteMobileInput').val('').removeClass('error');
$('#userInviteNotifyConsent').prop('checked', false);
$('#userInvitePopupError').removeClass('show').text('');
// 이벤트 리스너 제거
$('#userInvitePopupConfirmButton').off('click');
$('#userInvitePopupCancelButton').off('click');
$('#userInvitePopupCloseButton').off('click');
$('#userInviteMobileInput').off('keypress').off('input');
},
/**
* 사용자 초대 에러 메시지 표시
* @param {string} message - 에러 메시지
*/
showUserInviteError: function (message) {
$('#userInvitePopupError').text(message).addClass('show');
$('#userInviteMobileInput').addClass('error');
},
/**
* 사용자 초대 에러 메시지 제거
*/
clearUserInviteError: function () {
$('#userInvitePopupError').removeClass('show');
$('#userInviteMobileInput').removeClass('error');
},
/**
* 초대취소 팝업 표시 (알림 수신 동의 체크박스 포함)
* @param {Object} options - 팝업 옵션
* @param {string} options.target - 취소 대상 표시 문자열 (마스킹된 이메일/휴대폰)
* @param {Function} options.onConfirm - 확인 버튼 클릭 시 호출되는 콜백 (파라미터: notifyConsent)
* @param {Function} options.onCancel - 취소(닫기) 버튼 클릭 시 호출되는 콜백 (선택사항)
*/
showCancelInvitation: function (options) {
options = options || {};
const target = options.target || '';
const onConfirm = options.onConfirm;
const onCancel = options.onCancel;
// 대상 정보 및 체크박스 초기화
$('#cancelInvitationTarget').text(target);
$('#cancelInvitationNotifyConsent').prop('checked', false);
// 팝업 표시 (modal 구조 사용)
$('#cancelInvitationPopup').show();
setTimeout(function() {
$('#cancelInvitationModalBackdrop').addClass('show');
$('#cancelInvitationModal').addClass('show');
}, 10);
// Body 스크롤 방지
$('body').css('overflow', 'hidden');
// 확인 버튼 이벤트 (기존 이벤트 제거 후 재등록)
$('#cancelInvitationPopupConfirmButton').off('click').on('click', function () {
const notifyConsent = $('#cancelInvitationNotifyConsent').is(':checked');
if (typeof onConfirm === 'function') {
onConfirm(notifyConsent);
}
});
// 닫기 버튼 이벤트
$('#cancelInvitationPopupCancelButton').off('click').on('click', function () {
customPopups.hideCancelInvitation();
if (typeof onCancel === 'function') {
onCancel();
}
});
// X 버튼 이벤트
$('#cancelInvitationPopupCloseButton').off('click').on('click', function () {
customPopups.hideCancelInvitation();
if (typeof onCancel === 'function') {
onCancel();
}
});
// Escape 키 이벤트
$(document).off('keydown.cancelInvitation').on('keydown.cancelInvitation', function (e) {
if (e.key === 'Escape') {
customPopups.hideCancelInvitation();
if (typeof onCancel === 'function') {
onCancel();
}
}
});
},
/**
* 초대취소 팝업 숨기기
*/
hideCancelInvitation: function () {
// Modal 숨김 애니메이션
$('#cancelInvitationModalBackdrop').removeClass('show');
$('#cancelInvitationModal').removeClass('show');
// 애니메이션 완료 후 숨김
setTimeout(function() {
$('#cancelInvitationPopup').hide();
}, 300);
// Body 스크롤 복원
$('body').css('overflow', '');
// 체크박스 초기화
$('#cancelInvitationNotifyConsent').prop('checked', false);
// 이벤트 리스너 제거
$('#cancelInvitationPopupConfirmButton').off('click');
$('#cancelInvitationPopupCancelButton').off('click');
$('#cancelInvitationPopupCloseButton').off('click');
$(document).off('keydown.cancelInvitation');
},
/**
* 권한 변경 팝업 표시
* @param {Object} options - 팝업 옵션
* @param {string} options.userName - 사용자 이름
* @param {string} options.userEmail - 사용자 이메일
* @param {string} options.userId - 사용자 ID
* @param {Function} options.onConfirm - 확인 버튼 클릭 시 호출되는 콜백 (파라미터: userId)
* @param {Function} options.onCancel - 취소 버튼 클릭 시 호출되는 콜백 (선택사항)
*/
showChangeRole: function (options) {
options = options || {};
const userName = options.userName || '';
const userEmail = options.userEmail || '';
const userId = options.userId;
const onConfirm = options.onConfirm;
const onCancel = options.onCancel;
// 사용자 정보 설정
$('#changeRoleUserName').text(userName);
$('#changeRoleUserEmail').text(userEmail ? `(${userEmail})` : '');
// 팝업 표시 (modal 구조 사용)
$('#changeRolePopup').show();
setTimeout(function() {
$('#changeRoleModalBackdrop').addClass('show');
$('#changeRoleModal').addClass('show');
}, 10);
// Body 스크롤 방지
$('body').css('overflow', 'hidden');
// 확인 버튼 이벤트 (기존 이벤트 제거 후 재등록)
$('#changeRolePopupConfirmButton').off('click').on('click', function () {
if (typeof onConfirm === 'function') {
onConfirm(userId);
}
});
// 취소 버튼 이벤트
$('#changeRolePopupCancelButton').off('click').on('click', function () {
customPopups.hideChangeRole();
if (typeof onCancel === 'function') {
onCancel();
}
});
// 닫기 버튼 이벤트
$('#changeRolePopupCloseButton').off('click').on('click', function () {
customPopups.hideChangeRole();
if (typeof onCancel === 'function') {
onCancel();
}
});
// Escape 키 이벤트
$(document).off('keydown.changeRole').on('keydown.changeRole', function (e) {
if (e.key === 'Escape') {
customPopups.hideChangeRole();
if (typeof onCancel === 'function') {
onCancel();
}
}
});
},
/**
* 권한 변경 팝업 숨기기
*/
hideChangeRole: function () {
// Modal 숨김 애니메이션
$('#changeRoleModalBackdrop').removeClass('show');
$('#changeRoleModal').removeClass('show');
// 애니메이션 완료 후 숨김
setTimeout(function() {
$('#changeRolePopup').hide();
}, 300);
// Body 스크롤 복원
$('body').css('overflow', '');
// 이벤트 리스너 제거
$('#changeRolePopupConfirmButton').off('click');
$('#changeRolePopupCancelButton').off('click');
$('#changeRolePopupCloseButton').off('click');
$(document).off('keydown.changeRole');
},
showWithdrawal: function () {
$('#withdrawalPopup').show();
setTimeout(function() {
$('#withdrawalModalBackdrop').addClass('show');
$('#withdrawalModal').addClass('show');
}, 10);
$('body').css('overflow', 'hidden');
$('#withdrawalPopupConfirmButton').off('click').on('click', function () {
customPopups.hideWithdrawal();
$('#withdrawalForm').submit();
});
$('#withdrawalPopupCancelButton').off('click').on('click', function () {
customPopups.hideWithdrawal();
});
$('#withdrawalPopupCloseButton').off('click').on('click', function () {
customPopups.hideWithdrawal();
});
$(document).off('keydown.withdrawal').on('keydown.withdrawal', function (e) {
if (e.key === 'Escape') {
customPopups.hideWithdrawal();
}
});
},
hideWithdrawal: function () {
$('#withdrawalModalBackdrop').removeClass('show');
$('#withdrawalModal').removeClass('show');
setTimeout(function() {
$('#withdrawalPopup').hide();
}, 300);
$('body').css('overflow', '');
$('#withdrawalPopupConfirmButton').off('click');
$('#withdrawalPopupCancelButton').off('click');
$('#withdrawalPopupCloseButton').off('click');
$(document).off('keydown.withdrawal');
},
init: function () {
// emailValidationPopup 팝업의 닫기 버튼에 이벤트 리스너 추가
$('#emailValidationPopupCloseButton').on('click', function () {
$('#emailValidationPopup').hide();
});
$('#confirmButton, #emailResendPopupCloseButton').on('click', function () {
$('#emailResend').hide();
});
// 다른 팝업의 닫기 버튼에 이벤트 리스너 추가 (modernized popups 제외)
$('.btn_close').on('click', function () {
const $popup = $(this).closest('.popup_total');
if ($popup.length) {
$popup.hide();
}
});
}
};
$(document).ready(function () {
customPopups.init();
});