//////////////////////////////////////////////////////////////////////////////////////// // A-RMS Patch Note Page JavaScript - FF14 Pure Style with Infinite Scroll //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// // Document Ready //////////////////////////////////////////////////////////////////////////////////////// function execDocReady() { const pluginGroups = [ ["../reference/light-blue/lib/vendor/jquery.ui.widget.js", "../reference/lightblue4/docs/lib/widgster/widgster.js"], ["../reference/lightblue4/docs/lib/bootstrap-select/dist/js/bootstrap-select.min.js"], ["../../cover/js/util/authorize.js"] ]; loadPluginGroupsParallelAndSequential(pluginGroups) .then(function () { console.log("모든 플러그인 로드 완료"); $(".widget").widgster(); $("#sidebar").hide(); $(".wrap").css("margin-left", 0); $("#footer").load("/cover/html/template/landing-footer.html"); // 패치노트 페이지 초기화 initializePatchNotePage(); }) .catch(function (error) { console.error("플러그인 로드 중 오류 발생"); console.error(error); }); } //////////////////////////////////////////////////////////////////////////////////////// // 패치노트 페이지 초기화 //////////////////////////////////////////////////////////////////////////////////////// function initializePatchNotePage() { // CSS 파일 로드 loadPatchNoteCSS(); // 로드 더 버튼 설정 setupLoadMoreButton(); // 이벤트 리스너 등록 setupEventListeners(); // 패치노트 데이터 초기화 initializePatchData(); // CRUD 버튼 표시 초기화 initializeCrudButtonDisplay(); } //////////////////////////////////////////////////////////////////////////////////////// // CSS 파일 로드 - Bootstrap만 사용하므로 주석처리 //////////////////////////////////////////////////////////////////////////////////////// function loadPatchNoteCSS() { // Pure Bootstrap을 사용하므로 별도 CSS 로드 불필요 // 지정된 색상 테마 적용을 위한 인라인 스타일 추가 const styleRules = ` `; $("head").append(styleRules); } //////////////////////////////////////////////////////////////////////////////////////// // 무한 스크롤 설정 //////////////////////////////////////////////////////////////////////////////////////// const patchNoteManager = { currentPage: 1, isLoading: false, hasMoreData: true, itemsPerPage: 3, throttleTimer: null, totalCount: -999 }; function setupLoadMoreButton() { // 더보기 버튼에 호버 효과 추가 $("#load_more_button").hover( function () { $(this).css({ transform: "translateY(-2px)", "box-shadow": "0 6px 20px rgba(0, 0, 0, 0.3)" }); }, function () { $(this).css({ transform: "translateY(0)", "box-shadow": "0 4px 15px rgba(0, 0, 0, 0.1)" }); } ); } function handleLoadMoreClick() { if (patchNoteManager.isLoading || !patchNoteManager.hasMoreData) { return; } loadMorePatchNotes(); } function loadMorePatchNotes() { if (patchNoteManager.isLoading) return; patchNoteManager.isLoading = true; showLoadingIndicator(); patchNoteManager.currentPage++; fetchPaginatedPatchnoteList(function (newPatchNotes) { if (newPatchNotes && newPatchNotes.length > 0) { appendPatchNotes(newPatchNotes); } else { // 더 가져올 데이터가 없음. patchNoteManager.hasMoreData = false; hideLoadMoreButton(); showScrollEndIndicator(); } patchNoteManager.isLoading = false; hideLoadingIndicator(); }); } //////////////////////////////////////////////////////////////////////////////////////// // 패치노트 데이터 생성 및 관리 //////////////////////////////////////////////////////////////////////////////////////// function initializePatchData() { fetchPaginatedPatchnoteList(appendPatchNotes); } // 성공 콜백을 넘기면 fetch 후 데이터를 넘겨서 처리 function fetchPaginatedPatchnoteList(successCallback) { $.ajax({ url: "/auth-anon/api/arms/patchnote/getPatchnoteList.do", type: "GET", data: { pageIndex: patchNoteManager.currentPage, pageUnit: patchNoteManager.itemsPerPage }, success: function (response) { const { paginationInfo: { totalRecordCount } } = response; if (totalRecordCount < 1) { hideLoadMoreButton(); showDataNotFoundIndicator(); return; } if (patchNoteManager.totalCount === -999) { patchNoteManager.totalCount = totalRecordCount || 0; } if (typeof successCallback === "function") { successCallback(response.data); } if (patchNoteManager.currentPage * patchNoteManager.itemsPerPage >= totalRecordCount) { patchNoteManager.hasMoreData = false; hideLoadMoreButton(); showScrollEndIndicator(); } }, error: function (xhr, status, error) { console.error("패치노트 데이터 로드 실패:", error); } }); } function appendPatchNotes(patchData) { const $patchList = $(".body .row").first(); // 이전에 추가된 아이템들의 border-bottom을 복원 $patchList.children().find(".row").css("border-bottom", "1px solid #e9ecef"); patchData.forEach(function (patch, index) { const patchHtml = createPatchNoteHTML(patch); const $patchItem = $(patchHtml); // 페이드인 애니메이션 $patchItem.css("opacity", "0").appendTo($patchList); setTimeout(function () { $patchItem.animate({ opacity: 1 }, 500); }, index * 150); // 순차적 애니메이션 }); // 새로 추가된 아이템들을 포함하여, 가장 마지막 아이템의 border-bottom을 제거 $patchList.children().last().find(".row").css("border-bottom", "none"); } function createPatchNoteHTML(patch) { const { year: patchYear, month: patchMonth, day: patchDay } = parseDate(patch.c_patchnote_created); return `
${patchYear}
${patchMonth}.${patchDay}
patchnote thumbnail

