/**
* 파일: js/script.js
* 설명: Autolinker 프론트엔드 JavaScript 기능
* 작성자: Assistant
* 최종수정일: 2024-02-13
*
* 이 파일은 키워드 관리 시스템의 프론트엔드 기능을 담당합니다.
* - 키워드 CRUD 작업
* - 클릭 추적
* - 폼 검증
* - UI 상호작용
*/
//----------------------------------------------------------------------------
// 전역 설정 및 유틸리티
//----------------------------------------------------------------------------
/**
* 토스트 메시지 표시 함수
* @param {string} message 표시할 메시지
* @param {string} type 메시지 타입 (success, error, warning, info)
*/
function showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `toast align-items-center text-white bg-${type} border-0`;
toast.setAttribute('role', 'alert');
toast.setAttribute('aria-live', 'assertive');
toast.setAttribute('aria-atomic', 'true');
toast.innerHTML = `
`;
const container = document.getElementById('toast-container');
container.appendChild(toast);
const bsToast = new bootstrap.Toast(toast);
bsToast.show();
// 3초 후 자동 제거
setTimeout(() => {
bsToast.hide();
setTimeout(() => toast.remove(), 500);
}, 3000);
}
//----------------------------------------------------------------------------
// 키워드 관리 기능
//----------------------------------------------------------------------------
/**
* 키워드 추가 폼 제출 처리
* @param {Event} e 폼 이벤트
*/
function handleAddKeyword(e) {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
formData.append('action', 'add');
const submitButton = form.querySelector('button[type="submit"]');
if (submitButton) {
submitButton.disabled = true;
}
form.submit();
}
/**
* 키워드 수정 처리
*/
function handleEditKeyword(e) {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
formData.append('action', 'edit');
const submitButton = form.querySelector('button[type="submit"]');
if (submitButton) {
submitButton.disabled = true;
}
form.submit();
}
/**
* 키워드 수정 폼 제출 처리
* 키워드 수정 모달 실행
* @param {Event} e 폼 이벤트
*/
function editKeyword(keywordData) {
// 모달 폼에 데이터 설정
document.getElementById('edit_id').value = keywordData.id;
document.getElementById('edit_keyword').value = keywordData.keyword;
document.getElementById('edit_url').value = keywordData.url;
document.getElementById('edit_open_new').checked = keywordData.open_new;
// 모달 표시
var editModal = new bootstrap.Modal(document.getElementById('editKeywordModal'));
editModal.show();
}
/**
* 키워드 삭제 처리
* @param {number} id 삭제할 키워드 ID
*/
function deleteKeyword(id) {
if (confirm('정말 이 키워드를 삭제하시겠습니까?')) {
// 삭제 폼 생성 및 제출
var form = document.createElement('form');
form.method = 'POST';
form.action = 'process.php';
// hidden 필드 추가
var actionInput = document.createElement('input');
actionInput.type = 'hidden';
actionInput.name = 'action';
actionInput.value = 'delete';
form.appendChild(actionInput);
var idInput = document.createElement('input');
idInput.type = 'hidden';
idInput.name = 'id';
idInput.value = id;
form.appendChild(idInput);
// 폼을 body에 추가하고 제출
document.body.appendChild(form);
form.submit();
}
}
//----------------------------------------------------------------------------
// 폼 검증 및 UI 갱신
//----------------------------------------------------------------------------
/**
* 키워드 폼 검증
* @param {FormData} formData 검증할 폼 데이터
* @returns {boolean} 검증 통과 여부
*/
function validateKeywordForm(formData) {
const keyword = formData.get('keyword');
const url = formData.get('url');
if (!keyword.trim()) {
showToast('키워드를 입력해주세요.', 'warning');
return false;
}
if (!url.trim()) {
showToast('URL을 입력해주세요.', 'warning');
return false;
}
// URL 형식 검증
try {
new URL(url);
} catch (e) {
showToast('올바른 URL 형식이 아닙니다.', 'warning');
return false;
}
return true;
}
/**
* 키워드 목록 새로고침
*/
function refreshKeywordList() {
const container = document.getElementById('keyword-list');
const currentPage = new URLSearchParams(window.location.search).get('page') || 1;
fetch(`list.php?page=${currentPage}`)
.then(response => response.text())
.then(html => {
container.innerHTML = html;
})
.catch(error => {
console.error('Error:', error);
showToast('목록 새로고침 실패', 'error');
});
}
//----------------------------------------------------------------------------
// 클릭 추적 기능
//----------------------------------------------------------------------------
document.addEventListener('click', function(e) {
const link = e.target.closest('a.autolink');
if (!link) return;
const keywordId = link.getAttribute('data-keyword-id');
if (!keywordId) return;
console.log('Autolink clicked:', keywordId);
const formData = new FormData();
formData.append('action', 'log_click');
formData.append('keyword_id', keywordId);
// 현재 페이지의 base URL에서 process.php의 경로 구성
const currentPath = window.location.pathname;
const processUrl = currentPath.includes('/admin/')
? './process.php' // admin 폴더 내부에서 접근
: BASE_URL + '/admin/process.php'; // 외부에서 접근
console.log('Sending request to:', processUrl);
fetch(processUrl, {
method: 'POST',
body: formData,
headers: {
'Accept': 'application/json'
}
})
.then(response => {
if (!response.ok) {
return response.text().then(text => {
console.error('Server response:', text);
throw new Error('Server response was not ok');
});
}
return response.json();
})
.then(data => {
console.log('Click logged successfully:', data);
})
.catch(error => {
console.error('Error logging click:', error.message || error);
});
});
//----------------------------------------------------------------------------
// 이벤트 리스너 등록
//----------------------------------------------------------------------------
document.addEventListener('DOMContentLoaded', function() {
// 폼 제출 이벤트 리스너
const addForm = document.getElementById('addKeywordForm');
if (addForm) {
addForm.addEventListener('submit', handleAddKeyword);
}
const editForm = document.getElementById('editKeywordForm');
if (editForm) {
editForm.addEventListener('submit', handleEditKeyword);
}
// 검색 폼 처리
const searchForm = document.getElementById('searchForm');
if (searchForm) {
searchForm.addEventListener('submit', function(e) {
e.preventDefault();
const searchInput = this.querySelector('input[name="search"]');
if (searchInput.value.trim()) {
this.submit();
}
});
}
});