no message

main
이범준 1 year ago
parent 8775ae13e4
commit 40a3b97357

@ -38,7 +38,7 @@ public class input extends TagSupport {
}
sb.append(" />");
sb.append("<input type='text' id='").append(this.id+"$mask").append("'");
sb.append("<input type='text' id='").append("mask-"+this.id).append("'");
sb.append(" class='privacy-mask");
if(!this.cls.equals("")){
sb.append(" ").append(this.cls);

@ -1,146 +0,0 @@
/*
* 단축키 Event
*/
document.onkeydown=function(e) {
if (e.key == "F1" && e.ctrlKey == true) {
if ( self !== top ) {
$(top.document.getElementById("favorites")).trigger("click");
} else {
$("#favorites").trigger("click");
}
}
};
/*
* 보안모드
*/
function fn_securityModeToggle(flag){
if(flag){ //개인정보 숨김
//인풋
$("input.privacy").attr("hidden","hidden");
$("input.privacy-mask").removeAttr("hidden");
for(let i=0; i< $("input.privacy").length; i++){
let originId = $("input.privacy")[i].id;
let originValue= $("input.privacy")[i].value;
let maskingValue = originValue.replace(/[0-9a-zA-Z]/g, "*");
document.getElementById(originId+"$mask").value = maskingValue;
}
//그리드
//그리드가 1개일 때
if(!(typeof GRID === 'undefined')) {
for(let key in GRID.store.column.allColumnMap){
if(GRID.store.column.allColumnMap[key].className == "privacy"){
GRID.hideColumn(key, '');
}
if(GRID.store.column.allColumnMap[key].className == "privacy-mask"){
GRID.showColumn(key, '');
}
}
}
//그리드가 여러개일 때
if(!(typeof ARR_GRID === 'undefined')){
for(let i=0; i < ARR_GRID.length; i++){
for(let key in ARR_GRID[i].store.column.allColumnMap){
if(ARR_GRID[i].store.column.allColumnMap[key].className){
if(ARR_GRID[i].store.column.allColumnMap[key].className == "privacy"){
ARR_GRID[i].hideColumn(key, '');
}
if(ARR_GRID[i].store.column.allColumnMap[key].className == "privacy-mask"){
ARR_GRID[i].showColumn(key, '');
}
}
}
}
}
} else { //개인정보 표시
//인풋
$("input.privacy").removeAttr("hidden");
$("input.privacy-mask").attr("hidden","hidden");
for(let i=0; i< $("input.privacy").length; i++){
let originId = $("input.privacy")[i].id;
let originValue= $("input.privacy")[i].value;
let maskingValue = originValue.replace(/[0-9a-zA-Z]/g, "*");
document.getElementById(originId+"$mask").value = maskingValue;
}
//그리드
//그리드가 1개일 때
if(!(typeof GRID === 'undefined')){
for(let key in GRID.store.column.allColumnMap){
if(GRID.store.column.allColumnMap[key].className == "privacy"){
GRID.showColumn(key, '');
}
if(GRID.store.column.allColumnMap[key].className == "privacy-mask"){
GRID.hideColumn(key, '');
}
}
}
//그리드가 여러개일 때
if(!(typeof ARR_GRID === 'undefined')){
for(let i=0; i < ARR_GRID.length; i++){
for(let key in ARR_GRID[i].store.column.allColumnMap){
if(ARR_GRID[i].store.column.allColumnMap[key].className){
if(ARR_GRID[i].store.column.allColumnMap[key].className == "privacy"){
ARR_GRID[i].showColumn(key, '');
}
if(ARR_GRID[i].store.column.allColumnMap[key].className == "privacy-mask"){
ARR_GRID[i].hideColumn(key, '');
}
}
}
}
}
}
//재귀 호출
let ifrs = document.getElementsByTagName('IFRAME');
for(let i=0; i < ifrs.length; i++){
let ifr = ifrs[i];
ifr.contentWindow.fn_securityModeToggle(flag);
}
}
$(document).ready(function(){
/*--------------------- 검색영역 상세검색 제어 ---------------------*/
$( "body" ).on( "click", ".btn-open-detail", function() {
$(this).find('i').toggleClass('bx-chevron-down');
$(this).find('i').toggleClass('bx-chevron-up');
});
/*--------------------- 달력 제어 ---------------------*/
$(".form-date").datepicker({
changeMonth: true,
changeYear: true,
showButtonPanel: true
});
$( "body .form-date" ).next("button.bx-calendar").on("click", function() {
$(this).prev().focus();
});
/*------- 팝업 제어 ---------*/
/*------- 팝업 열림 -------*/
$( "body" ).on( "click", "button[data-show-popup]", function(e) {
var popId = $(e.currentTarget).data("show-popup");
$(".modal-wrap").css("display",'table');
$(".modal-wrap .cont-box#"+popId).show();
});
/*------- 팝업 닫힘 -------*/
$( "body" ).on( "click", ".modal-wrap button[data-modal-close]", function() {
$(".modal-wrap, .modal-wrap .cont-box").hide();
});
});

@ -1,86 +0,0 @@
const fimsApiUrl = {
/**
* fims 공통 API URL
*/
FIND_RCV_PATH_FILES: '/fims/biz/cmm/findRcvPathFiles.do' //연계파일 경로 파일 목록 조회
,POPUP_CRACKDOWN_TOTAL: '/fims/biz/cmm/cmmFimsCrackdownTotMgtPopup.do' //단속현황 개별 총정보 팝업
,POPUP_CRACKDOWN_EDIT: '/fims/biz/cmm/cmmFimsCrackdownEditPopup.do' //단속 정보 편집 팝업
,POPUP_EXTR_CRACKDOWN_FILE_SEL: '/fims/biz/cmm/cmmCrackdownRcvFilePopup.do' //CCTV 외부연계 데이타 선택
,POPUP_ENLIGHT_DISALLOW: '/fims/biz/cmm/cmmEnlightDisallowPopup.do' //서손 / 계도 처리 popup
,POPUP_IMPOSE: '/fims/biz/cmm/cmmImposePopup.do' //과태료시스템등록 popup
,POPUP_CTZN_ANS_PREVIEW: '/fims/biz/cmm/cmmCtznAnswerPreviewPopup.do' //시민신고 답변 미리보기 팝업
,POPUP_CTZN_CMPLNT_HIST: '/fims/biz/cmm/cmmCtznComplaintHistPopup.do' //민원이력 팝업
,POPUP_CAR_CRACKDOWN_CNT: '/fims/biz/cmm/cmmCarCrackdownCntPopup.do' //차량번호 단속건수 조회 팝업
,FIND_CRACKDOWNS: '/fims/biz/cmm/findCrackdownInfos.do' //단속현황-외부연계자료목록
,FIND_CRACKDOWN_INFO: '/fims/biz/cmm/findCrackdownInfoAndAttchFiles.do' //단속현황-개별총정보 위반정보탭 조회
,FIND_CTZN_ANS_INFO: '/fims/biz/cmm/findCtznStmtAnswer.do' //시민신고 답변 정보 조회
,MODIFY_CTZN_ANS_TXT: '/fims/biz/cmm/modifyCtznStmtAnswer.do' //시민신고 답변 내용 변경
,ADD_CTZN_ANS: '/fims/biz/cmm/addCtznStmtAnswer.do' //시민신고 답변 생성
,ADD_CTZN_ANS_LIST: '/fims/biz/cmm/addCtznStmtAnswers.do' //시민신고 목록 답변 생성
,FIND_CTZN_ANS_TMPL_INFO: '/fims/biz/cmm/findCtznAnswerTmplInfo.do' //시민신고 답변 템플릿 조회
,FIND_CRACKDOWN_VHRNO_CNT: '/fims/biz/cmm/findCrackdownVhrnoCnt.do' //차량 단속건수 조회
,FIND_PROCESS_STTUS_CHANGE_HIST: '/fims/biz/cmm/findProcessSttusChangeHist.do'
,FIND_RTPYR_ADRES_HIST: '/fims/biz/cmm/findRtpyrAdresHist.do'
,FIND_ELCTRN_NTIC_SNDNG: '/fims/biz/cmm/findElctrnNticSndng.do'
,FIND_CTZN_STTEMNT_CMPLT: '/fims/biz/cmm/findCtznSttemntCmplt.do'
,ADD_CTZN_STTEMNT_CMPLT: '/fims/biz/cmm/addCtznSttemntCmplt.do'
,SEND_CRACKDOWN_PHOTO_FILE_TO_NTRI: '/fims/biz/cmm/sendCrackdownPhotoToNtri.do' //단속사진 차세대 세외수입 연계
/**
* fims API URL
*/
//외부연계처리 - 시민신고(국민신문고) 데이타 관리
,POPUP_EC_NATL_NEWS_PAPER_INFO: '/fims/biz/ec/ecNatlNewspaperPopup.do' //국민신문고 데이타 상세
,SAVE_EC_NATL_NEWS_PAPER: '/fims/biz/ec/saveNatlNewspaers.do' //국민신문고 데이타 등록
,FIND_EC_NATL_NEWS_PAPERS: '/fims/biz/ec/findNatlNewspaers.do' //국민신문고 목록 조회
,FIND_EC_NATL_NEWS_PAPER_ATTCH_FILES: '/fims/biz/ec/findNatlNewspaperAttchFiles.do' //국민신문고 첨부파일 목록 조회
//외부연계처리 - 시민신고 접수관리
,POPUP_EC_CTZN_STMT: '/fims/biz/ec/ecCtznSttemntMgtPopup.do' //주민 신고 데이타 상세
,POPUP_EC_CTZN_STMT_ANS: '/fims/biz/ec/ecCtznSttemntAnsMgtPopup.do' //주민 신고 데이타 답변
,FIND_EC_CTZN_STMT_DTLS: '/fims/biz/ec/findCtznStmtDtls.do' //주민신고 상세 목록 조회
,FIND_EC_CTZN_STMT_DTL_AND_ATTCH_FILES: '/fims/biz/ec/findCtznStmtDtlAndAttchFiles.do' //주민신고 상세 및 첨부파일 조회
,MODIFY_EC_CTZN_STMT_DTL: '/fims/biz/ec/modifyCtznStmtDtl.do' //주민신고 상세 변경
,REMOVE_EC_CTZN_STMT_DTL: '/fims/biz/ec/removeCtznStmtDtl.do' //주민신고 상세 삭제
,SAVE_EC_CTZN_STMT_RT_REGLT: '/fims/biz/ec/saveRtReglt.do' //주민신고 단속자료 생성
,SAVE_EC_CTZN_STMT_RT_ERPP: '/fims/biz/ec/saveRtErpp.do' //주민신고 서손자료 생성
,SAVE_EC_CTZN_STMT_ANSWER: '/fims/biz/ec/saveCtznStmtAns.do' //주민신고 답변 생성
//외부연계처리 - CCTV 데이타 관리(cctv고정형 / 이동형 / 버스장착형)
,FIND_CCTV_EC_EXTRL_REGLT_CNTCS: '/fims/biz/ec/findExtrlRegltCntcs.do' //CCTV 외부연계 데이타 목록 조회
,FIND_CCTV_EC_EXTRL_REGLT_CNTC: '/fims/biz/ec/findExtrlRegltCntc.do' //CCTV 외부연계 데이타 목록 조회
,FIND_CCTV_EC_EXTRL_REGLT_CNTC_AND_ATTCH_FILES: '/fims/biz/ec/findExtrlRegltCntcAndAttchFiles.do' //CCTV 외부연계 정보 및 첨부파일 조회
,SAVE_CCTV_EC_EXTRL_REGLT_CNTCS: '/fims/biz/ec/saveCctvCrackdownDatas.do' //CCTV 외부연계(고정형 / 이동형) 데이타 저장
,SAVE_BUS_INSTALL_EC_EXTRL_REGLT_CNTC: '/fims/biz/ec/saveBusCctvCrackdownDatas.do' //CCTV 외부연계(버스장착형) 데이타 저장
,MODIFY_EC_EXTRL_REGLT_CNTC: '/fims/biz/ec/modifyExtrlRegltCntc.do' //CCTV 외부연계 데이타 변경
,SAVE_EC_EXTRL_REGLT_CNTC_RT_REGLT: '/fims/biz/ec/saveExtrRtReglt.do' //CCTV 외부연계 데이타 단속자료 생성
,SAVE_EC_EXTRL_REGLT_CNTC_RT_ERPP: '/fims/biz/ec/saveExtrRtErpp.do' //CCTV 외부연계 데이타 서손자료 생성
,FIND_BUS_INSTALL_EC_EXTRL_REGLT_CNTC_ATTCH_FILES: '/fims/biz/ec/findBusCctvCrackdownFiles.do' //CCTV 외부연계(버스장착형) 데이타 조회
,FIND_EC_EXTRL_REGLT_CNTC_ATTCH_FILES: '/fims/biz/ec/findExtrlRegltCntcAttchFiles.do' //CCTV 외부연계 첨부파일 목록 조회
,FIND_RT_REGLTS: '/fims/biz/rt/findRtReglts.do' //단속 목록 조회
,FIND_RT_REGLT_INFO_AND_ATTCH_FILES: '/fims/biz/rt/findRtRegltAndAttchFiles.do' //단속 정보 및 첨부파일 목록 조회
,ADD_RT_REGLT: '/fims/biz/rt/addRtReglt.do' //단속 데이타 등록
,MODIFY_RT_REGLT: '/fims/biz/rt/modifyRtReglt.do' //단속 데이타 변경
,REMOVE_RT_REGLT: '/fims/biz/rt/removeRtReglt.do' //단속 데이타 변경
,FIND_RT_REGLT_ATTCH_FILES: '/fims/biz/rt/findRtRegltAttchFiles.do' //단속 정보 첨부파일 목록 조회
,FIND_RT_REGLT_CAR_CRACKDOWN_CNT: '/fims/biz/rt/findRtRegltByVhrno.do' //차량 단속 정보 목록 조회
}

@ -0,0 +1,98 @@
/*
* 단축키 Event
*/
document.onkeydown=function(e) {
if (e.key == "F1" && e.ctrlKey == true) {
if ( self !== top ) {
$(top.document.getElementById("favorites")).trigger("click");
} else {
$("#favorites").trigger("click");
}
}
};
/*
* 보안모드
*/
function fn_securityModeToggle(flag, elementId){
var executionArea;
if(elementId){
executionArea = $("#"+elementId);
} else {
executionArea = $(document);
}
var targets = executionArea.find("input.privacy");
for(let i=0; i< targets.length; i++){
let originId = targets[i].id;
let originValue= targets[i].value;
let maskingValue = originValue.replace(/[0-9a-zA-Z]/g, "*");
document.getElementById("mask-"+originId).value = maskingValue;
}
if(flag){ //개인정보 숨김
//입력상자
$("input.privacy").attr("hidden","hidden");
$("input.privacy-mask").removeAttr("hidden");
//그리드
$("th.privacy").attr("hidden","hidden");
$("td.privacy").attr("hidden","hidden");
$("th.privacy-mask").removeAttr("hidden");
$("td.privacy-mask").removeAttr("hidden");
} else { //개인정보 표시
//입력상자
$("input.privacy").removeAttr("hidden");
$("input.privacy-mask").attr("hidden","hidden");
$("th.privacy").removeAttr("hidden");
$("td.privacy").removeAttr("hidden");
$("th.privacy-mask").attr("hidden","hidden");
$("td.privacy-mask").attr("hidden","hidden");
}
}
$(document).ready(function(){
/*--------------------- 검색영역 상세검색 제어 ---------------------*/
$( "body" ).on( "click", ".btn-open-detail", function() {
$(this).find('i').toggleClass('bx-chevron-down');
$(this).find('i').toggleClass('bx-chevron-up');
});
/*--------------------- 달력 제어 ---------------------*/
$(".form-date").datepicker({
changeMonth: true,
changeYear: true,
showButtonPanel: true
});
$( "body .form-date" ).next("button.bx-calendar").on("click", function() {
$(this).prev().focus();
});
/*------- 팝업 제어 ---------*/
/*------- 팝업 열림 -------*/
$( "body" ).on( "click", "button[data-show-popup]", function(e) {
var popId = $(e.currentTarget).data("show-popup");
$(".modal-wrap").css("display",'table');
$(".modal-wrap .cont-box#"+popId).show();
});
/*------- 팝업 닫힘 -------*/
$( "body" ).on( "click", ".modal-wrap button[data-modal-close]", function() {
$(".modal-wrap, .modal-wrap .cont-box").hide();
});
});

@ -0,0 +1,404 @@
/**
* XitFrame 공통 Util
*/
var XitCmmnUtil = {
/* ===================================
* 동적 Form 생성
* -설명: 객체에 담긴 key,value를 form으로 생성하여 반환
* @author 박민규
=================================== */
createForm : function(obj){
var form = document.createElement("form");
for(key in obj){
var param = document.createElement('input');
param.setAttribute('type', 'hidden');
param.setAttribute('name', key);
param.setAttribute('value', obj[key]);
form.appendChild(param);
}
return form;
},
/*===================================
* 엑셀 export
* -설명: SheetJS를 이용한 Excel export
* -참조: https://github.com/hhurz/tableExport.jquery.plugin
* https://www.npmjs.com/package/tableexport.jquery.plugin
* @author 박민규
*
* [Options]
* TableExport(document.getElementsByTagName("table"), {
* headers: true, // (Boolean), display table headers (th or td elements) in the <thead>, (default: true)
* footers: true, // (Boolean), display table footers (th or td elements) in the <tfoot>, (default: false)
* formats: ["xls", "csv", "txt"], // (String[]), filetype(s) for the export, (default: ['xls', 'csv', 'txt'])
* filename: "id", // (id, String), filename for the downloaded file, (default: 'id')
* bootstrap: false, // (Boolean), style buttons using bootstrap, (default: true)
* exportButtons: true, // (Boolean), automatically generate the built-in export buttons for each of the specified formats (default: true)
* position: "bottom", // (top, bottom), position of the caption element relative to table, (default: 'bottom')
* ignoreRows: null, // (Number, Number[]), row indices to exclude from the exported file(s) (default: null)
* ignoreCols: null, // (Number, Number[]), column indices to exclude from the exported file(s) (default: null)
* trimWhitespace: true // (Boolean), remove all leading/trailing newlines, spaces, and tabs from cell text in the exported file(s) (default: false)
* });
===================================*/
excelExport : function(fileName){
//selector 설정
var _sltHead = '#div_thead';
var _sltBody = '#div_tbody';
var _sltFoot = '#div_tfoot';
var _htmlColgroup = $('#div_thead > table > colgroup').html();;
var _htmlHead = $(_sltHead+' > table > thead').html();
var _htmlBody = $(_sltBody+' > table > tbody').html();
//필수조건 확인
if($(_sltHead).length==0){
alert('헤더 데이터는 필수조건 입니다.');
return false;
}
if($(_sltBody).length==0){
alert('바디 데이터는 필수조건 입니다.');
return false;
}
//소유자번호 유무 확인
var arrCellsOfOwnerNo = new Array();
$(_sltHead+' table tr:last-child th').each(function(){
if(this.innerHTML.indexOf('주민번호')>-1
||this.innerHTML.indexOf('주민등록번호')>-1
||this.innerHTML.indexOf('소유자번호')>-1
||this.innerHTML.indexOf('소유자주민번호')>-1
||this.innerHTML.indexOf('주민/법인번호')>-1
)
arrCellsOfOwnerNo.push(this.cellIndex);
});
//소유자번호 마스킹 처리
if(arrCellsOfOwnerNo.length>0){
var isMask = confirm('개인정보를 마스킹처리 하시겠습니까?');
var _maskBody = '';
$(_htmlBody).each(function(){
var row = this;
arrCellsOfOwnerNo.forEach(function(cellIdx){
var cell = $(row).find('td:eq('+cellIdx+')').text();
$(row).find('td:eq('+cellIdx+')').text(nvl(cell).fmtJuminNo(isMask));
});
_maskBody += '<tr>'+$(row).html()+'</tr>';
});
_htmlBody = _maskBody;
}
//파일명 설정
if(fileName==undefined || fileName==null || fileName=='')
fileName = $('#docTitleNm').text();
//테이블 설정
var colgroup = '<colgroup>'+ _htmlColgroup +'</colgroup>';
var thead = '<thead>'+ _htmlHead +'</thead>';
var tbody = '<tbody>'+ _htmlBody +'</tbody>';
if($(_sltBody+' > table > tfoot').length>0)
tbody += '<tfoot>'+$(_sltBody+' > table > tfoot').html()+'</tfoot>';
var tfoot = $(_sltFoot).length==0?'':'<tfoot>'+$(_sltFoot+' > table > tfoot').html()+'</tfoot>';
var table = '<table>'+colgroup+thead+tbody+tfoot+'</table>';
ExcelUtil.download(table, fileName);
},
pdfExport : function(fileName, selector){
//pdf_wrap을 canvas객체로 변환
html2canvas($(selector)[0]).then(function(canvas) {
var doc = new jsPDF('p', 'mm', 'a4'); //jspdf객체 생성
var imgData = canvas.toDataURL('image/png'); //캔버스를 이미지로 변환
doc.addImage(imgData, 'PNG', 0, 0, doc.internal.pageSize.getWidth(), doc.internal.pageSize.getHeight()); //이미지를 기반으로 pdf생성
doc.addPage();
doc.save(fileName+'.pdf'); //pdf저장
});
},
wordExport : function(fileName){
},
pptExport : function(fileName){
}
}
/**
* <pre>
* ajax 실행
* ex)
* cmmAjax({
* url: "<c:url value='/biz/prd/dealer/dealerList.do' />"
* ,data: {
* DLR_ID : $("#dealerSelect_dlrId").val()
* ,DLR_NM : $("#dealerSelect_dlrNm").val()
* }
* ,success: (response)=>{ //선택
* //callback function
* }
* ,exception: (response)=>{ //선택
* // callback function
* }
* });
* @param {object} param
* </pre>
*/
const cmmAjax = (param) => {
$.ajax({
url: param.url
,type: nvl(param.type, "post")
,data: param.data
,async: nvl(param.async, true)
,dataType: nvl(param.dataType, "json")
,processData: nvl(param.processData, true)
,contentType: nvl(param.contentType, 'application/x-www-form-urlencoded;charset=UTF-8')
,cache : false
,beforeSend: (jqXhr, settings) => {
jqXhr.setRequestHeader('AJAX',true);
}
,success: function (res) {
if (param.showSuccessMsg === undefined || param.showSuccessMsg === true) {
if(res.message) alert(res.message);
}
if ($.type(param.success) === 'function') {
param.success(res)
}
}
,error: function(jqXHR, error, errThrown ){
console.error('==============================================================');
console.error('>>>>>>>>>ajax call error<<<<<<<<<<<');
//console.error('::ajaxError >>>>> ', event, status, error)
console.error(`status=${jqXHR.status}, responseText=${jqXHR.responseText}, errorThrow=${errThrown}`);
console.error('==============================================================');
const resText = jqXHR.responseText;
if(typeof resText === 'string'){
alert(JSON.parse(resText).message);
return false;
}
if(typeof resText === 'object'){
alert(resText.message);
return false;
}
return document.write(jqXHR.responseText);
}
});
};
/**
* <pre>
* 팝업호출시(isPopup)
* 1) alert confirm 업무처리
* 2) 부모(opener) callBackSerch 실행
* 3) window close
* 일반호출시
* 1) alert confirm 업무처리
* 2) fnBiz.search() 호출
*
* @param {string} workType add | modify | remove
* @param {object} param parameter data
* </pre>
*/
const cmmBizAjax = (workType, param, isPopup = true) => {
let confirmMsg = '하시겠습니까?';
if(workType === 'add') confirmMsg = `등록 ${confirmMsg}`;
else if(workType === 'modify') confirmMsg = `변경 ${confirmMsg}`;
else if(workType === 'remove') confirmMsg = `삭제 ${confirmMsg}`;
else confirmMsg = `${workType} ${confirmMsg}`;
// else{
// alert('workType이 부정확 합니다.');
// return false;
// }
param = $.extend(param, {
success: ()=>{
//if(callback === 'function') window.opener.callback();
//else window.opener.callbackSearch();
if(isPopup) {
if(workType === 'add' || workType === 'remove'){
window.opener.callbackSearch();
window.close();
} else {
window.location.reload();
}
}else{
fnBiz.search();
}
}
});
dialog.alert({
content: confirmMsg,
onOK:() => {
cmmAjax(param);
}
});
};
const cmmApiCall = (param) => {
$.ajax({
url: param.url
,type: nvl(param.type, "post")
,data: param.data
,async: nvl(param.async, true)
,dataType: nvl(param.dataType, "json")
,processData: nvl(param.processData, true)
,contentType: nvl(param.contentType, 'application/json;charset=UTF-8')
,cache : false
,beforeSend: (jqXhr, settings) => {
jqXhr.setRequestHeader('AJAX',true);
}
,success: function (res) {
if (param.showSuccessMsg === undefined || param.showSuccessMsg === true) {
if(res.message) alert(res.message);
}
if ($.type(param.success) === 'function') {
param.success(res.data)
}
}
,error: function(jqXHR, error, errThrown ){
console.error('==============================================================');
console.error('>>>>>>>>>ajax call error<<<<<<<<<<<');
//console.error('::ajaxError >>>>> ', event, status, error)
console.error(`status=${jqXHR.status}, responseText=${jqXHR.responseText}, errorThrow=${errThrown}`);
console.error('==============================================================');
const resText = jqXHR.responseText;
if(typeof resText === 'string'){
alert(JSON.parse(resText).message);
return false;
}
if(typeof resText === 'object'){
alert(resText.message);
return false;
}
return document.write(jqXHR.responseText);
}
});
};
const cmmDownloadAjax = (param) => {
$.ajax({
url: param.url
,type: nvl(param.type, "post")
,data: param.data
,async: nvl(param.async, true)
,dataType: nvl(param.dataType, "json")
//,contentType: nvl(param.contentType, 'application/x-www-form-urlencoded;charset=UTF-8')
//,contentType: 'blob'
/*
,xhr: function () {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
//response 데이터를 바이너리로 처리한다. 세팅하지 않으면 default가 text
xhr.responseType = "blob";
};
return xhr;
}
*/
,success: function (res, msg, xhr) {
if (xhr.readyState == 4 && xhr.status == 200) {
// 성공했을때만 파일 다운로드 처리하고
let disposition = xhr.getResponseHeader('Content-Disposition');
let filename;
if (disposition && disposition.indexOf('attachment') !== -1) {
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
let matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
let blob = new Blob([res]);
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
}else{
//실패했을때는 alert 메시지 출력
alertPopup("다운로드에 실패하였습니다.");
}
if (param.showSuccessMsg === undefined || param.showSuccessMsg === true) {
if(res.message) alert(res.message);
}
if ($.type(param.success) === 'function') {
param.success(res)
}
}
,exception: function (res) {
alert(res.message);
if ($.type(param.exception) === 'function') {
param.exception(res);
}
}
});
};
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
function downloadImg(imgSrc) {
var image = new Image();
image.crossOrigin = "anonymous";
image.src = imgSrc;
var fileName = image.src.split("/").pop();
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
canvas.getContext('2d').drawImage(this, 0, 0);
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(dataURLtoBlob(canvas.toDataURL()), fileName);
} else {
var link = document.createElement('a');
link.href = canvas.toDataURL();
link.download = fileName;
link.click();
}
};
}
/**
* <pre>
* val 값이 null이면 ifNulVal(미지정시 '')
* null이 아니면 ifNotNullVal(미지정시 val)
* @param {string} val
* @param {string} ifNullVal
* @param {string} ifNotNullVal
* @returns {string|*}
* </pre>
*/
window.nvl = (val, ifNullVal, ifNotNullVal) => {
return val==null
?( ifNullVal==null?"":ifNullVal)
:(ifNotNullVal==null?val:ifNotNullVal);
};

