728x90
반응형
[JavaScript] 29. JavaScript를 사용한 글쓰기 기능 만들기
1. boardList.js
// 샘플 데이터 입력
const sampleBoardList = [
{
id: 1,
title: "첫번째 게시글",
content: "첫번째 게시글에 내용 입니다.",
username: "홍길동",
today: "2024.08.25",
count: 5,
},
{
id: 2,
title: "두번째 게시글",
content: "두번째 게시글에 내용 입니다.",
username: "이몽룡",
today: "2024.08.25",
count: 5,
},
{
id: 3,
title: "세번째 게시글",
content: "세번째 게시글에 내용 입니다.",
username: "성춘향",
today: "2024.08.25",
count: 14,
},
{
id: 4,
title: "네번째 게시글",
content: "네번째 게시글에 내용 입니다.",
username: "변학도",
today: "2024.08.25",
count: 21,
},
{
id: 5,
title: "다번째 게시글",
content: "다번째 게시글에 내용 입니다.",
username: "심청",
today: "2024.08.25",
count: 51,
},
];
//localStorage.setItem('boardList', JSON.stringify(sampleBoardList));
document.addEventListener("DOMContentLoaded", function () {
// DOM 접근
const boardContainer = document.querySelector(".board-content-box"); // 컨텐트를 넣을 Element 선택
const writeButton = document.querySelector(".btn"); // 글쓰기 버튼 Element 선택
const paginationContainer = document.querySelector(".num-box");
// 로컬 스토리지에서 게시글 목록 가져오기
const storedBoardList = JSON.parse(localStorage.getItem("boardList"));
// 게시글 목록을 내림차수능로 정렬하기
if (storedBoardList) {
storedBoardList.reverse();
}
// 페이징 처리 필요한 변수
let currentPage = 0;
const limit = 2; // 한 페이지당 게시글 수
loadPosts(currentPage);
// 게시글을 로드 하는 함수
function loadPosts(page) {
const offset = page * limit;
const end = offset + limit;
let postElements = ""; // 게시긁 HTML 요소을 저장할 변수
// 방어적 코드 작성
if (storedBoardList != null && storedBoardList.length > 0) {
// 반복문을 사용 ()
for (let i = offset; i < end && i < storedBoardList.length; i++) {
postElements += `<div class="board" data-id=${storedBoardList[i].id}>
<div class="board-1">${i + 1}</div>
<div class="board-2">${storedBoardList[i].title}</div>
<div class="board-3">${storedBoardList[i].username}</div>
<div class="board-4">${storedBoardList[i].today}</div>
<div class="board-5">${storedBoardList[i].count}</div>
</div>`;
}
boardContainer.innerHTML = postElements; // 게시글 컨테이너에 HTML 추가
// 페이지 네이션 생성 하기
createPagination(storedBoardList, page);
} else {
// 게시글이 없는 경우 메세지 표시
boardContainer.innerHTML = '<div class="no-list" style="text-align:center; margin-top:20px"> 조회된 게시글이 없습니다 </div>';
}
}
// 페이지 네이션 생성 함수 선언
function createPagination(boardList, currentPage) {
// 전체 게시글 수 , 한 페이장 보여질 게시글 수
const totalPosts = boardList.length; // 전체 게시글 수
const totalPages = Math.ceil(totalPosts / limit); // 전체 페이지 수
// 페이지 번호 HTML 저장할 변수
let paginationHTML = "";
for (let i = 0; i < totalPages; i++) {
paginationHTML += `<span class="num" data-page="${i}">${i + 1}</span>`;
}
paginationContainer.innerHTML = paginationHTML;
// 생성된 페이지 번호의 요소 접근 (동적 할당)
const pageNumbers = document.querySelectorAll('.num');
// 현재 페이지 번호에 스타일 적용
pageNumbers[currentPage].style.backgroundColor = 'grey';
pageNumbers[currentPage].style.fontWeight = 600;
pageNumbers.forEach( (pageNumber) => {
pageNumber.addEventListener('click', (event) => {
// console.log('event', event);
// console.log('event.target', event.target);
// console.log('event.target.dataset', event.target.dataset);
// console.log('event.target.dataset.page', event.target.dataset.page);
// 해당하는 번호를 가지고 와서 다시 렌더링
const targetPageNumber = parseInt(event.target.dataset.page); // 문자열 --> number 변환
loadPosts(targetPageNumber);
})
});
}
// 하나의 게시글 클릭 시 상세보기 화면 이동 처리
function postClickListeners(){
}
// 글쓰기 버튼 눌렀을 경우 -> 글쓰기 페이지 이동 처리
writeButton.onclick = function() {
location.href = "board-write.html";
}
});
2. board-write.html
<!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" />
<link rel="stylesheet" href="../css/boardWrite.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">
</td>
</tr>
<tr>
<th>작성자</th>
<td>
<input type="text" class="inputs username" readonly>
</td>
</tr>
<tr>
<th>첨부파일</th>
<td>
<input type="file" class="file" accept="image/*">
</td>
</tr>
<tr>
<th>내용</th>
<td>
<div class="img-box" >이미지 미리보기</div>
<textarea name="" id="" class="content"></textarea>
</td>
</tr>
</table>
<div class="btn-area">
<button type="button" class="btn">글쓰기</button>
</div>
</section>
</main>
<script src="../js/header.js"></script>
<script src="../js/boardWrite.js"></script>
</body>
</html>
3. boardWrite.css
.content {
width: 95%;
height: 300px;
font-size: 18px;
border: none;
resize: none;
margin-top: 5px;
}
.img-box {
width: 100%;
display: flex;
justify-content: center;
}
.img-box img {
width: 100%;
max-width: 300px;
}
4. boardWrite.js
// 로그인 상태 여부
redirectToPageIfNotLoggedIn('sign-in');
document.addEventListener('DOMContentLoaded', function() {
// 사용 할 요소에 접근
const title = document.querySelector('.title');
const username = document.querySelector('.username');
const fileInput = document.querySelector('.file');
const imgViewBox = document.querySelector('.img-box');
const content = document.querySelector('.content');
const button = document.querySelector('button');
const day = new Date();
// 사용자 선택한 이미지를 저장할 공간이 필요
let imageData = null;
// 사용자 정보 가져 오기
const getUser = JSON.parse(localStorage.getItem('user'));
username.value = getUser.username;
// 파일 미리보기 기능 만들기
function fileUpload(event) {
const file = event.target.files[0];
//console.log('file', file);
// 파일 크기 유효성 검사
// 1024 * 1024 * 5 = (5MB) 이하만 허용
if(file.size >= 5242880) {
alert('첨부 파일은 5MB 이하만 가능 합니다');
event.target.value = "";
return;
}
// 파일 타입 유효성 검사
const validFileTypes = ['image/jpeg', 'image/png', 'image/gif'];
if(!validFileTypes.includes(file.type)) {
alert('유효한 파일 타입이 아닙니다.(jpeg, png, gif만 허용');
return;
}
// 파일 미리보기 기능
const reader = new FileReader();
reader.readAsDataURL(file); // Base64 인코딩 바이트 단위 데이터를 -- 64개 문자로 표현하는 인코딩 방식
reader.onload = function (e) {
console.log('Base64', e.target.result);
imgViewBox.innerHTML = `<img src="${e.target.result}" alt="Upload Image">`;
// 글 저장시에 로컬스토리지에 바이너리 데이터를 -- 64 인코딩 저장
imageData = reader.result;
}
}
// 글 저장하는 기능 만들기
function saveBoard() {
// 유효성 검사
if(title.value === "") {
alert('제목을 입력하시오');
return;
}
if(content.value === "") {
alert('내용을 입력하시오');
return;
}
// 로컬 스토리지에 게시글 전체 목록 가져오기
let boardList = JSON.parse(localStorage.getItem('boardList') || '[]' );
// 고유 ID 생성
const newId = generateUniqueId(boardList);
// 객체 리터럴 표기법 사용
const board = {
id: newId,
title : title.value,
content : content.value,
username: username.value,
today: `${day.getFullYear()}.${day.getMonth() + 1}.${day.getDate()}`,
count: 0,
imgData: imageData
};
// 배열에다가 생성한 객체 추가
boardList.push(board);
// 로컬 스토리지에 저장 (배열 전체)
localStorage.setItem("boardList", JSON.stringify(boardList));
// 페이지 이동 처리
location.href = 'board-list.html';
}
// 고유 아이디 생성 함수
function generateUniqueId(boardList) {
return boardList.length > 0 ? boardList[boardList.length - 1].id + 1 : 1 ;
}
// 이벤트 리스너 등록 처리 - file change
fileInput.addEventListener('change', fileUpload);
button.addEventListener('click', saveBoard);
});
728x90
반응형
'HTML,CSS, JS > JavaScript' 카테고리의 다른 글
[JavaScript] 31. JavaScript를 사용한 게시글 상세보기 기능 만들기(2) (0) | 2024.08.29 |
---|---|
[JavaScript] 30. JavaScript를 사용한 게시글 상세보기 기능 만들기(1) (0) | 2024.08.28 |
[JavaScript] 28. JavaScript를 사용한 목록 페이지 만들기(3) (0) | 2024.08.26 |
[JavaScript] 27. JavaScript를 사용한 목록 페이지 만들기(1) (0) | 2024.08.26 |
[JavaScript] 26. JavaScript를 사용한 헤더 만들기 (0) | 2024.08.26 |