// 텍스트 필드에서 엔터 입력시 폼전송 되는것 방지 하고, 지정한 함수를 실행 한다. function on_enter_go(f){ // onkeydown="on_enter_go(_=>func())" var keycode = event.keyCode; if(keycode==13){ event.preventDefault(); if(f) f(); return false; } } document.addEventListener('DOMContentLoaded', () => { let tooltip = null; const getElemPos = (obj) => { let left = 0, top = 0; let width = obj.offsetWidth; let height = obj.offsetHeight; let elem = obj; while(elem) { left += elem.offsetLeft || 0; top += elem.offsetTop || 0; elem = elem.offsetParent; } // 내부 스크롤이 있는 영역에 있을 경우 보정 elem = obj.parentNode; while(elem && elem.tagName !== 'BODY' && elem.tagName !== 'HTML') { if(elem.scrollTop) top -= elem.scrollTop; if(elem.scrollLeft) left -= elem.scrollLeft; elem = elem.parentNode; } return { left, top, width, height }; }; document.addEventListener('mouseover', (e) => { const trigger = e.target.closest('.html-tooltip[desc]'); if (!trigger) return; const htmlContent = trigger.getAttribute('desc'); if (!htmlContent || htmlContent.trim() === '') return; if (tooltip) tooltip.remove(); tooltip = document.createElement('div'); tooltip.className = 'custom-tooltip'; tooltip.innerHTML = htmlContent; document.body.appendChild(tooltip); const pos = getElemPos(trigger); const top = pos.top - 10; // 타겟 위로 10px 띄움 const left = pos.left + (pos.width / 2); // 타겟의 가로 중앙 tooltip.style.top = `${top}px`; tooltip.style.left = `${left}px`; }); document.addEventListener('mouseout', (e) => { const trigger = e.target.closest('.html-tooltip[desc]'); if (!trigger) return; if (tooltip) { tooltip.remove(); tooltip = null; } }); }); function check_tabkey(o, e){ if(window.event) e = window.event; var ch = e.keyCode; if(ch==9){ o.focus(); InsertTextarea(o, "\t"); if(e.preventDefault) e.preventDefault(); if(e.returnValue) e.returnValue = false; return false; } } function cat_rule_check(arr, cat_1, cat_2){ // 카테고리 규칙에 맞는가? const cat_match_rule = (cat1, cat2, rule)=>{ // 카테고리 1/2차 매칭여부판단 함수 실제 사용 법 if([규칙들].some(rule=>cat_match_rule(frm.cat_1.value, frm.cat_2.value, rule))) { ... } const [r1, r2] = rule.includes('|') ? rule.split('|') : [rule, '*']; const cat1Match = r1 === '*' || (r1.endsWith('*') && cat1.startsWith(r1.slice(0, -1))) || r1 === cat1; const cat2Match = r2 === '*' || r2 === cat2; return cat1Match && cat2Match; }; return arr.some(rule=>cat_match_rule(cat_1, cat_2, rule)); } function open_cash_popup(a_idx, o_idx, mode){ if(mode==null) mode = ''; var fc = openWinS(ADMIN_URL+'admin_agent_list.php?cmd=call_cash_history&a_idx='+a_idx+'&o_idx='+o_idx+'&mode='+mode, 1200, screen.availHeight); } function open_feed_history(o_idx){ var fc = openWinS(ADMIN_URL+'admin_order_list.php?cmd=call_feed_history&q_idx='+o_idx, 700, 700, 'FEED_HISTORY_WIN', 'yes'); } function open_odr_stat_history(o_idx){ var fc = openWinS(ADMIN_URL+'admin_order_list.php?cmd=call_stat_history&q_idx='+o_idx, 900, 700, 'ODR_STAT_HISTORY_WIN', 'yes'); } function up_down_key(el_name, n, m, with_bar){ // 블록형 입력상자 커서로 위아래 이동 onkeydown="up_down_key('a_managers',=$n?>,0)" name="a_managers_{n}_{m}" 형태 // name="elname_{n}_{m}" 형태가 불가능하면 // data-updown_ptr="tag_name_{n}_{m}" 설정 후 onkeydown"up_down_key('data-updown_ptr=tag_name', n, m)" 호출하면 됨 var bar = '_'; if(with_bar==false) bar = ''; var key = event.code; var el_names = 'input[name="' + el_name; if(el_name.startsWith('data-updown_ptr=')){ el_names = 'input[data-updown_ptr="' + el_name.replace('data-updown_ptr=', ''); } if(['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)){ event.preventDefault(); } if(key=='ArrowUp'){ if(n > 0){ var el = document.querySelector(el_names + bar + (n - 1) + '_' + m + '"]'); if(el){ el.focus(); if(el.type !== 'checkbox' && el.type !== 'radio') el.select(); } return false; } } if(key=='ArrowDown'){ var el = document.querySelector(el_names + bar + (n + 1) + '_' + m + '"]'); if(el){ el.focus(); if(el.type !== 'checkbox' && el.type !== 'radio') el.select(); } return false; } if((event.ctrlKey || event.metaKey) && key === 'ArrowLeft' && m > 0){ var el = document.querySelector(el_names + bar + n + '_' + (m - 1) + '"]'); if(m==1){ console.log(el_names + bar + n + '_' + (m - 1) + '"]', el); } if(el){ if(el.type !== 'checkbox' && el.type !== 'radio') el.focus(); else el.focus({ focusVisible: true }); if(el.type !== 'checkbox' && el.type !== 'radio') el.select(); } return false; } if((event.ctrlKey || event.metaKey) && key === 'ArrowRight'){ var el = document.querySelector(el_names + bar + n + '_' + (m + 1) + '"]'); if (el) { if(el.type !== 'checkbox' && el.type !== 'radio') el.focus(); else el.focus({ focusVisible: true }); if(el.type !== 'checkbox' && el.type !== 'radio') el.select(); } return false; } } function send_sms_popup(pcs, kind){ // '폰번호;번호', '$mode/$o_idx/$a_idx' if(kind == null) kind = ''; let msg = ''; if(arguments.length>2){ msg = arguments[2]; } if(kind==''){ // 일반 메시지 openWinS(ADMIN_URL + 'popup_sms_send.php?pcs=' + encodeURIComponent(pcs) + '&msg=' + encodeURIComponent(msg) , 450, 500, 'SMS_SEND_WIN'); }else{ // kind = mode/o_idx/a_idx openWinS(ADMIN_URL + 'popup_sms_send_kind.php?pcs=' + encodeURIComponent(pcs) + '&kind=' + encodeURIComponent(kind) + '&msg=' + encodeURIComponent(msg) , 450, 500, 'SMS_SEND_WIN'); } } function log_message_view(o) { if (window.event) { window.event.preventDefault(); } // 속성값 추출 및 기본값 처리 const toTel = o.getAttribute('toTel') || ''; const fromTel = o.getAttribute('fromTel') || ''; const mode = o.getAttribute('mode') || ''; const desc = o.getAttribute('desc') || ''; const tail = o.getAttribute('tail') || ''; const text = o.innerHTML.replaceAll('', '\n'); const fc = openWinS('', 450, 480, 'SMS_VIEW_WINDOW'); // CSS 스타일 정의 const cssStyles = ` `; // 조건부 HTML 생성 const fromTelHtml = fromTel ? `