@ -0,0 +1,472 @@
/*=====================================================================
*
* File Export 도구 Script
* -XitFileExportUtil.exportExcel() 기능을 사용하기 위해선 "xlsx.full.min.js" "Filesaver.min.js" 라이브러리가 반드시 필요 하다.
* @date 2020.02.27
* @author 박민규
*
=====================================================================*/
/**
* Xit 파일 Export 도구
* @author 박민규
* @date 2020.05.29.
*/
var XitFileExportUtil = function(fileName, dataType, dataSet, ext){
this._fileName = fileName; //파일명
this._dataType = dataType; //Data 타입(table, json, array)
this._dataSet = dataSet; //DataSet( Object 또는 Array<Object> )
}
XitFileExportUtil.prototype.setFileName = function(fileName){ this._fileName = fileName; }
XitFileExportUtil.prototype.setDataType = function(dataType){ this._dataType = dataType; }
XitFileExportUtil.prototype.setDataSet = function(arrDataSet){ this._dataSet = dataSet; }
XitFileExportUtil.prototype.exportExcel = function(){
// 변수 declare
var _fileName = fnIsEmpty(this._fileName)?'noname':this._fileName;
var _dataType = this._dataType;
var _dataSet = this._dataSet;
var _isMultiSheet = this._dataSet instanceof Array;
var _sheetName = 'Sheet';
// step 1. workbook 생성
var wb = XLSX.utils.book_new();
if(_isMultiSheet){
_dataSet.forEach(function(data, idx){
// step 2. 시트 만들기
var worksheet = createWorkSheet(data);
// step 3. workbook에 새로만든 워크시트에 이름을 주고 붙인다.
XLSX.utils.book_append_sheet(wb, worksheet, _sheetName+(idx+1));
});
}else{
// step 2. 시트 만들기
var worksheet = createWorkSheet(_dataSet);
// step 3. workbook에 새로만든 워크시트에 이름을 주고 붙인다.
XLSX.utils.book_append_sheet(wb, worksheet, _sheetName+'1');
}
// step 4. 엑셀 파일 만들기
var wbout = XLSX.write(wb, {bookType:'xlsx', type: 'binary'});
// step 5. 엑셀 파일 내보내기
saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), _fileName+'.xlsx');
// function Declare
function fnIsEmpty(val){
if(val==undefined||val==null||val==''||val=={}||val==[])
return true;
return false;
}
function createWorkSheet(data){
var result;
switch (_dataType) {
case 'table':
result = XLSX.utils.table_to_sheet(data);//table타입 data( ex: <table>...</table> )
break;
case 'json':
result = XLSX.utils.json_to_sheet(data);//json타입 data( ex: [{'이름':'홍길동', '나이':'18세', '출생연도':'1443'}, ... ] )
break;
case 'array':
result = XLSX.utils.aoa_to_sheet(data);//배열타입 data( ex: [['이름', '나이', '출생연도'],['홍길동', '18세', '1443'], ... ] )
break;
default:
result = '';
break;
}
return result;
}
function s2ab(s) {
var buf = new ArrayBuffer(s.length); //convert s to arrayBuffer
var view = new Uint8Array(buf); //create uint8array as viewer
for (var i=0; i<s.length; i++) view[i] = s.charCodeAt(i) & 0xFF; //convert to octet
return buf;
}
}
// /* JSON 데이터 만들기 */
// var arr = new Array();
// var data = new Object();
// data['하하']='123';
// data['호호']='123';
// arr.push(data);
// data = new Object();
// data['하하']='abc';
// data['호호']='abc';
// arr.push(data);
// console.log(JSON.stringify(arr));
// return arr;
function exportExcel(includeEntireTableId, type, type_case, fileName){
if(includeEntireTableId==undefined||includeEntireTableId==null||includeEntireTableId=='')
includeEntireTableId = excelHandler.getTableDataId();
var excelData = '';
switch (type) {
case 'table':
//checked checkbox의 nocheck 이슈 처리
$('#'+includeEntireTableId+' table input[type="checkbox"]:checked').attr('checked','checked');
$('#'+includeEntireTableId+' table input[type="checkbox"]:not(:checked)').removeAttr('checked');
//서비스 분기
switch (type_case) {
case 'case1': //전체 테이블 영역 내 하나의 테이블을 n개로 분할한 경우
excelData = excelTableDataCreateByCase.case1(includeEntireTableId);
break;
case 'case2': //전체 테이블 영역 내 테이블이 n개 인 경우
excelData = excelTableDataCreateByCase.case2(includeEntireTableId);
break;
default:
excelData = excelTableDataCreateByCase.case1(includeEntireTableId);
break;
}
break;
case 'json':
break;
case 'array':
break;
default:
alert('유효하지 않은 요청 타입 입니다.');
return false;
break;
}
/* export Excel */
var fileUtil = new XitFileExportUtil(fileName, type, excelData);
fileUtil.exportExcel();
}
/**
* 테이블 유형별 table타입 엑셀데이터 생성
*/
var excelTableDataCreateByCase = {
/*
* case1. 전체 테이블 영역 하나의 테이블을 n개로 분할한 경우
* @date 2020.02.27
* @author 박민규
*/
case1 : function(includeEntireTableId){
/*===================
* DATA 생성
===================*/
//head 데이터 설정
var arrHead = new Array();
$('#'+includeEntireTableId+' table thead').each(function(){
$(this).children('tr').each(function(rowidx, row){
/* 주석처리사유: tr 영역 내 input[type="hidden"] 과 같은 엘리먼트가 포함되어 있을 경우 레이아웃이 틀어 짐*/
// if(arrHead[rowidx]==undefined) arrHead[rowidx] = row.innerHTML;
// else arrHead[rowidx] += row.innerHTML;
$(row).find('th, td').each(function(cellidx, cell){
if(arrHead[rowidx]==undefined) arrHead[rowidx] = cell.outerHTML;
else arrHead[rowidx] += cell.outerHTML;
});
});
});
// console.log(arrHead);
//body 데이터 설정
var arrBody = new Array();
$('#'+includeEntireTableId+' table tbody').each(function(){
$(this).children('tr').each(function(rowidx, row){
/* 주석처리사유: tr 영역 내 input[type="hidden"] 과 같은 엘리먼트가 포함되어 있을 경우 레이아웃이 틀어 짐*/
// if(arrBody[rowidx]==undefined) arrBody[rowidx] = row.innerHTML;
// else arrBody[rowidx] += row.innerHTML;
$(row).find('th, td').each(function(cellidx, cell){
if(arrBody[rowidx]==undefined) arrBody[rowidx] = cell.outerHTML;
else arrBody[rowidx] += cell.outerHTML;
});
});
});
// console.log(arrBody);
//foot 데이터 설정
var arrFoot = new Array();
$('#'+includeEntireTableId+' table tfoot').each(function(){
$(this).children('tr').each(function(rowidx, row){
/* 주석처리사유: tr 영역 내 input[type="hidden"] 과 같은 엘리먼트가 포함되어 있을 경우 레이아웃이 틀어 짐*/
// if(arrFoot[rowidx]==undefined) arrFoot[rowidx] = row.innerHTML;
// else arrFoot[rowidx] += row.innerHTML;
$(row).find('th, td').each(function(cellidx, cell){
if(arrFoot[rowidx]==undefined) arrFoot[rowidx] = cell.outerHTML;
else arrFoot[rowidx] += cell.outerHTML;
});
});
});
// console.log(arrBody);
/*===================
* TABLE 그리기
===================*/
//table draw
var table = document.createElement('table');
//table>thead draw
var thead = document.createElement('thead');
for(var i=0; i<arrHead.length; i++){
thead.insertAdjacentHTML('beforeend','<tr>'+arrHead[i]+'</tr>');
}
table.appendChild(thead);
//table>tbody draw
var tbody = document.createElement('tbody');
for(var i=0; i<arrBody.length; i++){
tbody.insertAdjacentHTML('beforeend','<tr>'+arrBody[i]+'</tr>');
}
table.appendChild(tbody);
//table>tfoot draw
var tfoot = document.createElement('tfoot');
for(var i=0; i<arrFoot.length; i++){
tfoot.insertAdjacentHTML('beforeend','<tr>'+arrFoot[i]+'</tr>');
}
table.appendChild(tfoot);
//전체 테이블영역에 append
var div = document.createElement('div');
div.appendChild(table);
/*===================
* After 처리
===================*/
div = this.afterProc(div);
return div;
},
/*
* case2. 전체 테이블 영역 테이블이 n개 경우
* @date 2020.02.27
* @author 박민규
*/
case2 : function(includeEntireTableId){
/*===================
* DATA 생성
===================*/
var arrTable = new Array();
$('#'+includeEntireTableId+' table').each(function(tableidx, table){
//head 데이터 설정
var arrHead = new Array();
$(table).find('thead > tr').each(function(rowidx, row){
/* 주석처리사유: tr 영역 내 input[type="hidden"] 과 같은 엘리먼트가 포함되어 있을 경우 레이아웃이 틀어 짐*/
// if(arrHead[rowidx]==undefined) arrHead[rowidx] = row.innerHTML;
// else arrHead[rowidx] += row.innerHTML;
$(row).find('th, td').each(function(cellidx, cell){
if(arrHead[rowidx]==undefined) arrHead[rowidx] = cell.outerHTML;
else arrHead[rowidx] += cell.outerHTML;
});
});
// console.log(arrHead);
//body 데이터 설정
var arrBody = new Array();
$(table).find('tbody > tr').each(function(rowidx, row){
/* 주석처리사유: tr 영역 내 input[type="hidden"] 과 같은 엘리먼트가 포함되어 있을 경우 레이아웃이 틀어 짐*/
// if(arrBody[rowidx]==undefined) arrBody[rowidx] = row.innerHTML;
// else arrBody[rowidx] += row.innerHTML;
$(row).find('th, td').each(function(cellidx, cell){
if(arrBody[rowidx]==undefined) arrBody[rowidx] = cell.outerHTML;
else arrBody[rowidx] += cell.outerHTML;
});
});
// console.log(arrBody);
//body 데이터 설정
var arrFoot = new Array();
$(table).find('tfoot > tr').each(function(rowidx, row){
/* 주석처리사유: tr 영역 내 input[type="hidden"] 과 같은 엘리먼트가 포함되어 있을 경우 레이아웃이 틀어 짐*/
// if(arrFoot[rowidx]==undefined) arrFoot[rowidx] = row.innerHTML;
// else arrFoot[rowidx] += row.innerHTML;
$(row).find('th, td').each(function(cellidx, cell){
if(arrFoot[rowidx]==undefined) arrFoot[rowidx] = cell.outerHTML;
else arrFoot[rowidx] += cell.outerHTML;
});
});
// console.log(arrBody);
//table 데이터 설정
var tableData = new Object();
tableData['thead'] = arrHead;
tableData['tbody'] = arrBody;
tableData['tfoot'] = arrFoot;
arrTable[tableidx] = tableData;
});
// console.log(arrTable);
/*===================
* TABLE 그리기
===================*/
//div draw
var div = document.createElement('div');
arrTable.forEach(function(table, tableidx){
var arrHead = arrTable[tableidx].thead;
var arrBody = arrTable[tableidx].tbody;
var arrFoot = arrTable[tableidx].tfoot;
//table draw
var table = document.createElement('table');
//table>thead draw
var thead = document.createElement('thead');
for(var i=0; i<arrHead.length; i++){
thead.insertAdjacentHTML('beforeend', '<tr>'+arrHead[i]+'</tr>');
}
table.appendChild(thead);
//table>tbody draw
var tbody = document.createElement('tbody');
for(var i=0; i<arrBody.length; i++){
tbody.insertAdjacentHTML('beforeend', '<tr>'+arrBody[i]+'</tr>');
}
table.appendChild(tbody);
//table>tfoot draw
var tfoot = document.createElement('tfoot');
for(var i=0; i<arrFoot.length; i++){
tfoot.insertAdjacentHTML('beforeend', '<tr>'+arrFoot[i]+'</tr>');
}
table.appendChild(tfoot);
//전체 테이블영역에 append
div.appendChild(table);
});
/*===================
* After 처리
===================*/
div = this.afterProc(div);
return div;
},
/*
* 완료된 Table Data에 대한 후처리
* @date 2020.02.27
* @author 박민규
*/
afterProc : function(div){
//checkbox 처리
$(div).find('table tr > td > input[type="checkbox"]').each(function(cellidx, cell){
if($(cell).is(':checked'))
$(cell).parent().html('?');
else
$(cell).parent().html('?');
});
//selectbox 처리
$(div).find('table tr > td > select').each(function(cellidx, cell){
$(cell).parent().html(cell.options[cell.selectedIndex].text);
});
//특정 단어가 포함된 열(col) index 설정
var arrCellsOfOwnerNo = new Array();
var arrCellOfAdres = new Array();
$(div).find('table thead tr th').each(function(){
if(this.innerHTML.indexOf('주민번호')>-1
||this.innerHTML.indexOf('주민등록번호')>-1
||this.innerHTML.indexOf('소유자번호')>-1
||this.innerHTML.indexOf('소유자주민번호')>-1
||this.innerHTML.indexOf('주민/법인번호')>-1
)
arrCellsOfOwnerNo.push(this.cellIndex);
if(this.innerHTML.indexOf('주소')>-1||this.innerHTML.indexOf('번호')>-1)
arrCellOfAdres.push(this.cellIndex);
});
//소유자번호 마스킹 처리
if(arrCellsOfOwnerNo.length>0){
var isMask = confirm('개인정보를 마스킹처리 하시겠습니까?\n -[확인] 선택 시 마스킹 처리\n -[취소] 선택 시 전체 노출');
arrCellsOfOwnerNo.forEach(function(value){
$(div).find('table tbody tr td:nth-child('+(Number(value)+1)+')').each(function(cellidx, cell){
cell.innerHTML = fmtOwnerNo(cell.innerHTML, isMask);
});
});
}
//일부 주소데이터의 날짜 타입변환 방지 처리(case는 아래주석 참조)
//case1. 서울 종로구 홍지문길 84-5 -> (as-is)1984-05-01 -> (to-be)서울 종로구 홍지문길 84 - 5
//case2. 서울 종로구 창신길 33-4 -> (as-is)2033-04-01 -> (to-be)서울 종로구 창신길 33 - 4
if(arrCellOfAdres.length>0){
arrCellOfAdres.forEach(function(value){
$(div).find('table tbody tr td:nth-child('+(Number(value)+1)+')').each(function(cellidx, cell){
cell.innerHTML = cell.innerHTML.replace(/[-]/gi, ' - ');
});
});
}
// console.log(div);
return div;
}
};
/**
* 테이블 유형별 json타입 엑셀데이터 생성
*/
var excelJsonDataCreateByCase;
/**
* 테이블 유형별 배열(array)타입 엑셀데이터 생성
*/
var excelArrayDataCreateByCase;
/**
* 소유자번호 포맷설정 마스킹 처리
* @param ownerNo 소유자번호
* @param isMask 마스킹처리여부
* @returns
* @date 2020.02.27.
* @author 박민규
*/
function fmtOwnerNo(ownerNo, isMask){
if(ownerNo==null||ownerNo==undefined||ownerNo=='')
return ownerNo;
if(isMask==null||isMask==undefined||isMask=='')
isMask=false;
var value = ownerNo.replace(/[-]/gi,'');
if(value.length == 13) //주민번호
if(isMask)
value = value.substring(0, 6) + '-' +'*******';
else
value = value.substring(0, 6) + '-' +value.substring(6, 13);
else if(value.length == 10) //사업자번호
value = value.substring(0, 3) + '-' +value.substring(3, 5) + '-' + value.substring(5, 10);
return value;
}

