웹 스토리지 ?

- 웹 스토리지 API는 웹 브라우저가 직접 데이터를 저장한다.

- HTML5 이전에는 응용 프로그램이 데이터를 서버에게 요청할 때마다 매번 쿠키(cookie)에 정보를 저장했지만, 웹 스토리지는 사용자 측에서 좀 더 많은 양의 정보를 안전하게 저장할 수 있다.

- 데이터는 모든 서버 요청에 포함되어 있지 않지만, 요구하는 경우에만 사용된다. 이는 웹사이트의 성능에 영향을 주지 않고 대량의 데이터를 저장할 수도 있다.

- 데이터는 key/value 쌍을 저장하고 웹페이지는 자체적으로 저장된 데이터에 액세스할 수 있다.

- 웹 스토리지는 오리진(origin)마다 단 하나씩만 존재한다.

오리진 - 도메인(domain)과 프로토콜(protocol)의 한쌍으로 이루어진 식별자.

 

웹 스토리지를 활용한 대표적인 기능

- sesstionStorage를 활용해서 사용자가 '입력폼'을 입력하다가 페이지에서 벗어난 경우 백업/복구

- 글쓰기를 하다가 사용자가 창을 벗어난 경우 관련 작성하던 내용 백업/복구

- 웹페이지의 개인화 설정들에 대한 저장과 제공(캐쉬로 활용)

- 현재 읽은 글의 히스토리 저장(카운팅, 읽은 글 표시 등으로 활용)

- Canvas나 이미지에 대한 임시 저장 기능(base64로 변환)

- 웹페이지간 정보 전달(웹서버를 경유하지 않고 정보를 로컬에 유지)

 

웹 스토리지 객체

- sesstionStorage : 하나의 세션(sesstion)만을 위한 데이터를 저장하는 객체

- localStorage : 보관 기한이 없는 데이터를 저장할 수 있는 객체

 

 

예제 - localStorage

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>localStorage</h3>
<p>
 - 데이터 보존기간에 제한 없음<br>
 - 도메인당 하나가 생성<br>
 - 쿠키를 이용한 설정을 대신하기 적당
</p>

<p>
	<button type="button" onclick="clickCount()">카운트증가</button>
	<button type="button" onclick="deleteCount()">삭제</button>
</p>
<hr>

<div id="log"></div>

<script type="text/javascript">
viewCount();

function clickCount() {
	// Storage를 지원하지 않으면
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	// 웹 스토리지 값 가져오기
	var cnt = localStorage.count; // count는 내가 웹 스토리지에 저장할 때 사용한 이름
	// var cnt = localStorage.getItem('count');
	
	if(cnt) {
		cnt = Number(cnt) + 1;
	} else {
		cnt = 1;
	}
	
	// 웹 스토리지에 count라는 이름으로 저장
	localStorage.count = cnt;
	localStorage.setItem("count", cnt);
	
	viewCount();
}

function deleteCount() {
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	delete localStorage.count;
	
	viewCount();
}

function viewCount() {
	// Storage를 지원하지 않으면
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	var cnt = localStorage.count;
	cnt = cnt ? cnt : "";
	document.getElementById("log").innerHTML = "카운터의 현재 횟수 : " + cnt;
}
</script>
</body>
</html>

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>localStorage</h3>

<p>
	<input type="text" id="subject" placeholder="좋아하는 과목">
	<button type="button" onclick="addLog()">추가</button>
	<button type="button" onclick="deleteLog()">삭제</button>
</p>
<div id="log"></div>

<script type="text/javascript">

viewLog();

function viewLog() {
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	var ss = JSON.parse(localStorage.getItem("subject")) || [];
	var s = ss.join();
	
	document.getElementById("log").innerHTML = "좋아하는 과목 : " + s;
}

function addLog() {
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	var s = document.getElementById("subject").value.trim();
	if(! s) {
		return;
	}
	
	var ss = JSON.parse(localStorage.getItem("subject")) || [];
	// 처음 실행 시, 아무 것도 없어서 undefined.
	// 따라서 첫 실행시에는 var ss = []; 가 된다.
	
	ss.push(s);
	localStorage.setItem("subject", JSON.stringify(ss));
	
	viewLog();
	
	document.getElementById("subject").value = "";
	
}

function deleteLog() {
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	delete localStorage.removeItem("subject");
	viewLog();
}

</script>

</body>
</html>

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">


<style type="text/css">
.list li {
	cursor: pointer;
}

.list li:hover:after, .list li.chk:after {
	content: '\2605';
	color: tomato;
}

.list li.chk:hover:after {
	content: '\2605';
}
</style>

</head>
<body>

<h3>localStorage 예제</h3>

<ul class="list">
	<li id="java">자바</li>
	<li id="oracle">Oracle</li>
	<li id="html">HTML</li>
	<li id="javascript">자바스크립트</li>
	<li id="spring">스프링</li>
	<li id="css">css</li>
</ul>

<script type="text/javascript">
	var progs = JSON.parse(localStorage.getItem("progs")) || [];
	
	progs.forEach(function(data) {
		document.getElementById(data).className = "chk";
	});
	
	document.querySelector(".list").addEventListener("click", function(e) {
		var id = e.target.id;
		var item = e.target;
		var index = progs.indexOf(id);
		
		if(index == -1) {
			progs.push(id);
			item.className = "chk";
		} else {
			progs.splice(index, 1);
			item.className = "";
		}
		
		localStorage.setItem("progs", JSON.stringify(progs));
		
		
	})
	
</script>

</body>
</html>

 

예제 - sesstionStorage 

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>sessionStorage</h3>
<p>
 - 한번의 세션 동안만 유지<br>
 - 유효범위와 보존기간이 있다.<br>
 - 같은 브라우저도 새로 생성되는 창에서는 세션이 다르므로 다른 스트로지를 가진다.<br>
 - 도메인마다 따로 생성된다.<br>
</p>

<p>
	<button type="button" onclick="clickCount()">카운트증가</button>
	<button type="button" onclick="deleteCount()">삭제</button>
</p>
<hr>

<div id="log"></div>

<script type="text/javascript">
viewCount();

function clickCount() {
	// Storage를 지원하지 않으면
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	// 웹 스토리지 값 가져오기
	var cnt = sessionStorage.count; // count는 내가 웹 스토리지에 저장할 때 사용한 이름
	// var cnt = sessionStorage.getItem('count');
	
	if(cnt) {
		cnt = Number(cnt) + 1;
	} else {
		cnt = 1;
	}
	
	// 웹 스토리지에 count라는 이름으로 저장
	sessionStorage.count = cnt;
	sessionStorage.setItem("count", cnt);
	
	viewCount();
}

