본문으로 바로가기

권한이 있는 경우 (본인 작성 글)

권한이 없는 경우 (다른 사용자 작성 글, 비로그인 시)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>글상세보기</title>
    <link rel="stylesheet" href="../css/common.css" />
    <link rel="stylesheet" href="../css/header.css" />
</head>
<body>
         <!-- 헤더 섹션과 네비 영역 -->
         <header>
            <nav class="nav-container">
              <div class="nav-item">
                <span class="menu-link" id="board">게시판</span>
              </div>
              <div class="nav-item" id="authLinks">
                <span class="menu-link" id="signIn">로그인</span>
                <span class="menu-link" id="signUp">회원가입</span>
              </div>
            </nav>
          </header>

          <main class="content-wrapper">
            <section class="form-title">
                <h1>상세보기 화면 by JS</h1>
            </section>
    
            <section>
                <table>
                    <tr>
                        <th>제목</th>
                        <td>
                            <input type="text" class="inputs title" readonly="true" id="title" >
                        </td>
                    </tr>
                    <tr>
                        <th>작성자</th>
                        <td>
                            <input type="text" class="inputs username" readonly="true" id="username">
                        </td>
                    </tr>
                    <tr>
                        <th>내용</th>
                        <td>
                            <div class="img-box" id="imgBox"></div>
                            <pre id="content" class="content"></pre>
                        </td>
                    </tr>
                </table>
    
                <div class="btn-area">
                    <button type="button" class="btn update-button" >수정</button>
                    &nbsp;&nbsp;
                    <button type="button" class="btn delete-button" >삭제</button>
                </div>
    
            </section>
          
        </main>
          
          <script src="../js/header.js"></script>
          <script src="../js/boardDetail.js"></script>
</body>
</html>

사전 기반 지식

