JQuery

Ajax & JSON

AJAX 와 JSON 을 다시 한번 복습하고 넘어가보자.

AJAX(Async JavaScript And XML)

Ajax는 웹페이지에서 새로운 데이터를 보여주려고 할 때 웹페이지 전체를 새로고침 하지 않고, 보여주고자 하는 데이터가 포함된 페이지의 일부분 만을 로드하기 위해 비동기 (non-blocking)을 사용하여 데이터를 처리

AJAX 동작방식

  1. 요청(request) - 브라우저가 서버에 정보를 요청
  2. 서버의 동작 - 서버는 JSON, XML등의 형식으로 데이터를 전달한다.
  3. 응답(response) - 브라우저에서 이벤트가 발생하여 콘텐츠를 처리한다.

데이터 타입

Ajax는 Async Javascript And XML의 약어로, 이름에 나와있는 것처럼 XML 형식으로 데이터를 주고 받을 수 있습니다. 하지만 최근에는 많은 경우를 JSON 형식으로 데이터를 주고 받습니다.

JSON(JavaScript Object Notation)

JSON은 자바스크립트의 객체 표현식과 유사한 방식으로 데이터를 주고받는 방식이다. 자바스크립트 객체와 거의 비슷하지만 차이점이 있다. JSON은 객체를 정의하지 않는다. 자바스크립트 객체가 아니라 객체 표현식으로 데이터를 표현한다.

요약

*스크립트 언어는 컴파일 하지 않고 바로 실행할 수 있는 언어들을 주로 얘기함
JSP, ASP, PHP, Python, JavaScript 등이 대표적인 스크립트 언어

  • JSON : 인터넷에서 자료를 주고받을때 쓰는 문법
  • AJAX : 비동기로 화면깜박임 없이 데이터를 주고받는 방법

자세한건 다시한번 복습을 하겠다.


01. 공지사항 게시판 만들기 (AJAX , JSON)

결과

결과 부터 보자면 이런 구성과 동작이다.

HTML

    <div id="wrap">
        <header id="header"></header>
        <main id="main">
            <section id="notice">
                <div class="container">
                    <div class="notice-title">
                        <h2><img src="./img/tit_notice.png" alt="notice-title"></h2>
                    </div>
                    <div class="notice-title-double-line">
                        <p></p>
                    </div>
                    <nav class="noticeBtn-wrap">
                        <ul>
                            <li>
                                <div><a href="javascript:" class="noticeBt addNav" title="전체공지">전체공지</a></div>
                            </li>
                            <li>    
                                <div><a href="javascript:" class="noticeBt" title="쇼핑공지">쇼핑공지</a></div>
                            </li>
                            <li>    
                                <div><a href="javascript:" class="noticeBt" title="브랜드소식">브랜드소식</a></div>
                            </li>
                        </ul>
                    </nav>
                    <div class="notice-board">
                        <table>
                            <colgroup>
                                <col style="width:8%">
                                <col style="width:12%">
                                <col style="width:60%">
                                <col style="width:20%">
                            </colgroup>
                            <thead>
                                <tr>
                                    <th>번호</th>
                                    <th>구분</th>
                                    <th>제목</th>
                                    <th>날짜</th>
                                </tr>
                            </thead>
                            <tbody>
                                <!-- ajax 바인딩 -->
                            </tbody>
                        </table>
                        <div class="notice-page">
                            <ul>
                                <li>
                                    <div class="pagePrev">
                                        <a href="javascript:" class="pagePrevBt">
                                            <img src="./img/btn_page_prev.png" alt="prev">
                                        </a>
                                    </div>
                                </li>
                                <li>
                                    <div class="notice-page-number">
                                        <!-- 페이지 자동 추가 -->
                                    </div>
                                </li>
                                <li>
                                    <div class="pageNext">
                                        <a href="javascript:" class="pageNextBt">
                                            <img src="./img/btn_page_next.png" alt="prev">
                                        </a>
                                    </div>
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
            </section>
        </main>
        <footer id="footer"></footer>
    </div>

완벽 이해하는 부분이 없으므로.. 복습을 차근차근히 하면서 HTML 부터 알아보자

01. HTML

                    <nav class="noticeBtn-wrap">
                        <ul>
                            <li>
                                <div><a href="javascript:" class="noticeBt addNav" title="전체공지">전체공지</a></div>
                            </li>
                            <li>    
                                <div><a href="javascript:" class="noticeBt" title="쇼핑공지">쇼핑공지</a></div>
                            </li>
                            <li>    
                                <div><a href="javascript:" class="noticeBt" title="브랜드소식">브랜드소식</a></div>
                            </li>
                        </ul>
                    </nav>

