보안 전공생의 공부

게시판 만들기 / front end + scope + breadcrumb +bootstrap grid 본문

WEB/Node

게시판 만들기 / front end + scope + breadcrumb +bootstrap grid

수잉 2021. 10. 19. 16:04
// public/js/script.js

$(function(){
    function get2digits (num){
      return ('0' + num).slice(-2);
    }
  
    function getDate(dateObj){
      if(dateObj instanceof Date)
        return dateObj.getFullYear() + '-' + get2digits(dateObj.getMonth()+1)+ '-' + get2digits(dateObj.getDate());
    }
  
    function getTime(dateObj){
      if(dateObj instanceof Date)
        return get2digits(dateObj.getHours()) + ':' + get2digits(dateObj.getMinutes())+ ':' + get2digits(dateObj.getSeconds());
    }
  
    function convertDate(){
      $('[data-date]').each(function(index,element){
        const dateString = $(element).data('date');
        if(dateString){
          const date = new Date(dateString);
          $(element).html(getDate(date));
        }
      });
    }
  
    function convertDateTime(){
      $('[data-date-time]').each(function(index,element){
        const dateString = $(element).data('date-time');
        if(dateString){
          const date = new Date(dateString);
          $(element).html(getDate(date)+' '+getTime(date));
        }
      });
    }
  
    convertDate();
    convertDateTime();
  });

client의 브라우저에서 사용하게 될 js이다. 

function convertDate(){

  $('[data-date]').each(function(index,element){

    var dateString = $(element).data('date');

    if(dateString){

      var date = new Date(dateString);

     $(element).html(getDate(date));

    }

  });

}

html element 중 data-date가 있는 것을 찾아

data-date에 날짜 데이터가 있으면, 해당 데이터를 년-월-일 형태로 변환해 element의 텍스트 데이터로 넣는다.

웹페이자상에서 이용자가 xxxx-xx-xx 글짜를 보게 된다.

function convertDateTime(){

 $('[data-date-time]').each(function(index,element){

    var dateString = $(element).data('date-time');

    if(dateString){

      var date = new Date(dateString);

      $(element).html(getDate(date)+' '+getTime(date));

    }

  });

}

data-date-time을 찾아서 년-월-일 시:분:초 형태로 변환해 출력한다.

 

script.js는 날짜/시간을 원하는 형태(format)로 만들기 위해 만든 것이다.

js에서 제공하는 기본 형태의 날짜/시간을 원하는 형태로 변환하기 위해서는

moment 같은 외부 라이브러리를 사용하거나, 위처럼 해당 함수를 직접 만들어야한다.

 

이 js파일을 적용하기 위해

head.ejs 파일에 다음 코드를 추가한다.

<script src="/js/script.js"></script>

 

<!-- views/posts/index.ejs -->

<!DOCTYPE html>
<html>
  <head>
    <%- include('../partials/head') %>
  </head>
  <body>
    <%- include('../partials/nav') %>

    <div class="container mb-3">

      <h2 class="mb-3">Board</h2>

      <table class="board-table table table-sm border-bottom">

        <thead class="thead-light">
          <tr>
            <th scope="col">Title</th>
            <th scope="col" class="date">Date</th>
          </tr>
        </thead>

        <tbody>
          <% if(posts == null || posts.length == 0){ %>
            <tr>
              <td colspan=2> 보여줄게 없쪙 ㅠ </td>
            </tr>
          <% } %>
          <% posts.forEach(function(post) { %>
            <tr>
              <td>
                <a href="/posts/<%= post._id %>"><div class="ellipsis"><%= post.title %></div></a>
              </td>
              <td class="date">
                <span data-date="<%= post.createdAt %>"></span>
              </td>
            </tr>
          <% }) %>
        </tbody>

      </table>

      <div>
        <a class="btn btn-primary" href="/posts/new">New</a>
      </div>

    </div>
  </body>
</html>

<tr>

<th scope="col">Title</th>

<th scope="col" class="date">Date</th>

</tr>

table에 scope="col"과 scope="row"을 사용하는 이유는, 시각장애인이 웹페이지를 보기 위해 사용하는 스크린리더기 프로그램을 위함에 있다. 시각장애인은 이 프로그램을 사용하여 테이블에 대한 정보를 청각으로 얻는다. scope="col"scope="row"을 작성하면 테이블의 데이터를 인식하고 읽는 순서를 결정할 수 있다.

thead 영역에 해당하는 Title과 Date에 scope="col"(열↓)을 붙이면 다음과 같은 table이 된다.

Title Date
td1 td2

스크린 리더기가 읽어주는 방향은 Title td1 -> Date td2 가 된다.

 

