first commit 2
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('.preview-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const base64 = btn.getAttribute('data-content');
|
||||
const decodedHtml = atob(base64);
|
||||
previewTemplate(decodedHtml);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function previewTemplate(htmlContent) {
|
||||
const popup = window.open('', '미리보기', 'width=800,height=600,scrollbars=yes');
|
||||
if (!popup) {
|
||||
alert('팝업이 차단되었습니다. 브라우저의 팝업 차단을 해제하고 다시 시도해 주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
const popupContent = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>템플릿 미리보기</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; padding: 20px; line-height: 1.6; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
${htmlContent}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
popup.document.write(popupContent);
|
||||
popup.document.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const form = document.getElementById('fmaillog');
|
||||
if (!form) return;
|
||||
|
||||
const tableWrap = document.querySelector('.tbl_wrap');
|
||||
// [수정] AJAX URL을 PHP에서 정의한 전역 변수(ajax_resend_url)로 변경하여 경로 오류를 해결합니다.
|
||||
const resend_url = ajax_resend_url;
|
||||
const token = form.querySelector('input[name="token"]')?.value || '';
|
||||
|
||||
// 전체 선택/해제
|
||||
const chkAll = document.getElementById('chkall');
|
||||
if (chkAll) {
|
||||
chkAll.addEventListener('click', function() {
|
||||
const checkboxes = form.querySelectorAll('input[name="chk[]"]:not(:disabled)');
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.checked = this.checked;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 선택 재발송 버튼
|
||||
const bulkResendBtn = document.getElementById('bulk-resend-btn');
|
||||
if (bulkResendBtn) {
|
||||
bulkResendBtn.addEventListener('click', function() {
|
||||
const checkedItems = form.querySelectorAll('input[name="chk[]"]:checked');
|
||||
if (checkedItems.length === 0) {
|
||||
alert('재발송할 항목을 하나 이상 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm(`선택된 ${checkedItems.length}개의 메일을 재발송하시겠습니까?`)) {
|
||||
const ids = Array.from(checkedItems).map(cb => cb.value);
|
||||
resendMails(ids, this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 개별 재발송 및 미리보기 (이벤트 위임)
|
||||
tableWrap.addEventListener('click', function(e) {
|
||||
const target = e.target;
|
||||
|
||||
// 개별 재발송
|
||||
if (target.classList.contains('resend-btn')) {
|
||||
const logId = target.dataset.id;
|
||||
if (logId && confirm('이 메일을 재발송하시겠습니까?')) {
|
||||
resendMails([logId], target);
|
||||
}
|
||||
}
|
||||
|
||||
// 미리보기
|
||||
if (target.classList.contains('preview-btn')) {
|
||||
const content = target.dataset.content;
|
||||
if (content) {
|
||||
try {
|
||||
const decodedContent = decodeURIComponent(atob(content).split('').map(function(c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
}).join(''));
|
||||
const popup = window.open('', '메일 미리보기', 'width=800,height=700,scrollbars=yes');
|
||||
popup.document.write(decodedContent);
|
||||
popup.document.close();
|
||||
} catch (error) {
|
||||
alert('미리보기 내용을 여는 데 실패했습니다.');
|
||||
console.error('Base64 디코딩 오류:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 메일 재발송 실행 함수
|
||||
function resendMails(ids, buttonElement) {
|
||||
const originalText = buttonElement.textContent;
|
||||
buttonElement.disabled = true;
|
||||
buttonElement.textContent = '전송중...';
|
||||
|
||||
const formData = new FormData();
|
||||
ids.forEach(id => formData.append('ids[]', id));
|
||||
formData.append('token', token);
|
||||
|
||||
fetch(resend_url, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) throw new Error('서버 응답 오류');
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// [디버깅 개선] alert()는 긴 메시지를 자를 수 있으므로, console.log로 전체 메시지를 확인합니다.
|
||||
console.log('서버 응답:', data);
|
||||
alert(data.message);
|
||||
if (data.success) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
buttonElement.disabled = false;
|
||||
buttonElement.textContent = originalText;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('재발송 오류:', error);
|
||||
alert('재발송 처리 중 오류가 발생했습니다.');
|
||||
buttonElement.disabled = false;
|
||||
buttonElement.textContent = originalText;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,89 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const templateSelect = document.getElementById('template_code');
|
||||
const varContainer = document.getElementById('variable_fields');
|
||||
|
||||
if (templateSelect) {
|
||||
templateSelect.addEventListener('change', function() {
|
||||
const selectedCode = this.value;
|
||||
varContainer.innerHTML = ''; // 기존 필드 초기화
|
||||
varContainer.style.display = 'none'; // 컨테이너 숨김
|
||||
|
||||
if (!selectedCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX 요청으로 선택된 템플릿의 변수 가져오기
|
||||
fetch(`./ajax_get_template_vars.php?code=${selectedCode}`)
|
||||
.then(response => {
|
||||
// [개선] 네트워크 오류 발생 시, 더 명확한 에러를 throw합니다.
|
||||
if (!response.ok) {
|
||||
throw new Error('네트워크 응답이 올바르지 않습니다.');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
alert(data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.success && Object.keys(data.variables).length > 0) {
|
||||
// [개선] 테이블 구조를 명확하게 생성합니다.
|
||||
const table = document.createElement('table');
|
||||
const colgroup = document.createElement('colgroup');
|
||||
const col1 = document.createElement('col');
|
||||
col1.className = 'grid_4';
|
||||
const col2 = document.createElement('col');
|
||||
colgroup.appendChild(col1);
|
||||
colgroup.appendChild(col2);
|
||||
table.appendChild(colgroup);
|
||||
|
||||
const tbody = document.createElement('tbody');
|
||||
|
||||
// 제목 행 추가
|
||||
const caption = document.createElement('caption');
|
||||
caption.textContent = '치환 변수 값 입력';
|
||||
caption.className = 'sound_only'; // 스크린리더만 읽도록 처리
|
||||
table.appendChild(caption);
|
||||
|
||||
for (const varName in data.variables) {
|
||||
const defaultValue = data.variables[varName];
|
||||
|
||||
const tr = document.createElement('tr');
|
||||
|
||||
const th = document.createElement('th');
|
||||
th.scope = 'row';
|
||||
const label = document.createElement('label');
|
||||
// [개선] label의 for 속성값에 특수문자가 없도록 varName을 사용합니다.
|
||||
label.htmlFor = `variable_${varName}`;
|
||||
label.textContent = `{${varName}}`;
|
||||
th.appendChild(label);
|
||||
|
||||
const td = document.createElement('td');
|
||||
const input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.name = `variables[${varName}]`;
|
||||
input.id = `variable_${varName}`;
|
||||
input.className = 'frm_input';
|
||||
input.style.width = '95%';
|
||||
input.value = defaultValue;
|
||||
input.placeholder = `${varName}에 치환될 값을 입력하세요`;
|
||||
td.appendChild(input);
|
||||
|
||||
tr.appendChild(th);
|
||||
tr.appendChild(td);
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
|
||||
table.appendChild(tbody);
|
||||
varContainer.appendChild(table);
|
||||
varContainer.style.display = 'block';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('변수 정보를 가져오는 중 오류가 발생했습니다:', error);
|
||||
alert('변수 정보를 가져오는 데 실패했습니다. 개발자 콘솔을 확인해주세요.');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,155 @@
|
||||
////////////////////////////// 템플릿폼
|
||||
// 이메일 내용에서 {변수명}을 감지하여 입력 필드를 생성/제거하는 함수
|
||||
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;
|
||||
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 html = '';
|
||||
|
||||
// 1. 스마트 에디터 2.0
|
||||
if (typeof oEditors !== 'undefined' && oEditors.getById['content']) {
|
||||
html = oEditors.getById['content'].getContents();
|
||||
}
|
||||
// 2. CHEditor5
|
||||
else if (typeof ed_content !== 'undefined') {
|
||||
html = ed_content.outputBodyHTML();
|
||||
}
|
||||
else {
|
||||
alert('에디터가 로드되지 않았습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
const variableInputs = document.querySelectorAll('#variableInputs input');
|
||||
|
||||
variableInputs.forEach(input => {
|
||||
const varName = input.dataset.var;
|
||||
const value = input.value;
|
||||
if (value) {
|
||||
const regex = new RegExp('{' + varName.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '}', 'g');
|
||||
html = html.replace(regex, value);
|
||||
}
|
||||
});
|
||||
|
||||
const popup = window.open('', '미리보기', 'width=800,height=600,scrollbars=yes');
|
||||
popup.document.write('<html><head><title>템플릿 미리보기</title></head><body>' + html + '</body></html>');
|
||||
popup.document.close();
|
||||
}
|
||||
|
||||
// 폼 전송 시 에디터 내용 업데이트 및 유효성 검사
|
||||
function form_check(f) {
|
||||
// 1. 스마트 에디터 2.0
|
||||
if (typeof oEditors !== 'undefined' && oEditors.getById['content']) {
|
||||
oEditors.getById['content'].exec("UPDATE_CONTENTS_FIELD", []);
|
||||
sanitizeEditorContent();
|
||||
}
|
||||
// 2. CHEditor5
|
||||
else if (typeof ed_content !== 'undefined') {
|
||||
f.content.value = ed_content.outputBodyHTML();
|
||||
}
|
||||
|
||||
// 에디터 내용이 비어있는지 체크
|
||||
const content = jQuery.trim(f.content.value);
|
||||
const emptyPatterns = ['', '<p> </p>', '<p><br></p>', '<div><br></div>', ' '];
|
||||
|
||||
// 태그 제거 후 공백 체크
|
||||
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;
|
||||
}
|
||||
|
||||
// 에디터 내용 정제 - 빈 값 판별 및 공백 처리 (스마트 에디터용)
|
||||
function sanitizeEditorContent() {
|
||||
if (typeof oEditors === 'undefined' || !oEditors.getById['content']) return;
|
||||
|
||||
const contentEl = document.getElementById('content');
|
||||
const html = oEditors.getById['content'].getIR();
|
||||
oEditors.getById['content'].exec('UPDATE_CONTENTS_FIELD', []);
|
||||
|
||||
const val = contentEl.value.toLowerCase().replace(/^\s*|\s*$/g, '');
|
||||
const emptyPatterns = [' ', '<p> </p>', '<p><br></p>', '<div><br></div>', '<p></p>', '<br>', ''];
|
||||
|
||||
if (emptyPatterns.includes(val)) {
|
||||
contentEl.value = '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
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 = '<p>이곳에 메일 본문 내용을 입력하세요.</p>';
|
||||
|
||||
// 에디터의 실제 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 === '<p> </p>' || currentIR === '<p><br></p>') {
|
||||
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 = ['', '<p> </p>', '<p><br></p>', '<div><br></div>', ' '];
|
||||
|
||||
// 태그 제거 후 공백 체크
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const previewButtons = document.querySelectorAll('.preview-btn');
|
||||
|
||||
previewButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
// data-content 속성에 base64로 인코딩된 HTML 컨텐츠를 가져옵니다.
|
||||
const encodedContent = this.dataset.content;
|
||||
console.log(encodedContent);
|
||||
if (!encodedContent) {
|
||||
alert('미리보기할 내용이 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// base64로 인코딩된 HTML 컨텐츠를 디코딩합니다.
|
||||
// atob()는 base64 문자열을 디코딩하고, decodeURIComponent/escape 트릭으로 UTF-8 문자열을 올바르게 처리합니다.
|
||||
const decodedContent = decodeURIComponent(atob(encodedContent).split('').map(function(c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
}).join(''));
|
||||
|
||||
const popup = window.open('', '미리보기', 'width=800,height=600,scrollbars=yes');
|
||||
// [수정] decodedContent는 이미 완성된 HTML 문서이므로, 추가적인 태그로 감싸지 않고 그대로 출력합니다.
|
||||
// 이렇게 해야 폼 페이지의 미리보기와 동일하게 작동합니다.
|
||||
popup.document.write(decodedContent);
|
||||
popup.document.close();
|
||||
} catch (e) {
|
||||
console.error('미리보기 컨텐츠 디코딩 오류:', e);
|
||||
alert('미리보기 내용을 여는 데 실패했습니다.');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user