웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.06.10

shine94 2020. 6. 10. 10:35

[AJAX + SPA게시판 클라이언트단 글 작성, 삭제 구현]

1. index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/CSS/common.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a076d05399.js"></script>
<script src="${pageContext.request.contextPath }/JS/board.js"></script>

<title>SPA 게시판</title>
</head>
<body>
<h2>게시판 - SPA</h2>
<%-- 글목록 --%>
<div id="list">
	<div class="d01">
		<div class="left" id="pageinfo"></div>
		<div class="right" id="pageRows"></div>
	</div>
	
	<div class="clear"></div>
	
	<form id="frmList" name="frmList">
	
	<table>
		<thead>
			<th>#</th>
			<th>UID</th>
			<th>제목</th>
			<th>작성자</th>
			<th>조회수</th>
			<th>작성일</th>
		</thead>
		
		<tbody>
		
		</tbody>
	</table>
	
	</form>
	
	<%--버튼 --%>
	<div class="d01">
		<div class="left">
			<button type="button" id="btnDel" class="btn danger">글삭제</button>
		</div>
		<div class="right">
			<button type="button" id="btnWrite" class="btn success">글작성</button>
		</div>	
	</div>
	

</div>

<br>
<%-- 페이징 --%>
<div class="center">
	<ul class="pagination" id="pagination">
	
	</ul>
</div>


<%--글작성 --%>
<div id="dlg_write" class="modal">
  
  <form class="modal-content animate" id="frmWrite" name="frmWrite" method="post">

    <div class="container">      
      <h3>새글 작성</h3>
      
      <span class="close" title="Close Modal">&times;</span>
      
      <label for="subject"><b>글제목</b></label>
      <input type="text" placeholder="글제목(필수)" name="subject" required>

      <label for="name"><b>작성자</b></label>
      <input type="text" placeholder="작성자(필수)" name="name" required>
      
      <label for="content"><b>내용</b></label>
      <textarea placeholder="글내용" name="content"></textarea>
        
      <button type="submit" class="btn success">작성</button>
    </div>
  </form>
</div>


</body>
</html>

 

 

2. board.js

var page = 1  // 현재 페이지 
var pageRows = 10   // 한 페이지에 보여지는 게시글 개수

$(document).ready(function(){
	// 게시판 목록 1페이지 로딩
	loadPage(page);
	
	// 글작성 버튼 누르면 팝업
	$("#btnWrite").click(function() {
		$("#dlg_write").show();
	});
	
	// 모달 대화상자에서 close 버튼 누르면 닫기
	$(".modal .close").click(function(){
		$(this).parents(".modal").hide();
	});
	
	// 글 작성 submit 되면
	$("#frmWrite").submit(function(){
		$(this).parents(".modal").hide();
		return chkWrite();
	});
	
	// 글 삭제 버튼 누르면
	$("#btnDel").click(function(){
		chkDelete();
	});
	
});

// page 번째 페이지 로딩
function loadPage(page){
	
	$.ajax({
		url : "list.ajax?page=" + page + "&pageRows=" + pageRows
		, type : "GET"
		, cache : false
		, success : function(data, status){
			if(status == "success"){
				//alert("AJAX 성공: 받아쮸~");
				updateList(data);
			}			
		}
	});
} // end loadPage()

//
function updateList(jsonObj){
	result = ""; 
	
	if(jsonObj.status == "OK"){
		
		var count = jsonObj.count;
		
		// 전역변수 업데이트!
		window.page = jsonObj.page;
		window.pageRows = jsonObj.pagerows;
		
		var i;
		var items = jsonObj.data;   // 배열
		for(i = 0; i < count; i++){
			result += "<tr>\n";
			result += "<td><input type='checkbox' name='uid' value='" + items[i].uid + "'></td>\n";
			result += "<td>" + items[i].uid + "</td>\n";
			result += "<td>" + items[i].subject + "</td>\n";
			result += "<td>" + items[i].name + "</td>\n";
			result += "<td>" + items[i].viewcnt + "</td>\n";
			result += "<td>" + items[i].regdate + "</td>\n";			
			result += "</tr>\n";
		} // end for
		$("#list tbody").html(result);  // 테이블 업데이트!
		
		// 페이지 정보 업데이트
		$("#pageinfo").text(jsonObj.page + "/" + jsonObj.totalpage + "페이지, " + jsonObj.totalcnt + "개의 글");
		
		// pageRows
		var txt = "<select id='rows' onchange='changePageRows()'>\n";
		txt += "<option " + ((window.pageRows == 10)?"selected":"") + " value='10'>10개씩</option>\n";
		txt += "<option " + ((window.pageRows == 20)?"selected":"") + " value='20'>20개씩</option>\n";
		txt += "<option " + ((window.pageRows == 50)?"selected":"") + " value='50'>50개씩</option>\n";
		txt += "<option " + ((window.pageRows == 100)?"selected":"") + " value='100'>100개씩</option>\n";		
		txt += "</select>\n";
		$("#pageRows").html(txt);
		
		
		// 페이징 업데이트
		var pagination = buildPagination(jsonObj.writepages, jsonObj.totalpage, jsonObj.page, jsonObj.pagerows);
		$("#pagination").html(pagination);
		
		return true;
	} else {
		alert(jsonObj.message);
		return false;
	}
	return false;
} // end updateList()


