이전 글
2023.06.27 - [자바스크립트] - 시베리안 허숙희의 자바스크립트 비기닝 29
에서 페이지 나누기를 위한 localStorage에 더미 데이터를 넣기 위해 울 게시판에 맞는
더미 데이터를 만들어 주는 ranUtil.js를 맹글어 첨부해 주었고, 그것을 dummy.html을
이용하여 108개의 있어보이는 더미 데이터을 넣었당. (준비 완료?)
자~~ 이제 페이지 나누기 산수를 해보장. (아주 쉽당, 외우지 말고 필요한 걸 생각하는 습관!)
급할 꺼 없당. 차분히 생각해 보면 아래 정도의 정보와 세팅이 필요함이 이해된당.
1. 페이지당 글 수(갯수_
2. 전체 글 수(갯수)
3. 페이지 수(갯수) ( 계산해야함!, 전체 글 수를 페이지당 글 수로 나누면 되는데, 나머지가?)
4. 페이지 별 시작 글넘버, 끝 글넘버 (배열에 들어있으니 index넘버를 이용)
5. 마지막 페이지 글 수(갯수)가 페이지당 글 수 만큼 안 될 때 처리
위 생각을 코드로 바꾸어 보면, 사람에 따라 조금 차이는 있겠지만 비슷하지 않을깡?
코드를 보고 생각과 동기화 시켜 보장! (일단 필요와 흐름이 이해되어야 한당!)
// localStorage key값(테이블 이름처럼 사용됨)
const tblName = "E7eBoard";
// localStorage에 데이타가 없는 경우는 없다 치장,없다면 dummy.html을 실행하장
let loDatas = JSON.parse(localStorage.getItem(tblName));
/* Paging 처리를 위한 산수 */
// 전체 글 수
let totalGulCnt = loDatas.length;
// 페이지당 몇개의 글? 일단 10개로 지정
const cntPerPage = 10;
// 계산되는 페이지 수, 108개면 11페이지가 나와야 함!(나머지가 있다면 올림)
let pageCnt = Math.ceil(totalGulCnt / cntPerPage);
// 현재 페이지? page=넘버 형태로 넘겨받음
let page = request.getParameter("page");
if(!page){ // 넘겨 받은 게 없다면 그냥 디폴트로 1 로 지정
page = 1;
}
// 페이지 별 시작글 index와 마지막 글 index (글이 배열에 담겨져 있음을 인식)
/* page startIndex endIndex 갯수
1 0 9 10
2 10 19 10
3 20 29 10
11 100 109(실제107) 9 마지막페이지에 쭈목
*/
let startGulIndex = (page - 1)*cntPerPage;
//let endGulIndex = startGulIndex + (pageCnt - 1);
// 반복문 < 으로 처리하면 -1은 하지 않아도 됨!
let endGulIndex = startGulIndex + cntPerPage;
// 글의 존재여부 상관없이 계산한 endGulIndex가 실제 존재하는 글의 index보다
// (곧 배열의 마지막index -> 토탈갯수-1) 보다 큰 경우에 추가 처리 필요
if(endGulIndex > (totalGulCnt-1)){
endGulIndex = totalGulCnt-1;
}
위 코드에서 페이지별 시작글 인덱스와 끝글 인덱스를 구했기 때문에 리스틀 출력할 때(getList함수)
해당 범위의 글을 출력해 주공, 페이지수도 계산되었으니 역시 반복문으로 페이지를 출력하고
만약 현재페이지라면 약간의 CSS를 가미해서 누네띠게(mark class 참고) 해주면 된당!
출력 핵심 코드는 아래와 같당. ( 누네 힘주면 왜 그리도 어렵지 않당.)
//글 리스트 출력함수
function gulList(){
// loDatas = JSON.parse(localStorage.getItem(tblName));
let tblStr = `<table id="list"><tbody>`;
tblStr += `<tr><th>글번</th><th>제목</th><th>지으니</th><th>관련</th><th>날짜</th></tr>`;
for(let i=startGulIndex; i < endGulIndex; i++){ // 시작인덱스, 끝인덱스 주목
let gul = loDatas[i];
tblStr += `<tr>`;
tblStr += `<td>${gul.num}</td>`;
tblStr += `<td><a href="#" onclick="fmodalOpen('${gul.num}')">${gul.title}</a></td>`;
tblStr += `<td>${gul.writer}</td>`;
tblStr += `<td>${gul.cate}</td>`;
tblStr += `<td>${gul.date}</td>`;
tblStr += `<tr>`;
}
tblStr += `</tbody></table>`;
let pageStr = "<br><br>";
for(let i=1; i <= pageCnt; i++){
if(page == i){ //현재 페이지 라면
pageStr += `<a class="mark" href="list.html?page=${i}">${i}</a> `;
}else {
pageStr += `<a href="list.html?page=${i}">${i}</a> `;
}
}
tblStr += pageStr;
tblStr += writeLink;
myContent.innerHTML = tblStr;
}
//모든 태그해석이 끝나면(DOMContentLoaded 이벤트) 자동실행
window.addEventListener("DOMContentLoaded",function(){
gulList();
});
요렇게만 설명하면 분명 당신은 전체 코드를 달라 할 거시다. 그래서 준비했당!
지금까지 작성한 list.html의 css 포함 전체 코드당. (정리하면서 흐름을 머리에 넣어보장!)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>E7E JS 께시판</title>
<link rel="shortcut icon"
href="https://img.icons8.com/?size=512&id=42814&format=png"
type="image/x-icon">
<style>
#wrapper {
width:750px;
margin: 20px auto;
color: rgb(83, 0, 161);
}
#header {
border-bottom: 2px solid orange;
text-align: center;
}
#content {
height:70vh;
overflow: auto;
}
#footer {
height:10vh;
line-height: 200%;
text-align: center;
}
#list,#list th,#list td {
border:1px solid black;
text-align: center;
}
th {
background-color: orange;
}
table {
width: 100%;
}
#modalWin{
position: fixed;
width:100vw;
height:100vh;
left:0px;
top:0px;
z-index: 1000;
/* background-color: blueviolet; */
background-color: rgba(138, 43, 226, 0.9);
display: none;
}
#modalCont {
width:400px;
height:70%;
margin:10% auto;
border:3px solid black; /* 낸중에 필요없음 주석 */
background-color: gray;
color:yellow;
text-align: center;
}
#menu {
width:100%;
height:10%;
text-align: right;
}
#close {
font-size: 2em;
}
.mark {
font-size:5em;
color:blueviolet;
}
</style>
</head>
<body>
<!-- 모달 모달 -->
<div id="modalWin">
<div id="modalCont">
<div id="menu">
<button id="close" onclick="fmodalClose()">X</button>
</div>
<div id="detail">
<form action="" method="get">
<input type="hidden" name="n_num" value="">
<table>
<tr><td>제목</td><td><input type="text" name="n_title" value="" required></td></tr>
<tr><td>글쓰니</td><td><input type="text" name="n_writer" value="" disabled></td></tr>
<tr><td colspan="2">내용</td></tr>
<tr><td colspan="2">
<textarea name="n_cont" cols="40" rows="10" required></textarea>
</td>
</tr>
<tr><td colspan="2">관련언어(최소1개 MAX 3개까지 선택)</td></tr>
<tr><td colspan="2">
HTML<input type="checkbox" name="n_cate" value="HTML" onclick="ckCnt(this)">
CSS<input type="checkbox" name="n_cate" value="CSS" onclick="ckCnt(this)">
JS<input type="checkbox" name="n_cate" value="JS" onclick="ckCnt(this)">
JAVA<input type="checkbox" name="n_cate" value="JAVA" onclick="ckCnt(this)">
ORACLE<input type="checkbox" name="n_cate" value="ORACLE" onclick="ckCnt(this)">
</td>
</tr>
<tr><td colspan="2"><br>
<button onclick="fPreSub('modify')">수정</button>
<button onclick="fPreSub('delete')">삭제</button>
</td>
</tr>
</table>
</form>
<div>
<img src="https://cdn.pixabay.com/photo/2019/11/28/21/31/lynx-4660096_1280.jpg"
style="width:100%;height:150px">
</div>
</div>
</div>
</div>
<!-- 화면 레이아웃-->
<div id="wrapper">
<div id="header">
<h1>어리둥절 JS 께시판</h1>
</div>
<div id="content"></div>
<div id="footer">
<h1>©E7E Compony Since 1969</h1>
</div>
</div>
<script src="./jsp.js"></script>
<script>
// localStorage key값(테이블 이름처럼 사용됨)
const tblName = "E7eBoard";
// 데이타가 없는 경우는 없다 치장,없다면 dummy.html을 실행하장
let loDatas = JSON.parse(localStorage.getItem(tblName));
/* Paging 처리를 위한 산수 */
// 전체 글 수
let totalGulCnt = loDatas.length;
// 페이지당 몇개의 글?
const cntPerPage = 10;
// 계산되는 페이지 수, 108개면 11페이지가 나와야 함!(나머지가 있다면 올림)
let pageCnt = Math.ceil(totalGulCnt / cntPerPage);
// 현재 페이지? page=넘버 형태로 넘겨받음
let page = request.getParameter("page");
if(!page){ // 넘겨 받은 게 없다면 그냥 디폴트로 1 로 지정
page = 1;
}
// 페이지 별 시작글 index와 마지막 글 index (글이 배열에 담겨져 있음을 인시)
/* page startIndex endIndex 갯수
1 0 9 10
2 10 19 10
3 20 29 10
11 100 109(실제107) 9 마지막페이지에 쭈목
*/
let startGulIndex = (page - 1)*cntPerPage;
//let endGulIndex = startGulIndex + (pageCnt - 1);
// 반복문 < 으로 처리하면 -1은 하지 않아도 됨!
let endGulIndex = startGulIndex + cntPerPage;
// 글의 존재여부 상관없이 계산한 endGulIndex가 실제 존재하는 글의 index보다
// (곧 배열의 마지막index -> 토탈갯수-1) 보다 큰 경우에 추가 처리 필요
if(endGulIndex > (totalGulCnt-1)){
endGulIndex = totalGulCnt-1;
}
//전역 변수
const myModalWin = document.querySelector("#modalWin");
const myHeader = document.querySelector("#header");
const myContent = document.querySelector("#content");
const myFooter = document.querySelector("#footer");
const myTitle = document.querySelector("[name=n_title]");
const myWriter = document.querySelector("[name=n_writer]");
const myCont = document.querySelector("[name=n_cont]");
const myCate = document.querySelectorAll("[name=n_cate]");
//괘니 백틱으로 써보는 템플릿
const writeLink = `
<div id="links" style="text-align:right">
<a href="write.html"><button>새글 쓰깅</button></a>
</div>
`;
// Global variables
const maxCnt = 3;
let totalCnt = 0;
const myForm = document.forms[0];
let modOrDel ="";
function fPreSub(pSet){
modOrDel = pSet;
}
// Global functions
const ckCnt = function(pThis){
if(pThis.checked){
totalCnt++;
}else {
totalCnt--;
}
if(totalCnt > maxCnt){
alert("3개 까지망");
pThis.checked = !1;
totalCnt--;
}
}
myForm.onsubmit = function(){
alert(`${modOrDel}을 누르셨군용`);
event.preventDefault();
ckboxs = document.querySelectorAll("[name=n_cate]:checked");
if(ckboxs.length < 2){
alert("최소 2개는 선택하셔야 해용");
}else {
myForm.action=`${modOrDel}_action.html`;
myForm.submit();
}
}
//글 리스트 출력함수
function gulList(){
// loDatas = JSON.parse(localStorage.getItem(tblName));
let tblStr = `<table id="list"><tbody>`;
tblStr += `<tr><th>글번</th><th>제목</th><th>지으니</th><th>관련</th><th>날짜</th></tr>`;
for(let i=startGulIndex; i < endGulIndex; i++){
let gul = loDatas[i];
tblStr += `<tr>`;
tblStr += `<td>${gul.num}</td>`;
tblStr += `<td><a href="#" onclick="fmodalOpen('${gul.num}')">${gul.title}</a></td>`;
tblStr += `<td>${gul.writer}</td>`;
tblStr += `<td>${gul.cate}</td>`;
tblStr += `<td>${gul.date}</td>`;
tblStr += `<tr>`;
}
tblStr += `</tbody></table>`;
let pageStr = "<br><br>";
for(let i=1; i <= pageCnt; i++){
if(page == i){
pageStr += `<a class="mark" href="list.html?page=${i}">${i}</a> `;
}else {
pageStr += `<a href="list.html?page=${i}">${i}</a> `;
}
}
tblStr += pageStr;
tblStr += writeLink;
myContent.innerHTML = tblStr;
}
//모든 태그해석이 끝나면(DOMContentLoaded 이벤트) 자동실행
window.addEventListener("DOMContentLoaded",function(){
gulList();
});
//모달 열기
const fmodalOpen = function(pNum){
event.preventDefault(); // a 태그 링크 이동 막깅
document.querySelector("[name=n_num]").value = pNum;
for(let i=0; i<loDatas.length; i++){
if(loDatas[i].num == pNum){
myTitle.value = loDatas[i].title;
myWriter.value = loDatas[i].writer;
myCont.value = loDatas[i].cont;
let cates = loDatas[i].cate;
totalCnt = cates.length;
for(let j=0; j < cates.length; j++){
document.querySelector(`[type=checkbox][value=${cates[j]}]`).checked = true;
}
break;
}
}
myModalWin.style.display = "block";
}
//모달 닫기
const fmodalClose = function(){
myModalWin.style.display = "none";
}
</script>
</body>
</html>
참고로 나의 경우 아래와 같은 결과 화면을 얻었당.
서버사이드 프로그래밍 전혀 없이 HTML,CSS, 자바스크립트만으로 게시판을 만들어 보았당!
이것이 무슨 의미일까?, action에 html 페이지를 쓰다닝, 꼬옥 한번 생각해 보장.
정말 이대로 괜찮은 걸깡?
개인적인 추천은 위 리스트에 검색, 페이지 출력모습 변경도 한번 넣어보길 추천한당.
어느새 시베리안 허숙희의 글이 30번까지 오고 말았당. ~~
두서없는 설명과 기럭지 긴 코드가 범벅되는 듯 한 아쉬움이 있지만,
진정 아쉬운 건 나 혼자만 빠져든다는 이 느낌 같은 느낌!, 글 속에 날 가두는 느낌!
누군가 내 글, 내 노래를 더 멋지게 커버해 주었으면 하는 바램의 바람의 비기닝이 느껴진당!
(진심은 모두를 덮지 않는다, 그저 곳곳에 묻어있을 뿐, 찾는 사람의 거시당)
https://www.youtube.com/watch?v=HQjMa28UsrI
시베리안 허숙희의 자바스크립트 비기닝 32 (무한 스크롤) (0) | 2023.06.28 |
---|---|
시베리안 허숙희의 자바스크립트 비기닝 31 (3D 움직임 맛보깅...) (0) | 2023.06.28 |
시베리안 허숙희의 자바스크립트 비기닝 29 (스크립트 게시판 계속...) (0) | 2023.06.27 |
시베리안 허숙희의 자바스크립트 비기닝 28 (모달 modal) (2) | 2023.06.23 |
시베리안 허숙희의 자바스크립트 비기닝 27 ( 스크립트 게시판!) (0) | 2023.06.22 |