재밌고 어려운 IT를 이해해보자~!

Pagination [TEAM PROJECT] 본문

코리아IT핀테크과정

Pagination [TEAM PROJECT]

언제나즐거운IT 2024. 2. 15. 11:32

게시글이 많아지면 한 화면에 전체 게시글을 출력해 주는 것이 아닌

정해진 게시글 수 만큼 출력해주고 다음 게시글은 페이지 버튼을 통해서 볼 수 있도록 페이지 버튼을 만들어 준다.

pagination.js

/**
 * 일반검색 & 필터검색 JS파일 
 */
// 필요한 변수 및 함수 선언
var jsonFilteredBoardDatas; // 필터링된 게시글 데이터를 저장할 변수
var loadReviewData; // 데이터를 로드하는 함수
const dataContainer = document.getElementById('dataContainer'); // 데이터 컨테이너 요소를 가져옴
const jsonBoardDatas = JSON.parse(dataContainer.getAttribute('data-jsonBoardDatas')); // 게시글 데이터를 JSON 형식으로 파싱하여 가져옴
const id = dataContainer.getAttribute("data-id"); 
var currentPage; 
var totalPages; 


$(document).ready(function() {
    // 페이징 버튼 클릭 이벤트 리스너
    // 페이지네이션 버튼 클릭 이벤트
	// paginationContainer에는 처음에는 .page 클래스를 가진 요소가 없지만, 
	// displayPagination 함수에서 동적으로 생성
	// displayPagination 함수는 서버로부터 받아온 페이지네이션 데이터를 기반으로 페이지네이션 버튼을 생성하며,
	// 이 때 각 버튼에는 .page 클래스와 data-page 속성이 부여 됨
	// data-page 속성은 해당 버튼이 클릭될 때 이동해야 할 페이지 번호를 저장
    $(document).on("click", "#paginationContainer .page", function(event) {
        event.preventDefault(); // 기본 동작 방지
        currentPage = $(this).data("page"); // 클릭된 페이지 번호를 가져와 currentPage에 저장
        loadReviewData(currentPage); // 해당 페이지 데이터 로드
        // console.log("[로그] currentPage :" + currentPage); 
});
    // 데이터를 로드하는 함수 정의
    loadReviewData = function(currentPage) {
        var displayDatas = jsonBoardDatas; // 출력할 데이터를 일반 데이터로 초기화
        if (isFiltered) {
            displayDatas = jsonFilteredBoardDatas; // 필터링된 데이터가 있으면 필터링된 데이터 사용
        }

        var pageDataSize = 20; // 페이지당 데이터 크기
        var totalSize = displayDatas.length; // 전체 데이터 크기
        totalPages = Math.ceil(totalSize / pageDataSize); // 전체 페이지 수 계산

        var startIndex = (currentPage - 1) * pageDataSize; // 시작 인덱스 계산
        var endIndex = Math.min(startIndex + pageDataSize, totalSize); // 끝 인덱스 계산

        var currentPageDatas = displayDatas.slice(startIndex, endIndex); // 현재 페이지에 나타낼 데이터 

        displayReviewData(currentPageDatas); // 데이터 표시 함수 호출
        displayPagination(currentPage); // 페이지네이션 표시 함수 호출
    }

    // 데이터를 화면에 표시하는 함수
    function displayReviewData(currentPageDatas) {
        // console.log("[로그]" + currentPageDatas); 
        var tbody = document.querySelector('.alt tbody'); 
        var thead = document.querySelector('.alt thead'); 
        var thCnt = thead.getElementsByTagName('th'); 
        var maxColspan = thCnt.length; // 최대 컬럼 수
        tbody.innerHTML = ''; // tbody 초기화
        if (currentPageDatas.length === 0) {
            tbody.innerHTML = '<tr><td colspan="' + maxColspan + '" align="center">등록된 글이 없습니다. 새 글을 작성해주세요.</td></tr>'; // 데이터가 없을 때 메시지 출력
        } else {
            currentPageDatas.forEach(function(boardData) { // 각 데이터를 순회하면서 행 추가
                var row = document.createElement('tr'); // 새로운 행 요소 생성
                // 데이터에 따라 행 채우기
                if (id === boardData.id) {
                    // console.log('[로그] myBoard & memberBoard');
                    // 내가 작성한 게시글 및 유저가 작성한 게시글인 경우
                    row.innerHTML =
                        '<td>' + boardData.rownum + '</td>' +
                        '<td>' + boardData.title + '</td>' +
                        '<td>' + boardData.nickname + '</td>' +
                        '<td>' + boardData.boardDate + '</td>' +
                        '<td>' + boardData.recommendCNT + '</td>' +
                        '<td>' + boardData.viewCount + '</td>';
                } else if (boardData.category === '판매게시판') {
                    // 판매 게시판인 경우
                    row.innerHTML =
                        '<td>' + boardData.rownum + '</td>' +
                        '<td><a href="/chalKag/sellBoardSelectOnePage.do?boardNum=' + boardData.boardNum + '">' + boardData.title + '</a></td>' +
                        '<td><a href="/chalKag/memberPage.do?nickname=' + boardData.nickname + '">' + boardData.nickname + '</a></td>' +
                        '<td>' + boardData.boardDate + '</td>' +
                        '<td>' + numberWithCommas(boardData.price) + '원</td>' +
                        '<td>' + boardData.viewCount + '</td>' +
                        '<td>' + boardData.state + '</td>';
                    console.log('[로그]' + boardData.state);
                } else if (boardData.category === '리뷰게시판') {
                    // 리뷰 게시판인 경우
                    row.innerHTML =
                        '<td>' + boardData.rownum + '</td>' +
                        '<td><a href="/chalKag/cameraReviewSelectOnePage.do?boardNum=' + boardData.boardNum + '">' + boardData.title + '</a></td>' +
                        '<td><a href="/chalKag/memberPage.do?nickname=' + boardData.nickname + '">' + boardData.nickname + '</a></td>' +
                        '<td>' + boardData.boardDate + '</td>' +
                        '<td>' + boardData.recommendCNT + '</td>' +
                        '<td>' + numberWithCommas(boardData.price) + '원</td>' +
                        '<td>' + boardData.viewCount + '</td>';
                } else {
                    // 그 외 게시판인 경우
                    row.innerHTML =
                        '<td>' + boardData.rownum + '</td>' +
                        '<td><a href="/chalKag/freeBoardSelectOnePage.do?boardNum=' + boardData.boardNum + '">' + boardData.title + '</a></td>' +
                        '<td><a href="/chalKag/memberPage.do?nickname=' + boardData.nickname + '">' + boardData.nickname + '</a></td>' +
                        '<td>' + boardData.boardDate + '</td>' +
                        '<td>' + boardData.recommendCNT + '</td>' +
                        '<td>' + boardData.viewCount + '</td>';
                }
                tbody.appendChild(row); // tbody에 행 추가
            });
        }
    }

    // 가격을 3자리마다 컴마로 구분하는 함수
    function numberWithCommas(price) {
        return price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    }

    // 페이징을 화면에 표시하는 함수
    function displayPagination(currentPage) {
        var paginationContainer = $("#paginationContainer"); // 페이지네이션 컨테이너 요소 가져오기
        paginationContainer.empty(); // 컨테이너 초기화

        var pageSize = 10; // 한 페이지 그룹에 표시할 페이지 수
        var currentGroup = Math.floor((currentPage - 1) / pageSize); // 현재 페이지 그룹
        var startPage = currentGroup * pageSize + 1; // 시작 페이지
        var endPage = Math.min((currentGroup + 1) * pageSize, totalPages); // 끝 페이지

        // 이전 페이지 그룹으로 이동하는 버튼 추가
        if (startPage > 1) {
            var prevGroupPage = startPage - 1;
            var prevGroupLink = "<a href='#' class='page' data-page='" + prevGroupPage + "'>&laquo; PREV</a>";
            paginationContainer.append(prevGroupLink);
        }

        // 페이지 버튼 추가
        for (var i = startPage; i <= endPage; i++) {
            var pageLinkClass = (i === currentPage) ? "page active" : "page";
            var pageLink = "<a href='#' class='" + pageLinkClass + "' data-page='" + i + "'>" + i + "</a>";
            paginationContainer.append(pageLink);
        }

        // 다음 페이지 그룹으로 이동하는 버튼 추가
        if (endPage < totalPages) {
            var nextGroupPage = endPage + 1;
            var nextGroupLink = "<a href='#' class='page' data-page='" + nextGroupPage + "'>NEXT &raquo;</a>";
            paginationContainer.append(nextGroupLink);
        }
    }

    // 초기 페이지 로드
    loadReviewData(1);
});


대부분의 사이트들이 페이징처리를 동기로 해두어서 
나는 ajax를 통해 비동기로 진행을 해야 하는 줄 알았다.

 

하지만 그게아닌 script만 사용해도 
원하는 페이지 출력이 동적으로 진행될 수 있고,

페이징 버튼 또한 동적으로 생성이 될 수 있다.

결론적으로 비동기가 아닌 script만 사용해도 비동기적인 느김으로 페이징 처리가 가능하다.

Comments