Controller
@Controller public class HospitalController { @Autowired private HospitalService hospitalService; @RequestMapping({ "/hosp/{actTp}" }) public String movePageByPostMode(@RequestParam Map<String, Object> paramMap, @PathVariable String actTp, HttpServletRequest req, Model model) { switch (actTp) { case "list": // 목록 model = this.hospitalService.selectHospitalList(paramMap, model); break; case "listScroll": //ajax 처리시 목록 model = this.hospitalService.selectHospitalList(paramMap, model); break; } model.addAttribute("paramMap", paramMap); return "hospital/" + actTp; } }
list 페이지는 목록화면 부모 페이지이며 listScroll 페이지는 ajax로 데이터를 받는 자식 페이지 이다.
list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%> <!DOCTYPE html> <html> <link href="${pageContext.request.contextPath}/resources/css/custom.css" rel="stylesheet" type="text/css" > <body> <div class="loading2" style="display:none;"><div><span class="loading-txt">Loading...</span></div></div> <input type="hidden" value="${empty param.currentPage ? '1':param.currentPage }" id="currentPage" > <div id="wrapper"> <!-- header --> <header> <!-- 검색 처리 폼 --> <div class="searchBox"> <form id="frm-search" name="frm" action="${pageContext.request.contextPath}/hosp/list" method="post" onsubmit="return frmSubmit();"> <input type="hidden" id="page" name="page" value="${paging.pageNo}" /> <input type="hidden" id="pageSize" name="pageSize" value="${paging.pageSize}" /> <input type="hidden" id="sMethod" name="sMethod" /> <dl> <dt><spring:message code='hosp.label.search' /></dt> <dd><input type="text" id="searchinput" name="keyword" placeholder="<spring:message code='common.msg.searchTxt' />" value="${paramMap.keyword}" /> <button type="button" id="searchclear">X</button> <input type="submit" value="<spring:message code='common.btn.search' />"> </dd> </dl> </form> </div> </header> <!-- //header --> <!-- container --> <div id="container"> <!-- 콘텐츠 영역 --> <div id="content"> <div class="hosList"> <c:choose> <c:when test="${empty list}"> <!-- 등록된 내용이 없습니다. --> <div class="noData"><spring:message code='common.msg.nodata' /></div> <!-- //등록된 내용이 없습니다. --> </c:when> <c:otherwise> <dl class="list" id="infinite-scroll"> <%-- <c:forEach var="item" items="${list}" varStatus="status"> </c:forEach> --%> </dl> <!-- 마지막 페이지 번호 --> <input type="hidden" id="paging_finalPageNo" value="${paging.finalPageNo}"> </c:otherwise> </c:choose> </div> </div> <!-- //콘텐츠 영역 --> </div> </div> <script type="text/javascript"> var searchAction=false;//검색 처리시 기존 ajax 중단 var idMoving = true; //해당 아이디 이동 여부 var idMovingCount=0; var page = parseInt($("#currentPage").val()); var pagingFinalPageNo='${paging.finalPageNo}';//마지막 페이지 switch (page){ case 1 : //1페이지일 경우 1페이지만 movePageWithPageNoScroll(page); break; case 2 : //2페이지일 경우 1~2페이지 movePageWithPageNoScroll(1); movePageWithPageNoScroll(page); break; case 3 : //3페이지일 경우 1~3페이지 movePageWithPageNoScroll(1); movePageWithPageNoScroll(2); movePageWithPageNoScroll(page); break; default : //3페이지 이상 앞페이지 2개를 표시한다. movePageWithPageNoScroll(page-2); movePageWithPageNoScroll(page-1); movePageWithPageNoScroll(page); } //스크롤 바닥 감지 window.onscroll = function(ev) { if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { //추가되는 임시 콘텐츠 //window height + window scrollY 값이 document height보다 클 경우, if((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { //실행할 로직 (콘텐츠 추가) page++; if(page> parseInt(pagingFinalPageNo)){ return; } //article에 추가되는 콘텐츠를 append movePageWithPageNoScroll(page); $("#currentPage").val(page); } } }; function movePageWithPageNoScroll(pageNo) { //검색 처리시 기존 ajax 중단 if(searchAction==true) return; var path="${pageContext.request.contextPath}/hosp/listScroll"; $("#page").val(pageNo); $("#sMethod").val("paging"); var queryString=$("#frm-search").serialize(); $(".loading2").show(); $.ajax({ type:"post", url:path, data:queryString, success:function(result){ $("#infinite-scroll").append(result); //해당 아이디값으로 이동 var hospIdx="${param.HOSP_IDX}"; if(hospIdx!=""){ idMovingCount++; //console.log("idMovingCount:"+idMovingCount); //** 뒤로가기시 리스트 유지 if(idMoving==true){ //length >0 "#HOSP_IDX_"+hospIdx 의 해당 아이디값이 존재하면 if($("#HOSP_IDX_"+hospIdx).length>0){ //상단에 너무 붙기 때문에 50px 여백을 준다. $("#HOSP_IDX_"+hospIdx).css("height","50px"); //해당 아이디 이동 location.href = "#HOSP_IDX_"+hospIdx; idMoving=false; //파라미터 제거 history.replaceState({}, null, location.pathname); } } } $(".loading2").hide(); }, error:function(result){ console.log("error:"+result); } }); } function detailPagetMove(e){ var href=$(e).attr("data-href"); var idx=$(e).attr("data-idx"); var currentPage=$(e).attr("data-currentPage"); //검색어 var keyword=$("#searchinput").val(); location.href=href+"¤tPage="+currentPage+"&keyword="+keyword; } //스크롤이 끝으로 가면 리스트 호출 - 다음 코드는 모바일에서 적용이 안된다. /* document.addEventListener("scroll", function(){ if(document.documentElement.scrollTop + document.documentElement.clientHeight == document.documentElement.scrollHeight){ if (page < pagingFinalPageNo) { page++; movePageWithPageNoScroll(page); } } }); */ </script> </body> </html>
=================================================================
뒤로가기시 리스트 유지방법은 쿠키를 이용한 다음과 같은 방법이 있다.
pc 에서는 다음 코드가 적용되나
//아이폰에서 백버튼 클릭시 /* window.onpageshow = function(event) { //back 이벤트 일 경우 if ( event.persisted) { alert("back 버튼"); } } */ window.history.pushState({page: 1}, "", ""); window.onpopstate = function(event) { if(event){ hospMoveBackPage(); } } window.onpageshow = function(event) { if (event.persisted) { hospMoveBackPage(); } };
따라서 모바일에서는 위 코드가 적용이 되지 않아서 쿠키를 이용한 링크 정보를 저장한다.
자바스크립트를 이용한 방법
페이지 로딩후 자바스크립트로 쿠키 확인 다시 이동하는 방법으로 불필요한 페지이동 되는 처리 될 수 있으나
코드는 간단하다.
1)쿠키를 통해 상세보기 페이지에서 파라미터 정보를 저장한다.
view.jsp
<script type="text/javascript"> const para = document.location.href.split("?"); var link="${pageContext.request.contextPath}/hosp/list"+get_query(); //쿠키저장 $.cookie('scrollCapture', link); function get_query(){ return "?"+para[1]; } </script>
list.jsp
<script type="text/javascript"> getCookie(); function getCookie(){ var link=$.cookie('scrollCapture'); if(link!=undefined){ //scrollCapture 쿠키 존재시 쿠키 삭제 후이동 $.removeCookie('scrollCapture'); location.href=link; } } </script>
서버단에서 쿠키를 확인후 이동 처리 하는 방법이다.
@RequestMapping({ "/hosp/{actTp}" }) public String movePageByPostMode(@RequestParam Map<String, Object> paramMap, @PathVariable String actTp, HttpServletRequest req, Model model) { //쿠키 Cookie cookie[] =request.getCookies(); System.out.println("쿠키의 개수 : " + cookie.length); String scrollCapture=""; for(Cookie co:cookie) { System.out.println(co.getName()+"="+co.getValue()+"<br/>"); if(co.getName().equals("scrollCapture")){ scrollCapture=co.getValue(); System.out.println(co.getValue()); } } //scrollCapture 쿠키값이 존재하면 다음을 실행 if(scrollCapture!=null&& !scrollCapture.equals("")){ String urlDecode=URLDecoder.decode(scrollCapture); System.out.println("urlDecode :"+urlDecode); //결과 예 :/hosp/list?HOSP_IDX=31¤tPage=1&keyword= String url[] =urlDecode.split("\\?"); System.out.println("url[0] :"+url[0]); actTp=url[0]; if(url.length>1){ //& 을 기준으로 분리 String param[]=url[1].split("&"); for(String str : param){ System.out.println("param str [] :"+str.toString()); //= 을 기준으로 분리 String ss[]=str.split("="); System.out.println("s[] : "+ ss.length); if(ss.length >1 && ss[0].contains("HOSP_IDX")){ paramMap.put("HOSP_IDX", ss[1]); }else if(ss.length >1 && ss[0].contains("currentPage")){ paramMap.put("currentPage", ss[1]); }else if(ss.length >1 && ss[0].contains("keyword")){ paramMap.put("keyword", ss[1]); } } } } ------------------------------------------------------------------------- String[] selChkAry; switch (actTp) { case "list": model = this.hospitalService.selectHospitalList(paramMap, model); model.addAttribute("naviOn", "hosp"); break; case "listScroll": model = this.hospitalService.selectHospitalList(paramMap, model); model.addAttribute("naviOn", "hosp"); break; case "view": paramMap = CommonUtils.setUserIdx(paramMap, req.getSession()); model.addAttribute("data", this.hospitalService.selectHospitalInfo(paramMap)); model.addAttribute("naviOn", "hosp"); break; case "plstview": paramMap = CommonUtils.setUserIdx(paramMap, req.getSession()); model.addAttribute("data", this.hospitalService.selectHospitalInfo(paramMap)); model.addAttribute("naviOn", "hosp"); break; case "plstList": selChkAry = req.getParameterValues("sel_check"); paramMap.put("selChkAry", selChkAry); model = this.hospitalService.selectPlasticSurgeryPictureList(paramMap, model); model.addAttribute("naviOn", "plst"); break; case "beforePlstList": selChkAry = req.getParameterValues("sel_check"); paramMap.put("selChkAry", selChkAry); model = this.hospitalService.selectPlasticSurgeryPictureList(paramMap, model); model.addAttribute("naviOn", "plst"); break; case "plstListScroll": selChkAry = req.getParameterValues("sel_check"); paramMap.put("selChkAry", selChkAry); model = this.hospitalService.selectPlasticSurgeryPictureList(paramMap, model); model.addAttribute("naviOn", "plst"); break; } model.addAttribute("paramMap", paramMap); return "hospital/" + actTp; } 파라미터 예 System.out.println("paramMap2 :"+paramMap2.toString()); ${paramMap.toString()}; <!-- =={HOSP_IDX=31, currentPage=1, keyword=, page=1, pageSize=18, startNo=0}; -->
=================================================================
listScroll.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%> <c:forEach var="item" items="${list}" varStatus="status"> <div id="HOSP_IDX_${item.HOSP_IDX}" ></div> <dt class="box" > <a href="#" data-href="${pageContext.request.contextPath}/hosp/view?HOSP_IDX=${item.HOSP_IDX}" data-currentPage="${currentPage}" data-idx="${item.HOSP_IDX}" onclick="detailPagetMove(this); return false;">${item.HOSP_NM}</a> <div class="smBtonLy"> </div> </dt> <dd> <div class="photo"> </a> </div> <ul> </c:forEach> </ul> </dd> </c:forEach>
페이징
ServiceImpl.java
페이징 처리에서 현재 페이지 저장
@Service public class HospitalServiceImpl implements HospitalService { @Autowired private HospitalDao hospitalDao; public Model selectHospitalList(Map<String, Object> paramMap, Model model) { int page = (paramMap.get("page") == null) ? 1 : Integer.parseInt((String) paramMap.get("page")); int pageSize = (paramMap.get("pageSize") == null) ? 6 : Integer.parseInt((String) paramMap.get("pageSize")); paramMap.put("page", Integer.valueOf(page)); paramMap.put("pageSize", Integer.valueOf(pageSize)); PagingUtil paging = new PagingUtil(); paging.setPageNo(page); paging.setPageSize(pageSize); paging.setTotalCount(this.hospitalDao.selectHospitalTotalCount(paramMap)); paramMap.put("startNo", Integer.valueOf(paging.getStartNo())); List<Map<String, Object>> list = this.hospitalDao.selectHospitalList(paramMap); model.addAttribute("list", list); model.addAttribute("paging", paging); model.addAttribute("currentPage", page); return model; } }
paging.jsp
무한 스크롤 사용 안할 경우
//기존 페이징 처리시 페이징 처리 방식
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <div class="page"> <a href="javascript:;" <c:if test="${paging.prevPageNo ne paging.pageNo}">onclick="javascript:movePageWithPageNo(${paging.prevPageNo});"</c:if> class="bimg"><img src="${pageContext.request.contextPath}/resources/img/page_before${colorNo}.png" alt="page before"></a> <c:forEach var="i" begin="${paging.startPageNo}" end="${paging.endPageNo}" step="1"> <c:choose> <c:when test="${i eq paging.pageNo}"> <a href="javascript:;" onclick="javascript:movePageWithPageNo(${i});"><strong>${i}</strong></a> </c:when> <c:otherwise> <a href="javascript:;" onclick="javascript:movePageWithPageNo(${i});">${i}</a> </c:otherwise> </c:choose> </c:forEach> <a href="javascript:;" <c:if test="${paging.nextPageNo ne paging.pageNo}">onclick="javascript:movePageWithPageNo(${paging.nextPageNo});"</c:if> class="bimg"><img src="${pageContext.request.contextPath}/resources/img/page_next${colorNo}.png" alt="page next"></a> </div>
상세보기
view.jsp
뒤로 가기 버튼 클릭시, 아이디값, 페이지 번호를 가져온다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%> <!DOCTYPE html> <html > <%@ include file="/WEB-INF/views/include/title.jsp" %> <script type="text/javascript"> const para = document.location.href.split("?"); function hospMoveBackPage(){ location.href="${pageContext.request.contextPath}/hosp/list"+get_query(); } function get_query(){ return "?"+para[1]; } //아이폰에서 백버튼 클릭시 /* window.onpageshow = function(event) { //back 이벤트 일 경우 if ( event.persisted) { alert("back 버튼"); } } */ window.history.pushState({page: 1}, "", ""); window.onpopstate = function(event) { if(event){ console.log("백버튼: 1"); hospMoveBackPage(); }else{ console.log("2"); } } </script> <body> <div id="wrapper"> <!-- header --> <header> <div class="head_box4"> <span class="btnBack"><a href="javascript:;" onclick="javascript:hospMoveBackPage();"><spring:message code='common.btn.back' /></a></span> </div> </header> <!-- //header --> <!-- container --> <div id="container"> <!-- 콘텐츠 영역 --> <div id="content"> </div> </div> <!-- //콘텐츠 영역 --> </div> <!-- //container --> </div>
페이지 로딩 css
css
.loading2{position:fixed;top:0;left:0;width:100%;height:100%;text-align:center;background:rgba(255,255,255,0.8)} .loading2 div{position:absolute;top:50%;left:50%;margin:-35px 0 0 -40px;padding-top:50px; background:url('../img/loading_ic.gif') no-repeat center top; background-size:100px; width: 100px;height: 100px; } .loading2 .loading-txt{ top: 72px; position: relative; }
댓글 ( 2)
댓글 남기기