function buildPagination(writePages, totalPage, curPage, pageRows){
	
	var str = "";   // 최종적으로 페이징에 나타날 HTML 문자열 <li> 태그로 구성

	// 페이징에 보여질 숫자들 (시작숫자 start_page ~ 끝숫자 end_page)
    var start_page = ( (parseInt( (curPage - 1 ) / writePages ) ) * writePages ) + 1;
    var end_page = start_page + writePages - 1;

    if (end_page >= totalPage){
    	end_page = totalPage;
    }
    
    //■ << 표시 여부
	if(curPage > 1){
		str += "<li><a onclick='loadPage(1)' class='tooltip-top' title='처음'><i class='fas fa-angle-double-left'></i></a></li>\n";
	}
	
  	//■  < 표시 여부
    if (start_page > 1) 
    	str += "<li><a onclick='loadPage(" + (start_page -1) + ")' class='tooltip-top' title='이전'><i class='fas fa-angle-left'></i></a></li>\n";
    
    //■  페이징 안의 '숫자' 표시	
	if (totalPage > 1) {
	    for (var k = start_page; k <= end_page; k++) {
	        if (curPage != k)
	            str += "<li><a onclick='loadPage(" + k + ")'>" + k + "</a></li>\n";
	        else
	            str += "<li><a class='active tooltip-top' title='현재페이지'>" + k + "</a></li>\n";
	    }
	}
	
	//■ > 표시
    if (totalPage > end_page){
    	str += "<li><a onclick='loadPage("+ (end_page + 1 ) + ")' class='tooltip-top' title='다음'><i class='fas fa-angle-right'></i></a></li>\n";
    }

	//■ >> 표시
    if (curPage < totalPage) {
        str += "<li><a onclick='(" + totalPage + ")' class='tooltip-top' title='맨끝'><i class='fas fa-angle-double-right'></i></a></li>\n";
    }

    return str;

	
	
	
} // end buildPagination()

function changePageRows(){
	window.pageRows = $("#rows").val();
	loadPage(window.page);
}

// 새글 등록 처리
function chkWrite() {
	
	var data = $("#frmWrite").serialize();	// 해당 폼 안의 name이 있는 것들을 끌어 들어옴
											// 리턴값은 Object
	//alert(data + "--" + typeof data);
	//subject=aaa&name=bbb&content=ccc--string
	
	
	// ajax request
	$.ajax({
		url : "writeOk.ajax",
		type : "POST",
		cache : false,
		data : data,  // POST 로 ajax request 하는 경우 parameter 담기
		success : function(data, status){
			if(status == "success"){
				if(data.status = "OK") {
					alert("INSERT 성공" + data.count + "개 : " + data.status);
					loadPage(1);	// 첫 페이지 리로딩
				} else {
					alert("INSERT 실패" + data.status + " : " + data.message);
				}
			}
		}
	});
	
	// request 후, form 에 입력된것 reset()
	$("#frmWrite")[0].reset();
	
	// type이 submit일때 비록 action이 없더라도
	// 자기 페이지로 리로딩된다...!!
	// 페이지 리로딩을 원치 않는다면 리턴 값을 false 값을 주면 된다!
	return false;	// 페이지 리로딩은 안 할 것이다
} // end chkWrite();