@ -0,0 +1,22 @@
const cmmBS = {
contextMenu: ({ rowKey, columnName }) => (
[
[
{
name: 'bsAdd',
label: '바텀시트에 추가',
action: function() {
$('#bs').show(500);
var props = {};
props['rowKey'] = rowKey;
props['grid'] = columnName;
fnBiz.bsAdd(props);
},
classNames: ['']
},
],
]
),
}

@ -0,0 +1,224 @@
/* Download an img */
/**
* <pre>
* 첨부파일 정보 목록으로 부터 이미지 download
* 이미지 url 사용
* @param {string} divImgListElementId
* @param {object} cmmFileDtls json
* @param {function} fnBizPagePopup 이벤트 발생시 호출할 함수
* @param {boolean} isEditor 이미지 클릭시 이미지 에디터로 open
* @param {string} thumbnailSize 썸네일 이미지 크기 - default 100px
* </pre>
*/
function cmmImgDownload(divImgListElementId, cmmFileDtls, fnBizPagePopup = fnBiz.pagePopup, isEditor, thumbnailSize = '100px', callback) {
const downloadUrl = '/framework/biz/cmm/file/download.do';
$(divImgListElementId).children().remove();
if(cmmFileDtls != null){
cmmFileDtls.forEach((dtl, idx) => {
let imgDiv = document.getElementById(dtl.infKey);
if(!imgDiv?.hasChildNodes()){
imgDiv = document.createElement("div");
imgDiv.setAttribute("id", dtl.infKey);
imgDiv.setAttribute("value", dtl.fileMastrId);
imgDiv.setAttribute("class", "dragDiv")
}
//const params = `?filename=${dtl.orginlFileNm}&` + $.param(dtl);
const params = `?fileId=${dtl.fileId}&filePath=${dtl.filePath}&orginlFileNm=${dtl.orginlFileNm}`;
const title = dtl.orginlFileNm;
const x = document.createElement("img");
//x.setAttribute("class", "draggable")
x.setAttribute("src", downloadUrl+params);
x.setAttribute("id", dtl.fileId);
x.setAttribute("class", "draggable")
x.style = 'width:'+ thumbnailSize;
x.style = 'height:'+ thumbnailSize;
//x.style = 'object-fit: "contain";';
//x.style = 'object-fit: scale-down;';
x.setAttribute("title", title);
x.setAttribute("alt", dtl.orginlFileNm);
x.setAttribute("name", dtl.orginlFileNm);
x.setAttribute("data-file-mastr-id", dtl.fileMastrId);
x.setAttribute("data-file-id", dtl.fileId);
x.setAttribute("data-file-path", dtl.filePath);
x.setAttribute("data-file-size", dtl.fileSize);
x.addEventListener('dblclick', (e)=>{
if(isEditor) {
fnBizPagePopup('imageEditor', {imageTagId: dtl.fileId});
}else{
dtl.downloadUrl = downloadUrl+params;
//dtl.editor = true;
fnBizPagePopup('imageView', dtl);
}
})
imgDiv.appendChild(x);
document.querySelector(divImgListElementId).appendChild(imgDiv);
});
}
dragable();
if(callback) callback();
}
/**
* file download 실행
* @param blob
* @param fileName
*/
function downloadFile(blob, fileName, callback){
const url = URL.createObjectURL(blob);
const anchorElement = document.createElement('a');
document.body.appendChild(anchorElement);
anchorElement.download = fileName; // a tag에 download 속성을 줘서 클릭할 때 다운로드가 일어날 수 있도록 하기
anchorElement.href = url; // href에 url 달아주기
anchorElement.click(); // 코드 상으로 클릭을 해줘서 다운로드를 트리거
// cleanup - 쓰임을 다한 url 객체 삭제
anchorElement.onload = () => {
URL.revokeObjectUrl(url);
}
//URL.revokeObjectUrl(url);
document.body.removeChild(anchorElement); // cleanup - 쓰임을 다한 a 태그 삭제
if($.type(callback) === 'function') callback();
}
function download(img) {
var link = document.createElement("a");
link.href = img.src;
link.download = true;
link.style.display = "none";
var evt = new MouseEvent("click", {
"view": window,
"bubbles": true,
"cancelable": true
});
document.body.appendChild(link);
link.dispatchEvent(evt);
document.body.removeChild(link);
console.log("Downloading...");
}
/* Download all images in 'imgs'.
* Optionaly filter them by extension (e.g. "jpg") and/or
* download the 'limit' first only */
function downloadAll(imgs, ext, limit) {
/* If specified, filter images by extension */
if (ext) {
ext = "." + ext;
imgs = [].slice.call(imgs).filter(function (img) {
var src = img.src;
return (src && (src.indexOf(ext, src.length - ext.length) !== -1));
});
}
/* Determine the number of images to download */
limit = (limit && (0 <= limit) && (limit <= imgs.length))
? limit : imgs.length;
/* (Try to) download the images */
for (var i = 0; i < limit; i++) {
var img = imgs[i];
console.log("IMG: " + img.src + " (", img, ")");
download(img);
}
}
/*이미지 드레그앤 드롭 start*/
function dragable() {
const draggables = document.querySelectorAll(".draggable");
const containers = document.querySelectorAll(".dragDiv");
draggables.forEach(draggable => {
draggable.addEventListener("dragstart", () => {
console.log('drag start => ', draggable.getAttribute('id'));
draggable.classList.add("dragging");
});
draggable.addEventListener("dragend", () => {
console.log('drag end => ', draggable.getAttribute('data-file-mastr-id'));
draggable.classList.remove("dragging");
});
});
containers.forEach(container => {
container.addEventListener("dragover", e => {
e.preventDefault();
const afterElement = getDragAfterElement(container, e.clientX);
const draggable = document.querySelector(".dragging");
if (afterElement === undefined) {
container.appendChild(draggable);
} else {
container.insertBefore(draggable, afterElement);
}
});
});
}
function getDragAfterElement(container, x) {
const draggableElements = [
...container.querySelectorAll(".draggable:not(.dragging)"),
];
return draggableElements.reduce(
(closest, child) => {
const box = child.getBoundingClientRect();
const offset = x - box.left - box.width / 2;
// console.log(offset);
if (offset < 0 && offset > closest.offset) {
return { offset: offset, element: child };
} else {
return closest;
}
},
{ offset: Number.NEGATIVE_INFINITY },
).element;
}
/*이미지 드레그앤 드롭 end*/
/*이미지 드레그앤 드롭 저장 start*/
function dragableSave() {
let imgData = {};
let imgNode = document.querySelector("#imgList").childNodes;
console.log(imgNode);
for(let i=0; i<imgNode.length; i++) {
console.log('imgNode',imgNode[i]);
let imgNodeNo = imgNode[i];
imgNodeNo = imgNodeNo.attributes.value.value;
let imgNodeChild = imgNode[i].children;
var arr = new Array();
imgData[imgNodeNo] = arr;
for(let i=0; i<imgNodeChild.length; i++){
imgData[imgNodeNo].push(imgNodeChild[i].id);
}
}
console.log('final', imgData);
const imgEl = imgData;
dragableSaveAjax(imgEl);
}
function dragableSaveAjax(imgEl){
cmmAjax({
showSuccessMsg: false
,url: "/fims/biz/ec/saveImg.do"
,data: JSON.stringify(imgEl)
,contentType: 'application/json'
,success: (res) => {
alert('저장되었습니다.')
}
})
}