nav 부분 부터 보자면 nav > ul > li > div > a 식으로 되어 있고,
전체공지 , 쇼핑공지 , 브랜드소식 으로 나열돼있다. 공통으로 들어가는 클래스는 noticeBt 이며
마우스 on 혹은 active 효과를 주려고 addNav전체공지에 추가된 것을 볼 수 있다.

02. HTML

<table>
	<colgroup>
    	<col style="width:8%">
        <col style="width:12%">
        <col style="width:60%">
        <col style="width:20%">
   	</colgroup>
    <thead>
    	<tr>
        	<th>번호</th>
            <th>구분</th>
            <th>제목</th>
            <th>날짜</th>
    	</tr>
	</thead>
    <tbody>
    	<!-- ajax 바인딩 -->
 	</tbody>
</table>

결과물을 먼저 보자면


이부분이다. ( div class="notice-board"바로 밑 table 코드이다. )
테이블을 만들고 HTML 내에서 colgroup을 만들어 th만큼 만들어서 width 값을 부여한다.
tbody 의 주석 (ajax 바인딩) 부분은 나중에 저 부분에 .html()로 바인딩 되어 들어오는 부분이다.

03. HTML

<div class="notice-page">
	<ul>
    	<li>
        	<div class="pagePrev">
            	<a href="javascript:" class="pagePrevBt">
                	<img src="./img/btn_page_prev.png" alt="prev">
               	</a>
        	</div>
   		</li>
        <li>
        	<div class="notice-page-number">
            	<!-- 페이지 자동 추가 -->
         	</div>
    	</li>
        <li>
        	<div class="pageNext">
            	<a href="javascript:" class="pageNextBt">
                	<img src="./img/btn_page_next.png" alt="prev">
            	</a>
          	</div>
      	</li>
 	</ul>
</div>

결과물을 먼저 보자면

지금은 데이터가 들어오지 않아 간격이 없고 버튼만 있는 상태이다. 추후 저부분에는 페이지넘버가 들어간다.

이런식으로..
다른부분은 기존 CSS와 HTML만으로 충분히 이해가 가는 부분이고,

<div class="notice-page-number">
            	<!-- 페이지 자동 추가 -->
	</div>

div class="notice-page-number" 중간에 비어 있는 이부분은 나중에 페이지 넘버가 들어올 자리이므로 태그와 클래스만 지정해둔다.

CSS

*{margin: 0; padding: 0;}
ul{list-style: none;}
a{text-decoration: none;}
#wrap{width: 100%;}
#header{width: 100%; height: 186px; background: #222;}
#main{width: 100%;}
#main h2{text-align: center;}
#main .notice-title-double-line{padding: 30px 0; width: 100%;}
#main .notice-title-double-line p{width: 100%; height: 3px; background: url(../img/bg_tit_line.png) repeat-x 0 0;}
#main .noticeBtn-wrap{padding-bottom: 50px; text-align: center;}
#main .noticeBtn-wrap ul{display: flex; justify-content: center;}
#main .noticeBtn-wrap ul li{flex-basis: 145px; height: 40px; text-align: center;}
#main .noticeBtn-wrap ul li div{border: 1px solid #e1e4e8; margin-right: -1px;}
#main .noticeBtn-wrap ul li div a{display: block; font-size: 13px; color: #222; line-height: 38px; background: #fff;}
#main .noticeBtn-wrap ul li div a.addNav{color: #fff; background: #b68957;}
#main .notice-board{width: 100%;}
#main .notice-board table{width: 100%;}
#main .notice-board table tr{width: 100%;}
#main .notice-board table tr th{border-top: 1px solid #e1e4e8; border-bottom: 1px solid #e1e4e8; height: 44px; font-size: 12px; font-weight: bold; color: #555; background: #f8f8f8;}
#main .notice-board table tr td{text-align: center; color: #777; font-size: 17px; border-bottom: 1px solid #e1e4e8; height: 56px;}
#main .notice-page{padding: 30px 0;}
#main .notice-page > ul{display: flex; justify-content: center;}
#main .notice-page > ul > li{}
#main .notice-page > ul > li .pagePrev{width: 27px; height: 27px;}
#main .notice-page > ul > li .pagePrev > a{}
#main .notice-page > ul > li .pagePrev > a > img{width: auto;}
#main .notice-page > ul > li .notice-page-number{display: flex; width: auto;}
#main .notice-page > ul > li .notice-page-number span > a{display: block; padding: 2px 8px; font-size: 12px; color: #777; text-decoration: none; /* font-weight: bold; */} 
#main .notice-page > ul > li .notice-page-number span > a.addPage{color: #b88857;} 
#main .notice-page > ul > li .notice-page-number span > a:hover{color: #b88857;} 
#main .notice-page > ul > li .pageNext{width: 27px; height: 27px;}
#main .notice-page > ul > li .pageNext > a > img{width: auto;}
#footer{width: 100%;}