function deleteCount() {
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	delete sessionStorage.count;
	
	viewCount();
}

function viewCount() {
	// Storage를 지원하지 않으면
	if(typeof(Storage) === "undefined") {
		return;
	}
	
	var cnt = sessionStorage.count;
	cnt = cnt ? cnt : "";
	document.getElementById("log").innerHTML = "카운터의 현재 횟수 : " + cnt;
}
</script>
</body>
</html>

 

File interface

- File 인터페이스는 파일에 대한 정보를 제공하고, 웹 페이지의 JavaScript가 해당 내용에 접근할 수 있는 방법을 제공한다.

- File 객체는 보통 FileList 객체에서 가져올 수 있다.

- FileList 객체는 사용자가 <input> 요소에서 파일을 선택했을 때, 드래그 앤 드롭 작업의 DtaTransfer 객체, 그리고 HTMLCanvasElemnt의 mozGetAsFile() API 에서 반환한다.

- File 객체는 특정 종류의 Blob이며, Blob을 사용할 수 있는 모든 맥락에서 사용할 수 있다.

FileReader, URL.createObjectURL(), createImageBitmap(), XMLHttpRequest.send()는 Blob과 File을 모두 허용한다.

 

File interface 생성자 및 주요 속성

- File() : 새로 생성한 File을 반환

- name : File 객체가 참조하는 파일의 이름을 반환

- type : File의 MIME 유형을 반환(알 수 없을 때는 null)

- size  File의 크기를 바이트 단위로 반환

 

 

FileReader interface : File의 내용을 읽을 수 있는 기능을 제공한다.

 

주요 속성 및 메소드

- readAsBinaryString(fileBlob) : File 내용을 읽어 Binary 문자열로 저장

- readAsText(fileBlob, encoding) : File 내용을 읽어들여 문자열로 저장, 두번째 인수는 File의 문자 encoding을 지정할 수 있음. (기본값 : UTF-8)

- readAsDataURL(file) : File내용을 읽어 dataURL 형식의 문자열로 저장

- result : 읽어 들인 File내용

- error : error 발생시의 error 정보

- onload : 읽어 들이기에 성공했을 때 호출하는 event handler. load event에 대응

- onprogress : 읽어 들이기의 진행 상황을 얻을 수 있는 event handler. progress event에 대응

- onerror : 읽어 들이기 error 시에 호출되는 event handler. error event에 대응

 

FileList

- HTML <input> 엘리먼트의 files 속성으로부터 반환되며, <input type="file"> 엘리먼트로 선택된 파일의 리스트에 접근하도록 한다.

- 드래그 앤 드랍 API를 사용할 때 웹 컨텐트에 드랍된 파일의 리스트에도 사용된다.

 

주요 속성 및 메소드

- length : 목록에 있는 파일의 수

- File item(index) : 파일리스트의 지정된 인덱스에 있는 파일을 나타내는 File 객체를 리턴

 

예제 - 파일 용량 체크

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
function checkFilesize(file) {
	var maxSize = 10*1024*1024; // 10M
	var fileSize = file.files[0].size;
	// multiple="multiple"로 파일을 여러 개 선택할 수 있음. 따라서 배열
	
	console.log(fileSize+" bytes.");
	
	return maxSize >= fileSize;
}


function send() {
	var f = document.myForm;
	
	if(! f.selectFile.value ) {
		alert("파일을 선택하세요...");
		f.selectFile.focus();
		return;
	}
	
	if(! checkFilesize(f.selectFile) ) {
		alert("파일은 최대 10M까지 업로드 가능합니다.")
		f.selectFile.focus();
		return;
	}
	
	alert("서버 전송...");
	
}
</script>

</head>
<body>

<h3>파일 용량 체크</h3>

<form name="myForm"> 
	<p> <input type="file" name="selectFile"> </p>
	<p>
		<button type="button" onclick="send();">등록하기</button>
	</p>
</form>

</body>
</html>

 

예제 - FileList

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>File List</h3>

<p>
	<input type="file" multiple="multiple" id="myFiles">
</p>

<script type="text/javascript">
var fileList = function() {
	var fileInput = document.querySelector('#myFiles'); // 홑따옴표사용해야함
	var files = fileInput.files;
	
	for(var i=0; i<files.length; i++) {
		var f = files[i];
		console.log(f.name); // 파일 이름
	}
};

document.querySelector('#myFiles').onchange = fileList; 
</script>

</body>
</html>

 

예제 - text File읽기

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
function readFile(inputs) {
	if(! inputs.value) {
		return;
	}
	
	var f = inputs.files[0];
	var reader = new FileReader(); // 파일의 내용을 읽을 수 있는 기능 제공
	reader.onload = function(e) { // 읽어 들이기에 성공할 때 호출되는 이벤트 핸들러
		console.log(e.target.result); // result : 파일의 내용
	};
	reader.readAsText(f); // utf-8
	// reader.readAsTest(f, "euc-kr"); // euc-kr
}

</script>

</head>
<body>

<h3> text File 읽기</h3>

<div>
	<form name="frm">
		<p>
			<input type="file" name="selectFile" accept="text/*"
				onchange="readFile(this)">
		</p>
	</form>
</div>

</body>
</html>

 

예제 - 이미지 파일 업로드 전 미리보기

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<style type="text/css">
.image-preViewer {
	width: 200px; height: 200px; margin-top: 5px; margin-bottom: 5px;
}

.image-preViewer img {
	max-width: 100%;
}

</style>

<script type="text/javascript">
function isValidImageFile(filename) {
	var p = /(\.gif|\.jpg|\.jpeg|\.png)$/i;
	return p.test(filename);
}

function imagePreview(inputs) {
	var f = inputs.files[0];
	// 이미지 파일이 아닌 경우
	if(! f.type.match("image.*")) {
		inputs.focus();
		return;
	}
	
	var reader = new FileReader();
	reader.onload = function(e) {
		document.getElementById("imgPreView").setAttribute("src", e.target.result);
	};
	reader.readAsDataURL(f);
}

function sendOk() {
	var f = document.frm;
	
	if(! f.selectFile.value) {
		alert("파일을 선택하세요.");
		f.selectFile.focus();
		return;
	}
	
	if(! isValidImageFile(f.selectFile.value) ) {
		alert("이미지 파일만 가능합니다.");
		f.selectFile.value.focus();
		return;
	}
	
	alert("ok");
}
</script>

</head>
<body>

<h3>이미지 미리보기</h3>

