스크롤 페이징 처리
- 특정 div의 스크롤 이벤트를 감지하여 해당 div의 스크롤 위치가 최하단에 도달할 경우 데이터를 추가로 가져오는 스크롤 페이징 처리
컨트롤러
<?php class ScrollPaging
{
// 데이터를 가져오는 프로세스
public function get_data_process()
{
header('Content-type: application/json; charset=utf-8');
$params = $this->vars['params'];
// 한 페이지에 출력될 데이터 개수
$result['pagePerEntries'] = 20;
// 모든 데이터의 개수 (총 개수를 구해서 최대가 몇 페이지인지 알아내기 위함)
$result['totalEntries'] = $this->model->getFunction($where, 'count');
// $this->pagination->navy($totalEntries(해당 데이터의 총 개수), $page(몇 페이지의 데이터를 가져와야 하는지), $pagePerEntries = 20(한 페이지당 출력될 데이터 개수))
$result['pagination'] = $this->pagination->navy($result['totalEntries'], $params['page'], $result['pagePerEntries']);
$result['data_list'] = [];
// 데이터가 존재한다면
if ($result['totalEntries'] > 0) {
// sql 문법으로 limit에 offset[예)1번째부터 10번째 데이터를 가져오겠다(1, 10)]을 넣어서 해당되는 값을 가져오는 방식
$result['data_list'] = $this->model->getFunction($where, $result['pagination']['Offset']);
}
echo json_encode($result);
exit;
}
}
?>
js
var offsetCnt = 0;
var page = 1;
var scroll_active = true;
// 현재 페이지 값에 해당되는 데이터 배열을 받아와 html 형식에 맞춰 출력
function getDataFunction() {
var params = {
'page': page
};
$.ajax({
type: "POST",
data: params,
dataType: "json",
url: "/get_data_process",
success: function (result) {
// 가져온 데이터로 html 생성
createTagHtml(result);
},
error: function (request, status, error) {
// 에러 출력
console.error("code:" + request.status + "\n" + "message:" + request.responseText + "\n" + "error:" + error + "\n" + "request:" + request);
},
beforeSend: function () {
scroll_active = false;
$('html').css("cursor", "wait");
},
complete: function () {
$('html').css("cursor", "auto");
}
});
}
function createTagHtml(result) {
var data_list = result.data_list;
// 가져온 데이터를 html 형식에 맞춰 append를 이용해 페이지에 추가해준다.
var html = '';
if (data_list.length > 0) {
// 데이터가 있을 경우
data_list.forEach((data) => {
html += `<div>${data}</div>`;
});
offsetCnt += data_list.length;
if (result.totalEntries <= offsetCnt) {
scroll_active = false;
} else {
scroll_active = true;
}
$('.tag').append(html);
} else {
// 데이터가 없을 경우
scroll_active = false;
$('.no_data').show();
$('.tag').hide();
}
}
window.onpageshow = function (event) {
// 페이지 이동 감지 시 스크롤 페이징 데이터 저장
$(window).on('beforeunload', function () {
history.replaceState({
scrollList: $('.tag').html(),
scroll_active: scroll_active,
page: page
}, null);
$.cookie("scroll_position", $(window).scrollTop(), 1);
});
// 스크롤 이벤트를 감지하여 스크롤이 최하단에 도달했을 경우 조건에 따라 데이터 가져오는 함수 실행
var tag = document.getElementsByClassName('tag')[0];
tag.addEventListener('scroll', (function () {
var scrollTop = tag.pageYOffset || tag.scrollTop;
if (scroll_active && scrollTop != 0) {
var scroll = scrollTop + tag.offsetHeight; // 최하단에 도달하기 전에 데이터를 불러오려면 +200 (div 크기에 따라 적절하게 +값 조정 ** +값이 너무 크면 한 번에 같은 데이터를 여러 번 가져오게 될 수 있고 데이터를 계속 가져오는 오류가 발생할 수 있음 **)
var height = tag.scrollHeight;
if (scroll >= height) {
page++;
getDataFunction();
scroll_active = false;
}
}
}));
if (event.persisted || (window.performance && window.performance.navigation.type == 2)) {
// 페이지 로드 시 뒤로가기 이벤트 감지하여 이전 데이터 출력 & 스크롤 이동
var data = history.state;
if (data) {
data.scrolllist = data.scrolllist.replace(/undefined/gi, "");
$('.tag').html(data.scrolllist);
var scrollPosition = $.cookie("scroll_position");
if (scrollPosition != "" && scrollPosition != undefined) {
$('.tag').scrollTop(scrollPosition);
}
scroll_active = data.scroll_active;
page = data.page;
}
} else {
// 뒤로가기 이벤트로 인한 페이지 로드가 아닐 시 데이터 가져오는 함수 실행
getDataFunction();
}
}
html
<!-- html이 추가 될 태그 -->
<div class="tag"></div>
<!-- 데이터가 없을 때 출력되는 태그 -->
<div class="no_data" hidden></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>