CSS 중 중요하다고 생각되는건 버튼 사이 데이터가 들어올 자리
width: auto;display: flex; 염두해두기!

JSON

{
	"공지사항":
	[
		  {"구분":"쇼핑",   	"제목":"더페이스샵 시스템 점검 안내 (01/11)",											"날짜":"2020.01.11"},
		  {"구분":"쇼핑",   	"제목":"더페이스샵 시스템 점검 안내 (01/05)",											"날짜":"2020.01.04"},
		  {"구분":"브랜드",   	"제목":"더페이스샵, 겨울 선크림 ‘파워 롱래스팅 모이스처 선’ 출시",								"날짜":"2019.12.05"},
		  {"구분":"브랜드",   	"제목":"LG생활건강, fmgt '잉크래스팅 파운데이션’ X 대세 캐릭터 ‘펭수’",						"날짜":"2019.11.29"},
		  {"구분":"브랜드",   	"제목":"LG생활건강, fmgt ‘골드콜라겐 베이스 라인’ 리뉴얼 출시",								"날짜":"2019.11.15"},
		  {"구분":"브랜드",   	"제목":"LG생활건강, fmgt ‘루즈 샤인 비비드’ 출시",										"날짜":"2019.11.14"},
		  {"구분":"브랜드",   	"제목":"더페이스샵 ‘TWINKLE PARTY 홀리데이 에디션’ 출시",								"날짜":"2019.11.12"},
		  {"구분":"쇼핑",   	"제목":"더페이스샵 시스템 점검 안내 (11/09)",											"날짜":"2019.11.09"},
		  {"구분":"쇼핑",   	"제목":"더페이스샵 시스템 점검 안내 (10/31)",											"날짜":"2019.10.30"},
		  {"구분":"쇼핑",   	"제목":"더페이스샵 시스템 점검 안내 (10/12)",											"날짜":"2019.10.12"},
		  {"구분":"쇼핑",   	"제목":"더페이스샵 시스템 점검 안내 (8/10)",											"날짜":"2019.08.10"},
		  {"구분":"쇼핑",   	"제목":"포인트 사용 및 출석체크 이벤트 종료 안내",											"날짜":"2019.07.25"},
		  {"구분":"쇼핑",   	"제목":"더페이스샵 온라인전용 제품 단종 당첨자 발표 안내드립니다",								"날짜":"2019.07.19"},
		  {"구분":"쇼핑",   	"제목":"더페이스샵 포인트 교환기능 당첨자 발표 오픈 공지 (6/27기준 1만포인트 이상 보유고객)",			"날짜":"2019.07.04"},
		  {"구분":"쇼핑",   	"제목":"출석체크 이벤트 연장 관련 공지",												"날짜":"2019.06.27"},
		  {"구분":"브랜드", 	"제목":"LG생활건강 저자극 마스크시트 ‘닥터벨머 마일드 더마’ 5종 출시",							"날짜":"2019.06.21"},
		  {"구분":"쇼핑",   	"제목":"<중요> 쇼핑기능 종료에 따른 잔여 쿠폰 포인트 사용 안내 (6/27 수정)",					"날짜":"2019.06.13"},
		  {"구분":"브랜드", 	"제목":"LG생활건강 저자극 클렌징 & 각질케어 솔루션 ‘닥터벨머 아미노클리어’ 출시!",					"날짜":"2019.06.13"}
]
}

JSON 구성은 대략적으로 공지사항 > 구분 : 쇼핑, 브랜드 제목 , 날짜 데이터로 구성되어 있다. total 개수는 200개이다.

script