<div style="margin: 5px;">
	<form name="frm">
		<p>
		<!--<input type="file" name="selectFile" onchange="imagePreview(this)"> -->
			<input type="file" name="selectFile" accept="image/*" onchange="imagePreview(this)">
		</p>
		<div class="image-preViewer">
			<img id="imgPreView">
		</div>
		<p>
			<button type="button" onclick="sendOk()">등록하기</button>
		</p>
	</form>
</div>

</body>
</html>

문서 객체 모델(Document Object Model, DOM)이란 ?

- 웹 페이지 콘텐츠를 조작하는 메소드와 인터페이스를 제공한다.

- XML을 HTML에서 사용할 수 있도록 확장된 애플리케이션 프로그래밍 인터페이스이다

- DOM(Document Object Model)은 HTML 문서의 모든 요소에 접근하여 방법을 정의한 API이다.

- DOM은 전체 페이지를 노드 계층 구조로 변환하며, HTML 페이지의 각 부분은 각기 다른 데이터를 포함하는 다양한 타입의 노드로 표현된다.

- DOM은 문서를 표현하는 트리를 생성하고 개발자는 이를 통해 문서의 콘텐츠와 구조를 자유롭게 추가, 수정, 제거할 수 있다.

- DOM은 W3C의 표준 객체 모델이며, 트리 구조로 표현된다.

 

자바스크립트를 이용한 문서 객체 모델 사용 예

- 새로운 HTML요소나 속성을 추가할 수 있다.

- 존재하는 HTML 요소나 속성을 제거할 수 있다.

- HTML 문서의 모든 HTML 요소를 변경할 수 있다.

- HTML 문서의 모든 HTML 속성을 변경할 수 있다.

- HTML 문서의 모든 CSS 속성을 변경할 수 있다.

- HTML 문서에 새로운 HTML이벤트를 추가할 수 있다.

- HTML 문서의 모든 HTML 이벤트에 반응할 수 있다.

 

HTML DOM API

document 객체

- document 객체는 웹 페이지 그 자체를 의미하며, 웹 페이지에 존재하는 HTML 요소에 접근할 때 document객체로 접근한다.

- document 객체는 Document 인터페이스 구현체이다.

- HTMLDocument는 HTML에 특화된 Document의 하위 인터페이스로서 location 프로퍼티를 비롯해 forms[] 배열, write() 메소드 등 다양한 문서 프로퍼티와 메소드가 정의되어 있다.

 

Node

- DOM의 기본 원자를 Node이며 노드는 HTML 문서의 트리를 구성하는 단위이다.

- Document, Element, Text, Comment 등 모두 Node로부터 파생되며, Node의 속성은 DOM의 모든 객체가 공통으로 지원한다.

- HTML DOM은 노드(node)들을 정의하고, 그들 사이의 관계를 설명해 주는 역할을 한다.

- 자바스크립트에서는 HTML DOM을 이용하여 노드 트리에 포함된 모든 노드에 접근할 수 있다.

 

예제1

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script type="text/javascript">

function getElements(attrName, attrValue) {
	// 모든 요소 
	var elements = document.getElementsByTagName("*");
	var founds = [];
	
	for(var i=0; i<elements.length; i++) {
		if(elements[i].hasAttribute(attrName) && elements[i].getAttribute(attrName).toLowerCase() === attrValue.toLowerCase()) {
			founds.push(elements[i]);
		}
	}
	
	return founds;
}


function result() {
	var s;
	
	// id로 접근
	var name = document.getElementById("name").value; 
	
	// name으로 접근
	var age = document.getElementsByName("age")[0].value;
	
	// tag로 접근
	var birth = document.getElementsByTagName("input")[2].value;
	
	// 선택자로 접근
	// var chk = document.querySelector("input[type=checkbox]").checked;
	
	// 속성으로 접근
	var chk = getElements("type", "checkbox")[0].checked;
	
	// class 속성으로 접근
	var tel = document.getElementsByClassName("telClass")[0].value;
	
	s = "<p>이름 : " + name + "</p>";
	s += "<p>나이 : " + age + "</p>";
	s += "<p>생년월일 : " + birth +", 양력 : " + chk + "</p>";
	s += "<p>전화번호 : " + tel + "</p>";
	
	// document.getElementById("layout").innerText = s;
	// document.getElementById("layout").innerHTML = s;
	// 선택자로 접근(클래스 등 동일한 이름의 선택자가 두 개 이상이면 처음 객체만 찾음)
	document.querySelector("#layout").innerHTML = s;
	
	// 스타일 변경
	var inputs = document.getElementsByTagName("input");
	for(var i = 0; i<inputs.length; i++) {
		if(inputs[i].type === "text") {
			inputs[i].style.border = "1px solid red";
		}
	}
	
	// document.getElementById("layout").style.background = '#ff0';
	// background-color
	document.getElementById("layout").style.backgroundColor = '#ff0';
	
}
</script>


</head>
<body>

<h3>DOM</h3>

<div>
	<p>이름 : <input type="text" id="name"> </p>
	<p>나이 : <input type="text" name="age"> </p>
	<p>생년월일 : <input type="text"> <input type="checkbox">양력 </p>
	<p>전화번호 : <input type="text" class="telClass"> </p>
	<p>
		<button type="button" onclick="result()">확인</button>
	</p>
</div>
<div id="layout"></div>

</body>
</html>

 

노드 추가 및 삭제

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
function fun() {
	// alert("음 언제 배웠지 ???");
	alert(event.currentTarget.firstChild.nodeValue);
}


// 속성 값 및 자식 노드 수 알아보기
function sub1() {
	var str;
	var div = document.getElementById("layout");
	
	// 속성 값 가져오기 
	str = div.getAttribute("style");
	
	// 자식 노드 정보(childNodes : 문자열, 공백, 엔터 등도 검색)
	// (NodeList(7) [text, p, text, p, text, p, text])
	// str += "\n자식수 : " + div.childNodes.length; // 7
	// console.log(div.childNodes);
	// 자식 노드 정보(children:태그만)
	str += "\n자식수 : " + div.children.length; // 3
	// console.log(div.children); // [p, p, p]
	alert(str);
}

// 노드를 마지막에 추가
function sub2() {
	var div = document.getElementById("layout");
	
	var node = document.createElement("p");
	node.setAttribute("onclick", "fun();"); // click 이벤트 추가
	var textNode = document.createTextNode("마지막!!!");
	node.appendChild(textNode);
	div.appendChild(node);
}

// 노드를 특정 노드 앞에 추가
function sub3() {
	var div = document.getElementById("layout");
	
	var node = document.createElement("p");
	var textNode = document.createTextNode("앞!!!");
	node.appendChild(textNode);
	div.insertBefore(node, div.childNodes[0]);
	// div.insertBefore(node, div.childNodes[1]);
	// div.insertBefore(node, div.children[1]);
}

