Web-Node.js/간단한 익명게시판 만들기
3. 각 화면 구성
초보개발자뀨
2021. 3. 24. 16:40
레이아웃 엔진은 ejs를 사용하였습니다.
board.ejs - 글들을 보여주는 화면입니다.
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/board.css">
<title>문의 게시판</title>
</head>
<body>
<div class="head">
<h2>예제 게시판!!</h2>
<p>CRUD 예제 익명 게시판 입니다용!</p>
</div>
<div class="content">
<table border='1' id="list">
<colgroup>
<col style="width: 10%;">
<col style="width: 50%;">
<col style="width: 20%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<th>순번</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
</tr>
</thead>
<tbody >
<% for(i = 0; i < list.length; i++) { %>
<tr>
<td name="order"><%=i+1 %></td>
<td>
<a href="/read/<%=list[i].id %>"><%=list[i].title %></a>
</td>
<td name="name"><%=list[i].writer%></td>
<td><%=list[i].date%>
</td>
</tr>
<% } %>
</tbody>
</table boader='1'>
<button id="btn_write" onclick="location.href='../write'">글쓰기</button>
</div>
<script src="/js/board.js"></script>
</body>
</html>
board.css
@import url('https://fonts.googleapis.com/css2?family=Nanum+Gothic:wght@800&display=swap');
.head {
font-family: 'Nanum Gothic', sans-serif;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
color: white;
background-color: #a7acf1;
height: 250px;
width: 1300px;
display: flex;
flex-direction: column;
align-items: center;
margin: auto;
padding: 0px;
}
.head h2 {
padding-bottom: 10px;
font-size: 40px;
border-bottom: 2px solid white;
}
.head p {
font-size: 30px;
}
.content {
font-family: 'Nanum Gothic', sans-serif;
height: 800px;
background-color: rgb(220, 247, 255);
width: 1300px;
display: flex;
margin: auto;
flex-direction: column;
align-items: center;
}
table {
margin-top: 30px;
font-size: 15px;
font-weight: bold;
width: 1200px;
}
tr{
text-align: center;
}
#btn_write {
border-radius: 20px;
font-weight: bold;
font-size: large;
height: 50px;
margin-top: 150px;
width: 600px;
}
th{
padding: 10px;
font-size: 20px;
}
td{
font-size: 15px;
}
td a{
text-decoration: none;
}
@media(min-width: 320px) and (max-width: 480px){
.head {
border-top-left-radius: 20px;
border-top-right-radius: 20px;
color: white;
background-color: #a7acf1;
height: 250px;
width: 412px;
display: flex;
flex-direction: column;
align-items: center;
margin: auto;
padding: 0px;
}
.head h2 {
padding-bottom: 10px;
font-size: 40px;
border-bottom: 2px solid white;
}
.head p {
font-size: 25px;
}
.content {
height: 800px;
background-color: rgb(220, 247, 255);
width: 412px;
display: flex;
margin: auto;
flex-direction: column;
align-items: center;
}
table {
margin-top: 30px;
font-size: 15px;
font-weight: bold;
width: 412px;
}
tr{
text-align: center;
}
#btn_write {
border-radius: 20px;
font-weight: bold;
font-size: large;
height: 50px;
margin-top: 150px;
width: 400px;
}
th{
padding: 10px;
font-size: 20px;
}
td{
font-size: 15px;
}
td a{
text-decoration: none;
}
}
write.ejs - 글쓰기 버튼을 눌럿을 시 글 작성 화면입니다.
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/write.css">
<title>글쓰기</title>
</head>
<body>
<form name ='write_form' action='/writeAf' method='post'>
<div class="content">
<h2>게시글 작성</h2>
<div class="input_type">
<label id="label_title"> 제목</label>
<input id="input_title" name = "title" type="text">
</div>
<div class="input_type">
<label> 작성자</label>
<input id="input_writer" name = "writer" type="text">
</div>
<div class="input_type">
<label> 내용</label>
<textarea id="input_text" style="font-size: 15px;" name="context" id="" cols="70" rows="20"></textarea>
</div>
<div class="input_type">
<label > 비밀번호</label>
<input id ="input_password" name = "password" type="password">
</div>
<p style="font-size: 10px;">나쁜말 작성 시 사전동의 없이 삭제 될 수 있습니다.</p>
<p style="font-size: 10px;">비밀번호 분실 시에는 전화주세욧!.</p>
<button type="button" id='btn_submit'>글쓰기</button>
</div>
</form>
<script src="/js/write.js"></script>
</body>
</html>
write.css
h2 {
text-align: center;
width: 100%;
border-bottom: 2px solid lightgray;
padding-bottom: 10px;
}
.content {
font-family: 'Nanum Gothic', sans-serif;
padding: 20px;
border: rgb(88, 86, 86) solid 2px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
width: 700px;
margin: auto;
justify-content: space-evenly;
}
.input_type {
border-bottom: 1px solid lightgray;
width: 100%;
padding-bottom: 10px;
font-size: 20px;
font-weight: bold;
display: flex;
align-items: center;
margin-bottom: 30px;
justify-content: flex-start;
}
#label_title {
margin-right: 20px;
}
#input_password {
margin-left: 120px;
}
.input_type input {
font-size: 20px;
width: 400px;
margin-left: 140px;
}
.input_type textarea {
font-family: 'Nanum Gothic', sans-serif;
font-size: 20px;
width: 400px;
margin-left: 160px;
resize: none;
}
#btn_submit {
margin-top: 30px;
border-radius: 20px;
font-size: 20px;
width: 100px;
}
@media(min-width: 320px) and (max-width: 480px) {
h2 {
text-align: center;
width: 100%;
border-bottom: 2px solid lightgray;
padding-bottom: 10px;
}
.content {
height: 100%;
border: rgb(88, 86, 86) solid 2px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
width: 390px;
margin: auto;
justify-content: space-evenly;
}
.input_type {
border-bottom: 1px solid lightgray;
width: 412px;
padding-bottom: 10px;
font-size: 15px;
font-weight: bold;
display: flex;
align-items: center;
margin-bottom: 30px;
}
#label_title {
margin-right: 20px;
}
.input_type input {
font-size: 15px;
width: 200px;
margin-left: 50px;
}
.input_type textarea {
font-weight: bold;
font-size: 15px;
width: 300px;
margin-left: 30px;
resize: none;
}
#btn_submit {
margin-top: 30px;
border-radius: 20px;
font-size: 20px;
width: 100px;
}
}
write.js
const btn_submit = document.getElementById("btn_submit");
const title = document.getElementById("input_title");
const writer = document.getElementById("input_writer");
const text = document.getElementById("input_text");
const password = document.getElementById('input_password');
btn_submit.addEventListener('click',function(){
if(!text.value) {
alert("내용을 입력해주세요");
}
else if(!title.value){
alert("제목을 입력해주세요");
}
else if(!writer.value){
alert("작성자을 입력해주세요");
}
else if(!password.value){
alert("비밀번호를 입력해주세요");
}
else {
document.write_form.submit();
}
});
read.ejs - 글을 클릭 했을 시 상세 내용을 보여줄 화면입니다. footer태그로 댓글들을 보여줄 show.ejs를 포함시켜주었습니다.
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/read.css">
<title>글쓰기</title>
</head>
<body>
<div id="list" ,="," class="<%=list[0].password%>"></div>
<div class="content">
<h2>게시물 보기</h2>
<div class="input_type">
<label id="label_title">
제목</label>
<input readonly="readonly" type='text' name="title" value="<%=list[0].title%>">
</div>
<div class="input_type">
<label >
작성자</label>
<input readonly="readonly" type='text' name="name" value="<%=list[0].writer%>">
</div>
<div class="input_type">
<label >
내용</label>
<textarea readonly="readonly" name="content" id="content" cols="70" rows="20"><%=list[0].context%></textarea>
</div>
<div class="btn">
<button class='<%=list[0].id%>' id="update" name="123">수정</button>
<button id="delete">삭제</button>
</div>
</div>
<footer>
<%- include('show')%>
</footer>
<script src="/js/read.js"></script>
</body>
</html>
read.css
h2 {
text-align: center;
width: 100%;
border-bottom: 2px solid lightgray;
padding-bottom: 10px;
}
.content {
padding: 20px;
border: rgb(88, 86, 86) solid 2px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
width: 700px;
margin: auto;
justify-content: space-evenly;
}
.input_type {
border-bottom: 1px solid lightgray;
width: 100%;
padding-bottom: 10px;
font-size: 20px;
font-weight: bold;
display: flex;
align-items: center;
margin-bottom: 30px;
justify-content: flex-start;
}
#label_title {
margin-right: 20px;
}
.input_type input{
font-size: 20px;
width: 400px;
margin-left: 140px ;
}
.input_type textarea{
font-weight: bold;
font-size: 20px;
width: 400px;
margin-left: 160px;
resize: none;
}
#btn_submit{
margin-top: 30px;
border-radius: 20px;
font-size: 20px;
width: 100px;
}
@media(min-width: 320px) and (max-width: 480px){
h2 {
text-align: center;
width: 100%;
border-bottom: 2px solid lightgray;
padding-bottom: 10px;
}
.content {
height: 100%;
border: rgb(88, 86, 86) solid 2px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
width: 390px;
margin: auto;
justify-content: space-evenly;
}
.input_type {
border-bottom: 1px solid lightgray;
width: 412px;
padding-bottom: 10px;
font-size: 15px;
font-weight: bold;
display: flex;
align-items: center;
margin-bottom: 30px;
}
#label_title {
margin-right: 20px;
}
.input_type input{
font-size: 15px;
width: 200px;
margin-left: 50px ;
}
.input_type textarea{
font-weight: bold;
font-size: 15px;
width: 300px;
margin-left: 30px;
resize: none;
}
#btn_submit{
margin-top: 30px;
border-radius: 20px;
font-size: 20px;
width: 100px;
}
}
read.js
const btn_update = document.getElementById('update');
const btn_delete = document.getElementById('delete');
const list = document.getElementById('list');
let number = btn_update.className;
const db_password =list.className;
btn_update.addEventListener('click',function(){
if(db_password === null){
alert("수정하시겠습니까?");
let url='/read/update/'+number;
location.href=url;
}
else if(db_password !==null) {
let password = prompt("비밀번호를 입력해주세요");
if(password == db_password) {
let url='/read/update/'+number;
location.href=url;
}
else {
alert("비밀번호가 맞지 않습니다 다시 입력해주세요");
}
}
});
btn_delete.addEventListener('click',function() {
if(db_password === null){
alert("삭제되었습니다.");
let url='/read/remove/'+number;
location.href=url;
}
else if(db_password !==null) {
let password = prompt("비밀번호를 입력해주세요");
if(password == db_password) {
alert("삭제되었습니다.");
let url='/read/remove/'+number;
location.href=url;
}
else {
alert("비밀번호가 맞지 않습니다 다시 입력해주세요");
}
}
});
update.ejs - read.ejs에서 수정 버튼을 누를 시 글 수정화면으로 이동하여 보여줄 화면입니다.
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/update.css">
<title>글쓰기</title>
</head>
<body>
<form action='/updateAf' method='post'>
<div class="content">
<h2>게시글 작성</h2>
<div class="input_type">
<label id="label_title"> 제목</label>
<input name = "title" type="text" value="<%=list[0].title%>">
</div>
<div class="input_type">
<label>닉네임</label>
<input readonly name = "writer" value="<%=list[0].writer%>" type="text">
</div>
<div class="input_type">
<label >내용</label>
<textarea name="context" id="" cols="70" rows="20"><%=list[0].context%></textarea>
</div>
<button name="id" value="<%=list[0].id%>" id='btn_submit' type='submit'>수정하기</button>
</div>
</form>
<script src="/js/update.js"></script>
</body>
</html>
update.css
h2 {
text-align: center;
width: 100%;
border-bottom: 2px solid lightgray;
padding-bottom: 10px;
}
.content {
padding: 20px;
border: rgb(88, 86, 86) solid 2px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
width: 700px;
margin: auto;
justify-content: space-evenly;
}
.input_type {
border-bottom: 1px solid lightgray;
width: 100%;
padding-bottom: 10px;
font-size: 20px;
font-weight: bold;
display: flex;
align-items: center;
margin-bottom: 30px;
justify-content: flex-start;
}
#label_title {
margin-right: 20px;
}
.input_type input {
font-size: 20px;
width: 400px;
margin-left: 140px;
}
.input_type textarea {
font-weight: bold;
font-size: 20px;
width: 400px;
margin-left: 160px;
resize: none;
}
#input_number {
display: none;
}
#btn_submit {
margin-top: 30px;
border-radius: 20px;
font-size: 20px;
width: 100px;
}
@media(min-width: 320px) and (max-width: 480px) {
h2 {
text-align: center;
width: 100%;
border-bottom: 2px solid lightgray;
padding-bottom: 10px;
}
.content {
height: 100%;
border: rgb(88, 86, 86) solid 2px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
width: 390px;
margin: auto;
justify-content: space-evenly;
}
.input_type {
border-bottom: 1px solid lightgray;
width: 412px;
padding-bottom: 10px;
font-size: 15px;
font-weight: bold;
display: flex;
align-items: center;
margin-bottom: 30px;
}
#label_title {
margin-right: 20px;
}
.input_type input {
font-size: 15px;
width: 200px;
margin-left: 50px;
}
.input_type textarea {
font-weight: bold;
font-size: 15px;
width: 300px;
margin-left: 30px;
resize: none;
}
#btn_submit {
margin-top: 30px;
border-radius: 20px;
font-size: 20px;
width: 100px;
}
}
show.ejs - 댓글들을 보여줄 화면입니다.
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/show.css">
<title>글쓰기</title>
</head>
<body>
<form name= "sub_form" action="/read/sub/insert" method="POST">
<div class="sub_content">
<h3>댓글</h3>
<div class="input">
<label> 작성자</label>
<input name ="sub_writer" type="text">
<label > 내용</label>
<input name = "sub_context" type="text">
<label > 비밀번호</label>
<input id="sub_password" name = "sub_password" type="password">
<button id="btn_sub_insert" type="button">댓글 달기</button>
</div>
<div class="sub_board">
<% for(i = 0; i < sub_list.length ; i++) { %>
<div class="show_sub_board">
<label class="<%=sub_list[i].spassword%>" id="sub_writer" ><%=sub_list[i].swriter%></label>
<p id="sub_text"><%=sub_list[i].scontext%></p>
<div class="btn">
<button id="<%=sub_list[i].spassword%>"onclick="sub_update(this.id,<%=sub_list[i].sid%>)" type="button" >수정</button>
<button id ="<%=sub_list[i].spassword%>"onclick="sub_delete(this.id,<%=sub_list[i].sid%>)" type="button">삭제</button>
</div>
</div>
<% } %>
</div>
</div>
</form>
<script src="/js/show.js"></script>
</body>
</html>
show.css
.sub_content {
padding: 20px;
border: rgb(88, 86, 86) solid 2px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
width: 700px;
margin: auto;
justify-content: space-evenly;
}
label {
font-size: 15px;
}
#text {
margin-top: 20px;
font-size: 20px;
font-weight: bold;
}
.show_sub_board {
width: 100%;
display: flex;
flex-direction: column;
border-top: lightgray 1px solid;
border-bottom: lightgray 1px solid;
margin-bottom: 10px;
}
.sub_board {
margin-top: 20px;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
#sub_writer {
margin-top: 10px;
}
#sub_text {
font-size: 20px;
}
.sub_content input {
width: 130px;
}
.btn {
margin-top: 20px;
display: flex;
}
#btn_delete {
margin-left: 20px;
}
@media(min-width: 320px) and (max-width: 480px) {
}
show.js
const btn_sub_insert = document.getElementById('btn_sub_insert');
const sub_password = document.getElementById('sub_password');
btn_sub_insert.addEventListener('click', function () {
if (!sub_password.value) {
alert("비밀번호를 입력해주세요.");
} else {
alert("댓글이 입력되었습니다.");
document
.sub_form
.submit();
}
});
function sub_delete(sub_pwd, sub_id) {
let pwd = prompt("비밀번호를 입력해주세요");
if (pwd == sub_pwd) {
alert("삭제되었습니다.");
let url = '/read/sub/remove/' + sub_id;
location.href = url;
} else {
alert("비밀번호를 다시 입력해주세요");
}
}
function sub_update(sub_pwd,sub_id) {
let pwd = prompt("비밀번호를 입력해주세요");
if (pwd == sub_pwd) {
let url = "/read/sub/update/"+sub_id;
let name = "popup test";
let option = "width = 500, height = 500, top = 100, left = 200, location = no"
window.open(url, name, option);
}
else {
alert("비밀번호를 다시 입력해주세요");
}
}
sub_update.ejs - 댓글 수정 버튼을 누를시 보여질 화면입니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style/sub_update.css">
<title>댓글 수정</title>
</head>
<body>
<form name = 'sub_update_form' action='/sub_updateAf' method="POST">
<div class="input">
<h2>수정할 댓글을 입력해주세요.</h2>
<textarea name="sub_context"><%=sub_list[0].scontext%></textarea>
<input type="hidden" value ="<%=sub_list[0].sid%>" name ="number">
<div class="btn">
<button type="button" onclick="update()">수정하기</button>
<button type="button">취소</button>
</div>
</div>
</form>
<script src="/js/sub.update.js"></script>
</body>
</html>
sub_update.css
.input {
display: flex;
flex-direction: column;
}
.btn {
margin : 20px;
display: flex;
}
sub_update.js
function update(){
sub_update_form.submit();
opener.location.reload();
};
null.ejs - 댓글 수정 후 창 닫기 위한 ejs 추후에 설명 하겠습니다!
<script>
setTimeout(function() {
self.close();
}, 1000);
</script>