const hPopup = { highestZIndex: 10000, baseElement: document.body, popups: {}, // 팝업의 상대적 위치 저장 (popup_id: {left, top}) init() { this.injectStyles(); window.addEventListener('resize', () => hPopup.adjust_popup_positions()); }, injectStyles() { const style = document.createElement("style"); style.innerHTML = ` .hpopup * { box-sizing: border-box; } .hpopup { padding:0; font-size:13px; line-height:120%; position: absolute; border: 1px solid #001d37; border-radius:5px 5px 5px 5px; background-color: white; box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.3); min-width: 200px; min-height: 150px; display: flex; flex-direction: column; z-index: 10000; } .hpopup-header { background-color: #001d37; color: white; padding: 15px 10px; cursor: move; display: flex; justify-content: space-between; align-items: center; user-select:none; height:30px; } .hpopup-header .close-btn { cursor: pointer; padding: 5px; } .hpopup-body { padding: 0; flex: 1; } .hpopup-footer { padding: 10px; background-color: #f0f0f0; display: flex; justify-content: space-between; align-items: center; user-select:none; height:30px; border-radius:5px; overflow:hidden; } .hpopup-footer input[type="checkbox"] { margin-right: 5px; } `; document.head.appendChild(style); }, setTopLeftBase(selector) { const elem = document.querySelector(selector); if (elem) { this.baseElement = elem; } else { this.baseElement = document.body; } }, loadPopup(p_grp, p_method){ if(p_method==null) p_method = ''; fetch(HOME_URL + 'util/?cmd=get_popup_list&p_grp=' + p_grp + '&p_method=' + p_method) .then(response => response.json()) .then(data =>{ console.log(p_grp,data); if(p_method==''){ // 일반 팝업 data.data.forEach(p_idx=>hPopup.show_popup(p_idx)); }else{ // 슬라이드팝업 hPopup.slide_popup(data.data); } }) .catch(err=>{ console.error("Error get_popup_list data : ", err); }); }, slide_popup(list){ console.log(list); }, show_popup(p_idx, strong) { let popup_id = 'POPUP_'+p_idx; if(strong==null && document.cookie.includes(`${popup_id}=hidden`)) return; if(!HOME_URL) HOME_URL = '/'; fetch(HOME_URL + 'util/?cmd=get_popup&p_idx=' + p_idx) .then(response => response.json()) .then(data =>{ if(!data || !data.title){ return; } //console.log(data); let title = data.title; let left = data.left; let top = data.top; let width = data.width; let height = data.height; let bgcolor = data.bgcolor; let bgimage = data.bgimage; let imgsize = data.imgsize; let content = data.content; let layer = data.layer; if(layer!='1'){ // 실제 창 var fc = window.open(HOME_URL+'util/?cmd=popup_content&p_idx=' + p_idx + '&strong=' + (strong ? 'y' : ''), 'SITE_POPUP_'+p_idx, 'width='+width+',height='+height+',top='+(top<0 ? screen.availHeight - height + top : top)+',left='+(left<0 ? screen.availWidth - width + left : left)+''); fc.focus(); return; } let bgstyle = 'overflow:' + (data.scl=='1' ? 'auto' : 'hidden') + ';'; bgstyle += bgcolor!='' ? 'background-color:' + bgcolor + ';' : ''; bgstyle += bgimage!='' ? 'background-image: url(' + bgimage + '); background-position: center; background-repeat:no-repeat;background-size:'+(imgsize=='' ? 'auto' : imgsize) + ';' : ''; let popup = document.getElementById(popup_id); if (popup) popup.remove(); popup = document.createElement('div'); popup.className = 'hpopup'; popup.id = popup_id; popup.style.width = `${width + 2}px`; popup.style.height = `${height + 60}px`; const baseRect = this.baseElement.getBoundingClientRect(); const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; const scrollTop = window.pageYOffset || document.documentElement.scrollTop; let baseLeft = baseRect.left + scrollLeft; let baseTop = baseRect.top + scrollTop; if (left < 0) { if(this.baseElement.offsetWidth<300){ // 기준요소 가로폭 300 이하이면 body꺼 사용 const bodyRect = document.body.getBoundingClientRect(); baseLeft = bodyRect.left + scrollLeft; left = baseLeft + document.body.offsetWidth + left - width; }else{ left = baseLeft + this.baseElement.offsetWidth + left - width; } } else { left = baseLeft + left; } if (top < 0) { if(this.baseElement.offsetHeight<100){ // 기준요소 높이 100 이하이면 body꺼 사용 const bodyRect = document.body.getBoundingClientRect(); baseTop = bodyRect.top + scrollTop; top = baseTop + document.body.offsetHeight + top - (height + 60); }else{ top = baseTop + this.baseElement.offsetHeight + top - (height + 60); } } else { top = baseTop + top; } popup.style.left = `${left}px`; popup.style.top = `${top}px`; // 모바일기기 크기 자동 조절 추가 시작 const screenWidth = window.innerWidth; const screenHeight = window.innerHeight; // 팝업 전체 높이 (body + header + footer 포함) let popupTotalHeight = height + 60; // 크기 조정 if (width > screenWidth) { width = screenWidth; } if (popupTotalHeight > screenHeight) { height = screenHeight - 60; // header/footer 포함 고려 popupTotalHeight = height + 60; } // 위치 조정 if (left + width > screenWidth) { left = screenWidth - width; } if (top + popupTotalHeight > screenHeight) { top = screenHeight - popupTotalHeight; } if (left < 0) left = 0; if (top < 0) top = 0; // 보정된 위치/크기 적용 popup.style.left = `${left}px`; popup.style.top = `${top}px`; popup.style.width = `${width + 2}px`; popup.style.height = `${popupTotalHeight}px`; // 여기까지 popup.innerHTML = `
${title}
${content}
`; document.body.appendChild(popup); this.make_draggable(popup); popup.addEventListener('mousedown', () => this.bring_to_front(popup)); this.bring_to_front(popup); // 팝업의 상대적 위치 저장 this.popups[popup_id] = { offsetX: left - baseLeft, offsetY: top - baseTop }; }) .catch(err=>{ console.error("Error get_popup data : ", err); }); }, adjust_popup_positions() { const baseRect = this.baseElement.getBoundingClientRect(); const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; const scrollTop = window.pageYOffset || document.documentElement.scrollTop; const baseLeft = baseRect.left + scrollLeft; const baseTop = baseRect.top + scrollTop; for (const popup_id in this.popups) { const popup = document.getElementById(popup_id); if (popup) { const { offsetX, offsetY } = this.popups[popup_id]; popup.style.left = `${baseLeft + offsetX}px`; popup.style.top = `${baseTop + offsetY}px`; } } }, close_popup(popup_id, setCookie) { const popup = document.getElementById(popup_id); if (!popup) return; var now = new Date(); var midnight = new Date(now); midnight.setHours(23, 59, 59, 999); var leftSec = Math.floor((midnight - now) / 1000); // 초 단위 변환 if (setCookie) { const dontShow = document.getElementById(`${popup_id}_dontshow`).checked; if (dontShow) { document.cookie = `${popup_id}=hidden; path=/; max-age=${leftSec};`; } } popup.remove(); }, bring_to_front(popup) { this.highestZIndex++; popup.style.zIndex = this.highestZIndex; }, make_draggable(popup) { const header = popup.querySelector('.hpopup-header'); const popup_id = popup.id; let offsetX = 0, offsetY = 0, isDragging = false; header.addEventListener('mousedown', (e) => { if(e.button!=0) return; isDragging = true; offsetX = e.clientX - popup.offsetLeft; offsetY = e.clientY - popup.offsetTop; document.addEventListener('mousemove', movePopup); document.addEventListener('mouseup', (e) =>isDragging = false, { once: true }); }); function movePopup(e) { if (!isDragging) return; popup.style.left = (e.clientX - offsetX) + 'px'; popup.style.top = (e.clientY - offsetY) + 'px'; } } }; hPopup.init();