// 노드 삭제
function sub4() {
	var div = document.getElementById("layout");
	if(div.childNodes.length > 1) {
		div.removeChild(div.childNodes[1]);
	}
}

// 스타일 없애기
function sub5() {
	var div = document.getElementById("layout");
	// div.style.border = "none";
	div.style.removeProperty("border");
}

// 처음 p 태그 세개를 클릭하면 요소의 text 값 가져오기
window.onload = function() {
	var ps = document.getElementById("layout").children;
	for(var i=0; i<ps.length; i++){
		ps[i].addEventListener("click", function() {
			alert(this.firstChild.nodeValue); // 태그의 텍스트 가져오기
		})
	}
}

</script>


</head>
<body>

<h3>노드 추가 및 삭제</h3>

<div id="layout" style="width: 300px; height: 300px; border: 1px solid #f00;">
	<p>자바</p>
	<p>안드로이드</p>
	<p>프레임워크</p>
</div>
<hr>

<div>
	<p>
		<button type="button" onclick="sub1()">노드정보</button>
		<button type="button" onclick="sub2()">노드추가</button>
		<button type="button" onclick="sub3()">특정노드앞에추가</button>
		<button type="button" onclick="sub4()">노드삭제</button>
		<button type="button" onclick="sub5()">스타일없애기</button>
	</p>
</div>

</body>
</html>

- 노드 정보

 

- 노드 추가

 

- 특정 노드 앞에 추가

 

- 노드 삭제

 

- 스타일 없애기 (스타일 속성의 border 프로퍼티 없애기)

 

노드 찾기

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>

<h3>노드 찾기</h3>
<div>
	<p><a>HTML</a></p>
	<p class="css"><a>CSS</a></p>
	<p>
		<A>javacript</A>
		<span>jquery</span>
	</p>
</div>
<hr>

<div class="pp">
	<div class="p">
		<div class="c1">javascript</div>
		<div class="c2">css</div>
	</div>
</div>

<script type="text/javascript">
// 모든 p 태그
var list = document.getElementsByTagName("p");

// 자식검색 : text(공백, 문자열 엔터 등), tag 검색
var c1 = list[2].childNodes;
// 자식검색 : tag만 검색
var c2 = list[2].children;
// a태그만 검색
var c3 = list[2].getElementsByTagName("a");

console.log(c1); // NodeList(5) [text,a,text,span,text]
console.log(c2); // HTMLCollection(2) [a,span]
console.log(c3); // HTMLCollection(1) [a]

var child = document.querySelector(".c1");
// 부모 검색
var p1 = child.parentNode; // 부모노드, 빈공간도 포함
var p2 = child.parentElement; // 부모노드만

console.log(p1);
console.log(p2);

// 형제
var s1 = child.nextSibling; // 텍스트(빈공간)도 포함
var s2 = child.nextElementSibling; // 태그만

console.log(s1); // #text
console.log(s2); // <div class="c2">css</div>

// 텍스트
var s3 = s2.firstChild.nodeValue;
console.log(s3);

</script>

</body>
</html>

정규식(regular expression)이란 ?

- 정규식(정규 표현식)은 문자열에서 나타나는 특정 문자 조합과 대응시키기 위해 사용되는 패턴이다.

- 정규식을 이용하면 특정 패턴과 일치하는 문자열의 검색, 치환, 추출 등이 가능하다.

- 자바 스크립트에서 정규식은 객체이다.

- 정규식 패턴(pattern)은 RegExp 객체의 exec(), test(), compile() 함수, 그리고 String 객체의 match(), replace(), search(), split() 메소드 등과 함께 쓰인다.

 

RegExp 객체 개요

- RegExp 객체는 정규 표현식을 구현한 자바스크립트 표준 내장 객체이다.

- RegExp 객체 생성

(1) 형식 var 변수 = new RegExp(pattern[, flags]);

(2) 매개변수

1) pattern : 정규식(regular expression)을 나타내는 문자로, 패턴은 따옴표나 슬래시(/)로 감싸야 한다.

2) flags : 기본 검색 설정을 변경할 수 있는 플래그로 다음 값이 조합을 가질 수 있다.

g : global match 일치하는 첫 번째 문자에서 멈추지 않고 전체에서 일치하는 모든 문자를 검색한다.

i : ignore case 대소문자를 구별하지 않는다.

m : multiline. 시작 또는 끝 문자 탐색(^or$)이 다중 행에 적용되도록 한다.

y : 대상 문자열에서 이 정규 표현식이 lastindex 속성에 의해 지정된 인덱스에서만 일치하며, 이후의 모든 인덱스에서 일치하지 않는다.

 

RegExp 객체 생성의 방법

- 리터럴 방식 : 파라미터에 따옴표를 사용해선 안된다.

- 생성자 방식 : 파라미터에 따옴표를 사용해야 한다.

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
var p, s;

// 1. 리터널 방식 : 파라미터에 따옴표를 사용하지 않는다.
p = /ab+c/i; // + : 앞문자 1개 이상, i:대소문자를 구분하지 않음
  // ac(X), abbc(O), ab(X), a1bc(X), xy abc 12(o)
s = 'xy abc 12';
console.log( p.test(s) );

// 2. 생성자 방식
p = new RegExp('ab+c', 'i');
s = 'xy Abc 12';
console.log(p.test(s));

</script>

</head>
<body>

<h3>정규식(Regular Expression) - 정규식 생성방법</h3>

</body>
</html>

 

flag

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<script type="text/javascript">
var p, s;

// g : global match - 일치하는 모든 문자 검색. 치환할 때 유용
// i : ignore case - 대소문자 구문안함

p = /[a-d]+/;
s = '12ax';
console.log( p.test(s) ); // true
s = '12Ax';
console.log( p.test(s) ); // false

p = /[a-d]+/i;
s = '12ax';
console.log( p.test(s) ); // true
s = '12Ax';
console.log( p.test(s) ); // true

s = "web 자바 jsp 자바 html 자바";
p = /자바/;
var a = s.replace(p, 'java');
console.log(a); // web java jsp 자바 html 자바

p = /자바/g;
var a = s.replace(p, 'java');
console.log(a); // web java jsp java html java

</script>

</head>
<body>

<h3>정규식(Regular Expression) - flag </h3>

</body>
</html>

 

패턴

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script type="text/javascript">
var p, s;

p = /a.s/;
s = "abs";
console.log( p.test(s) ); // true
s = "as";
console.log( p.test(s) ); // false


