FE/javascript(jQuery)

JQuery 게시판 페이지 (핸들바, ajax의 json데이터 사용, 벡틱 기호 ``)

시녜's 2023. 2. 11. 12:53

< html >

 # part1  - 웹 페이지 틀 & 메뉴 생성

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.1/handlebars.js"></script>
    <link rel="stylesheet" href="../style.css"/>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시글목록</title>   
</head>
<body>
    <div id="page">
        <div id="header">
            <img src="http://via.placeholder.com/960x150">
        </div>
        <div id="menu">
            <span><a href="ex01.html">게시글</a></span>
            <span><a href="ex02.html">앨범</a></span>
            <span><a href="ex03.html">할일</a></span>
            <span><a href="ex04.html">사진</a></span>
        </div>
        <div id="content">
            <h1>게시글목록</h1>

  head태그 부분

1. 제이쿼리 사용하기 위해 CDN 서버 연결
2. 제이쿼리 핸들바 라이브러리 사용하기 위해 연결
3. 만들어둔 css(외부파일) link 태그로 연결

 

  body태그 부분
4. div태그로 page를 생성해 전체적인 틀을 잡아준다.
5. div태그로 page안에 header, menu, content, footer를 생성해 각 영역을 구분하고 역할을 부여한다.
6. content에는 스크립트와 핸들바+ajax를 이용해 생성한 데이터가 들어간다.

7. header에 img태그로 메인 이미지 삽입

8. menu에는 span태그를 이용해 한 줄로 각 메뉴를 출력

9. content에는 h1으로 타이틀을 삽입

 

 # part2  - 첫 번째 핸들바(temp)