${ patch.c_patchnote_subtitle }

${ patch.c_patchnote_title }

업데이트 노트 보기
`; } //////////////////////////////////////////////////////////////////////////////////////// // 이벤트 리스너 설정 //////////////////////////////////////////////////////////////////////////////////////// function setupEventListeners() { // 버전 버튼 클릭 이벤트 $(document).on("click", ".btn-default", handleVersionButtonClick); // 이미지 플레이스홀더 클릭 이벤트 (gradient div 클릭) $(document).on("click", '.col-md-2 > div[style*="background"]', handleImageClick); // 더보기 버튼 클릭 이벤트 $(document).on("click", "#load_more_button", handleLoadMoreClick); // 등록 버튼 클릭 이벤트 $(document).on("click", "#new_patch_button", function () { window.location.href = "/cover/template.html?page=patchnoteEditor"; }); } function handleVersionButtonClick() { const versionText = $(this).text(); console.log(`버전 버튼 클릭: ${versionText}`); // 실제 프로젝트에서는 해당 버전 패치노트로 이동 alert(`${versionText} 페이지로 이동합니다.`); } function handleImageClick() { const $item = $(this).closest(".row"); const title = $item.find("h3").text(); // 이미지 확대 보기 또는 갤러리 기능 // 현재는 패치노트 클릭과 동일한 동작 $item.find(".btn-primary").click(); } //////////////////////////////////////////////////////////////////////////////////////// // 로딩 상태 관리 //////////////////////////////////////////////////////////////////////////////////////// function showLoadingIndicator() { $("#loading_indicator").fadeIn(300); } function hideLoadingIndicator() { $("#loading_indicator").fadeOut(300); } function showScrollEndIndicator() { $("#scroll_end_indicator").fadeIn(500); // 3초 후 자동으로 숨김 setTimeout(function () { $("#scroll_end_indicator").fadeOut(500); }, 3000); } function hideLoadMoreButton() { $("#load_more_container").fadeOut(500); } //////////////////////////////////////////////////////////////////////////////////////// // 유틸리티 함수들 //////////////////////////////////////////////////////////////////////////////////////// function throttle(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } function parseDate(dateStr) { const parts = dateStr.split(" ")[0].split("-"); // 시분초를 자르고 다시 년/월/일을 각각 분리 return { year: parts[0], month: parts[1], day: parts[2] }; } function showDataNotFoundIndicator() { $("#data_not_found_indicator").show(); } function initializeCrudButtonDisplay() { function valid(json) {} function invalid() { $("#new_patch_button").hide(); } validateAdminRole(valid, invalid, invalid); // 오류 시에도 버튼 숨김 }