만약 scope="row"(행→)가 있는 table이 있다고 하면,

<tr>

  <th scope="col">No</th>

  <th scope="col">Title</th>

  <th scope="col" class="date">Date</th>

</tr>

No 밑에 부분에 scope="row"(행→)을 사용해보자.

<tr>

  <th scope="row">1</th>

  <th scope="row">2</th>

</tr>

No Title Date
1 td1 td2
2 td3 td4

스크린 리더기가 읽어주는 방향은 No 2 -> Title td3 -> Date td4 가 된다.

 

즉, scope를 이용하여 제목에서 흘러가는 방향을 잡아주는 것이라고 볼 수 있다.

 

(참조 : https://jowook.tistory.com/61)

 

 

 

<% if(posts == null || posts.length == 0){ %> -> java code

  <tr>

<tdcolspan=2> 보여줄게 없쪙 ㅠ </td>-> html code

  </tr>

<% } %>-> java code

이 부분을 보면 처음과 if구문이 <% %>로 감싸져 있는 것을 확인할 수 있다.

<% %>(JSP script tag 중 scriptlet tag)로 감싸져 있는 부분은 JSP(JavaServer Pages)코드 중 java를 구현한 부분이다.

 

· JSP(JavaServer Pages) : HTML 코드에 JAVA 코드를 넣어 동적 웹페이지를 생성하는 웹어플리케이션 도구이다.

  - JSP가 실행되면 자바 서블릿(servlet)으로 변환되며 웹 어플리케이션 서버에서 동작한다.

· 스크립트릿 태그(scriptlet tag) : 클라이언트의 요청에 대해 서비스하는 동적 코드(java 실행구문)을 작성하기 위한 태그

 - 태그 내의 코드는 서블릿으로 변환시 _jspService()의 로컬 코드로 삽입된다.

 

더 자세한 사항은 참조글로 ...쓰기 귀찬...^^

(참조 : https://gap85.tistory.com/entry/%EC%95%A1%EC%85%98%ED%83%9C%EA%B7%B8

https://javacpro.tistory.com/43)

 

 

 <span data-date="<%= post.createdAt %>"></span>

<span>태그의 요소에 data-date가 사용된 것을 확인 할 수 있다. 

public/js/script에 의해 post.createdAt이 년-월-일 형태로 출력된다.

 

<!-- views/posts/new.ejs -->

<!DOCTYPE html>
<html>
  <head>
    <%- include('../partials/head') %>
  </head>
  <body>
    <%- include('../partials/nav') %>

    <div class="container mb-3">

      <nav aria-label="breadcrumb"> <!-- 1 -->
        <ol class="breadcrumb p-1 pl-2 pr-2">
          <li class="breadcrumb-item"><a href="/">Home</a></li>
          <li class="breadcrumb-item"><a href="/posts">Board</a></li>
          <li class="breadcrumb-item active" aria-current="page">New Post</li>
        </ol>
      </nav>

      <form action="/posts" method="post">

        <div class="form-group">
          <label for="title">Title</label>
          <input type="text" id="title" name="title" value="" class="form-control">
        </div>
        
        <div class="form-group">
          <label for="body">Body</label>
          <textarea id="body" name="body" rows="5" class="form-control"></textarea>
        </div>

        <div>
          <a class="btn btn-primary" href="/posts">Back</a>
          <button type="submit" class="btn btn-primary">Submit</button>
        </div>

      </form>

    </div>
  </body>
</html>

· Breadcrumb : 탐색 계층 구조 내에서 현재 페이지의 위치를 나타낸다. 이때 사용되는 구분자(/)는 CSS에 의해 자동으로 설정된다.

  [TMI] 빵부스러기로 표시한 길을 뜻하며, 헨젤과 그레텔에서 가져온 용어이다.

(참조 : https://getbootstrap.com/docs/4.4/components/breadcrumb/ )

 

<실행결과>

/posts/new

Home을 클릭하면 -> http://localhost:3000/ 로 이동

Board을 클릭하면 -> http://localhost:3000/posts 로 이동

 

<!-- views/posts/show.ejs -->

<!DOCTYPE html>
<html>
  <head>
    <%- include('../partials/head') %>
  </head>
  <body>
    <%- include('../partials/nav') %>

    <div class="container mb-3">

      <nav aria-label="breadcrumb">
        <ol class="breadcrumb p-1 pl-2 pr-2">
          <li class="breadcrumb-item"><a href="/">Home</a></li>
          <li class="breadcrumb-item"><a href="/posts">Board</a></li>
          <li class="breadcrumb-item active" aria-current="page"><%= post.title %></li>
        </ol>
      </nav>

      <div class="card">
        <h5 class="card-header p-2"><%= post.title %></h5>
        <div class="row">

          <div class="col-md-7 col-lg-8 col-xl-9 order-sm-2 order-md-1">
            <div class="post-body p-2"><%= post.body %></div>
          </div>

          <div class="col-md-5 col-lg-4 col-xl-3 order-sm-1 order-md-2">
            <div class="post-info card m-2 p-2"> 
              <div><span>Created</span> : <span data-date-time="<%= post.createdAt %>"></span></div>
              <% if(post.updatedAt) { %>
                <div><span>Updated</span> : <span data-date-time="<%= post.updatedAt %>"></span></div>
              <% } %>
            </div>
          </div>

        </div>
      </div>

      <div class="mt-3">
        <a class="btn btn-primary" href="/posts">Back</a>
        <a class="btn btn-primary" href="/posts/<%= post._id %>/edit">Edit</a>
        <form action="/posts/<%= post._id %>?_method=delete" method="post" class="d-inline">
          <a class="btn btn-primary" href="javascript:void(0)" onclick="confirm('Do you want to delete this?')?this.parentElement.submit():null;">Delete</a>
        </form>
      </div>

    </div>
  </body>
</html>

<div class="container mb-3">

bootstrap은 콘텐츠를 감싸는 wrapping요소(container)을 포함해야한다.

그리드 시스템의 필수요소이다.

 

<div class="row">

그리드 레이아웃을 구성 시에는 row(행→)먼저 배치해야 한다.

 

<div class="col-md-7 col-lg-8 col-xl-9 order-sm-2 order-md-1">

<div class="col-md-5 col-lg-4 col-xl-3 order-sm-1 order-md-2">

그리고 행 안에 col-*-*(열↓)을 필요한 갯수만큼 배치한다.

콘텐츠는 col-*-* 내에 배치한다.

 

- 첫 번째 *에는 xs,sm.md.lg 중 하나를 지정한다.

grid option (출처 : https://poiemaweb.com/bootstrap-grid-system )

- 두번째 *에는 1~12까지의 숫자 중 하나를 지정한다 (bootstrap의 그리드 시스템은 12열까지 지원한다)

  col-md-7은 화면 크기가 보통일 때, 행의 너비의 7/12를 열의 너비로 한다는 의미이다.

  col-md-5는 화면 크기가 보통일 때, 행의 너비의 5/12를 열의 너비로 한다는 의미이다.

  두번째 *의 합이 12가 되며, 행의 너비를 꽉 채우게 된다.

 

(참조 : https://poiemaweb.com/bootstrap-grid-system)

 

<div><span>Created</span> : <span data-date-time="<%= post.createdAt %>"></span></div>

<% if(post.updatedAt) { %>

  <div><span>Updated</span> : <span data-date-time="<%= post.updatedAt %>"></span></div>

<% } %>

data-date-time이 Created : 와 Updated : 옆에 <span>요소에서 사용되었다.각각의 시간이 년-월-일 시:분:초 형태로 출력된다.

 

<실행결과>

show 실행결과
edit 후 Updated 날짜가 추가됨

 

<!-- views/posts/edit.ejs -->

<!DOCTYPE html>
<html>
  <head>
    <%- include('../partials/head') %>
  </head>
  <body>
    <%- include('../partials/nav') %>

    <div class="container mb-3">

      <nav aria-label="breadcrumb">
        <ol class="breadcrumb p-1 pl-2 pr-2">
          <li class="breadcrumb-item"><a href="/">Home</a></li>
          <li class="breadcrumb-item"><a href="/posts">Board</a></li>
          <li class="breadcrumb-item"><a href="/posts/<%= post._id %>"><%= post.title %></a></li>
          <li class="breadcrumb-item active" aria-current="page">Edit Post</li>
        </ol>
      </nav>

      <form action="/posts/<%= post._id %>?_method=put" method="post">

        <div class="form-group">
          <label for="title">Title</label>
          <input type="text" id="title" name="title" value="<%= post.title %>" class="form-control">
        </div>

        <div class="form-group">
          <label for="body">Body</label>
            <textarea id="body" name="body" rows="5" class="form-control"><%= post.body %></textarea>
        </div>

        <div>
          <a class="btn btn-primary" href="/posts/<%= post._id %>">Back</a>
          <button type="submit" class="btn btn-primary">Submit</button>
        </div>

      </form>

    </div>
  </body>
</html>

<form action="/posts/<%= post._id %>?_method=put" method="post">

form actiondp ?_method=put 을 넣으면

//index.js

const methodOverride = require('method-override')

app.use(methodOverride('_method'));

에 의해 app.put이 HTTP request를 받을 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

Comments