// check된 uid의 게시글들만 삭제하기
function chkDelete() {
	var uids = [];	// 빈 배열 준비
	
	// .each는 $("#list tbody input[name=uid") 각각에
	// each function()을 실행시키라는 의미!
	$("#list tbody input[name=uid]").each(function() {
		//$(this)는 checkbox
		if($(this).is(":checked")) {	// jQuery에서 check 여부 확인 방법
			uids.push($(this).val());	// 배열에 uid 값 추가
		}
	});
	
	//alert(uids);
	
	if(uids.length == 0) {
		alert("삭제할 글을 체크해 주세요");
	} else {
		
		if(!confirm(uids.length + "개의 글을 삭제하시겠습니까?")) return false;
		
		var data = $("#frmList").serialize();
			//   uid=1010&uid=1011&uid=1012
		
		$.ajax({
			url : "deleteOk.ajax",
			type : "POST",
			data : data,
			cache : false,
			success : function(data, status){
				if(status == "success"){
					if(data.status == "OK"){
						alert("DELETE 성공 " + data.count + "개");
						// 현재 페이지 리로딩
						loadPage(window.page);
					} else {
						alert("DELETE 실패 " + data.message);
					}
				}
			}
		});
		
	}
	
} // end chkDelete()

 

 

3. common.css

@charset "UTF-8";

/* 기본 버튼 */
.btn {
  border: none;
  color: white;
  padding: 14px 28px;
  font-size: 16px;
  cursor: pointer;
}

.success {background-color: #4CAF50;} /* Green */
.success:hover {background-color: #46a049;}

.info {background-color: #2196F3;} /* Blue */
.info:hover {background: #0b7dda;}

.warning {background-color: #ff9800;} /* Orange */
.warning:hover {background: #e68a00;}

.danger {background-color: #f44336;} /* Red */ 
.danger:hover {background: #da190b;}

.default {background-color: #e7e7e7; color: black;} /* Gray */ 
.default:hover {background: #ddd;}

/* 글 목록 */
#list table {width: 100%;}

#list table, #list th, #list td {
	border: 1px solid black;
	border-collapse: collapse;
}

#list th, #list td {
	padding: 10px;
}

.clear { clear: both; }

.left {
	float: left;
}

.right {
	float: right;
}

/* 페이징 */
.center {
    text-align: center;
}

ul.pagination{
	list-style-type:none
}

ul.pagination li{
    display: inline-block;
}

ul.pagination a {
    color: black;
    float: left;
    padding: 4px 8px;
    text-decoration: none;
    transition: background-color .3s;
    /* border: 1px solid #ddd; */
    /* margin: 0 4px; */
    margin: 0px;
}

ul.pagination a.active {
    background-color: #4CAF50;
    color: white;
    border: 1px solid #4CAF50;
}

ul.pagination a:hover:not(.active) {background-color: #ddd;}

/* 버튼 그룹 */
.d01 {
	margin: 5px 0;
}

/* 모달 팝업 */
/* 모달 팝업 */
.modal {   /* 모달 전체 적용 */	
	background-color: rgba(0, 0, 0, 0.4);
	width: 100%;
	height: 100%;
	position : fixed;
	top: 0;
	left: 0;
	z-index: 1;
	padding-top: 40px;  /* 내부여백  */
	overflow: auto;
	
	display : none;  /* 기본적으로 안보이기 */  
}

.modal .modal-content {
	background-color: #fefefe;  /* 배경은 흰색 */
	width: 80%;   /* 화면대비 80% */
	margin: 5% auto 15% auto;  /* 위에서 5%,  아래에서 15%, 좌우 중앙정렬 */
	border: 1px solid #888;  /* 테두리 */
}

.modal .container {
	padding: 16px;
	position: relative;  /* 이래야 안에 있는 absolute 들이 동작 */
} 

.modal .close {  /* close 버튼 */
	font-size: 35px;	
	font-weight: bold;
	color: #000;
	position: absolute;
	right: 25px;
	top: 0px;
}

.modal .close:hover,
.modal .cloas:focus {
	color: red;
	cursor: pointer;
}


.modal input[type=text] {
	width: 100%;
	border: 1px solid #ccc;
	margin: 8px 0;
	padding: 12px 20px;
	display: inline-block;
	border: 1px solid #ccc;
	box-sizing: border-box;
}

.modal textarea {
	width: 100%;
	margin: 8px 0;
}

.modal button {
	width: 100%;
	cursor: pointer;
}

.modal .canbelbtn {  /* 취소 버튼일 경우 추가적인 스타일 */
	background-color: #f44336;
	width: auto;
	padding: 10px 18px;
}

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

2020.06.16  (0) 2020.06.16
JSP Team Project(2020.05.25 ~ 2020.06.15)  (0) 2020.06.16
2020.06.09  (0) 2020.06.09
2020.06.08  (0) 2020.06.08
2020.06.05  (0) 2020.06.05