document.addEventListener("DOMContentLoaded", function () { // 에디터 로드 대기 (setTimeout으로 안정성 확보) setTimeout(function() { // 1. 스마트 에디터 2.0 (SmartEditor2) if (typeof oEditors !== 'undefined' && oEditors.getById['content']) { detectVariables(oEditors.getById['content'].getContents()); // '이메일 내용' 에디터의 플레이스홀더 기능 구현 const contentEditor = oEditors.getById['content']; const placeholderHTML = '

이곳에 메일 본문 내용을 입력하세요.

'; // 에디터의 실제 body 요소를 가져옵니다. try { const editorBody = contentEditor.oApp.getWYSIWYGDocument().body; // 에디터에 포커스가 갔을 때 (클릭 또는 탭) const handleFocus = function() { const currentHTML = contentEditor.getContents().trim(); if (currentHTML === placeholderHTML) { contentEditor.setContents(''); } }; // 에디터에서 포커스가 벗어났을 때 const handleBlur = function() { const currentIR = contentEditor.getIR().trim(); if (currentIR === '' || currentIR === '

 

' || currentIR === '


') { contentEditor.setContents(placeholderHTML); } }; if(editorBody) { editorBody.addEventListener('focus', handleFocus); editorBody.addEventListener('blur', handleBlur); } } catch(e) { console.log("SmartEditor2 body access failed: " + e.message); } } // 2. CHEditor5 else if (typeof ed_content !== 'undefined') { // CHEditor는 로드 완료 후 실행해야 하므로, 에디터 객체의 메서드를 사용하거나 잠시 대기 // 여기서는 이미 로드되었다고 가정하고 내용 가져오기 시도 var content = ed_content.outputBodyHTML(); detectVariables(content); } }, 1000); // CHEditor 로딩 시간을 고려하여 1초로 늘림 }); // 이메일 내용에서 {변수명}을 감지하여 입력 필드를 생성/제거하는 함수 function detectVariables(content) { if (!content) return; // [수정] 정규식의 \w가 한글을 포함하지 못하므로, [a-zA-Z0-9_가-힣]로 변경하여 한글 변수도 감지하도록 합니다. const matches = [...new Set((content.match(/{([a-zA-Z0-9_가-힣]+)}/g) || []))]; const container = document.getElementById('variableInputs'); const existingVars = new Set(); const newVars = new Set(matches); container.querySelectorAll('input[data-var]').forEach(input => { existingVars.add(`{${input.dataset.var}}`); }); // 새로 발견된 변수는 입력 필드 추가 newVars.forEach(tag => { if (!existingVars.has(tag)) { const varName = tag.replace(/[{}]/g, ''); const label = document.createElement('label'); label.textContent = varName; const input = document.createElement('input'); input.type = 'text'; input.className = 'frm_input'; input.name = `variables[${varName}]`; input.dataset.var = varName; // serverVars는 template_form.php에서 PHP 변수를 JS로 변환하여 제공합니다. input.value = (typeof serverVars !== 'undefined' && serverVars[varName]) ? serverVars[varName] : ''; input.style.width = '95%'; input.placeholder = `${varName}의 기본값 입력`; container.appendChild(label); container.appendChild(input); } }); // 내용에서 삭제된 변수는 입력 필드 제거 existingVars.forEach(tag => { if (!newVars.has(tag)) { const varName = tag.replace(/[{}]/g, ''); const inputToRemove = container.querySelector(`input[data-var="${varName}"]`); if (inputToRemove) { if (inputToRemove.previousElementSibling && inputToRemove.previousElementSibling.tagName === 'LABEL') { inputToRemove.previousElementSibling.remove(); } inputToRemove.remove(); } } }); } // '변수 새로고침' 버튼 클릭 시 실행될 함수 function refreshVariables() { var content = ''; // 1. 스마트 에디터 2.0 if (typeof oEditors !== 'undefined' && oEditors.getById['content']) { content = oEditors.getById['content'].getContents(); } // 2. CHEditor5 else if (typeof ed_content !== 'undefined') { content = ed_content.outputBodyHTML(); } else { alert('에디터가 로드되지 않았거나 지원하지 않는 에디터입니다.'); return; } detectVariables(content); alert('변수 목록을 새로고침했습니다.'); } // 미리보기 기능 function previewTemplate() { let headerHtml = ''; let bodyHtml = ''; let footerHtml = ''; // 1. 스마트 에디터 2.0 if (typeof oEditors !== 'undefined' && oEditors.getById['content']) { headerHtml = oEditors.getById['header_html'] ? oEditors.getById['header_html'].getContents() : ''; bodyHtml = oEditors.getById['content'].getContents(); footerHtml = oEditors.getById['footer_html'] ? oEditors.getById['footer_html'].getContents() : ''; } // 2. CHEditor5 else if (typeof ed_content !== 'undefined') { headerHtml = typeof ed_header_html !== 'undefined' ? ed_header_html.outputBodyHTML() : ''; bodyHtml = ed_content.outputBodyHTML(); footerHtml = typeof ed_footer_html !== 'undefined' ? ed_footer_html.outputBodyHTML() : ''; } else { alert('에디터가 로드되지 않았습니다.'); return; } const variableInputs = document.querySelectorAll('#variableInputs input'); // 입력된 모든 변수 테스트 값을 헤더, 본문, 푸터에 각각 적용합니다. variableInputs.forEach(input => { const varName = input.dataset.var; const value = input.value; if (value) { // 정규식에 'g' 플래그를 사용하여 문서 전체의 변수를 모두 치환합니다. const regex = new RegExp('{' + varName.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '}', 'g'); headerHtml = headerHtml.replace(regex, value); bodyHtml = bodyHtml.replace(regex, value); footerHtml = footerHtml.replace(regex, value); } }); // 헤더 + 본문 + 푸터를 합쳐서 최종 HTML을 만듭니다. const finalHtml = headerHtml + bodyHtml + footerHtml; const popup = window.open('', '미리보기', 'width=800,height=600,scrollbars=yes'); popup.document.write(finalHtml); popup.document.close(); } // 폼 전송 시 에디터 내용 업데이트 및 유효성 검사 function form_check(f) { // 1. 스마트 에디터 2.0 if (typeof oEditors !== 'undefined' && oEditors.getById['content']) { oEditors.getById['header_html'].exec("UPDATE_CONTENTS_FIELD", []); oEditors.getById['content'].exec("UPDATE_CONTENTS_FIELD", []); oEditors.getById['footer_html'].exec("UPDATE_CONTENTS_FIELD", []); } // 2. CHEditor5 else if (typeof ed_content !== 'undefined') { // CHEditor는 outputBodyHTML()로 내용을 가져와서 textarea에 넣어줘야 함 if(typeof ed_header_html !== 'undefined') f.header_html.value = ed_header_html.outputBodyHTML(); f.content.value = ed_content.outputBodyHTML(); if(typeof ed_footer_html !== 'undefined') f.footer_html.value = ed_footer_html.outputBodyHTML(); } else { // 에디터가 없거나 로드되지 않은 경우 (일반 textarea 사용 시) // 별도 처리 없음 } // 에디터 내용이 비어있는지 체크 const content = f.content.value.trim(); const emptyPatterns = ['', '

 

', '


', '

', ' ']; // 태그 제거 후 공백 체크 const textContent = content.replace(/<[^>]*>?/gm, '').trim(); if (textContent === '' && emptyPatterns.includes(content.toLowerCase())) { alert('내용을 입력해 주십시오.'); if (typeof oEditors !== 'undefined') { oEditors.getById['content'].exec("FOCUS"); } else if (typeof ed_content !== 'undefined') { ed_content.returnFalse(); } else { f.content.focus(); } return false; } return true; }