Files
sake/src/main/resources/static/js/gcone.js
2025-12-16 18:18:53 +09:00

1319 lines
49 KiB
JavaScript

/**
*
*/
/**************************************************************
* CK editor객체 선언
****************************************************************/
let CKEditorArray = [];
/**************************************************************
* CKeditor 생성
* 파라미터 설명{
* selectorId : CKediotr가 생성될 HTML Object ID
* data : ediotr영역에 출력할 데이터
* }
****************************************************************/
const fn_create_ckeditor = function (selectorId, data) {
CKSource
.Editor
.create(document.querySelector(selectorId), {
extraPlugins: [gconeUploadAdapterPlugin],
removePlugins: [
'Markdown', 'Title'
],
toolbar: {
items: [
'undo', 'redo', '|',
'findAndReplace', 'selectAll', '|',
'link', 'insertImage', 'insertTable', 'blockQuote', 'mediaEmbed', 'codeBlock', 'horizontalLine', 'specialCharacters', '|',
'outdent', 'indent', '|',
'bulletedList', 'numberedList', 'todoList',
'-',
'heading', 'style', '|',
'bold', 'italic', 'underline', 'strikethrough',
{
label: 'Basic styles',
icon: 'text',
items: [
'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'highlight',
'superscript', 'subscript', 'code'
],
},
'removeFormat', '|',
'alignment', 'pageBreak'
],
shouldNotGroupWhenFull: true
},
mediaEmbed: {
previewsInData: true,
},
style: {
definitions: [
{
name: 'Title',
element: 'h1',
classes: ['document-title'],
},
{
name: 'Subtitle',
element: 'h2',
classes: ['document-subtitle'],
},
{
name: 'Callout',
element: 'p',
classes: ['callout'],
},
{
name: 'Side quote',
element: 'blockquote',
classes: ['side-quote'],
},
{
name: 'Needs clarification',
element: 'span',
classes: ['needs-clarification'],
},
{
name: 'Wide spacing',
element: 'span',
classes: ['wide-spacing'],
},
{
name: 'Small caps',
element: 'span',
classes: ['small-caps'],
},
{
name: 'Code (dark)',
element: 'pre',
classes: ['stylish-code', 'stylish-code-dark'],
},
{
name: 'Code (bright)',
element: 'pre',
classes: ['stylish-code', 'stylish-code-bright'],
},
],
},
}).then(editor => {
if (data != null) {
editor.setData(data);
}
CKEditorArray[selectorId] = editor;
}).catch(error => {
console.log(error);
});
}
/**************************************************************
* CKeditor에 작성된 값 가져오기
* 파라미터 설명{
* selectorId : CKediotr가 생성된 HTML Object ID
* }
****************************************************************/
const fn_get_editor_data = function (selectorId) {
return CKEditorArray[selectorId].getData();
}
/**************************************************************
* CKeditor에 특정값 설정하기
* 파라미터 설명{
* selectorId : CKediotr가 생성된 HTML Object ID
* data : 에디터 영역에 설정할 내용
* }
****************************************************************/
const fn_set_editor_data = function (selectorId, data) {
return CKEditorArray[selectorId].setData(data);
}
// gconeUploadAdapterPlugin 정의
const gconeUploadAdapterPlugin = function (editor) {
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return new UploadAdapter(loader);
};
};
/**************************************************************
* Tab영역 활성화/비활성화
* 파라미터 설명{
* index : 선택된 Tab버튼 순서
* }
****************************************************************/
const fn_set_content_tab = function (index) {
const contentTabBtn = $(".content-tab__btn");
const contentTabContent = $(".content-tab__content");
contentTabBtn.removeClass("active");
contentTabContent.removeClass("active");
contentTabBtn.eq(index).addClass("active");
contentTabContent.eq(index).addClass("active");
}
/* ********************************************************
* 카카오 주소 찾기 연동(pc)
* 파라미터 설명 {
* callback : 카카오 주소 찾기 팝업에서 주소 선택 후 호출될 콜백함수
* }
******************************************************** */
const fn_select_postcode = function (callback, btn = null) {
new daum.Postcode({
oncomplete: function (data) {
const postcode = data.zonecode;
const roadAddr = data.roadAddress;
const jibunAddress = data.jibunAddress;
let addressType = '';
let extraRoadAddr = '';
// userSelectedType R/J 검색 결과에서 사용자가 선택한 주소의 타입(R : 도로명, J : 지번)
if (data.userSelectedType == 'R') {
addressType = '01';
} else {
addressType = '02';
}
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if (data.bname !== '' && /[동|로|가]$/g.test(data.bname)) {
extraRoadAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if (data.buildingName !== '' || data.apartment === 'Y') {
extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if (extraRoadAddr !== '' && roadAddr !== '') {
extraRoadAddr = ' (' + extraRoadAddr + ')';
}
callback({
postcode: postcode,
roadAddress: roadAddr,
jibunAddress: jibunAddress,
addressType: addressType,
extraAddress: extraRoadAddr
}, btn);
}
}).open();
}
/* ************************************************************
* 모바일 모달 show 함수
* modalId : 콜백 함수 이름
************************************************************* */
const openModal = (modalId) => {
MicroModal.show(modalId, {
onShow: function (modal) {
// 이미 존재하지 않는 경우에만 Hash 추가
if (window.location.hash !== '#' + modalId) {
window.history.replaceState({modal: 'open'}, '', '#' + modalId);
}
}
});
window.history.replaceState({}, '', window.location.href.split('#')[0]);
}
/* ************************************************************
* 모바일 모달 show 함수_# 추가 X
* modalId : 콜백 함수 이름
************************************************************* */
const openModal2 = (modalId) => {
MicroModal.show(modalId);
}
/* ************************************************************
* 모바일 모달 show 함수
* modalId : 콜백 함수 이름
* message : 얼러트 내용
************************************************************* */
const openModal_message = (modalId, message) => {
MicroModal.show(modalId, {
onShow: function (modal) {
// 이미 존재하지 않는 경우에만 Hash 추가
if (window.location.hash !== '#' + modalId) {
window.history.replaceState({modal: 'open'}, '', '#' + modalId);
}
$('.message').text(message);
},
});
}
/* ************************************************************
* 모바일 모달 닫고, URL Hash 제거
* modalId : 콜백 함수 이름
************************************************************* */
const closeModal = (modalId) => {
// 모달 닫힐 때 body 스크롤 복원
document.body.style.overflow = '';
// MicroModal을 사용해 모달 닫기
MicroModal.close(modalId);
// 추가적인 히스토리 항목을 생성하지 않고 URL에서 #이후부터 Hash 제거
window.history.replaceState({}, '', window.location.href.split('#')[0]);
}
/* ********************************************************
* 카카오 주소 찾기 연동(모바일)
* 파라미터 설명 {
* callback : 카카오 주소 찾기 팝업에서 주소 선택 후 호출될 콜백함수
* }
******************************************************** */
const fn_select_post_mobile = (callback,modalNm,isModal, btn = null) => {
// 우편번호 찾기 화면을 넣을 element
var element_wrap = $('#postCodeCn');
// jQuery 객체를 DOM 요소로 변환
var element = element_wrap.get(0);
// 현재 scroll 위치를 저장해놓는다.
if (element) {
new daum.Postcode({
oncomplete: function (data) {
const postcode = data.zonecode;
const roadAddr = data.roadAddress;
const jibunAddress = data.jibunAddress;
let addressType = '';
let extraRoadAddr = '';
// userSelectedType R/J 검색 결과에서 사용자가 선택한 주소의 타입(R : 도로명, J : 지번)
if (data.userSelectedType == 'R') {
addressType = '01';
} else {
addressType = '02';
}
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if (data.bname !== '' && /[동|로|가]$/g.test(data.bname)) {
extraRoadAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if (data.buildingName !== '' && data.apartment === 'Y') {
extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if (extraRoadAddr !== '' && roadAddr !== '') {
extraRoadAddr = ' (' + extraRoadAddr + ')';
}
callback({
postcode: postcode,
roadAddress: roadAddr,
jibunAddress: jibunAddress,
addressType: addressType,
extraAddress: extraRoadAddr
}, btn);
},
width: '100%',
height: '100%'
}).embed(element);
} else {
console.error('선택한 요소가 존재하지 않습니다: ', '#postCodeCn');
}
// iframe을 넣은 element를 보이게 한다.
if (element) {
element.style.display = 'block';
openModal2("postModal");
}
}
/**************************************************************
* 모달팝업 열기
* 파라미터 설명{
* modalDivSltr : 모달팝업화면이 추가될 div html selector
* modalSlrt : 모달팝업화면 html selector
* url : 모달팝업화면을 조회할 url
* param : 모달팝업화면을 조회 시 사용할 파라미터Object
* callback : 모달팝업화면 조회 후 호출될 callback함수명
* }
****************************************************************/
const fn_open_modal = function (modalDivSltr, modalSlrt, url, param, callback) {
const submitType = 'POST';
$.ajax({
type: submitType,
contentType: 'application/json',
url: url,
data: param,
success: function (data) {
//callback함수가 없을 경우 default로 지정된 영역에 모달팝업 화면을 교체하고 화면 로딩
if (!callback) {
$(modalSlrt).remove();
$(modalDivSltr).html(data);
$(modalSlrt).modal();
} else {
callback(data);
}
}
});
}
/* ********************************************************
* modal 닫기
* 파라미터 설명 {
modalId : 모달 팝업 HTML Object ID
* }
******************************************************** */
const fn_close_modal = function (modalId) {
$("#" + modalId + " > a").each(function () {
if (this.href.indexOf('#close-modal')) {
$(this).click();
}
});
$('#' + modalId).remove();
}
/* ********************************************************
* form 초기화
* 파라미터 설명 {
* formId : 초기화 대상 form ID
* }
******************************************************** */
const fn_reset_form = function (formId) {
if ($('#' + formId)[0]) {
const radioArr = [];
$('#' + formId).eq(0).find('input,select,textarea').each(function () {
let type = this.type;
let tag = this.tagName.toLowerCase();
if (type === 'text'
|| tag === 'textarea') {
this.value = '';
} else if (type === 'checkbox') {
this.checked = false;
} else if (type === 'radio') {
this.checked = false;
if (!radioArr.includes($(this).prop('name'))) {
radioArr.push($(this).prop('name'));
}
} else if (tag === 'select') {
this.selectedIndex = 0;
$(".select-box > select").niceSelect('update');
}
});
radioArr.forEach((element) => $('input[name=' + element + ']').eq(0).prop('checked', 'checked'));
//$('#'+formId)[0].reset();
}
}
/**************************************************************
검색 날짜 지정시 날짜 변경
파라미터 설명{
fromObjId : 시작일
toObjId : 종료일
stdObjeId : 기준일(시작일'fromObjId' or 종료일'toObjId')
date : 계산할 날짜 => '-(전) or +(후)' + '계산할 숫자' + 'D(일) or M(월) or Y(년)'
Ex) 현재 날짜에서 하루 전(후) => -1D(+1D)
현재 날짜는 0
}
****************************************************************/
const fn_set_date = function (fromObjId, toObjId, stdObjeId, date) {
/* fromObj, toObj 값 변경 시 일자선택 버튼 초기화 추가 */
$('#' + fromObjId).on('change', function () {
$(this).parent().parent().find('.dateRange-btn').each(function () {
$(this).removeClass('selected');
});
fn_check_fromTo('#' + fromObjId, '#' + toObjId, 'date');
});
$('#' + toObjId).on('change', function () {
$(this).parent().parent().find('.dateRange-btn').each(function () {
$(this).removeClass('selected');
});
fn_check_fromTo('#' + fromObjId, '#' + toObjId, 'date');
});
/* 기준일 기본값 설정(종료일이 기준일)
* ※toObjId or fromObjId로 설정 가능*/
if (!stdObjeId) {
stdObjeId = toObjId;
}
/* 계산할 숫자 기본값 설정(현재 날짜가 기본값) 및 date 유효성 검사*/
if (!date) {
/* onready시 전체 버튼 셀렉티드 class 부여*/
//date = '0';
$('#' + fromObjId).parent().parent().find('.dateRange-btn').eq(8).addClass("selected");
} else {
//date의 형태가 숫자+'D, M, Y'경우인지 확인
let regex = /^\d+[DMY]$/;
if (!regex.test(date)) {
date = '0';
}
}
if (date != null) {
if (date === '1D') {
// 기준일을 현재 날짜로 설정
const today = new Date();
$('#' + stdObjeId).datepicker().datepicker("setDate", today);
// 날짜 계산
let fromDate, toDate;
let days = parseInt(date);
fromDate = new Date(today);
fromDate.setDate(today.getDate() - days); // 어제
toDate = new Date(fromDate); // 어제와 동일
// 시작일과 종료일 설정
$('#' + fromObjId).datepicker().datepicker("setDate", fromDate);
$('#' + toObjId).datepicker().datepicker("setDate", toDate);
} else {
/* 기준일을 현재 날짜로 설정*/
$('#' + stdObjeId).datepicker().datepicker("setDate", new Date());
/* 기준일에 따라 계산 방법 분기
stdObjeId = toObjId => '-'+date
= fromObjId => date*/
if (stdObjeId == toObjId) {
date = '-' + date;
$('#' + fromObjId).datepicker().datepicker("setDate", date);
} else {
$('#' + toObjId).datepicker().datepicker("setDate", date);
}
}
}
}
/**************************************************************
from ~ to 비교
파라미터 설명{
fromSelector : 검색 시작 input 셀렉터 이름 ex)''#fromSelect'
toSelector : 검색 끝 input 셀렉터 이름 ex)''#toSelect'
valType : 비교할 대상의 타입 ex)'date' or 'number'
}
****************************************************************/
const fn_check_fromTo = function (fromSelector, toSelector, valType) {
switch (valType) {
case 'date' :
if (!fn_check_date($(fromSelector).val(), $(toSelector).val())) {
alert("날짜 검색 '종료일'이 '시작일'보다 작습니다");
$(fromSelector).val('');
$(toSelector).val('');
setTimeout(function () {
$(fromSelector).datepicker().datepicker("show");
}, 200);
}
break;
case 'number' :
if (!fn_check_number($(fromSelector).val(), $(toSelector).val())) {
alert("검색 '종료'값이 '시작'값보다 작습니다");
$(fromSelector).val('');
$(toSelector).val('');
$(fromSelector).focus();
}
break;
}
}
/**************************************************************
fn_check_fromTo() >case 'date' boolean 반환 함수
=> 시작, 끝 날짜 값이 둘 다 존재시 날짜 비교
끝 날짜가 시작 날짜보다 작으면 false를 반환
파라미터 설명{
fromDate : 검색 시작 날짜 값
toDate : 검색 끝 날짜 값
}
****************************************************************/
const fn_check_date = function (fromDate, toDate) {
let result = true;
try {
if (fromDate != null
&& toDate != null) {
const srchStartDate = new Date(fromDate);
const srchEndDate = new Date(toDate);
if (srchStartDate > srchEndDate) {
result = false;
}
}
} catch (e) {
console.log(e);
}
return result;
}
/**************************************************************
fn_check_fromTo() >case 'number' boolean 반환 함수
onchange함수는 종료 값에만 부여
=> 시작, 끝 값이 둘 다 존재시 값 비교
끝 날짜가 시작 날짜보다 작으면 false를 반환
파라미터 설명{
fromNb : 검색 시작 값
toNb : 검색 끝 값
}
****************************************************************/
const fn_check_number = function (fromNb, toNb) {
if (fromNb == null) {
fromNb = 0;
}
if (toNb == null) {
toNb = 0;
}
let result = true;
try {
if (fromNb != null
&& toNb != null) {
if (fromNb > toNb) {
result = false;
}
}
} catch (e) {
console.log(e);
}
return result;
}
/**************************************************************
* 특정 input(select)에 특정 event 발생시 처리할 함수 지정
* 파라미터 설명{
* selector : 대상 input Object selector
* eventType : 대상 event종류(예시>keyup)
* callback : 대상 event발생 시 호출될 callback함수
* }
****************************************************************/
const fn_set_event = function (selector, eventType, callback) {
$(selector).on(eventType, function () {
let target = $(this);
callback(target);
});
}
/**************************************************************
* 포매팅 (조회 값 포매팅)
* 파라미터 설명{
* mbtlnb : 대상 텍스트
* }
****************************************************************/
const fn_format_mbtlnb = (mbtlnb) => {
if(!fn_is_empty(mbtlnb)){
if (mbtlnb.length >= 8 && mbtlnb.length <= 12) {
if(mbtlnb.length == 12){
mbtlnb = mbtlnb.replace(/(\d{4})(\d{4})(\d{4})/, '$1-$2-$3');
}else if (mbtlnb.length == 11) {
//11자리 전화번호
mbtlnb = mbtlnb.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3');
}else if (mbtlnb.length == 9) {
//02를 포함한 9자리 전화번호(02-000-0000)
mbtlnb = mbtlnb.replace(/(\d{2})(\d{3})(\d{4})/, '$1-$2-$3');
} else if (mbtlnb.length == 8) {
//대표전화번호 일경우(0000-0000)
mbtlnb = mbtlnb.replace(/(\d{4})(\d{4})/, '$1-$2');
} else {
if (mbtlnb.indexOf('02') == 0) {
//02를 포함한 10자리 전화번호(02-0000-0000)
mbtlnb = mbtlnb.replace(/(\d{2})(\d{4})(\d{4})/, '$1-$2-$3');
} else {
//02를 제외한 10자리 전화번호(032-000-0000)
mbtlnb = mbtlnb.replace(/(\d{3})(\d{3})(\d{4})/, '$1-$2-$3');
}
}
}
}
return mbtlnb;
}
/**************************************************************
* 전화번호(일반전화번호, 휴대전화번호, 대표번호) 자동 포매팅(-) 설정
* 파라미터 설명{
* target : 대상 Object
* }
****************************************************************/
const fn_fmt_telno = function (target) {
//숫자만 허용
target.val(target.val().replace(/[^0-9]/g, ''));
if (target.val().length <= 11) {
if (target.val().length == 11) {
//휴대전호번호 혹은 02를 제외한 전화번호
target.val(target.val().replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3'));
} else if (target.val().length == 9) {
//02를 포함한 9자리 전화번호(02-000-0000)
target.val(target.val().replace(/(\d{2})(\d{3})(\d{4})/, '$1-$2-$3'));
} else if (target.val().length == 8) {
//대표전화번호 일경우(0000-0000)
target.val(target.val().replace(/(\d{4})(\d{4})/, '$1-$2'));
} else {
if (target.val().indexOf('02') == 0) {
//02를 포함한 10자리 전화번호(02-0000-0000)
target.val(target.val().replace(/(\d{2})(\d{4})(\d{4})/, '$1-$2-$3'));
} else {
//02를 제외한 10자리 전화번호(032-000-0000)
target.val(target.val().replace(/(\d{3})(\d{3})(\d{4})/, '$1-$2-$3'));
}
}
}
}
/**************************************************************
* 계좌번호 자동 포매팅(-) 설정
* 파라미터 설명{
* target : 대상 Object
* }
****************************************************************/
const fn_fmt_accuntno = function (target) {
target.val(target.val().replace(/^[-]|[^0-9-]/gi, ''));
}
/**************************************************************
* 공통코드 목록을 이용한 input element 생성
* 파라미터 설명{
* tgtSelector : 생성된 input element가 삽입될 DOM selector정보
* inputType : 생성된 input element type(radio, checkbox, select)
* inputName : 생성된 input element name속성
* selectedValue : 생성된 input element 중 선택될(checked 혹은 selected) 값
* codeList : 공통코드 목록 JSON 객체
* initValue : select box의 초기값으로 노출
* }
****************************************************************/
const fn_add_codeList = function (tgtSelector, inputType, inputName, selectedValue, codeList, initValue) {
let tgtChildreObj;
//input이 추가될 dom에 있는 모든 element 초기화
$(tgtSelector).eq(0).children().remove();
switch (inputType) {
case 'radio' :
for (let idx = 0; idx < codeList.length; idx++) {
tgtChildreObj = document.createElement("div");
tgtChildreObj.setAttribute("class", "custom-radio");
if (selectedValue == codeList[idx].cd) {
tgtChildreObj.innerHTML = '<input type="radio" id="' + inputName + idx + '" name="' + inputName + '" value="' + codeList[idx].cd + '" checked="checked"><label for="' + inputName + idx + '">' + codeList[idx].cdNm + '</label>';
} else {
tgtChildreObj.innerHTML = '<input type="radio" id="' + inputName + idx + '" name="' + inputName + '" value="' + codeList[idx].cd + '"><label for="' + inputName + idx + '">' + codeList[idx].cdNm + '</label>';
}
$(tgtSelector).eq(0).append(tgtChildreObj);
}
break;
case 'checkbox' :
for (let idx = 0; idx < codeList.length; idx++) {
tgtChildreObj = document.createElement("label");
tgtChildreObj.setAttribute("class", "b-checkbox checkbox");
if (selectedValue == codeList[idx].cd) {
tgtChildreObj.innerHTML = '<input type="checkbox" id="' + inputName + idx + '" name="' + inputName + '" value="' + codeList[idx].cd + '" checked="checked"><span class="check"></span><span class="control-label">' + codeList[idx].cdNm + '</span>';
} else {
tgtChildreObj.innerHTML = '<input type="checkbox" id="' + inputName + idx + '" name="' + inputName + '" value="' + codeList[idx].cd + '"><span class="check"></span><span class="control-label">' + codeList[idx].cdNm + '</span>';
}
$(tgtSelector).eq(0).append(tgtChildreObj);
}
break;
case 'select' :
tgtChildreObj = document.createElement("div");
let selectInnerHtml = '';
tgtChildreObj.setAttribute("class", "select-box");
selectInnerHtml = '<select id="' + inputName + '" name="' + inputName + '">';
if (initValue) {
//초기값(전체)이 있을 경우
selectInnerHtml += '<option value="">' + initValue + '</option>';
}
for (let idx = 0; idx < codeList.length; idx++) {
if (selectedValue == codeList[idx].cd) {
selectInnerHtml += '<option value="' + codeList[idx].cd + '" selected="selected">' + codeList[idx].cdNm + '</option>';
} else {
selectInnerHtml += '<option value="' + codeList[idx].cd + '">' + codeList[idx].cdNm + '</option>';
}
}
selectInnerHtml += '</select>';
tgtChildreObj.innerHTML = selectInnerHtml;
$(tgtSelector).eq(0).append(tgtChildreObj);
$(".select-box > select").niceSelect();
break;
}
}
/**************************************************************
* datepicker 설정 수동적용
* 파라미터 설명{
* selector : datepicker가 적용될 DOM selector정보
* }
****************************************************************/
const fn_set_datepicker = function (selector) {
if (!selector) {
selector = '.datepicker';
}
$(selector).each(function () {
$(this).datepicker({
dateFormat: "yy-mm-dd",
prevText: "이전 달",
nextText: "다음 달",
changeMonth: "true",
changeYear: "true",
dayNames: ["월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"],
dayNamesMin: ["월", "화", "수", "목", "금", "토", "일"],
monthNames: [
"1월",
"2월",
"3월",
"4월",
"5월",
"6월",
"7월",
"8월",
"9월",
"10월",
"11월",
"12월",
],
monthNamesShort: [
"1월",
"2월",
"3월",
"4월",
"5월",
"6월",
"7월",
"8월",
"9월",
"10월",
"11월",
"12월",
],
showMonthAfterYear: true,
yearSuffix: "년",
firstDay: 6,
});
});
}
/**************************************************************
* 조건에 따른 대상input 활성화/비활성화
* 파라미터 설명{
* disArr : 비활성화 대상 input selector배열
* enArr : 활성화 대상 input selector배열
* }
****************************************************************/
const fn_ctrl_disable = function (disArr, enArr) {
const propUpdate = function (selector, bool) {
const boolean = bool;
$(selector).find('input, select').each(function () {
let type = this.type;
let tag = this.tagName.toLowerCase();
if (type === 'text' || tag === 'textarea' || type === 'checkbox'
|| type === 'radio' || type === 'hidden') {
this.disabled = boolean;
} else if (tag === 'select') {
this.disabled = boolean;
$(this).niceSelect('update');
}
});
};
if (disArr != null && disArr.length > 0) {
const isTrue = true;
for (let idx = 0; idx < disArr.length; idx++) {
propUpdate(disArr[idx], isTrue);
}
}
if (enArr != null && enArr.length > 0) {
const isFalse = false;
for (let idx = 0; idx < enArr.length; idx++) {
propUpdate(enArr[idx], isFalse);
}
}
}
/**************************************************************
* 체크박스 체크여부에 따른 전체 체크박스 제어
* 파라미터 설명{
* tgtSelector : 전체체크박스 대상 input
* selector : 나머지 체크박스 대상 input
* }
****************************************************************/
const fn_ctr_pCheckbox = function (tgtSelector, selector) {
let isCcked = true;
$(selector).each(function () {
if ($(this).prop('type') == 'checkbox' && !$(this).prop('checked')) {
isCcked = false;
return false;
}
});
$(tgtSelector).prop('checked', isCcked);
}
/**************************************************************
* 데이터 NULL 여부
* 파라미터 설명 {
* data : 데이터
* }
****************************************************************/
const fn_is_empty = (data) => {
if (typeof data === 'undefined' ||
data === 'undefined' ||
data === null ||
data === '' ||
data === 'null' ||
data.length === 0 ||
(typeof input === 'object' && !Object.keys(data).length)) {
return true;
} else {
return false;
}
}
/**************************************************************
* 데이터 NULL 일 경우 대체 문자 또는 데이터 반환
* 파라미터 설명 {
* expr1 : 데이터
* expr2 : 대체 데이터
* }
****************************************************************/
const fn_nvl = function (expr1, expr2) {
if (fn_is_empty(expr1)) {
expr1 = expr2;
}
return expr1;
}
/* ********************************************************
* ajax로 목록 조회시 나이스셀렉트 , datepicker 일괄 적용
* 파라미터 설명 {
* listIdSelector: 목록 조회 section ID 셀렉터
* }
******************************************************** */
const fn_set_niceSelect_datePicker = (listIdSelector) => {
//검색 조건 내 select 요소 찾기
const selectNiceArr = $(listIdSelector).find("select");
//select 요소 개수
if (selectNiceArr.length > 0) {
selectNiceArr.each(function (idx) {
selectNiceArr.eq(idx).niceSelect();
});
}
//datePicker 개수
const datePickerArr = $(listIdSelector).find(".datepicker");
if (datePickerArr.length > 0) {
datePickerArr.each(function (idx) {
fn_set_datepicker(datePickerArr.eq(idx));
});
}
}
/* ********************************************************
* 상품 상세 이동
* 파라미터: 상품고유번호
******************************************************** */
const fn_move_goods_dtl = (goodsInnb) => {
const form = $('<form>', {
'action': '/sopmal/goods/selectGoodsDtl',
'method': 'get'
}).append(
$('<input>', {
'type': 'hidden',
'name': 'goodsInnb',
'value': goodsInnb
})
)
$('body').append(form);
form.submit();
}
/********************************모바일 관련 스크립트***********************************/
/* ********************************************************
* 모바일 헤더 제목 set
* title: 각 페이지의 제목
******************************************************** */
const fn_set_header_title = (title) => {
$("#headerTitle").text(title);
}
/* ************************************************************
* 인피니티 스크롤 공통 처리 (footer가 보이면 callback함수 호출)
* callBack : 콜백 함수 이름
* callBackParam : callBack 함수의 파라미터
* selector
*************************************************************
const fn_infinite_scroll = (callBack, callBackParam,selector) => {
const target = document.querySelector(selector);
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
callBack(callBackParam);
}
});
});
observer.observe(target);
}
*/
const fn_infinite_scroll = (callBack, callBackParam, selector) => {
setTimeout(() => {
const target = document.querySelector(selector);
if (target) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
callBack(callBackParam);
}
});
});
observer.observe(target);
} else {
console.error('target을 찾을 수 없습니다.');
}
}, 500);
}
/* ************************************************************
* 확인, 성공 alert 호출 함수
* cfrmModalNm = 확인모달이름
* cfrmBtnNm = 확인버튼id #포함
* successModalNm = 성공모달이름
* successBtnNm = 성공버튼id #포함
* customCallback = 성공시 호출 함수
* customCallbackParam = 성공시 호출 함수 파라미터
************************************************************* */
// 컨펌 모달 열기
function openConfirmModal(callback,cfrmModalNm,cfrmBtnNm,successModalNm,successBtnNm,customCallback,customCallbackParam) {
openModal(cfrmModalNm);//4.cud 컨펌 모달을 호출한다.
$("#closeModalTarget").val(cfrmModalNm);
$(cfrmBtnNm).off('click').on('click', function () {//5.컨펌 모달 확인 버튼 클릭시 성공모달을 호출한다
// 예 버튼 클릭 시 콜백 함수 실행
callback(function () {
// Ajax 요청 성공 후 컨펌 모달 닫기 및 성공 모달 열기
closeModal(cfrmModalNm);//등록 모달 열기
openSuccessModal(function () {
if(typeof customCallback === 'function'){
customCallback(customCallbackParam);//성공모달 함수
}
},successModalNm,successBtnNm);
});
});
}
// 성공 모달 열기
function openSuccessModal(callback,successModalNm,successBtnNm) {
openModal(successModalNm);//등록 모달 열기
$(successBtnNm).off('click').on('click', function () {
// 성공 모달 확인 버튼 클릭 시 콜백 함수 실행
closeModal(successModalNm);//모달 닫기
if(typeof callback === 'function'){
callback();
}
});
}
// 컨펌 모달 열기_ver2 (초기화 후 정보 날라갈 시 사용*)
function openConfirmModal2(callback,cfrmModalNm,cfrmBtnNm,successModalNm,successBtnNm,customCallback,customCallbackParam) {
openModal2(cfrmModalNm);//4.cud 컨펌 모달을 호출한다.
$("#closeModalTarget").val(cfrmModalNm);
$(cfrmBtnNm).off('click').on('click', function () {//5.컨펌 모달 확인 버튼 클릭시 성공모달을 호출한다
// 예 버튼 클릭 시 콜백 함수 실행
callback(function () {
// Ajax 요청 성공 후 컨펌 모달 닫기 및 성공 모달 열기
closeModal(cfrmModalNm);//등록 모달 열기
openSuccessModal(function () {
if(typeof customCallback === 'function'){
customCallback(customCallbackParam);//성공모달 함수
}
},successModalNm,successBtnNm);
});
});
}
// 성공 모달 열기
function openSuccessModal2(callback,successModalNm,successBtnNm) {
openModal2(successModalNm);//등록 모달 열기
$(successBtnNm).off('click').on('click', function () {
// 성공 모달 확인 버튼 클릭 시 콜백 함수 실행
closeModal(successModalNm);//모달 닫기
if(typeof callback === 'function'){
callback();
}
});
}
/*비회원 로그인화면으로 이동*/
const fn_move_login = () => {
var fullUrl = $(location).attr('href');
var hashIndex = fullUrl.indexOf('#');
// # 기호가 있는 경우 URL에서 # 기호와 그 이후를 제거
var cleanUrl = hashIndex !== -1 ? fullUrl.substring(0, hashIndex) : fullUrl;
var encodedRedirectUri = encodeURIComponent(cleanUrl);
location.href = "/sopmal/login?redirect_uri="+encodedRedirectUri;
}
/***************************************************************
토큰 만료를 모니터링 하고 갱신을 요청하는 기능
***************************************************************/
const checkTokenExpiration = () => {
const tokenExpirationTime = localStorage.getItem('tokenExpirationTime');
if (tokenExpirationTime && Date.now() > tokenExpirationTime) {
refreshToken();
}
}
const refreshToken = () => {
fetch('/token/refresh', { method: 'POST' })
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error('Token refresh failed');
})
.then(data => {
localStorage.setItem('tokenExpirationTime', Date.now() + data.expiresIn * 1000);
})
.catch(error => {
console.error('Error refreshing token:', error);
window.location.href = '/login'; // 로그인 페이지로 리다이렉트
});
}
// 주기적으로 토큰 만료 확인 (예: 5분마다)
setInterval(checkTokenExpiration, 5 * 60 * 1000);
/**************************************************************
* JSON 객체인지 확인하는 script
****************************************************************/
const fn_check_json = function (str) {
try {
let json = JSON.parse(str);
return (typeof json === 'object');
} catch (e) {
return false;
}
}
/* ********************************************************
* 금액 포맷
******************************************************** */
const fn_format_comma = (target) => {
if(!fn_is_empty(target)){
target = target.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
return target;
}
/* ********************************************************
* 모바일 > 햄버거 메뉴 클릭시 회원 정보 get
******************************************************** */
const fn_select_mbrInfo = (cdnurl,isAuthenticated) => {
$.ajax({
type: "get",
url: "/sopmal/main/selectMbrInfo",
success: function (data) {
data = JSON.parse(data.resBody.result);
let info = data.info;
if(isAuthenticated){
/*회원등급아이콘경로*/
if (!fn_is_empty(info.mbrGradIconCours)) {
const imgSrc = cdnurl + info.mbrGradIconCours;
const imgHtml = `<img src=${imgSrc} alt="회원등급이미지"/>`;
$("#hambergerGradImg").html(imgHtml);
} else {//이미지 없을 시 이미지 영역 숨김
$("#hambergerGradImg").hide();
}
/*회원등급명*/
$("#hambergerGradNm").text(info.mbrGradNm);
/*회원명*/
const mbrNmHtml = `${info.mbrNm}<span class="append">님</span>`;
$("#hambergermbrNm").html(mbrNmHtml);
/*마일리지*/
const formatMlg = fn_format_comma(info.mbrMlgAmt);
$("#hambergerMbrMlgAmt").text(formatMlg);
/*쿠폰*/
$("#hambergerCoupnCnt").text(info.couponCnt);
/*위시리스트*/
$("#hambergerWslistCnt").html(info.wishGoodsCnt);
}
let recentGoods = '';
//최근본상품
if(data.recentGoods != null){
recentGoods += `<h1>최근 본 상품</h1>`;
recentGoods += `<div class="swiper recentlySide-swiper">`;
recentGoods += `<div class="swiper-wrapper" id="recentlySite">`;
data.recentGoods.forEach(function (item) {
recentGoods += ` <div class="swiper-slide recentlySide__image">`;
recentGoods += ` <a href="javascript:void(0);" onclick="fn_move_goods_dtl(${item.goodsInnb});">`;
recentGoods += ` <img src="${cdnurl}${ item.goodsImgCours }" alt="${item.goodsNm }" onerror="this.src='/pc/images/image_placeholder.png'">`;
recentGoods += ` </a>`;
recentGoods += ` </div>`;
});
recentGoods += ` </div>`;
recentGoods += ` <div class="swiper-pagination theme-pagination"></div>`;
recentGoods += `</div>`;
$("#recentlySite").html(recentGoods);
const recentSideSwiper = new Swiper('.recentlySide-swiper', {
slidesPerView: 3,
slidesPerGroup: 3,
spaceBetween: 20,
//loop: true,
pagination: {
el: '.recentlySide-swiper .swiper-pagination',
clickable: true,
},
});
}
}
});
}
// 버튼을 비활성화하는 함수
const disableButton = (selector) => {
$(selector).attr('disabled', true);
}
// 버튼을 활성화하는 함수
const enableButton = (selector) => {
$(selector).removeAttr('disabled');
}
//장바구니 상품 개수 리프레쉬
const fn_reflesh_cart_cnt = () => {
$.ajax({
type: 'get',
url: '/sopmal/ordr/selectCartCntRefresh',
success: function (data) {
data = JSON.parse(data.resBody.result);
$(".headerCartCnt").each(function () {
$(this).text(data.cartCnt);
});
}
});
}
function escapeHTML(str) {
if (!fn_is_empty(str)) {
str= str.replaceAll("<br>", "\n")
.replaceAll(/[&<>"]/g, function (match) {
switch (match) {
case '&':
return '&amp;';
case '<':
return '&lt;';
case '>':
return '&gt;';
case '"':
return '&quot;';
case "'":
return '&#39;';
default:
return match;
}
});
} else {
str = "";
}
return str;
}
/* ********************************************************
* 카카오 주소 찾기 연동(앱)
* 파라미터 설명 {
* callback : 카카오 주소 찾기 팝업에서 주소 선택 후 호출될 콜백함수
* }
******************************************************** */
const fn_select_postcode_app = function (callback) {
// 우편번호 찾기 화면을 넣을 element
var element_wrap = document.getElementById('postCodeWrap');
// element가 없으면 생성
if (!element_wrap) {
var div = document.createElement('div');
div.id = 'postCodeWrap';
div.style.display = 'none';
div.style.position = 'fixed';
div.style.left = '0';
div.style.top = '0';
div.style.width = '100%';
div.style.height = '100%';
div.style.backgroundColor = 'rgba(0,0,0,0.5)';
div.style.zIndex = '9999';
var innerDiv = document.createElement('div');
innerDiv.style.position = 'relative';
innerDiv.style.backgroundColor = '#fff';
innerDiv.style.width = '90%';
innerDiv.style.height = '80%';
innerDiv.style.margin = '10% auto';
innerDiv.style.overflow = 'hidden';
var closeBtn = document.createElement('img');
closeBtn.src = '//t1.daumcdn.net/postcode/resource/images/close.png';
closeBtn.style.cursor = 'pointer';
closeBtn.style.position = 'absolute';
closeBtn.style.right = '0px';
closeBtn.style.top = '0px';
closeBtn.style.zIndex = '1';
closeBtn.onclick = function() {
element_wrap.style.display = 'none';
document.body.style.overflow = '';
};
innerDiv.appendChild(closeBtn);
div.appendChild(innerDiv);
document.body.appendChild(div);
element_wrap = div;
}
// 현재 scroll 위치를 저장
var currentScroll = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
// body 스크롤 방지
document.body.style.overflow = 'hidden';
new daum.Postcode({
oncomplete: function (data) {
const postcode = data.zonecode;
const roadAddr = data.roadAddress;
const jibunAddress = data.jibunAddress;
let addressType = '';
let extraRoadAddr = '';
// userSelectedType R/J 검색 결과에서 사용자가 선택한 주소의 타입(R : 도로명, J : 지번)
if (data.userSelectedType == 'R') {
addressType = '01';
} else {
addressType = '02';
}
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if (data.bname !== '' && /[동|로|가]$/g.test(data.bname)) {
extraRoadAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if (data.buildingName !== '' || data.apartment === 'Y') {
extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if (extraRoadAddr !== '' && roadAddr !== '') {
extraRoadAddr = ' (' + extraRoadAddr + ')';
}
callback({
postcode: postcode,
roadAddress: roadAddr,
jibunAddress: jibunAddress,
addressType: addressType,
extraAddress: extraRoadAddr
});
// iframe을 넣은 element를 안보이게 한다.
element_wrap.style.display = 'none';
// body 스크롤 복원
document.body.style.overflow = '';
// 우편번호 찾기 화면이 보이기 이전으로 scroll 위치를 되돌린다.
document.body.scrollTop = currentScroll;
document.documentElement.scrollTop = currentScroll;
},
// 우편번호 찾기 화면 크기가 조정되었을때 실행할 코드를 작성하는 부분
onresize: function (size) {
element_wrap.children[0].style.height = size.height + 'px';
},
width: '100%',
height: '100%'
}).embed(element_wrap.children[0]);
// iframe을 넣은 element를 보이게 한다.
element_wrap.style.display = 'block';
}