@ -0,0 +1,466 @@
const CmmPopup = {
defaultOpenOptions: {
/**
* <pre>
* 창의 높이.
* </pre>
*
* @attribute {Number} (open) height
*/
height: 200
/**
* <pre>
* 창의 넓이.
* </pre>
*
* @attribute {Number} (open) width
*/
, width: 400
/**
* <pre>
* 위치(y좌표).
* </pre>
*
* @attribute {Number} (open) top
*/
, top: 0
/**
* <pre>
* 위치(x좌표).
* </pre>
*
* @attribute {Number} (open) left
*/
, left: 0
/**
* <pre>
* 메뉴바 사용 여부. 파일, 편집, 보기 등의 버튼이 있는 . yes or no ( )
* </pre>
*
* @attribute {Object} (open) menubar
*/
, menubar: "no"
/**
* <pre>
* 툴바 사용 여부. 뒤로, 앞으로, 검색, 즐겨찾기 등의 버튼이 나오는 . yes or no
* </pre>
*
* @attribute {Object} (open) toolbar
*/
, toolbar: "no"
/**
* <pre>
* 주소창 변경 여부. URL입력하는 . yes or no
* </pre>
*
* @attribute {Object} (open) location
*/
, location: "no"
/**
* <pre>
* 리사이징 가능 여부. 새창이 떴을 시에 최소화, 최대화 등을 비롯해 마우스로 창의 크기를 조절 가능 여부. yes or no
* </pre>
*
* @attribute {Object} (open) resizable
*/
, resizable: "no"
/**
* <pre>
* 아래 링크 사용 여부. 인터넷 아래부분 보면 회색깔의 링크 주소 나오는 부분. yes or no
* </pre>
*
* @attribute {Object} (open) status
*/
, status: "no"
/**
* <pre>
* 스크롤바 사용여부. 우측부분과 하단 부분에 생기는 스크롤바를 지칭. yes or no
* </pre>
*
* @attribute {Object} (open) scrollbars
*/
, scrollbars: "yes"
/**
* <pre>
* 최대화로 띄움. yes or no
* </pre>
*
* @attribute {Object} (open) fullscreen
*/
, fullscreen: "no"
/**
* <pre>
* 가운데 정렬 여부. true 경우 top과 left를 자동 계산한다.
* </pre>
*
* @attribute {Object} (open) useCenterLocation
*/
, useCenterLocation: true
/**
* <pre>
* method type. post일 경우 form을 생성하고 data attribute의 값을 넣어 전송.
* </pre>
*
* @attribute {Object} (open) method
*/
, method: "get"
/**
* <pre>
* parameter data
* </pre>
*
* @attribute {Object} (open) data
*/
, data: null
}
, defaultModalDaialogOptions: {
/**
* <pre>
* 창의 높이.
* </pre>
*
* @attribute {Number} (modal) dialogHeight
*/
dialogHeight: 200
/**
* <pre>
* 창의 넓이.
* </pre>
*
* @attribute {Number} (modal) dialogWidth
*/
, dialogWidth: 400
/**
* <pre>
* 위치(y좌표).
* </pre>
*
* @attribute {Number} (modal) dialogTop
*/
, dialogTop: 0
/**
* <pre>
* 위치(x좌표).
* </pre>
*
* @attribute {Number} (modal) dialogLeft
*/
, dialogLeft: 0
/**
* <pre>
* 가운데 정렬 여부. yes/no, 1/0, on/off (정확하지 않음. useCenterLocation 이용 권장.)
* </pre>
*
* @attribute {String} (modal) center
*/
, center: "no"
/**
* <pre>
* 도움말 사용 여부. yes/no, 1/0, on/off
* </pre>
*
* @attribute {String} (modal) help
*/
, help: "no"
/**
* <pre>
* 리사이징 가능 여부. 새창이 떴을 시에 최소화, 최대화 등을 비롯해 마우스로 창의 크기를 조절 가능 여부. yes/no, 1/0, on/off
* </pre>
*
* @attribute {String} (modal) resizable
*/
, resizable: "no"
/**
* <pre>
* 스크롤바 사용여부. 우측부분과 하단 부분에 생기는 스크롤바를 지칭. yes or no
* </pre>
*
* @attribute {String} (modal) scroll
*/
, scroll: "yes"
/**
* <pre>
* 메뉴바 사용 여부. 파일, 편집, 보기 등의 버튼이 있는 . yes or no ( )
* </pre>
*
* @attribute {String} (modal) menubar
*/
, menubar: "no"
/**
* <pre>
* 툴바 사용 여부. 뒤로, 앞으로, 검색, 즐겨찾기 등의 버튼이 나오는 . yes or no
* </pre>
*
* @attribute {String} (modal) toolbar
*/
, toolbar: "no"
/**
* <pre>
* 주소창 변경 여부. URL입력하는 . yes or no
* </pre>
*
* @attribute {String} (modal) location
*/
, locationbars: "no"
/**
* <pre>
* 상태바 사용여부. yes/no, 1/0, on/off
* </pre>
*
* @attribute {String} (modal) status
*/
, status: "no"
/**
* <pre>
* 가운데 정렬 여부. true 경우 top과 left를 자동 계산한다.
* </pre>
*
* @attribute {Boolean} (modal) useCenterLocation
*/
, useCenterLocation: true
}
/**
* <pre>
* modaless CmmPopup.open(). options에 추가적으로 사용할 option 값을 json 객체의 필드 형태로 넘기면 된다.
* @method open
* @param {String} url 문서의 주소
* @param {Object} options 추가적으로 사용할 option 값을 담은 json 객체
* @param {Object} params parameter json object
* @param {String} target default 'nonamePopup'
* @param {String} method default 'get'
* @returns {object} 새로 열린 팝업창의 윈도우 객체.
* </pre>
*/
,open: function (url, params, options, target = 'nonamePopup', method = 'post') {
var extendOptions = $.extend({}, this.defaultOpenOptions, options);
// 가운데 정렬 계산.
if (extendOptions.useCenterLocation) {
const centerPosition = this.getCenterPosition(extendOptions.width, extendOptions.height);
extendOptions.left = centerPosition.left;
extendOptions.top = centerPosition.top;
}
// status 문자열 생성.
var optionsString = "";
for (var i in extendOptions) {
optionsString += i + "=" + extendOptions[i] + ", ";
}
method = method.toLowerCase();
var popup;
switch (method) {
case "post":
popup = window.open("", target, optionsString);
const form = this._getForm(url, target, method, params ? params : {});
form.submit();
break;
case "get":
default:
url += params ? "?" + $.param(params) : "";
popup = window.open(url, target, optionsString);
break;
}
if (popup) popup.focus();
return popup;
}
, openModal: function (url, params, options, title = 'nonamePopup', method = 'post') {
if($("#popupShowBtn").length < 1){
var modalTemplate = `<button type="button"
id="popupShowBtn"
data-bs-toggle="modal"
data-bs-target="#cmmModal"
hidden>
</button>
<div class="modal fade" id="cmmModal" tabindex="-1">
<div id="modalDialog" class="modal-dialog">
<div class="modal-content">
<div class="modal-header modal-header-noheader">
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
</button>
</div>
<div id="modalBody" class="modal-body">
</div>
</div>
</div>
</div>`;
$("body").append(modalTemplate);
}
$("#modalDialog").attr("class","modal-dialog");
if(options.width) {
$("#modalDialog").addClass("w-dialog-px-"+options.width);
}
if($("#modalIframe").length > 0){
$("#modalIframe").remove();
}
var dynamicPopup = document.createElement("pop");
dynamicPopup.setAttribute("id","pop"+1);
// .setAttribute("src" , "")
// .setAttribute("width" , "100%")
// .setAttribute("frameborder" , "0")
// .setAttribute("scrolling" , "no")
// .css("border" , "0")
// .css("overflow" , "auto")
// .css("overflow-x" , "no")
;
$("#modalBody").append(dynamicPopup);
popup = CmmPopup.open(url, params, options, "modalIframe", method);
$(popup.frameElement).on("load", function(){
var popupHeight = $(popup.frameElement.contentDocument.getElementById("wrap")).height();
$(popup.frameElement).attr("height", popupHeight);
});
$("#popupShowBtn").trigger("click");
return popup;
}
/**
* <pre>
* 주소 검색 팝업 호출
* 결과 return callback 함수로 fnCallbackZipSearch 사용
* fnCallbackZipSearch 함수는 var 선언
*
* ex)
* var fnCallbackZipSearch = (obj) => fnSetZipSearch(obj, document.userInfoVO);
* </pre>
*/
,zipPopup: function(){
let popUrl = '/_anonymous_/api/AdresSearch.do';
const params = {callback: 'fnCallbackZipSearch'};
const popTitle = "주소 찾기";
const popOption = {width: 570, height:420};
this.open(popUrl, params ,popOption, '주소 검색');
}
/**
* <pre>
* 주소 검색 Popup 결과를 set하는 콜백 함수
* @param {Object} zipObj - 주소 검색 결과
* @param {Object} tgtObj - 주소 검색 결과값을 Set할 객체(addr, zip, zip_view, daddr)
*
* ex)
* var fnCallbackZipSearch = (obj) => CmmPopup.fnSetZipSearch(obj, document.userInfoVO);
* </pre>
*/
,setZipSearch: function(zipObj, tgtObj){
//화면에 출력
tgtObj.addr.value = zipObj.roadAddrPart1;
tgtObj.zip.value = zipObj.zipNo;
tgtObj.zip_view.value = zipObj.zipNo;
tgtObj.daddr.value = zipObj.roadAddrPart2 + ' ' + zipObj.addrDetail;
}
/**
* modal CmmPopup.showModalDialog(). options에 추가적으로 사용할 option 값을 json 객체의 필드 형태로 넘기면 된다.
* @method showModalDialog
* @param {String} url 문서의 주소
* @param {Object} argument 팝업창으로 넘길 데이터.
* @param {Object} options 추가적으로 사용할 option 값을 담은 json 객체
* @returns {object} 자식창에서 리턴하는 .
*/
,showModalDialog: function (url, argument, options) {
let extendOptions = $.extend({}, this.defaultModalDaialogOptions, options);
// 가운데 정렬 계산.
if (extendOptions.useCenterLocation) {
let centerPosition = this.getCenterPosition(extendOptions.dialogWidth, extendOptions.dialogHeight);
extendOptions.dialogLeft = centerPosition.left + "px";
extendOptions.dialogTop = centerPosition.top + "px";
}
extendOptions.dialogWidth += "px";
extendOptions.dialogHeight += "px";
// status 문자열 생성.
let optionsString = "";
for (let i in extendOptions) {
optionsString += i + "=" + extendOptions[i] + "; ";
}
return window.showModalDialog(url, argument, optionsString);
}
/**
* 현재 브라우저에서 주어진 높이와 넓이를 가지는 창이 가운데에 위치되는 좌표 값을 구한다.
* @method getCenterPosition
* @param {Integer} width 넓이
* @param {Integer} height 높이.
* @returns {object} 해당 창이 가운데에 위치되는 좌표 .
*/
,getCenterPosition : function(width, height) {
const offsetX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft;
const offsetY = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop;
const browserWidth = typeof window.outerWidth!='undefined' ? window.outerWidth : document.documentElement.clientWidth;
const browserHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight: (document.documentElement.clientHeight - 22);
const shownBrowserWidth = (offsetX < 0) ? window.screen.width + offsetX : offsetX;
const left = parseInt(shownBrowserWidth + ((browserWidth - width) / 2), 10);
const top = parseInt(offsetY + ((browserHeight - height) / 2), 10);
return {left:left, top:top};
}
/**
* 폼생성
* @method getProperty
* @param {String} url 문서의 주소
* @param {String} target 목표창 이름
* @param {String} method form method type(get, post, etc)
* @param {Object} data 서버로 전송할 parameter data
* @returns {object} 새로 열린 팝업창의 윈도우 객체.
*/
,_getForm: function(url, target, method, data) {
if($("#PopupForm").length) {
$("#PopupForm").remove();
}
const form = $("<form id='PopupForm'></form>").attr("method", method)
.attr("target", target)
.attr("action", url);
for(const i in data) {
const input = $("<input />").attr("type", "hidden")
.attr("name", i)
.attr("value", data[i]);
form.append(input);
}
$("body").append(form);
return form;
}
}