// .* : 모든 문자
// 자바로 시작
p = /^자바.*/; // .은 반드시 한글자 *은 앞에있는 글자가 0개 이상
s = "자바 사랑";
console.log( p.test(s) ); // true
s = "이자바";
console.log( p.test(s) ); // false

//자바로 끝
p = /.*자바$/; // .은 반드시 한글자 *은 앞에있는 글자가 0개 이상
s = "자바 사랑";
console.log( p.test(s) ); // false
s = "이자바";
console.log( p.test(s) ); // true

// 자바로 시작하고 웹으로 끝나는 모든 문자
p = /^자바.*웹$/;
s = "자바 스프링 웹";
console.log( p.test(s) ); // true
s = '자바 웹 스프링';
console.log( p.test(s) ); // false
s = "자바웹";
console.log( p.test(s) ); // true

// 한자리 숫자
// p = /\d{1}/; // a1b 도 됨. a13ba1도 됨.
// p = /^\d{1}$/;
p = /^[0-9]$/;
s = '7';
console.log( p.test(s) ); // true
s = '77';
console.log( p.test(s) ); // false

// 한자리 이상 숫자
// p = /^\d{1,}$/;
// p = /^(\d)+$/;
p = /^[0-9]+$/;
s = '12';
console.log( p.test(s) ); // true
s = '+12';
console.log( p.test(s) ); // false

// 한자리 이상 숫자(부호가능, 소수점 가능)
p = /^[+-]?\d+(\.?\d*)$/; // +-는 와도되고 안와도되고.
s = '12';
console.log( p.test(s) ); // true
s = '+12.5';
console.log( p.test(s) ); // true
s = '+12';
console.log( p.test(s) ); // true

// 1~3자리 자연수
p = /^\d{1,3}$/;
s = '123';
console.log( p.test(s) );
s = '1233';
console.log( p.test(s) );

</script>

</head>
<body>

<h3>정규식(Regular Expression) - 패턴</h3>

</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script type="text/javascript">
var p, s;

// 1자 이상의 영숫자
// p = /^[a-z0-9]+$/i;
p = /^[a-zA-Z0-9]+$/;

//1자 이상의 영숫자, _
p = /^\w+$/;

// 영문, 띄어쓰기만 가능
p = /^[a-zA-Z\s]+$/;
s = 'a b';
console.log( p.test(s) ); // true
s = 'a 1';
console.log( p.test(s) ); // false
s = '   ';
console.log( p.test(s) ); // true 

// 영문으로 시작하고 영문, 띄어쓰기만
p = /^(?=[a-z])[a-z\s]+$/i;
s = 'a b';
console.log( p.test(s) ); // true
s = '   ';
console.log( p.test(s) ); // false

// 자바, 웹, java, web 중 하나라도 존재 여부(영문은 대소문자 구분안함)
p = /(자바|웹|java|web)/i;
s = '스프링 오라클 서블릿';
console.log( p.test(s) ); // false
s = '스프링 오라클 web';
console.log( p.test(s) ); // true

// 0자 이상 한글
// p = /^[가-힣]*$/;
p = /^[\uac00-\ud7a3]*$/;

// 1자 이상 한글
p = /^[가-힣]+$/;

// 이미지 파일
p = /(\.gif|\.jpg|\.jpeg|\.png)$/i;

</script>

</head>
<body>

<h3>정규식(Regular Expression) - 패턴</h3>

</body>
</html>

 

 

HTML 태그를 특수문자로 변환