$(function(){
    let a=[]; //전체공지 배열 선언 2차원 글번호[0], 구분[1], 제목[2], 날짜[3]
    let b=[]; //쇼핑공지 배열 선언 2차원 글번호[0], 구분[1], 제목[2], 날짜[3]
    let c=[]; //브랜드소식 배열 선언 2차원 글번호[0], 구분[1], 제목[2], 날짜[3]
    let n=-1; //쇼핑공지 필터링 카운트 변수
    let m=-1; //브랜드소식 필터링 카운트 변수
    let txt="";  //출력할 배열 내용 변수
    let cnt=0; //글번호 변수
    let imgNum=''; //구분이미지 변수

    let noticeBtNum=0; //필터링 변수 전체공지=0 , 쇼핑공지=1 , 브랜드소식=2
    let totRecord=0; //전체 레코드 개수 전체공지=200개 중 쇼핑공지=150개 브랜드소식=50개
    let list=5; //한 화면에 보여질 목록 개수(총 200개 / 5개 = 40묶음이 나옴)
    let startRecord=0; //1페이지 시작 번호
    let endRecord=startRecord+list; //1페이지 끝 번호

    let totPage=0; //전체 페이지 (200/5)=40페이지, 쇼핑공지(150/5)=30페이지, 브랜드소식(50/5)=10페이지
    let group=1; //그룹번호 
    let groupPage=10; // 그룹 페이지 개수 10개씩
    let frontPage=0; //앞페이지 0
    let rearPage=frontPage+groupPage; //뒷페이지 10
    let currentPage=0; //현재페이지에서 페이지 표시할 addClass 사용 버튼 변수

    $.ajax({
        url: './data/notice.json',
        dataType: 'json',
        success:function(data){
            $.each(data.공지사항, function(idx, obj){
                a[idx]=[] //idx=0~199
                if(obj.구분=='쇼핑'){
                    imgNum="<img src='./img/icon_notice1.gif' alt='쇼핑'>";
                }else{
                    imgNum="<img src='./img/icon_notice2.gif' alt='브랜드'>";
                }
                a[idx][0]=idx+1;//글번호[0]
                a[idx][1]=imgNum;//구분[1]
                a[idx][2]=obj.제목;//제목[2]
                a[idx][3]=obj.날짜;//날짜[3]

                //필터링 쇼핑공지
                if(obj.구분=='쇼핑'){
                    n++;
                    b[n]=[]

                    b[n][0]=n+1;
                    b[n][1]=imgNum;
                    b[n][2]=obj.제목;
                    b[n][3]=obj.날짜;
                }
                //필터링 브랜드소식
                if(obj.구분=='브랜드'){
                    m++;
                    c[m]=[]

                    c[m][0]=n+1;
                    c[m][1]=imgNum;
                    c[m][2]=obj.제목;
                    c[m][3]=obj.날짜;
                }
            });
            //필터 버튼 클릭 이벤트
            $('.noticeBt').each(function(index){
                $(this).on({click: function(){
                    startRecord=0;
                    endRecord=startRecord+list;
                    noticeBtNum=index; //클릭된 번호
                    noticeFn();
                    $('.noticeBt').removeClass('addNav')
                    $(this).addClass('addNav')
                }
            });
            });
            //공지사항 메인 함수
            noticeFn();//호이스팅을 위해 호출
            function noticeFn(){
                if(noticeBtNum==0){//전체공지
                    totRecord=a.length;
                    cnt=a.length;
                    for(i=0; i<a.length; i++){
                        a[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+a[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
                else if(noticeBtNum==1){//쇼핑공지
                    totRecord=b.length;
                    cnt=b.length;
                    for(i=0; i<b.length; i++){
                        b[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+b[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
                else if(noticeBtNum==2){//브랜드소식
                    totRecord=c.length;
                    cnt=c.length;
                    for(i=0; i<c.length; i++){
                        c[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+c[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
                $('tbody').html(txt);
                txt='';
                cnt=0;
                
                //페이지 버튼 자동 추가
                //1. 전체 페이지 = 전체레코드/5
                totPage=totRecord/list;
                console.log(totPage);
                //2. 현재페이지(endRecode/list=5) / groupPage=10 )
                group=Math.ceil((endRecord/list)/groupPage);
                console.log(group);
                //3. 페이지 그룹범위 : 앞페이지와 뒷페이지 범위 값 설정
                frontPage=(group-1)*10
                rearPage=frontPage+groupPage;
                //4.나머지 단위 10페이지가 안되는 페이지수 정리
                if(rearPage>totPage){
                    rearPage=totPage
                }
                $('.notice-page-number>span').remove();
                for(i=frontPage; i<rearPage; i++)
                $('.notice-page-number').append("<span><a href='javascript:' class='pageBt'>"+ (i<9?('0'+(i+1)):(i+1))+"</a></span>");
                
                currentPage=(endRecord/list)%groupPage;
                console.log(currentPage);
                $('.pageBt').eq(currentPage-1).addClass('addPage')
            }//noticeFN END

            //추가된 버튼 이벤트 문제를 해결하기 위해 (2회 이상 클릭 인식 안되는 부분)
            $(document).on('mouseenter','.pageBt',function(){// <==이부분
            $('.pageBt').each(function(index){
                $(this).on({click:function(){
                    startRecord=(Number($(this).text())-1)*list;
                    endRecord=startRecord+list;
                    if(endRecord>totRecord){
                        endRecord = totRecord
                    }
                    noticeFn();
                }})
            });
            });
            $('.pageNextBt').on({
                click:function(){
                    startRecord += list; //list만큼 누적
                    endRecord=startRecord+list;
                    if(endRecord>totRecord){
                        startRecord=totRecord-(totRecord%list);//startRecord= 0
                        endRecord=totRecord;
                        if(startRecord==totRecord){
                            startRecord=totRecord-list;
                            endRecord=totRecord;
                            return false;
                        }
                    }
                    noticeFn();
                }
            });
            $('.pagePrevBt').on({click:function(){
                startRecord -= list;
                endRecord=startRecord+list;
                if(startRecord<0){
                    startRecord=0;
                    endRecord=startRecord+list;
                }
                noticeFn();
            }
        });
        },
        error:function(){
            console.log('error');
        }
    });
});

script 의 구성은 이렇다 풀이 하면서 풀어보자.

01. script

    let a=[]; //전체공지 배열 선언 2차원 글번호[0], 구분[1], 제목[2], 날짜[3]
    let b=[]; //쇼핑공지 배열 선언 2차원 글번호[0], 구분[1], 제목[2], 날짜[3]
    let c=[]; //브랜드소식 배열 선언 2차원 글번호[0], 구분[1], 제목[2], 날짜[3]
    let n=-1; //쇼핑공지 필터링 카운트 변수
    let m=-1; //브랜드소식 필터링 카운트 변수
    let txt="";  //출력할 배열 내용 변수
    let cnt=0; //글번호 변수
    let imgNum=''; //구분이미지 변수

    let noticeBtNum=0; //필터링 변수 전체공지=0 , 쇼핑공지=1 , 브랜드소식=2
    let totRecord=0; //전체 레코드 개수 전체공지=200개 중 쇼핑공지=150개 브랜드소식=50개
    let list=5; //한 화면에 보여질 목록 개수(총 200개 / 5개 = 40묶음이 나옴)
    let startRecord=0; //1페이지 시작 번호
    let endRecord=startRecord+list; //1페이지 끝 번호

    let totPage=0; //전체 페이지 (200/5)=40페이지, 쇼핑공지(150/5)=30페이지, 브랜드소식(50/5)=10페이지
    let group=1; //그룹번호 
    let groupPage=10; // 그룹 페이지 개수 10개씩
    let frontPage=0; //앞페이지 0
    let rearPage=frontPage+groupPage; //뒷페이지 10
    let currentPage=0; //현재페이지에서 페이지 표시할 addClass 사용 버튼 변수

우선 선언된 let 변수를 이해해보자
let a , b , c 의 배열선언
let a=[]; 는 전체공지
let b=[]; 는 쇼핑공지
let c=[]; 는 브랜드소식 이다.
배열 선언 2차원이라고 되어있다.
아래와 같이 배열은 이렇게 구성된다.

02.script

    $.ajax({
        url: './data/notice.json',
        dataType: 'json',
        success:function(data){
            console.log(data)
            $.each(data.공지사항, function(idx, obj){
                a[idx]=[] //idx=0~199
                if(obj.구분=='쇼핑'){
                    imgNum="<img src='./img/icon_notice1.gif' alt='쇼핑'>";
                }else{
                    imgNum="<img src='./img/icon_notice2.gif' alt='브랜드'>";
                }
                a[idx][0]=idx+1;//글번호[0]
                a[idx][1]=imgNum;//구분[1]
                a[idx][2]=obj.제목;//제목[2]
                a[idx][3]=obj.날짜;//날짜[3]

                //필터링 쇼핑공지
                if(obj.구분=='쇼핑'){
                    n++;
                    b[n]=[]

                    b[n][0]=n+1;
                    b[n][1]=imgNum;
                    b[n][2]=obj.제목;
                    b[n][3]=obj.날짜;
                }
                //필터링 브랜드소식
                if(obj.구분=='브랜드'){
                    m++;
                    c[m]=[]

                    c[m][0]=n+1;
                    c[m][1]=imgNum;
                    c[m][2]=obj.제목;
                    c[m][3]=obj.날짜;
                }
            });

$.ajax를 불러온다. url , dataType , success 한다면 function(){} 을 실행한다.

    $.ajax({
        url: './data/notice.json',
        dataType: 'json',
        success:function(data){
        console.log(data)

먼저 success:function(data)에 JSON data가 잘 들어갔는지 확인을 위해 console.log(data) 콘솔창을 확인해본다.

잘 들어간걸 확인한다.

다음..

$.each(data.공지사항, function(idx, obj){
                a[idx]=[] //idx=0~199
                if(obj.구분=='쇼핑'){
                    imgNum="<img src='./img/icon_notice1.gif' alt='쇼핑'>";
                }else{
                    imgNum="<img src='./img/icon_notice2.gif' alt='브랜드'>";
                }
                a[idx][0]=idx+1;//글번호[0]
                a[idx][1]=imgNum;//구분[1]
                a[idx][2]=obj.제목;//제목[2]
                a[idx][3]=obj.날짜;//날짜[3]
				//필터링 쇼핑공지
                if(obj.구분=='쇼핑'){
                    n++;
                    b[n]=[]
					b[n][0]=n+1;
                    b[n][1]=imgNum;
                    b[n][2]=obj.제목;
                    b[n][3]=obj.날짜;
                }
                //필터링 브랜드소식
                if(obj.구분=='브랜드'){
                    m++;
                    c[m]=[]
					c[m][0]=n+1;
                    c[m][1]=imgNum;
                    c[m][2]=obj.제목;
                    c[m][3]=obj.날짜;
                }
            });

each 문을 본다. $.each(data.공지사항) Json안에 공지사항을 불러주고 function(idx, obj)를 실행한다. index와 object를 의미하는 약자나 알파벳으로 써도 무방하다.
a[idx]=[] a의 [배열에] = [ ] 담는다. 0~199번 까지 (1~200)

if(obj.구분=='쇼핑'){
                    imgNum="<img src='./img/icon_notice1.gif' alt='쇼핑'>";
                }else{
                    imgNum="<img src='./img/icon_notice2.gif' alt='브랜드'>";
                }

다음 if문을 통해 JSON 데이터 "구분" 에서 "쇼핑"과 "브랜드"를 구분하여 구분 이미지를 넣는다.


a[idx][0]=idx+1;//글번호[0]
a[idx][1]=imgNum;//구분[1]
a[idx][2]=obj.제목;//제목[2]
a[idx][3]=obj.날짜;//날짜[3]

전체공지 배열선언 a[idx][0]:글번호,[1]:구분,[2]:제목,[3]날짜이다. JSON파일에 해당하는 배열을 넣어준다.


				//필터링 쇼핑공지
                if(obj.구분=='쇼핑'){
                    n++;
                    b[n]=[]
					b[n][0]=n+1;
                    b[n][1]=imgNum;
                    b[n][2]=obj.제목;
                    b[n][3]=obj.날짜;
                }
                //필터링 브랜드소식
                if(obj.구분=='브랜드'){
                    m++;
                    c[m]=[]
					c[m][0]=n+1;
                    c[m][1]=imgNum;
                    c[m][2]=obj.제목;
                    c[m][3]=obj.날짜;
                }

if문을 만들어 b:쇼핑공지 , c:브랜드소식을 만든다.


03.script

			//필터 버튼 클릭 이벤트
            $('.noticeBt').each(function(index){
                $(this).on({click: function(){
                    startRecord=0;
                    endRecord=startRecord+list;
                    noticeBtNum=index; //클릭된 번호
                    noticeFn();
                    $('.noticeBt').removeClass('addNav')
                    $(this).addClass('addNav')
                }
            });
            });
            //공지사항 메인 함수
            noticeFn();//호이스팅을 위해 호출
            function noticeFn(){
                if(noticeBtNum==0){//전체공지
                    totRecord=a.length;
                    cnt=a.length;
                    for(i=0; i<a.length; i++){
                        a[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+a[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
                else if(noticeBtNum==1){//쇼핑공지
                    totRecord=b.length;
                    cnt=b.length;
                    for(i=0; i<b.length; i++){
                        b[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+b[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
                else if(noticeBtNum==2){//브랜드소식
                    totRecord=c.length;
                    cnt=c.length;
                    for(i=0; i<c.length; i++){
                        c[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+c[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
			//필터 버튼 클릭 이벤트
            $('.noticeBt').each(function(index){
                $(this).on({click: function(){
                    startRecord=0;
                    endRecord=startRecord+list;
                    noticeBtNum=index; //클릭된 번호
                    noticeFn();
                    $('.noticeBt').removeClass('addNav')
                    $(this).addClass('addNav')
                }
            });
            });

html에서 전체공지, 쇼핑공지, 브랜드소식을 noticeBt 클래스를 지정했다. each문을 이용하여 함수안에 index를 담고 $(this)를 클릭하면 아래와 같이 바뀐다.

  • startRecord=0; : 1페이지 시작번호
  • endRecord=startRecord+list; : 1페이지 끝 번호
  • noticeBtNum=index; : 클릭된 번호 (index)

    다음 자바스크립트를 보자
//공지사항 메인 함수
            noticeFn();//호이스팅을 위해 호출
            function noticeFn(){
                if(noticeBtNum==0){//전체공지
                    totRecord=a.length;
                    cnt=a.length;
                    for(i=0; i<a.length; i++){
                        a[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+a[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
                else if(noticeBtNum==1){//쇼핑공지
                    totRecord=b.length;
                    cnt=b.length;
                    for(i=0; i<b.length; i++){
                        b[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+b[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }
                else if(noticeBtNum==2){//브랜드소식
                    totRecord=c.length;
                    cnt=c.length;
                    for(i=0; i<c.length; i++){
                        c[i][0]=cnt;
                        cnt--;
                    }
                    for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+c[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }
                }

공지사항 메인 함수이다. 함수 noticeFn()의 이름으로 함수를 생성하였고 if 조건문을 만든다. 만약noticeBtNum0(전체공지)라면 totRecordalength만큼 만들고 cnt의 변수는 글번호의 변수인데 거기에 글번호도 같이 담아준다.

totRecord=a.length;
cnt=a.length;

다음 for 반복문을 만들고 i=0; i< a.length; i++을 사용하여 a[i][0]=cnt (과거 게시물이 제일 첫번째이고 최신글까지 번호가 생성되는 순서로 된다.) for문의 조건이 될때까지 cnt--;가 된다. 아직 글이 생성되지는 않았고 순서만 정해주는 코드였고 다시 for문을 쓴다.

for(i=startRecord; i<endRecord; i++){
                        txt += "<tr>";
                        for(j=0; j<4; j++){
                            txt += "<td>"+a[i][j]+"</td>";
                        }
                        txt += "</tr>";
                    }

i0부터 시작하지만 변수 startRecord=0;와 같기에 i=startRecord로 지정하고 iendRecordstartRecord+list의 값이므로 05보다 작을때까지 i++이라고 생각하면 된다. 그러면 txt+="< tr > 조건문이 끝날때 까지 tr이 추가되고 td도 4보다 작을때까지 1씩 증가를 하고 txt += "< td >" 그리고 마지막 다 끝난후 < t d > 를 닫아준다.


나머지 쇼핑공지 , 브랜드소식도 동일하다. -생략-
다음

$('tbody').html(txt);
txt='';
cnt=0;

를 하면

tbody에 추가된다.

04.script

//페이지 버튼 자동 추가
                //1. 전체 페이지 = 전체레코드/5
                totPage=totRecord/list;
                console.log(totPage);
                //2. 현재페이지(endRecode/list=5) / groupPage=10 )
                group=Math.ceil((endRecord/list)/grupPage);
                console.log(group);
                //3. 페이지 그룹범위 : 앞페이지와 뒷페이지 범위 값 설정
                frontPage=(group-1)*10
                rearPage=frontPage+grupPage;
                //4.나머지 단위 10페이지가 안되는 페이지수 정리
                if(rearPage>totPage){
                    rearPage=totPage
                }
                $('.notice-page-number>span').remove();
                for(i=frontPage; i<rearPage; i++)
                $('.notice-page-number').append("<span><a href='javascript:' class='pageBt'>"+ (i<9?('0'+(i+1)):(i+1))+"</a></span>");
                
                currentPage=(endRecord/list)%grupPage;
                console.log(currentPage);
                $('.pageBt').eq(currentPage-1).addClass('addPage')
            }//noticeFN END

페이지 버튼을 자동으로 추가해본다.

1. 전체페이지

totPage=totRecord/list

totPage는 전체 공지의 개수이고 list= 5 이므로 5개씩 나눠서 페이지가 생성된다는 뜻이다.

2. 현재페이지

group=Math.ceil((endRecord/list)/grupPage);

현재 페이지는 endRecord=startRecord+list / 5 (list)의 값에서 groupPage=10; 10을 나눈 값이다. 소수점으로 나오기 때문에 Math.ceil을 사용한다.

3. 페이지 그룹범위

앞페이지와 뒷페이지 범의 값을 설정한다.

frontPage=(group-1)*10;
rearPage=frontPage+groupPage;

frontPage(group-1)*10 의 값을 대입하고
rearPagefrontPage + groupPage 로 만든다.

4. 나머지 단위 10페이지가 안되는 페이지 정리

if(rearPage>totPage){
                    rearPage=totPage
                }
$('.notice-page-number>span').remove();
	for(i=frontPage; i<rearPage; i++){
   	$('.notice-page-number').append("<span><a href='javascript:'class='pageBt'>"
    + (i<9?('0'+(i+1)):(i+1))+"</a></span>");
    }
    currentPage=(endRecord/list)%groupPage;
    $('.pageBt').eq(currentPage-1).addClass('addPage');
    }

나머지 10페이지가 안되는 페이지를 정리한다. if 조건문을 사용한다.
rearPage > totPage 가 될 때 rearPage=totPage 같게 대입한다.
.notice-page-number>spanremove 하고 irearPage보다 작을때까지 i++ 시키고 .notice-page-numberappend하여 태그를 생성한다.

5. 추가된 버튼 이벤트 문제를 해결하기 위해(2회이상 클릭 인식 안되는 부분)

이렇게 구성한다.

$(document).on('mouseenter', '.pageBt', function(){
            $('.pageBt').each(function(index){
                    $(this).on({click:function(){
                        startRecord=(Number($(this).text())-1)*list;
                        endRecord = startRecord+list;
						if(endRecord > totRecod){
                            endRecord = totRecod
                        }
                        noticeFn();
                    }})
                });
            });

6. 다음 페이지 이동

            //다음 페이지 이동
            $('.pageNextBt').on({
                click:function(){
                    startRecord += list; //list만큼 누적 
                    endRecord=startRecord+list;
					if(endRecord>totRecod){
                        startRecord=totRecod-(totRecod%list);
                        endRecord=totRecod;
                        if(startRecord==totRecod){
                            startRecord=totRecod-list;
                            endRecord=totRecod;
                            return false;
                        }
                    }
                    noticeFn();
                }
            });
            $('.pagePrevBt').on({click:function(){
                    startRecord -= list;
                    endRecord=startRecord+list;
                    if(startRecord<0){
                        startRecord=0;
                        endRecord=startRecord+list;
                    }
                    noticeFn();
                }
            });
        },
        error:function(){
          	console.log('error');
        }
    });
});

.pageNextBt 를 그룹메서드 click 하면 startRecord += list list만큼 누적된다.
endRecord=startRecord+list 페이지의 끝번호 ex) 1+5 = 6 번째 부터 된다.

if(endRecord>totRecod){
  	startRecord=totRecod-(totRecod%list);
  	endRecord=totRecod;
  if(startRecord==totRecod){
    startRecord=totRecod-list;
    endRecord=totRecod;
    return false;
  }

이렇게 구성을 하고나서 마지막은

error:function(){
            console.log('error');
        }

에러가 발생하면 console.log에 나타나게 한다.


나의 생각 정리

아직까지는 완벽하게 이해했다고 보기가 어렵다. 어떻게 구성이 됐고 어떤원리로 게시판이 만들어지는가에 대해 배운 시간이라고 생각한다. 앞으로 스스로 생각하여 코드를 짜고 작성하는 날이 오기를 바란다.

문제해결

지금은 페이지 next , prev 버튼을 누르면 한칸씩 이동이 된다. 보통 웹페이지에 다음이나 이전버튼을 누르면 1칸씩 움직이는거 보단 한 줄씩 이동이 된다. 그래서 다음에 시간이 된다면 그부분을 수정해보고 싶고 나만의 방법으로 구성해 보고싶다.

0개의 댓글