@ -0,0 +1,599 @@
function deepCopy(obj) {
if(typeof obj !== 'object' || obj === null) {
return obj;
}
if(obj instanceof Date) {
return new Date(obj.getTime());
}
if(obj instanceof Array) {
return obj.reduce((arr, item, i) => {
arr[i] = deepCopy(item);
return arr;
}, []);
}
if(obj instanceof Object) {
return Object.keys(obj).reduce((newObj, key) => {
newObj[key] = deepCopy(obj[key]);
return newObj;
}, {})
}
}
$(document).keydown(function(event){
let code;
if (event.keyCode) code = event.keyCode;
else if (event.which) code = event.which;
if(code==8){
const targetNode = event.target.nodeName;
const readonly = event.target.readOnly;
const disabled = event.target.disabled;
const type = event.target.type;
//type이 password나 text인 input와 textarea를 제외한 모든 엘리먼트에서 백스페이스기능을 제한함
if( !( ((targetNode=="INPUT"&&(type=="text"||type=="password"))||targetNode=="TEXTAREA")&&(!readonly&&!disabled))) {
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue = false;
}
}
}
});
/**
* cmmClearForm(tagElementId)
* tagElement의 하위 input tag 클리어 사용.
* resetForm() input tag의 action 이전 값을 기억.
* clearForm() input tag의 모든값을 nullString 세팅.
* @param targetId : 초기화 하고자하는 상위 targetId
* @param notClearNameArr : 폼안에 검색조건이 있는 경우 clear하지 않을 이름.
*/
window.cmmClearForm = function (targetId, notClearNameArr) {
$("#"+targetId+" :input").each(function() {
if ( $.inArray(this.name, notClearNameArr) > -1 ) {
return true; //=>continue
}
switch(this.type) {
case 'password':
case 'select-multiple':
case 'text':
case 'textarea':
$(this).val('');
break;
case 'select-one':
$(this).val($(this).find("option:first").val());
break;
case 'checkbox':
case 'radio':
this.checked = false;
}
});
};
/**
* hidden 포함한 form 모든 항목 초기화
* @param targetId : 초기화 하고자하는 상위 targetId
* @param notClearNameArr : 폼안에 검색조건이 있는 경우 clear하지 않을 이름.
*/
window.cmmClearFormAll = function (targetId, notClearNameArr) {
$("#"+targetId+" :input").each(function() {
if ( $.inArray(this.name, notClearNameArr) > -1 ) {
return true; //=>continue
}
switch(this.type) {
case 'password':
case 'select-multiple':
case 'text':
case 'hidden':
case 'textarea':
$(this).val('');
break;
case 'select-one':
$(this).val($(this).find("option:first").val());
break;
case 'checkbox':
case 'radio':
this.checked = false;
}
});
};
/**
* setTimeCombo(objectId, timeDiv)
* objectI에 시간 또는 combobox 생성
* timeDiv가 'H'이면 시간, 'M'이면
* @param id : 콤보박스를 생성할 element ID
* @param timeDiv : 'H'-시간, 'M'-
*/
window.setTimeCombo = function(id, timeDiv){
var hh;
if(timeDiv == 'H'){
for (var i=0; i<24; i++){
if(i < 10) hh = '0'+i;
else hh = i+'';
var option = document.createElement('option');
var txt = document.createTextNode(hh);
option.setAttribute("value", hh);
option.appendChild(txt);
$("#"+id).append(option);
}
}else{
for (var i=0; i<60; i++){
if(i < 10) hh = '0'+i;
else hh = i+'';
var option = document.createElement('option');
var txt = document.createTextNode(hh);
option.setAttribute("value", hh);
option.appendChild(txt);
$("#"+id).append(option);
}
}
};
/**
* 문자열에서 exceptChar를 제거한다.
* @param exceptChar - 제거할 문자
* @return exceptChar가 제거된 문자
*/
String.prototype.remove = function(exceptChar) {
if ( this == null ) return "";
if ( exceptChar == null ) return this;
var str = this;
for ( var i=0, len=exceptChar.length ; i < len ;i++ ) {
str = str.replace(new RegExp("[\\"+exceptChar.charAt(i)+"]", "g"), "");
}
return str;
}
/**
* 문자열이 숫자형인지의 여부를 반환한다.
* @param exceptChar - 추가 허용할 문자
* @return 숫자형여부
*/
String.prototype.isNum = function(exceptChar) {
return (/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/).test(this.remove(exceptChar)) ? true : false;
};
/**
* 문자열을 숫자형으로 캐스팅한다.
* @return 캐스팅된 숫자
*/
String.prototype.toNum = function() {
if(this.isNum()) {
return Number(this.remove(DELIMITER_AMT));
} else {
return null;
}
};
/**
* 문자열의 UTF8 byte 길이를 반환한다.
* @return 문자열의 UTF8 byte 길이
*/
window.cmmGetUTF8ByteSize = function(str) {
if ( str == null || str.length == 0 ) {
return 0;
}
var size = 0;
for ( var i=0, len=str.length ; i < len ;i++ ) {
var charCode = str.charCodeAt(i),
charSize = 0;
//http://ko.wikipedia.org/wiki/UTF-8
if ( charCode <= 0x00007F ) { //127
charSize = 1;
} else if ( charCode <= 0x0007FF) { //2047
charSize = 2;
} else if ( charCode <= 0x00FFFF) { //65535
charSize = 3;
} else {
charSize = 4;
}
size += charSize;
}
return size;
};
/**
* 문자열의 byte 길이를 반환한다.
* @return 문자열의 byte 길이
*/
String.prototype.getByte = function() {
return cmmGetUTF8ByteSize(this);
// var cnt = 0;
//
// for (var i = 0; i < this.length; i++) {
// if (this.charCodeAt(i) > 127) {
// cnt += 2;
// } else {
// cnt++;
// }
// }
//
// return cnt;
};
/**
* 문자열이 지정한 최소길이 이상인지의 여부를 반환한다.
* @param minLen - 최소길이
* @return 최소길이 이상인지의 여부
*/
String.prototype.isMin = function(minLen) {
return this.length >= minLen;
};
/**
* 문자열이 지정한 최대길이 이하인지의 여부를 반환한다.
* @param maxLen - 최대길이
* @return 최대길이 이하인지의 여부
*/
String.prototype.isMax = function(maxLen) {
return this.length <= maxLen;
};
/**
* 문자열이 지정한 최소바이트수 이상인지의 여부를 반환한다.
* @param minByte - 최소바이트수
* @return 최소바이트수 이상인지의 여부
*/
String.prototype.isMinByte = function(minByte) {
return this.getByte() >= minByte;
};
/**
* 문자열이 지정한 최대바이트수 이하인지의 여부를 반환한다.
* @param maxByte - 최대바이트수
* @return 최대바이트수 이하인지의 여부
*/
String.prototype.isMaxByte = function(maxByte) {
return this.getByte() <= maxByte;
};
/**
* 문자열 좌우 공백을 제거한다.
* @return 좌우 공백 제거된 문자열
*/
$(function() {
if ( !String.prototype.trim ) { // Use native String.trim function wherever possible
String.prototype.trim = function() {
return this.replace(/^\s+/g, '').replace(/\s+$/g, '');
};
}
});
/**
* 문자열 공백을 제거한다.
* @return 공백 제거된 문자열
*/
String.prototype.ltrim = function() {
return this.replace(/(^\s*)/, "");
};
/**
* 문자열 공백을 제거한다.
* @return 공백 제거된 문자열
*/
String.prototype.rtrim = function() {
return this.replace(/(\s*$)/, "");
};
/**
* 문자열에서 모든 교체할 문자열을 대체 문자열로 치환한다.
* @param pattnStr - 찾을 문자열
* @param chngStr - 대체 문자열
* @return 치환된 문자열
*/
String.prototype.replaceAll = function(pattnStr, chngStr) {
var retsult = "";
var trimStr = this;//.replace(/(^\s*)|(\s*$)/g, "");
if(trimStr && pattnStr != chngStr) {
retsult = trimStr;
while(retsult.indexOf(pattnStr) > -1) {
retsult = retsult.replace(pattnStr, chngStr);
}
}
return retsult;
};
/**
* 문자열을 거꾸로 치환한다.
* @return 거꾸로 치환된 문자열
*/
String.prototype.reverse = function() {
var result = '';
for(var i=this.length-1; i>-1; i--) {
result += this.substring(i, i+1);
}
return result;
};
/**
* 지정한 길이만큼 원본 문자열 왼쪽에 패딩문자열을 채운다.
* @param len - 채울 길이
* @param padStr - 채울 문자열
* @return 채워진 문자열
*/
String.prototype.lpad = function(len, padStr) {
var result = '';
var loop = Number(len) - this.length;
for(var i=0; i<loop; i++) {
result += padStr.toString();
}
return result + this;
};
/**
* 지정한 길이만큼 원본 문자열 오른쪽에 패딩문자열을 채운다.
* @param len - 채울 길이
* @param padStr - 채울 문자열
* @return 채워진 문자열
*/
String.prototype.rpad = function(len, padStr) {
var result = '';
var loop = Number(len) - this.length;
for(var i=0; i<loop; i++) {
result += padStr.toString();
}
return this + result;
};
/**
* 문자열이 공백이나 널인지의 여부를 반환한다.
* @return 공백이나 널인지의 여부
*/
String.prototype.isBlank = function() {
var str = this.trim();
for(var i = 0; i < str.length; i++) {
if ((str.charAt(i) != "\t") && (str.charAt(i) != "\n") && (str.charAt(i)!="\r")) {
return false;
}
}
return true;
};
/**
* 문자열이 영어만으로 구성되어 있는지의 여부를 반환한다.
* @param exceptChar - 추가 허용할 문자
* @return 영어만으로 구성되어 있는지의 여부
*/
String.prototype.isEng = function(exceptChar) {
return (/^[a-zA-Z]+$/).test(this.remove(exceptChar)) ? true : false;
};
/**
* 문자열이 숫자와 영어만으로 구성되어 있는지의 여부를 반환한다.
* @param exceptChar - 추가 허용할 문자
* @return 숫자와 영어만으로 구성되어 있는지의 여부
*/
String.prototype.isEngNum = function(exceptChar) {
return (/^[0-9a-zA-Z]+$/).test(this.remove(exceptChar)) ? true : false;
};
/**
* 이메일 주소의 유효성 여부를 반환한다.
* @return 유효성 여부
*/
String.prototype.isEmail = function() {
//return (/\w+([-+.]\w+)*@\w+([-.]\w+)*\.[a-zA-Z]{2,4}$/).test(this.trim());
return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(this);
};
/**
* <pre>
* [downloadImage]
* @param {[string]} img [base64encoded image data]
* @param {[string]} fileName [new file name]
* @return [image file]
* </pre>
*/
function downloadImage(img, fileName) {
var imgData = atob(img.split(',')[1]),
len = imgData.length,
buf = new ArrayBuffer(len),
view = new Uint8Array(buf),
blob,
i;
for (i = 0; i < len; i++) {
view[i] = imgData.charCodeAt(i) & 0xff; // masking
}
blob = new Blob([view], {
type: 'application/octet-stream',
});
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
//var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.style = 'display: none';
a.href = URL.createObjectURL(blob);;
//a.href = img.src;
a.download = fileName;
document.body.appendChild(a);
a.click();
setTimeout(function () {
document.body.removeChild(a);
//URL.revokeObjectURL(url);
}, 100);
}
}
var readBlob = async () => {
const data = await fetch('https://play-lh.googleusercontent.com/hYdIazwJBlPhmN74Yz3m_jU9nA6t02U7ZARfKunt6dauUAB6O3nLHp0v5ypisNt9OJk');
const blob = await data.blob();
const reader = new FileReader();
reader.onload = () => {
const base64data = reader.result;
console.log(base64data)
}
reader.readAsDataURL(blob);
fetch('https://www.business2community.com/wp-content/uploads/2014/04/Free.jpg')
.then((response) => response.blob())
.then((blob) => {
const url = URL.createObjectURL(blob);
document.querySelector('img').src = url;
document.querySelector('a').href = url;
});
}
/**
*
* @param b64Data
* @param contentType
* @param sliceSize
* @returns {Blob}
*/
// bas64를 blob으로 변환해주는 함수
function b64toBlob(b64Data, contentType = '', sliceSize = 512) {
const image_data = atob(b64Data.split(',')[1]); // data:image/gif;base64 필요없으니 떼주고, base64 인코딩을 풀어준다
const arraybuffer = new ArrayBuffer(image_data.length);
const view = new Uint8Array(arraybuffer);
for (let i = 0; i < image_data.length; i++) {
view[i] = image_data.charCodeAt(i) & 0xff;
// charCodeAt() 메서드는 주어진 인덱스에 대한 UTF-16 코드를 나타내는 0부터 65535 사이의 정수를 반환
// 비트연산자 & 와 0xff(255) 값은 숫자를 양수로 표현하기 위한 설정
}
return new Blob([arraybuffer], { type: contentType });
/*
const contentType = 'image/png';
const b64Data =
'data:image/gif;base64,R0lGODlhAAEAAcQAALe9v9ve3/b393mDiJScoO3u74KMkMnNz4uUmKatsOTm552kqK+1uNLW18DFx3B7gP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4MTE5QjEwQjYyNTc4MkUxRURBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjEzN0VEMDZBQjMyNzExRTE4REMzRUZGMkFCOTM1NkZBIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjEzN0VEMDY5QjMyNzExRTE4REMzRUZGMkFCOTM1NkZBIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDI4MDExNzQwNzIwNjgxMTlCMTBCNjI1NzgyRTFFREEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTlCMTBCNjI1NzgyRTFFREEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQAAAAAACwAAAAAAAEAAQAF/yAkjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP6LR6zW673/C4fE6v2+/4vH7P7/v/gIGCg4SFhoeIiYptBQEADAQED5OUlQ8DkQwAAQKLni0KDgsDlqWmpQYLDgqfrSINCQans7SWBgkNrogFDKS1v8APBgwFuoIBksHKwQsBxn3Iy9LKBM7PdwXJ09vAC8XXcwDc48EDAOBwCgjk7MAI3+hqB77t9bMDufFoDPb9tef6yiTwR3BWgoBiBKwryLDUQYRftDWcOOkhxC0DKWqseFGLuI0gHXS80gCkyQfWRv9KKUDvJMUBnVRGkeiS4gKZUA7UPJkP5xIBLXdSNOCTyUehIAEWPQIUqUmYS48cdbrxQFQjsqiCJHp1SEmtJlN2/ZER7EaLY30ENdtwQNofAdiaZPWWx1S5E0XW3UETL8Obe3Ws9UuQa+AbAghvPIwjrmKKYhnLcPy4YWTJMBxUntgTc4y7m/sp9QwDdOh6o0m7MH2aXWrVLFi3HmcV9ouvs+1dtp2Ccu52u3mfKPDbXkzhLIrXQ+5ioXJuBJi34PecGwPpLHRW39YZ+4nE26cd947CeXhg0cmr0Hw+WG31JQQ4AFC2fS1NB8aTVzDY/q8BdJHXlH/bQEUeewRuo5f/d30lGEx63jnIjVvkSciNehZug2GG0mzIoTIefgiMelmJWAuE2DVooiUoSkfdirO8hpx2MJ7yHnYK1DgLPN71B6Nh5NWn4yTXwefbkA8ESCKSkyAA3wg0DnkjfCXW6OSTIxy5YnBB6lgkliMoBCMC+oHJkolkgjmceRKmqeZ3APi4nTlvriDAAQCo+BsBADRQZp0o4LYdl4CiIOdpQBY6XXhfKgpKeDw6ygKbubUo6QpR/jblpSscqliinK4gW2UyhooCcb8ZaGoLQoaG1qoroDpbpLCq0Opjr9aqgqyh0aprCrf6Veqv33lKlarExrbZgsm2UCVeVzbrgpZsESqt/wkLEJbrtSqMihSz3K5ArVbWhjsCr2z9ae4JhK3bHF6WunuCnkIBJq8KL5o17L0ieFvTvvz661J3/JYwLlLlynuwUAm7u/BODa/7cE0RmzuxSxWHe/FJGXO7cVgFp5ApuSGjIPBJAN8bLFKNljzCs1pF67II6JqlbsCEgRvygHghW7CYirlZsDqbvVNwA8ZqhY+8BWSb2wI36xqncnRKewDMvxmwqalX+1cNrF07+PWlYWeodaHyYW2hAQ5EjRwvSSc4ADHqBeA0k5Qk0PFYd6qNt9Zuv6VAAnEPOUACSu51J6V4/0LA1lENXnjjlhyeOE6LU24PAvnhFMDKmo9z+P/euzjgd+j1sO2rKw3cjfpGCxC8CNyv72QAAKsTUgDotYOUQO6AnNz7RinrUQDjwyMlNCD8Jd/z5XsEMLnzGwH4x8fUu2Q9H81nT9j2eZzpvWI+0wH0+EHnwTv6WrUsh6DsK0Z6GDzH/2ng+9gfWvFm1Ky/XwMAHhrW9z+t8G8M4ClgZconDwWGBnJocJ0DCWOvNkxwMxRixAU3g78wYG+DFHOD8EBYE53lj4SEOWBEUEiYeJ3hdCwUiszUEMN2sSFHNcSLAMMAvxySbA0j9KFGVMgFAgoRJO4zA72OeBIXkmF6TCwIqMqQwChSZQ0ftCJD5leFkWmxJrIbQxC/SBD/ImZBgmR0ybbGsMQ0TsSJYXAjUjLYPzkipYNayKId68FFKSBojyeB4BfGCEjXoKGNhfRHBcmAvEQyBI5ecKRLzoBDSYJkh3m0JMjKQEhNTsOEX8iXJxtiRiogcpTkgOQWYIhKdswwjq2kSBn0GEtlQK8LPaxlP/rYhE7q8heljMIff9kPUHLBf8RkByaxgMZkjmOR9GOlM39hADxigWjT5AYCbkm/ZmazFlBjA9K+CYyluUEAUyOnKcxhzYSYTp2UYFs7zdA6csaOD3fypicX0DlACAAW0iTjLfxUugUENIepcMAyBVGAA0DCigRgwAEWqggF4IkAB82eAfh0AG5eaCQAeFrAKSlHgAUA4AC8DIgAAtCAR0QCb5noEyfgo4AAOMKlBGhkaxAQ000EwKOSqqlN8QSAooo0EpHQKTl4itSSFrWoKLUpUGdG1apa9apYzapWt8rVrnr1q2ANq1jHStaymvWseggBADs=';
const blob = b64toBlob(b64Data, contentType); // base64 -> blob
const blobUrl = URL.createObjectURL(blob); // object url 생성
const img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);
*/
}
/**
* 전달받은 이미지를 base64로 인코딩한다
* @param file - 이미지 파일 또는 이미지 URL
* @param maxWidth - 인코딩 시의 이미지 max width 사이즈
* @returns {Promise<any>}
*/
var readImage = () => {
let image = this.$refs.image.src
this.toBlob(image)
.then(res => {
console.log(res)
this.image = {
filename: res.name,
size: res.size,
type: res.type,
lastModified: res.lastModified
}
})
};
/**
* 이미지 url을 blob 파일로 변환하여 전달한다
* @param url
* @returns {Promise<any>}
*/
var toBlob = (url) => {
return new Promise((resolve, reject) => {
this.base64Encode(url)
.then(res => {
let byteString = atob(res.dataUrl)
let ab = new ArrayBuffer(byteString.length)
let ia = new Uint8Array(ab)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
// write the array buffer to blob
let blob = new Blob([ab], {type: 'image/' + res.type})
let formData = new FormData()
formData.append('file', blob, res.name)
resolve(formData.get('file'))
})
})
};
/**
* 전달받은 이미지를 base64로 인코딩한다
*/
var base64Encode = (url) => {
const re = new RegExp('.(gif|jpg|jpeg|tiff|png|ico)$', 'i')
let name = (/[^(/|\\)]*$/).exec(url)[0]
let type = re.test(name) ? re.exec(name)[0].replace('.', '') : 'jpg'
return new Promise((resolve, reject) => {
let image = new Image()
image.onload = function (event) {
let canvas = document.createElement('canvas')
// draw canvas
canvas.width = image.naturalWidth
canvas.height = image.naturalHeight
canvas.getContext('2d').drawImage(image, 0, 0)
let dataUrl = canvas.toDataURL('image/' + type)
resolve({
name: name,
type: type,
dataUrl: dataUrl.split(',')[1]
})
}
image.onerror = function () {
let msg = `"${file}"을 로딩하는 데 오류가 발생하였습니다. 이미지 파일을 확인해주세요.`
alert(msg)
console.error(msg)
}
image.crossOrigin = 'anonymous';
image.src = url
})
}