더보기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script type="text/javascript">
function symbolHtml(content) {
	if(! content ) return content;
	
	content = content.replace(/</g, "&lt;"); 
	content = content.replace(/>/g, "&gt;");
	// 붙여도 되는 것이 있고, 안붙여도 되는 것이 있음, 모르겠으면 \를 붙이자
	content = content.replace(/\"/g, "&quot;");
	content = content.replace(/\'/g, "&#39;");
	content = content.replace(/\(/g, "&#40;");
	content = content.replace(/\)/g, "&#41;");
	
	return content;
}

function send() {
	var f = document.myForm;
	var s;
	
	s = f.msg.value.trim();
	if( !s ) {
		alert("내용을 입력하세요.");
		f.msg.focus();
		return;
	}
	
	s = symbolHtml(s);
	f.msg.value = s;
	
	
}
</script>

</head>
<body>

<h3>HTML 태그를 특수 문자로 변환</h3>

<form name="myForm">
<p>
 내용 : <textarea rows="5" cols="50" name="msg"></textarea>
</p>
<p>
 <button type="button" onclick="send()">보내기</button>
</p>
</form>

</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
* {
	margin: 0; padding: 0;
    box-sizing: border-box;
}

body {
	font-size: 14px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
}

a {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}
a:active, a:hover {
	text-decoration: underline;
	color: #F28011;
}

.btn {
	color: #333;
	border: 1px solid #333;
	background-color: #fff;
	padding: 4px 10px;
	border-radius: 4px;
	font-weight: 500;
	cursor:pointer;
	font-size: 14px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}
.btn:hover, .btn:active, .btn:focus {
	background-color: #e6e6e6;
	border-color: #adadad;
	color:#333;
}
.boxTF {
	border: 1px solid #999;
	padding: 5px 5px;
	background-color: #fff;
	border-radius: 4px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}
.selectField {
	border: 1px solid #999;
	padding: 4px 5px;
	border-radius: 4px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}

.boxTA {
    border:1px solid #999;
    height:150px;
    padding:3px 5px;
    border-radius:4px;
    background-color:#fff;
	resize : none;
	vertical-align: baseline;
}

textarea:focus, input:focus {
	outline: none;
}

.title {
	width:100%;
	font-size: 16px;
	font-weight: bold;
	padding: 13px 0;
}

.container {
    width: 400px;
    margin: 30px auto;
}

.table {
	width: 100%;
	border-spacing: 0;
	border-collapse: collapse;
}

.table th, .table td {
	padding: 7px 0;
}

.table-border tr {
	border-bottom: 1px solid #ccc; 
}
.table-border tr:first-child {
	border-top: 2px solid #ccc;
}

</style>
<script type="text/javascript">

</script>
<script type="text/javascript">
function itemAdd() {
	var f = document.noteForm;
	var item = f.itemLeft;
	
	// select 요소에 option 요소 추가
	item[item.length] = new Option("김자바", "kim"); // text, value
	item[item.length] = new Option("스프링", "spring");
	item[item.length] = new Option("서블릿", "servlet");
	item[item.length] = new Option("오라클", "oracle");
	item[item.length] = new Option("이자바", "lee");
	item[item.length] = new Option("홍자바", "hong");
	item[item.length] = new Option("나대한", "na");
}

window.onload = () => itemAdd();

// 선택된 option을 좌 또는 우로 이동 
function itemMove(pos) {
	var f = document.noteForm;
	var source, target;
	
	if( pos==="left" ) { // right -> left
		source = f.itemRight;
		target = f.itemLeft;
	} else { // left -> right
		source = f.itemLeft;
		target = f.itemRight;
	}
	
	var len = source.length;
	for(var i =0; i<len; i++) {
		if(source.options[i].selected) { // 선택된 항목만
			target[target.length] = 
				new Option(source.options[i].text, source.options[i].value);
			source[i] = null; // 삭제
			i--;
			len--;
		}
	}
	
}

// 모든 option을 좌 또는 우로 이동
function itemAllMove(pos) {
	var f = document.noteForm;
	var source, target;
	
	if( pos==="left" ) { // right -> left
		source = f.itemRight;
		target = f.itemLeft;
	} else { // left -> right
		source = f.itemLeft;
		target = f.itemRight;
	}
	
	var len = source.length;
	for(var i =0; i<len; i++) {
		target[target.length] = new Option(source.options[0].text, source.options[0].value);
		source[0] = null; // 삭제
	}
	
}

function sendOk() {
	var f = document.noteForm;
	
	if( f.itemRight.length === 0 ) {
		alert("받는 사람을 먼저 추가 하세요...");
		f.itemRight.focus();
		return;
	}
	
	if(! f.msg.value.trim() ) {
		alert("메시지를 입력하세요...");
		f.msg.focus();
		return;
	}
	
	// select 요소는 서버로 전송하기 위해서 반드시 항목들이 선택되어 있어야 한다.
	for(var i=0; i < f.itemRight.length; i++) {
		f.itemRight[i].selected = true; // select 항목 선택
	}	
	
	alert("메시지 전송...");
	
}

</script>


</head>
<body>

<div class="container">

	<div class="title">
	   <h3><span>|</span> 쪽지 보내기</h3>
	</div>

	<form name="noteForm" method="post">
	<table class="table">
	<tr>
	    <td width="150"><span>친구목록</span></td>
	    <td width="100">&nbsp;</td>
	    <td width="150"><span>받는사람</span></td>
	</tr>
	
	<tr>
	    <td style="padding-left: 10px;">
	        <select name="itemLeft" multiple="multiple" class="selectField" style="width:130px; height:120px;"></select>
	    </td>
	    <td align="center">
		    <button type="button" class="btn" onclick="itemMove('right');" style="display:block; width:80px;"> &gt; </button>
		    <button type="button" class="btn" onclick="itemAllMove('right');" style="display:block;width:80px;"> &gt;&gt; </button>
		    <button type="button" class="btn" onclick="itemMove('left');" style="display:block;width:80px;"> &lt; </button>
		    <button type="button" class="btn" onclick="itemAllMove('left');" style="display:block;width:80px;"> &lt;&lt; </button>
	    </td>
	    <td style="padding-left: 10px;">
	        <select name="itemRight" multiple="multiple" class="selectField" style="width:130px; height:120px;">
	        </select>
	    </td>
	</tr>
	<tr>
	    <td colspan="3">
	       <span>메시지</span>
	    </td>
	</tr>
	<tr>
	    <td colspan="3" style="padding-left: 10px;">
	        <textarea name="msg" class="boxTA" style="height:60px; width: 98%;"></textarea>
	    </td>
	</tr>
	</table>
	
	<table class="table">
	<tr>
	    <td align="right" style="padding-right: 10px;">
	        <button type="button" class="btn" onclick="sendOk();"> 쪽지보내기 </button>
	    </td>
	</tr>
	</table>
	</form> 

</div>

</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
*{
	margin: 0; padding: 0;
    box-sizing: border-box;
}

body {
	font-size: 14px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
}

a {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}
a:active, a:hover {
	text-decoration: underline;
	color: #F28011;
}

.btn {
	color: #333;
	border: 1px solid #333;
	background-color: #fff;
	padding: 4px 10px;
	border-radius: 4px;
	font-weight: 500;
	cursor:pointer;
	font-size: 14px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline; /* 부모 요소의 기준선에 맞춤 */
}
.btn:hover, .btn:active, .btn:focus {
	background-color: #e6e6e6;
	border-color: #adadad;
	color:#333;
}
.boxTF {
	border: 1px solid #999;
	padding: 5px 5px;
	background-color: #fff;
	border-radius: 4px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}
.selectField {
	border: 1px solid #999;
	padding: 4px 5px;
	border-radius: 4px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}

textarea:focus, input:focus {
	outline: none;
}

.member {
	width: 600px; margin: 30px auto 25px;
}

.title {
	width:100%;
	font-size: 16px;
	font-weight: bold;
	padding: 13px 0;
}

.table {
	width: 100%;
	border-spacing: 0;
	border-collapse: collapse;
}

.table th, .table td {
	padding: 7px 0;
}

.table-border tr {
	border-bottom: 1px solid #ccc; 
}
.table-border tr:first-child {
	border-top: 2px solid #ccc;
}

.table-form tr td:first-child{
	background: #e6e6e6;
	text-align: center;
	width: 120px;
}

.table-form tr td:nth-child(2) {
	text-align: left;
	padding-left: 10px; 
}

.table-form input[type=text]:focus, .table-form input[type=password]:focus {
	border: 1px solid tomato;
}
</style>

<script type="text/javascript">
function isValidDateFormat(date) {
	if(date.length !=8 && date.length != 10) return false;
	
	var p = /(\.)|(\-)|(\/)/g;
	date = date.replace(p, "");
	
	var format = /^[12][0-9]{7}$/;
	if(! format.test(date) ) return false;
	
	var y = parseInt( date.substr(0,4) );
	var m = parseInt( date.substr(4,2) );
	var d = parseInt( date.substr(6) );
	
	if(m<1 || m>12) return false;
	
	var lastDay = (new Date(y,m,0)).getDate();
	if(d<1 || d>lastDay) return false;
	
	return true;
}


function memberOk() {
	var f = document.memberForm;
	var s;
	
	// 아이디는 5~10자 이며 영문자로 시작하고 영숫자와_로 구성
	// i 대소문자를 구분하지 않음 [a-zA-Z] 와 같은 의미
	// \w 영어, 숫자, _ 까지 가능
	if(! /^[a-z]\w{4,9}$/i.test(f.userId.value)) {
		alert("아이디는 영문자로 시작하며, 5~10자이내의 영숫자로 구성합니다.")
		f.userId.focus();
		return;
	}
	
	// 패스워드는 5~10자이며 영문자와 하나이상의 숫자 또는 특수문자를 포함해야함
	s = f.userPwd.value;
	if( ! /^(?=.*[a-z])(?=.[!@#$%^&*-=+]|.*[0-9]).{5,10}$/i.test(s)) {
		alert("패스워드는 5~10자 이내로 영문자와 숫자 또는 특수문자로 구성합니다.");
		f.userPwd.focus();
		return;
	}
	
	
	if( s != f.userPwd1.value ) {
		alert("패스워드가 일치하지 않습니다.");
		f.userPwd.focus();
		return;
	}
	
	// 이름은 한글 2~5자 이내이거나 영어 이름 : 이름(2~20) 성(2~20)
	
	// 이름은 한글 2~5자 이내
	s = f.userName.value;
	if(! /^[가-힣]{2,5}$/.test(s) ) {
		alert("이름을 입력하세요");
		f.userName.focus();
		return;
	}
	
	// 생년월일
	if(! isValidDateFormat(f.birth.value) ) {
		alert("생년월일 입력하세요");
		f.birth.focus();
		return;
	}
	
	if(! f.email1.value.trim() ) {
		alert("이메일을 입력하세요");
		f.email1.focus();
		return;
	}
	
	if(! f.email2.value.trim() ) {
		alert("이메일을 입력하세요");
		f.email2.focus();
		return;
	}
	
	if(! f.tel1.value ) {
		alert("전화번호를 입력하세요");
		f.tel1.focus();
		return;
	}
	
	if(! /^\d{3,4}$/.test(f.tel2.value) ) {
		alert("전화번호를 입력하세요");
		f.tel2.focus();
		return;
	}
	
	if(! /^\d{4}$/.test(f.tel3.value) ) {
		alert("전화번호를 입력하세요");
		f.tel3.focus();
		return;
	}
	
	alert("회원 가입 성공 ^^");
}

function changeEmail() {
	var f = document.memberForm;
	var s = f.selectEmail.value;
	
	if(s === "direct") {
		f.email2.value = "";
		f.email2.readOnly = false;
		f.email1.focus();		
	} else {
		f.email2.value = s;
		f.email2.readOnly = true;
		f.email1.focus();
	}
	
}

</script>

</head>
<body>

<div class="member">
	<div class="title">
		<h3><span>|</span> 회원 가입</h3>
	</div>
	
	<form name="memberForm" method="post">
	<table class="table table-border table-form">
		<tr>
			<td>아&nbsp;이&nbsp;디</td>
			<td>
				<input type="text" name="userId" id="userId" maxlength="10" class="boxTF" style="width: 50%;">
			</td>
		</tr>
	
		<tr>
			<td>패스워드</td>
			<td>
				<input type="password" name="userPwd" class="boxTF" maxlength="10" style="width: 50%;">
			</td>
		</tr>
	
		<tr>
			<td>패스워드 확인</td>
			<td >
				<input type="password" name="userPwd1" class="boxTF" maxlength="10" style="width: 50%;">
			</td>
		</tr>
	
		<tr>
			<td>이&nbsp;&nbsp;&nbsp;&nbsp;름</td>
			<td>
				<input type="text" name="userName" maxlength="10" class="boxTF" style="width: 50%;">
			</td>
		</tr>
	
		<tr>
			<td>생년월일</td>
			<td>
				<input type="date" name="birth" class="boxTF" style="width: 50%;">
			</td>
		</tr>
	
		<tr>
			<td>이 메 일</td>
			<td>
				  <select name="selectEmail" class="selectField" onchange="changeEmail();">
						<option value="">선 택</option>
						<option value="naver.com">네이버 메일</option>
						<option value="hanmail.net">한 메일</option>
						<option value="hotmail.com">핫 메일</option>
						<option value="gmail.com">지 메일</option>
						<option value="direct">직접입력</option>
				  </select>
				  <input type="text" name="email1" maxlength="30" class="boxTF" style="width: 33%;"> @ 
				  <input type="text" name="email2" maxlength="30" class="boxTF" style="width: 33%;" readonly="readonly">
			</td>
		</tr>
		
		<tr>
			<td>전화번호</td>
			<td>
				  <select name="tel1" class="selectField">
						<option value="">선 택</option>
						<option value="010">010</option>
						<option value="02">02</option>
						<option value="031">031</option>
						<option value="032">032</option>
						<option value="033">033</option>
						<option value="041">041</option>
						<option value="042">042</option>
						<option value="043">043</option>
						<option value="044">044</option>
						<option value="051">051</option>
						<option value="052">052</option>
						<option value="053">053</option>
						<option value="054">054</option>
						<option value="055">055</option>
						<option value="061">061</option>
						<option value="062">062</option>
						<option value="063">063</option>
						<option value="064">064</option>
						<option value="070">070</option>
				  </select>
				  <input type="text" name="tel2" maxlength="4" class="boxTF" style="width: 33%;"> -
				  <input type="text" name="tel3" maxlength="4" class="boxTF" style="width: 33%;">
			</td>
		</tr>
	
		<tr>
			<td>우편번호</td>
			<td>
				<input type="text" name="zip" maxlength="7" class="boxTF" readonly="readonly" style="width: 50%;">
				<button type="button" class="btn">우편번호검색</button>
			</td>
		</tr>
		
		<tr>
			<td valign="top">주&nbsp;&nbsp;&nbsp;&nbsp;소</td>
			<td>
				<label style="display: block;">
					<input type="text" name="addr1" maxlength="50" class="boxTF" readonly="readonly" style="width: 96%;">
				</label>
				<label style="display: block; margin-top: 2px;">
					<input type="text" name="addr2" maxlength="50"  class="boxTF" style="width: 96%;">
				</label>
			</td>
		</tr>
		
		<tr>
			<td>직&nbsp;&nbsp;&nbsp;&nbsp;업</td>
			<td>
				<input type="text" name="job" maxlength="10" class="boxTF" style="width: 50%;">
			</td>
		</tr>
	</table>
	
	<table class="table">
		<tr>
			<td align="center">
			    <button type="button" class="btn" onclick="memberOk();"> 회원가입 </button>
			    <button type="reset" class="btn"> 다시입력 </button>
			    <button type="button" class="btn"> 가입취소 </button>
			</td>
		</tr>
		
		<tr height="40">
			<td align="center">
				<span style="color: blue;"></span>
			</td>
		</tr>
	</table>
	</form>
	
</div>	

</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<style type="text/css">
* {
	margin: 0; padding: 0;
    box-sizing: border-box;
}

body {
	font-size: 14px;
	font-family: "Malgun Gothic", "맑은 고딕", NanumGothic, 나눔고딕, 돋움, sans-serif;
}

a {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}
a:active, a:hover {
	text-decoration: underline;
	color: #F28011;
}

.btn {
	color: #333;
	border: 1px solid #333;
	background-color: #fff;
	padding: 4px 10px;
	border-radius: 4px;
	font-weight: 500;
	cursor:pointer;
	font-size: 14px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}
.btn:hover, .btn:active, .btn:focus {
	background-color: #e6e6e6;
	border-color: #adadad;
	color:#333;
}
.boxTF {
	border: 1px solid #999;
	padding: 5px 5px;
	background-color: #fff;
	border-radius: 4px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}
.selectField {
	border: 1px solid #999;
	padding: 4px 5px;
	border-radius: 4px;
	font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif;
	vertical-align: baseline;
}

.board {
	margin: 30px auto;
	width: 700px;
}

.title {
	width:100%;
	font-size: 16px;
	font-weight: bold;
	padding: 13px 0;
}

.table {
	width: 100%;
	border-spacing: 0;
	border-collapse: collapse;
}

.table th, .table td {
	padding: 10px 0;
}

.table-border tr {
	border-bottom: 1px solid #ccc; 
}
.table-border thead tr:first-child {
	border-top: 2px solid #ccc;
}

.table-list thead tr:first-child{
	background: #eee;
}
.table-list td {
	text-align: center;
}

.table-list td:nth-child(6n+3) {
	text-align: left;
	padding-left: 5px; 
}

.table-list tbody tr:hover {
	background: #efffef;
}

.table-list .chk {
	width: 40px;
	color: #787878;
}
.table-list .num {
	width: 60px;
	color: #787878;
}
.table-list .subject {
	color: #787878;
}

.table-list .name {
	width: 100px;
	color: #787878;
}
.table-list .date {
	width: 100px;
	color: #787878;
}
.table-list .hit {
	width: 70px;
	color: #787878;
}

.paginate {
	clear: both;
	text-align: center;
	white-space: nowrap;
	font-size: 14px;	
}
.paginate a {
	border: 1px solid #ccc;
	color: #000;
	font-weight: 600;
	text-decoration: none;
	padding: 3px 7px;
	margin-left: 3px;
	vertical-align: middle;
}
.paginate a:hover, .paginate a:active {
	color: #6771ff;
}
.paginate span {
	border: 1px solid #e28d8d;
	color: #000;
	font-weight: 600;
	padding: 3px 7px;
	margin-left: 3px;
	vertical-align: middle;
}
.paginate :first-child {
	margin-left: 0;
}
</style>

<script type="text/javascript">
function check() {
	var f = document.listForm;
	
	// checkbox 이름이 nums 인 요소가 한 개도 없는 경우
	if( f.nums === undefined ) { // if(! f.nums ) {
		return;
	}
	
	// checkbox 이름이 nums 인 요소가 한 개인 경우
	if( f.nums.length === undefined ) {
		f.nums.checked = f.chkAll.checked;
	}
	
	// checkbox 이름이 nums 인 요소가 두 개 이상인 경우
	// 동일한 이름은 객체가 두 개 이상인 경우에만 length속성이 존재한다.
	// checked 속성 : checkbox, radio 버튼을 선택/해제하거나 선택 유무를 true/false로 반환
	for(var i=0; i < f.nums.length; i++){
		f.nums[i].checked = f.chkAll.checked;
	}
}

function deleteList() {
	var f = document.listForm;
	var cnt = 0;
	
	if( ! f.nums ){
		return;
	}
	
	if( f.nums.length ) {
		// nums가 여러 개인 경우
		for(var i=0; i<f.nums.length; i++){
			if(f.nums[i].checked) {
				cnt++;
			}
		}
	} else {
		// nums가 하나인 경우
		if(f.nums.checked) {
			cnt++;
		}
	}
	
	if( cnt === 0 ){
		alert("삭제할 게시물을 먼저 선택하세요");
		return;
	}
	
	if( confirm("선택한 게시글을 삭제하시겠습니까 ? ")) {
		alert("삭제 Ok...");
		
	}
}
	
</script>

</head>
<body>

<div class="board">

	<div class="title">
	    <h3><span>|</span> 게시판</h3>
	</div>

	<table class="table">
	   <tr>
		  <td align="left" width="50%">
		  	<button type="button" class="btn" onclick="deleteList();">삭제</button>
		  </td>
		  <td align="right">
			 <select name="rows" id="rows" class="selectField">
				   <option value="5">5개씩 출력</option>
				   <option value="10" selected="selected">10개씩 출력</option>
				   <option value="20">20개씩 출력</option>
				   <option value="30">30개씩 출력</option>
				   <option value="50">50개씩 출력</option>
			 </select>
		  </td>
	   </tr>
	</table>

	<form name="listForm" method="post">
	<table class="table table-border table-list">
	<thead>
		<tr> 
			<th class="chk">
				<input type="checkbox" name="chkAll" id="chkAll" onclick="check();" style="margin-top: 3px;">        
			</th>
			<th class="num">번호</th>
			<th class="subject">제목</th>
			<th class="name">작성자</th>
			<th class="date">작성일</th>
			<th class="hit">조회수</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td><input type="checkbox" name="nums" value="2" style="margin-top: 3px;"></td> 
			<td>2</td>
			<td>
				<a href="">HTML 강좌...</a>
			</td>
			<td>홍길동</td>
			<td>2017-03-03</td>
			<td>1</td>
		</tr>

		<tr> 
			<td><input type="checkbox" name="nums" value="1" style="margin-top: 3px;"></td> 
			<td>1</td>
			<td>
				<a href="">자바 강좌...</a>
			</td>
			<td>김자바</td>
			<td>2017-01-10</td>
			<td>1</td>
		</tr>
	</tbody>
	</table>
	</form>
	
	<table class="table">
		<tr height="50">
			<td align="center">
				<div class="paginate">
					<span>1</span>
					<a href="#">2</a>
					<a href="#">3</a>
				</div>
			</td>
	   </tr>
	</table>

	<table class="table">
		<tr height="45">
			<td width="100">
				<button type="button" class="btn">새로고침</button>
			</td>
			<td align="center">
				<form name="searchForm" action="" method="post">
					<select name="condition" class="selectField">
						<option value="all">제목+내용</option>
						<option value="name">작성자</option>
						<option value="regDate">등록일</option>
						<option value="subject">제목</option>
						<option value="content">내용</option>
					</select>
					<input type="text" name="keyword" value="" class="boxTF">
					<button type="button" class="btn">검색</button>
				</form>
			</td>
			<td align="right" width="100">
				<button type="button" class="btn">글올리기</button>
			</td>
		</tr>
	</table>

</div>

</body>
</html>

 

+ Recent posts