<aside> 💡 window.location 객체의 유용한 속성

  • window.location.href: 전체 URL (https://example.com/path/to/page?query=123)
  • window.location.protocol: 프로토콜 (https:)
  • window.location.host: 호스트 (example.com)
  • window.location.pathname: 경로 (/path/to/page)
  • window.location.search: 쿼리 스트링 (?query=123)
  • window.location.hash: 해시 값 (#hash) </aside>

boardDetail.js 파일

// 1. 해당 게시글에 대한 정보를 가져오기 
// 2. DOM API 
// 3. 삭제, 수정 버튼 활성화 여부 (권한 확인)
// 4. 삭제 기능만들기, 수정 기능 만들기 (권한 확인)

document.addEventListener('DOMContentLoaded', function() {

    // 1. 쿼리스트링 경로에 정보를 추출 방법 
    const urlParams = new URLSearchParams(window.location.search);
    // console.log(urlParams.get("id"));
    // 2. path , http:naver.com:8080/path/to/page
    // window.location.pathname; 경로 추출 가능   -->  /path/to/page
    const postId = urlParams.get('id');
    const storedBoardList = JSON.parse(localStorage.getItem('boardList'));
    const user = JSON.parse(localStorage.getItem('user')); // 현재 사용자 정보 가져오기 
    let currentPost; 

    if(storedBoardList && postId ) {
        currentPost = null;

        for( let i = 0; i < storedBoardList.length; i++) {
            let post = storedBoardList[i];
            if(post.id ===  parseInt(postId)) {
                currentPost = post;
                break;
            }
        }
        if(!currentPost) {
            alert('해당 게시글을 찰을 수 없습니다.');
            location.href = 'board-list.html';
        }
    } // end of if 

    // 2. DOM API 사용 
    const titleElement = document.querySelector("#title");
    const usernameElement = document.querySelector("#username");
    const imgBoxElement = document.querySelector("#imgBox");
    const contentElement = document.querySelector("#content");

    if(currentPost != null) {
        titleElement.value = currentPost.title; 
        usernameElement.value = currentPost.username; 
        
        // 사용자가 등록한 이미지 뿌려주기 
        if(currentPost.imgData != null) {
            const imgElement  =  document.createElement('img'); // JS 코드로 이미지 태그 생성 
            imgElement.src = currentPost.imgData;
            // 스타일도 설정하고자 한다면 
            imgElement.style.width = "100%";
            imgElement.style.heigh = "auto";

            // 부모태그로 사용 
            imgBoxElement.appendChild(imgElement);
        }
    }

    // 3. 사용자자  권한 확인 
    const deleteButton = document.querySelector(".delete-button");
    const updateButton = document.querySelector(".update-button");

    if(user &&  currentPost.username === user.username) {
        deleteButton.style.display = "block";
        updateButton.style.display = "block";
    } else {
        deleteButton.style.display = "none";
        updateButton.style.display = "none";
    } // end of if 

    // 삭제 기능 구현 (권한 확인)
    deleteButton.addEventListener("click", function() {
        if(confirm("정말 삭제하겠습니까?")) {
            const updateBoardList = [];
            for(let i = 0; i < storedBoardList.length; i++) {
                if(storedBoardList[i].id !== parseInt(postId)) {
                    updateBoardList.push(storedBoardList[i]);
                }
            }
            localStorage.setItem('boardList', JSON.stringify(updateBoardList));
            alert('게시글이 정상 삭제 되었습니다.');
            location.href = 'board-list.html';
        }
    });

    // 수정 화면 이동 처리 (권한 확인) -- 도전과제 

});

8. JavaScript boardDetail.js 상세보기 화면 만들기

권한이 있는 경우 (본인 작성 글)

권한이 없는 경우 (다른 사용자 작성 글, 비로그인 시)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>글상세보기</title>
    <link rel="stylesheet" href="../css/common.css" />
    <link rel="stylesheet" href="../css/header.css" />
</head>
<body>
         <!-- 헤더 섹션과 네비 영역 -->
         <header>
            <nav class="nav-container">
              <div class="nav-item">
                <span class="menu-link" id="board">게시판</span>
              </div>
              <div class="nav-item" id="authLinks">
                <span class="menu-link" id="signIn">로그인</span>
                <span class="menu-link" id="signUp">회원가입</span>
              </div>
            </nav>
          </header>

          <main class="content-wrapper">
            <section class="form-title">
                <h1>상세보기 화면 by JS</h1>
            </section>
    
            <section>
                <table>
                    <tr>
                        <th>제목</th>
                        <td>
                            <input type="text" class="inputs title" readonly="true" id="title" >
                        </td>
                    </tr>
                    <tr>
                        <th>작성자</th>
                        <td>
                            <input type="text" class="inputs username" readonly="true" id="username">
                        </td>
                    </tr>
                    <tr>
                        <th>내용</th>
                        <td>
                            <div class="img-box" id="imgBox"></div>
                            <pre id="content" class="content"></pre>
                        </td>
                    </tr>
                </table>
    
                <div class="btn-area">
                    <button type="button" class="btn update-button" >수정</button>
                    &nbsp;&nbsp;
                    <button type="button" class="btn delete-button" >삭제</button>
                </div>
    
            </section>
          
        </main>
          
          <script src="../js/header.js"></script>
          <script src="../js/boardDetail.js"></script>
</body>
</html>

사전 기반 지식

<aside> 💡 window.location 객체의 유용한 속성

  • window.location.href: 전체 URL (https://example.com/path/to/page?query=123)
  • window.location.protocol: 프로토콜 (https:)
  • window.location.host: 호스트 (example.com)
  • window.location.pathname: 경로 (/path/to/page)
  • window.location.search: 쿼리 스트링 (?query=123)
  • window.location.hash: 해시 값 (#hash) </aside>

boardDetail.js 파일

// 1. 해당 게시글에 대한 정보를 가져오기 
// 2. DOM API 
// 3. 삭제, 수정 버튼 활성화 여부 (권한 확인)
// 4. 삭제 기능만들기, 수정 기능 만들기 (권한 확인)

document.addEventListener('DOMContentLoaded', function() {

    // 1. 쿼리스트링 경로에 정보를 추출 방법 
    const urlParams = new URLSearchParams(window.location.search);
    // console.log(urlParams.get("id"));
    // 2. path , http:naver.com:8080/path/to/page
    // window.location.pathname; 경로 추출 가능   -->  /path/to/page
    const postId = urlParams.get('id');
    const storedBoardList = JSON.parse(localStorage.getItem('boardList'));
    const user = JSON.parse(localStorage.getItem('user')); // 현재 사용자 정보 가져오기 
    let currentPost; 

    if(storedBoardList && postId ) {
        currentPost = null;

        for( let i = 0; i < storedBoardList.length; i++) {
            let post = storedBoardList[i];
            if(post.id ===  parseInt(postId)) {
                currentPost = post;
                break;
            }
        }
        if(!currentPost) {
            alert('해당 게시글을 찰을 수 없습니다.');
            location.href = 'board-list.html';
        }
    } // end of if 

    // 2. DOM API 사용 
    const titleElement = document.querySelector("#title");
    const usernameElement = document.querySelector("#username");
    const imgBoxElement = document.querySelector("#imgBox");
    const contentElement = document.querySelector("#content");

    if(currentPost != null) {
        titleElement.value = currentPost.title; 
        usernameElement.value = currentPost.username; 
        
        // 사용자가 등록한 이미지 뿌려주기 
        if(currentPost.imgData != null) {
            const imgElement  =  document.createElement('img'); // JS 코드로 이미지 태그 생성 
            imgElement.src = currentPost.imgData;
            // 스타일도 설정하고자 한다면 
            imgElement.style.width = "100%";
            imgElement.style.heigh = "auto";

            // 부모태그로 사용 
            imgBoxElement.appendChild(imgElement);
        }
    }

    // 3. 사용자자  권한 확인 
    const deleteButton = document.querySelector(".delete-button");
    const updateButton = document.querySelector(".update-button");

    if(user &&  currentPost.username === user.username) {
        deleteButton.style.display = "block";
        updateButton.style.display = "block";
    } else {
        deleteButton.style.display = "none";
        updateButton.style.display = "none";
    } // end of if 

    // 삭제 기능 구현 (권한 확인)
    deleteButton.addEventListener("click", function() {
        if(confirm("정말 삭제하겠습니까?")) {
            const updateBoardList = [];
            for(let i = 0; i < storedBoardList.length; i++) {
                if(storedBoardList[i].id !== parseInt(postId)) {
                    updateBoardList.push(storedBoardList[i]);
                }
            }
            localStorage.setItem('boardList', JSON.stringify(updateBoardList));
            alert('게시글이 정상 삭제 되었습니다.');
            location.href = 'board-list.html';
        }
    });

    // 수정 화면 이동 처리 (권한 확인) -- 도전과제 

});