@ -0,0 +1,98 @@
/*
* 단축키 Event
*/
document.onkeydown=function(e) {
if (e.key == "F1" && e.ctrlKey == true) {
if ( self !== top ) {
$(top.document.getElementById("favorites")).trigger("click");
} else {
$("#favorites").trigger("click");
}
}
};
/*
* 보안모드
*/
function fn_securityModeToggle(flag, elementId){
var executionArea;
if(elementId){
executionArea = $("#"+elementId);
} else {
executionArea = $(document);
}
var targets = executionArea.find("input.privacy");
for(let i=0; i< targets.length; i++){
let originId = targets[i].id;
let originValue= targets[i].value;
let maskingValue = originValue.replace(/[0-9a-zA-Z]/g, "*");
document.getElementById("mask-"+originId).value = maskingValue;
}
if(flag){ //개인정보 숨김
//입력상자
$("input.privacy").attr("hidden","hidden");
$("input.privacy-mask").removeAttr("hidden");
//그리드
$("th.privacy").attr("hidden","hidden");
$("td.privacy").attr("hidden","hidden");
$("th.privacy-mask").removeAttr("hidden");
$("td.privacy-mask").removeAttr("hidden");
} else { //개인정보 표시
//입력상자
$("input.privacy").removeAttr("hidden");
$("input.privacy-mask").attr("hidden","hidden");
$("th.privacy").removeAttr("hidden");
$("td.privacy").removeAttr("hidden");
$("th.privacy-mask").attr("hidden","hidden");
$("td.privacy-mask").attr("hidden","hidden");
}
}
$(document).ready(function(){
/*--------------------- 검색영역 상세검색 제어 ---------------------*/
$( "body" ).on( "click", ".btn-open-detail", function() {
$(this).find('i').toggleClass('bx-chevron-down');
$(this).find('i').toggleClass('bx-chevron-up');
});
/*--------------------- 달력 제어 ---------------------*/
$(".form-date").datepicker({
changeMonth: true,
changeYear: true,
showButtonPanel: true
});
$( "body .form-date" ).next("button.bx-calendar").on("click", function() {
$(this).prev().focus();
});
/*------- 팝업 제어 ---------*/
/*------- 팝업 열림 -------*/
$( "body" ).on( "click", "button[data-show-popup]", function(e) {
var popId = $(e.currentTarget).data("show-popup");
$(".modal-wrap").css("display",'table');
$(".modal-wrap .cont-box#"+popId).show();
});
/*------- 팝업 닫힘 -------*/
$( "body" ).on( "click", ".modal-wrap button[data-modal-close]", function() {
$(".modal-wrap, .modal-wrap .cont-box").hide();
});
});