<table id="list"></table>
    <script id="temp" type="text/x-handlebars-template">
        <tr class="title">
            <td><input type="checkbox" id="all"></td>
            <td width="50">No.</td>
            <td width="500">제목</td>
            <td width="100">댓글</td>
        </tr>
        {{#each .}}
        <tr class="row">
            <td><input type="checkbox" class="chk"></td>
            <td style="text-align: center;" class="post_id">{{id}}</td>
            <td><div class="post_title ellipsis">{{title}}</div></td>
            <td><button class="button" post_id="{{id}}">댓글보기</button></td>
        </tr>
        {{/each}}
</script>

 

1. 스크립트에서 ajax를 통해 가져온 데이터를 table에 추가한다 (id는 list)
2. 스크립트 태그로 핸들바를 정의하여 템플릿 생성 (id는 temp)

**템플릿은 아무 곳에서나 생성해도 된다(틀만 만드는 것임. 보기 좋게 하기 위해 list밑에 script로 생성)
3. 리스트 타이틀 생성:css를 적용하기 위해  tr의 class명을 title로 부여 -> 아래 이미지에서 빨간색 선으로 표시한 부분이다

4. 출력할 데이터는 체크박스,  순번,  제목,  댓글버튼 총 네 가지이다.
5. ajax로 가져온 json타입 데이터에는 id와 title의 키값이 존재한다.
6. 핸들바의 반복문을 이용해 데이터를 순차적으로 반복 출력한다.
7. 반복문은 {{#each.}}로 시작해 {{/each}}로 끝나며 해당 tr에 class을 row로 주어 css 속성을 준다.

 

반복문 안 [row에 들어가는 4가지 데이터]

1 체크박스 class명을 chk로 부여하여 스크립트에서 체크박스 선택 함수를 생성할 때 선택자로 사용한다.
2 {{id}} ajax로 가져온 json데이터의 id키 값 출력, 핸들바를 컴파일해서 데이터를 삽입 및 바인딩하기 위해 {{ }}로 작성
class명 post_id
3 {{title}} ajax로 가져온 json데이터의 title키 값 출력, class명 post_title
4 button 태그  [댓글 보기] 버튼 반복 출력 , post_id라는 속성에 순차적으로 번호가 증가하는 {{id}}를 넣어 인덱스처럼 사용한다. 
- 스크립트에서 attr("post_id")로 불러온다.

※ {{title}}을 감싸고 있는 div에 css에서 만들어둔 ellipsis속성(글자 자름) 주기 위해 class명에 작성, post_title은 [선택항목출력] 버튼 클릭 시 체크박스로 선택된 해당열의 데이터를 출력하기 위해 부여한 클래스명이다. - attr("post_title")로 불러온다.

 # part3  - 버튼 생성

<div style="text-align: center;margin: 10px 0px;">
        <button class="button" id="prev">이전</button>
        <span id="curPage">1/20</span>
        <button class="button" id="next">다음</button>
        <button class="button" id="print">선택항목출력</button>
</div>
<hr>

 

1. 버튼을 감싸는 <div>를 생성해 안에 이전, 다음, 선택항목출력 버튼페이지 번호를 삽입한다.
2. css에서 button 디자인 만들어 둔 속성 부여하기 위해 class명에 button을 작성
3. 각각의 버튼에다 id를 부여하여 스크립트에서 선택자로 사용한다.(버튼 클릭 시 페이지 이동)

4. [  id ] 이전 prev, 다음 next, 출력 print
5.  <span>태그로 생성한 페이지번호는 id로 curpage 이름을 부여하여 스크립트에서 정의한 페이지번호를 삽입해 준다.

6. <hr>로 아래 구분선 생성

 

 # part4  - 두 번째 핸들바(temp1)

    <h1>선택항목출력</h1>
    <div id="list1"></div>
        <script id="temp1" type="text/x-handlebars-template">
            {{#each .}}
            <div>
                <h3>{{id}}:{{name}}:{{email}}</h3>
                <p>{{body}}</p>
                <hr>
            </div>
            {{/each}}
        </script>
    </div>
    <div id="footer">
    <h3>Copyright 2023. 인천아카데미 All rights reserved.</h3>
    </div>

</div> <!--page마감-->
</body>

1.  스크립트에서 ajax를 통해 가져온두 번째 데이터를 div에 추가한다 (id는 list1)
2. 스크립트 태그로 핸들바를 정의하여 두 번째 템플릿 생성 (id는 temp1)

3. ajax로 가져온 json타입 데이터에는 id와 name, email, body가 존재한다.

4. <h3> 태그에 id와 name email을 :(콜론)으로 구분해 출력하고 <p> 태그에는 body를 출력한다.

 

- 아래 footer는 페이지 하단에 보여지는 문구이다.

< Script >

 # part1  - 이전/다음 버튼 클릭 함수

var page=1;
$("#next").on("click", function(){
        page++;
        list();
    });
    
    $("#prev").on("click", function(){
        page--;
        list();
    });

1. 페이지 번호 담는 page 변수 생성 , 초기값 1로 설정(시작페이지)

2. [다음버튼]클릭 시 (버튼 id는 next) page를 1 증가시키고 리스트 함수 호출하는 이벤트 함수 생성

3. [이전버튼]클릭 시 (버튼 id는 next) page를 1 감소시키고 리스트 함수 호출하는 이벤트 함수 생성

※ 이벤트 핸들러인 .on을 사용해 클릭('click')했을 때의 동작(함수)을 처리해 준다.

 

# part 2  - 목록출력 함수 list

 

 list();
    
    function list(){
        $.ajax({
            type:"get",
            dataType:"json",
            url:"https://jsonplaceholder.typicode.com/posts",
            success:function(data){
                var start=(page-1)*5+1;
                var end=(page*5);
                var last=Math.ceil(data.length/5);
                var newData=[];
                $(data).each(function(){
                    var id=this.id;                   
                    if(id>=start && id<=end){
                        newData.push(this);
                    }
                });

 

 

※ 함수를 정의할 때는 function 함수명 함수는 정의하고 호출해야만 실행된다 -> 위에 list( );
1. $.ajax({ })를 사용해 서버에서 json샘플데이터를 가져온다 - 코드는 중괄호 안에 작성, 4가지 속성 선언
2. 데이터가 존재하는 서버의 URL을 입력해 준 후 success(성공)되었을 때 함수로 작업을 처리한다.
3. 서버의 데이터는 function(data) ->  data에 저장된다 (매개변수)
4. 데이터를 5개씩 페이징하여 출력하기 위해 데이터 시작번호~끝번호를 start와 end 변수로 정의해 준다 (1~5, 6~10..)
5. last변수는 마지막 페이지를 의미한다 (전체 데이터가 들어간 data의 크기를 5개로 나눈 값)
Math.ceil( )로 나머지가 있을 경우 숫자를 올림해 last 페이지를 1 증가시킨다.
6. 데이터를 5개씩 나눠 담아주기 위해 newData 배열 생성
7. 전체데이터(data)를 제이쿼리의 반복문 each( )를 통해 페이징 작업을 반복 실행
8. id 변수에 this로 data의 id(키값)를 선택해서 담아준다 (id는 1~데이터 개수만큼 들어가 있어 페이지 번호로 사용)
※  this는 (data) 데이터 배열의 각 항목을 차례로 참조한 값을 의미한다.
9. id가 start 이상이면서 end 이하일 때 반복하여 newData에 데이터(this)를 삽입 -> 총 5개씩 나눠 들어감

start와 end는 page값을 이용해 구했기 때문에 page의 숫자에 따라 값이 변해 페이지별로 이미지가 바뀌어 들어간다.

    var temp=Handlebars.compile($("#temp").html());
    $("#list").html(temp(newData));

10. temp변수에 핸들바를 이용해 만든 템플릿(id가 temp)의 html값을 컴파일하여 담아준다

11. 테이블(id가 list)에 만들어둔 temp틀에다 newData를 넣어 목록을 출력한다.

※ 그냥 data를 넣으면 전체 데이터가 출력되므로 5개씩 나눠 담은 newData를 넣어야 한다.

                if(page==1) $("#prev").prop("disabled", true);
                else $("#prev").prop("disabled", false);
                
                if(page==last) $("#next").prop("disabled", true);
                else $("#next").prop("disabled", false);

                $("#curPage").html(`${page} / ${last}`);
            }
        })
    }

 

12. 위에서 만든 페이지 이전/다음 버튼에 1페이지~마지막 페이지까지만 이동하도록 조건문 생성

13. 1페이지일 경우 이전버튼 (id가 prev) disabled속성으로 작동정지, 그 외에는 작동하도록 해준다

14.  마지막페이지(last)인 경우 (id가 next) disabled속성으로 작동정지, 그 외에는 작동하도록 해준다

15. 페이지 번호 삽입하기 위해 만들어둔 span에(id가 curPage) .html로 현재페이지 번호와 마지막 페이지를 넣어준다.

※ page번호는 버튼 누를 때마다 자동으로 변경, last는 고정이다

`` 백틱 기호를 사용해 변수를 연산자(+) 없이 작성하며 변수는 ${ } 플레이스 홀더 안에 작성해 준다.

▶ 벡틱(`)
- grave accent 억음부호로backtick 또는 backquoto등의 이름으로 불림

- 백틱 안 변수 선택 시 ${변수명}으로 삽입 (이와 같은 형태를 플레이스홀더라고 한다.)
- 따옴표로 구분해서 (+) 연산자 쓰지 않아도 돼 작성이 편리하다.

※ '' (작은따옴표) 안에 위와 같이 입력하게 되면 전체가 텍스트로 인식된다.
내장된 표현식을 사용하는 것을 허용하며 여러 줄로 이루어진 문자열과 문자를 연결해 줄 바꿈 기호(\n)없이 쓸 수 있다. 
※ 벡틱을 사용해 문자열을 표현하는 것을 템플릿 리터럴이라고 함

 

  # part3  - 체크박스 선택 함수 생성

//전체선택 체크박스를 클릭한 경우
    $("#list").on("click", "#all", function(){
        if($(this).is(":checked")) $("#list .chk").prop("checked", true);
        else $("#list .chk").prop("checked", false);
    });

//각 행의 체크박스를 클릭한 경우
    $("#list").on("click", ".chk", function(){
        var all=$("#list .chk").length;
        var chk=$("#list .chk:checked").length;
        if(all==chk) $("#list #all").prop("checked", true);
        else $("#list #all").prop("checked", false);
    });

1. 제목표시줄에 생성한 체크박스(id가 all)를 선택하려면 상위 테이블(id가 list)에서 찾아야 한다.

2. is( )메소드로 해당 요소 this(all)가 checked 되어 있는지 검사하여 true일 경우 하위 체크박스(class명이 chk)의 속성을 모두 체크

3. 아닌 경우 false로 하위 체크박스를 해제해 준다.

▶ jQuery의 is() 메서드
현재 선택된 요소가 지정된 조건을 만족하는지 확인하는 메서드.
-> 특정요소가 특정 선택자, 클래스, 아이디 또는 속성값을 가지는지 검사할 수 있다

예) $("p") is(". selected")는 현재 선택된 'p'요소 중에 selected 클래스를 가지고 있는 요소가 있는지 확인

4. 각 행에 있는 체크박스(class가 chk)를 선택하기 위해 상위테이블(id가 list)을 참조

5. all변수에 전체 chk의 개수를 length() 메서드로 구해 담아준다.

6. chk변수에 체크된 chk의 개수를 담아준다.

7. chk와 all의 값이 같을 때 (전체 체크박스가 선택되어 있는 경우) 타이틀의 박스 속성을 체크로 변경(id가 all)

8. 아닌 경우에는 false로 해제해 준다.

 

 # part4   - 선택한 게시글 출력 함수

 $("#print").on("click", function(){
        var chk=$("#list .chk:checked").length;
        if(chk==0) {
            alert("출력한 항목을 선택해주세요!");
            return;
        }else{
            $("#list1").html("");
            $("#list .chk:checked").each(function(){
                var row=$(this).parent().parent();
                var id=row.find(".post_id").html();
                var title=row.find(".post_title").html();
                var str=`<h3>${id}:${title}</h3>`;
                $("#list1").append(str);
            });
        }
        $("#list .chk").prop("checked", false);
        $("#list #all").prop("checked", false);
    });

1. 이벤트 핸들러인. on을 사용해 [선택항목출력] 버튼(id가 print)클릭('click')했을 때의 목력을 출력할 동작(함수)을 처리해 준다.

2. 선택되어 있는 체크박스 열(class가 chk)의 개수를 구해 chk변수에 담아준다.
3. 선택된 항목이 없을 경우(chk==0) 알림 창을 띄우고 return 해준다. 

4. 누적 작업을 방지하기 위해 출력할 공간(id가 list1)을 초기화한다.

5. this(chk지칭)로 parent() 메서드를 두 번 사용해 상위요소로 올라가 td->tr(class명 row)을 선택해 row변수에 담아준다.

※ 객체는 동일한 위치에서만 찾을 수 있다.

6. 올라간 행(row)에서 클래스가 post_id인 값과 post_title인 값을 html() 메서드로  가져와 각각 id, title변수에 담아준다.

7. id:title형태로 h3태그에 담아 출력하기 위해 str변수에 담아준 뒤 append() 메서드로 두 번째 템플릿(id가 list1)에다 출력한다.

8. 출력한 다음 체크박스를 초기화해 주기 위해 타이틀과 각행의 체크박스의 속성을 false로 바꿔준다.

 

 # part5  - 댓글보기 출력 함수

 $("#list").on("click", ".row .button", function(){
        var post_id=$(this).attr("post_id");
        var newData=[];
        $.ajax({
            type:"get",
            dataType:"json",
            url:"https://jsonplaceholder.typicode.com/comments",
            success:function(data){
                $(data).each(function(){
                    var postId=this.postId;
                    if(post_id==postId) newData.push(this);
                });
                var temp1=Handlebars.compile($("#temp1").html());
                $("#list1").html(temp1(newData));
            }
        });
    });

1. 해당 테이블(id가 list)에 on이벤트의 click함수를 생성해 안에서 버튼(클래스명 row의 button)을 선택해 준다.

2. [댓글보기] 버튼에 post id속성에다 핸들바로 {{id}}를 반복 출력해 부여한 인덱스값을 가져와 post_id변수에 담아준다. 

※누른 행의 값만 받아올 것이기 때문에 this선택자, attr() 속성 메서드 사용

3. 누른 해당 게시물에 존재하는 댓글은 값이 여러 개이기 때문에 newData라는 배열 변수를 선언해 사용한다.

4. A.jax를 이용해 댓글 샘플 데이터(json)를 해당 url 서버에서 받아온다. 

5. data가 성공적으로 들어오면 제이쿼리의 each() 메서드를 사용해 json에 존재하는 postId키postId변수에 담아준다.

6. post_id와 postId변수에 들어간 값이 같은 경우 newData배열에 this를 담아준다.

post_id에는 게시물 ajax데이터의 id키값이 순번대로 들어가 있고 postId에는 댓글 ajax데이터의 id키 값이 들어가 있다.

7. 만들어둔 핸들바 템플릿(id명 temp1)을 컴파일하여 temp1 변수에 담아준다

8. temp1의 newData를 html() 메서드를 이용해 선택항목출력 공간에 댓글을 출력해 준다.(id가 list1)

※ 하단 출력공간은 댓글보기/선택항목출력 두 함수가 공통적으로 사용하는 공간이다.

※ 해당 [댓글보기] 버튼을 누를 때마다 index값이 바뀌기 때문에 this의 값이 바뀌어 데이터도 자동으로 변경되어 출력된다.

 

<Result>