@ -0,0 +1,135 @@
// 이전/다음 페이지 navigation data
class PageNavigation {
grid = null;
pageNav = null;
// 현재 gridData 목록
gridInfo = {
gridDatas: null
// 현재 rowData
,curRowData: null
// 현재 데이타 위치
,curRowPos: null
// 현재 데이타 위치
,gridDataPos: null
// 현재 page
,pageNum: null
// 페이지당 갯수
,fetchSize: null
// 전체 데이타 count
,totalSize: null
// 페이지 이동 구분
,pageMove: null
};
/**
* 페이지 이동 or 팝업 호출시 생성
* @param {object} GRID
* @param {array} gridDatas 그리드 데이타 key 필드 배열
* @param {number} gridDataPos 현재 그리드 페이지의 데이타 row
*/
constructor(GRID, gridDatas, gridDataPos) {
let pageInfo = {
pageNum: 1,
fetchSize: null,
totalSize: null
};
if(GRID.paginationInfoRef.paging === true){
const {pageNum, fetchSize, totalSize} = GRID.paginationInfoRef;
pageInfo.pageNum = pageNum;
pageInfo.fetchSize = fetchSize;
pageInfo.totalSize = totalSize;
}else{
pageInfo.fetchSize = GRID.paginationInfoRef.totalSize;
pageInfo.totalSize = GRID.paginationInfoRef.totalSize;
}
this.gridInfo = {
gridDatas
,gridDataPos
,curRowData: gridDatas[gridDataPos]
,curRowPos: (pageInfo.pageNum - 1) * pageInfo.fetchSize + gridDataPos + 1
,pageNum: pageInfo.pageNum
,fetchSize: pageInfo.fetchSize
,totalSize: pageInfo.totalSize
,pageMove: null
,next: null
}
this.pageNav = this;
this.grid = GRID;
};
/**
* 팝업 페이지 에서 강제 페이징 처리시 호출
* @param {json} res 그리드 목록 조회 결과
* @param {array} gridDatas 그리드 데이타 key 필드 배열
* @param {function} callback 호출할 function - 생성한 PageNavigation을 함께 전달
*/
resetGrid(res, gridDatas, callback) {
this.grid.resetData(res.data?.contents);
if (this.gridInfo.next) this.pageNav = new PageNavigation(this.grid, gridDatas, 0);
else this.pageNav = new PageNavigation(this.grid, gridDatas, this.gridInfo.fetchSize - 1);
callback(this.pageNav)
}
/**
* 팝업창의 prev, next 버튼 클릭후 정보 갱신을 위해 호출
* @param {object} prevObj prev button object
* @param {object} nextObj next button object
* @param {object} totObj total tag object
*/
reloadNav(prevObj, nextObj, totObj){
if(this.gridInfo.curRowPos === 1){
prevObj.attr('disabled', true);
}else{
prevObj.attr('disabled', false);
}
if(this.gridInfo.curRowPos === this.gridInfo.totalSize){
nextObj.attr('disabled', true);
}else{
nextObj.attr('disabled', false);
}
totObj.text(this.gridInfo.curRowPos + " / " + this.gridInfo.totalSize);
}
/**
* 팝업창 prev, next 버튼 클릭시 호출
* @param {string} evDiv 'prev|next'
* @param {function} callback 페이지 이동시 호출할 callback
*/
onClickNavBtn(evDiv, callback) {
const isTypeScroll = this.grid.paginationInfoRef?.pagingType === 'scroll';
if (evDiv === 'next') {
if(this.gridInfo.gridDataPos + 1 === this.gridInfo.fetchSize){
this.gridInfo.pageMove = true;
this.gridInfo.next = true;
this.gridInfo.pageNum++;
}else{
this.gridInfo.curRowPos++;
this.gridInfo.gridDataPos++;
this.gridInfo.curRowData = this.gridInfo.gridDatas[this.gridInfo.gridDataPos];
callback(this.gridInfo);
}
} else {
if(this.gridInfo.gridDataPos === 0){
this.gridInfo.pageMove = true;
this.gridInfo.next = false;
this.gridInfo.pageNum--;
}else {
this.gridInfo.curRowPos--;
this.gridInfo.gridDataPos--;
this.gridInfo.curRowData = this.gridInfo.gridDatas[this.gridInfo.gridDataPos];
callback(this.gridInfo)
}
}
}
}

@ -1,31 +0,0 @@
const frwkApiUrl = {
/**
* framework 공통 API URL
*/
//paintweb image editor popup
POPUP_PAINTWEB_IMG_EDITOR: '/framework/biz/cmm/file/cmmPaintwebImageEditorPopup.do'
//image view
,POPUP_IMG_VIEW: '/framework/biz/cmm/file/cmmImageViewPopup.do'
//파일 download - file full path
,DOWNLOAD_BY_FILE_PATH: '/framework/biz/cmm/file/downloadFromFileFullPath.do'
,DOWNLOAD: '/framework/biz/cmm/file/download.do'
,REMOVE_FILE: '/framework/biz/cmm/file/removeFile.do'
//공통 답변 템플릿
,FIND_ANS_TMPLS: '/framework/biz/cmm/answer/findCmmAnsTmpls.do'
,POPUP_ANS_TMPLS: '/framework/biz/cmm/answer/cmmAnsTmplPopup.do'
,SAVE_ANS_TMPLS: '/framework/biz/cmm/answer/addCmmAnsTmpls.do'
,MODIFY_ANS_TMPLS: '/framework/biz/cmm/answer/modifyCmmAnsTmpls.do'
/**
* framework 업무 API URL
*/
//게시판 - 기본 화면 관리(게시판 기본 양식)
,FIND_BOARD_BASICS: '/framework/biz/mng/bbs/findBoardBasics.do'
,FIND_BOARD_BASIC_ATTCH_FILES: '/framework/biz/mng/bbs/findCmmBoardAttchFiles.do'
,POPUP_BOARD_BASIC: '/framework/biz/mng/bbs/mngBoardBasicMgtPopup.do'
,SAVE_BOARD_BASIC: '/framework/biz/mng/bbs/addBoardBasic.do'
,MODIFY_BOARD_BASIC: '/framework/biz/mng/bbs/modifyBoardBasic.do'
}
Loading…
Cancel
Save