<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>image preview</title>
<style>
.container {
	margin: 30px auto;
	width: 500px;
}

#image_zone {
  width: 660px;
  min-height: 150px;
  padding: 10px;
  border: 1px dotted #00f;
  margin-top: 5px;
}

#image_zone:empty:before {
  content: attr(data-placeholder);
  color: #999;
  font-size: .9em;
}

.image-box {
	display: inline-block;
	position: relative;
	width: 150px; height: 120px;
	margin: 5px;
	border: 1px solid #00f;
	z-index: 1;
}

.image {
	width: 100%; height: 100%;
	z-index: none;
}

.image-btn {
	/* width:30px; height:30px; */
	position: absolute;
	font-size: 15px;
	right: 0px;
	bottom: 0px;
	z-index: 999;
	background-color:rgba(255,255,255,0.1);
	color: #f00;
	border: 1px solid #333;
	cursor: pointer;
	padding: 2px 5px;
}
</style>
</head>
<body>

<div class='container'>
	<h3>이미지 미리보기</h3>
	<form name="frm">
		<input type='file' name='selectFile' id='selectFile' multiple='multiple'>
		<div id='image_zone'
			data-placeholder='파일을 첨부 하려면 파일 선택 버튼을 클릭하거나 파일을 드래그앤드롭 하세요'></div>
	</form>
</div>

<script type="text/javascript">
( /* vid : 이미지들이 들어갈 위치 id, fid : file 태그 id */
	imageView = function imageView(vid, fid) {
		var imageZone = document.getElementById(vid);
		var selectFile = document.getElementById(fid);
		var sel_files = [];
    
		selectFile.onchange = function(e){
			var files = e.target.files;
			var fileArr = Array.prototype.slice.call(files) 
            // begin부터 end-1 인덱스 까지 요소를 얕은 복사하여 새로운 배열 객체로 반환
			for(f of fileArr) {
				imageLoader(f);
			}
		}; 
  
		// 탐색기에서 드래그앤 드롭 사용
		
		// 드래그로 넣었을 때 
		imageZone.addEventListener('dragenter', function(e) {
			e.preventDefault();
			e.stopPropagation();
		}, false);
		
		
    	// 드롭대상위로 지나갈 때
		imageZone.addEventListener('dragover', function(e) {
			e.preventDefault();
			e.stopPropagation();
		}, false);
  
    	// 드래그 할 때
		imageZone.addEventListener('drop', function(e) {
			var files = {};
			e.preventDefault();
			e.stopPropagation();
			var dt = e.dataTransfer;
			files = dt.files;
			for(f of files) {
				imageLoader(f);
			}
		}, false);
    
	    // 첨부된 이미지를 배열에 넣고 미리보기
		var imageLoader = function(file){
			sel_files.push(file);
			var reader = new FileReader();
			reader.onload = function(e) {
				let img = document.createElement('img')
				img.classList.add("image"); // class 추가
				img.src = e.target.result;
				imageZone.appendChild(makeDiv(img, file));
			};
	      
			var dt = new DataTransfer();
			for(f in sel_files) {
				var file = sel_files[f];
				dt.items.add(file);
			}
			selectFile.files = dt.files;
			
			reader.readAsDataURL(file);
		};
    
		// 첨부된 파일이 있는 경우 button과 함께 imageZone에 추가할 div를 만들어 반환
		var makeDiv = function(img, file) {
			var div = document.createElement('div');
			div.classList.add("image-box");
      
			var btn = document.createElement('input');
			btn.setAttribute('type', 'button');
			btn.setAttribute('value', 'x');
			btn.setAttribute('delFile', file.name);
			btn.classList.add("image-btn");
			btn.onclick = function(ev){
				var ele = ev.srcElement;
				var delFile = ele.getAttribute('delFile');
				for(var i=0 ;i<sel_files.length; i++){
					if(delFile === sel_files[i].name){
						sel_files.splice(i, 1);      
					}
				}
        
				var dt = new DataTransfer();
				for(f in sel_files) {
					var file = sel_files[f];
					dt.items.add(file);
				}
				selectFile.files = dt.files;
				
				var p = ele.parentNode;
				imageZone.removeChild(p);
			};
			div.appendChild(img);
			div.appendChild(btn);
			return div;
		};
	}
)('image_zone', 'selectFile'); // 바로 실행 함수
</script>
</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 $videoId = "";

function play() {
	var url = document.getElementById("youtube-url").value.trim();
	if(! url) {
		document.getElementById("youtube-url").focus();
		return;
	} // 입력한 주소 가져오기
	
	$videoId = url.substring(url.lastIndexOf('/') +1); 
	if(url.indexOf("=") > 0) {
		$videoId = url.substring(url.indexOf("=") + 1);
	}
	
	// youtube 실행
	var tag = document.createElement('script');
	tag.src = "https://www.youtube.com/iframe_api";	

	var firstScriptTag = document.getElementsByTagName('script')[0];
	firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);	
}

var player;
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    height: '360',
    width: '640',
    videoId: $videoId,
    events: {
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange
    }
  });
}

function onPlayerReady(event) {
  event.target.playVideo();
}

var done = false;
function onPlayerStateChange(event) {
  if (event.data == YT.PlayerState.PLAYING && !done) {
    //setTimeout(stopVideo, 6000);
    done = true;
  }
}
function stopVideo() {
  player.stopVideo();
}

</script>
</head>
<body>

<div style="width: 800px; margin: 30px auto; text-align: center;">
	<div style="margin: 10px; ">
		<input type="text" id="youtube-url">
		<button type="button" onclick="play();">확인</button>
	</div>
	<div id="player"></div>
</div>

</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- // 반응형 웹을 만들기 위해서 위의 줄이 꼭 필요 -->
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<style type="text/css">
.box {
	width: 300px;
	height: 300px;
	margin: 30px auto;
	border: 3px dotted #333;
	padding: 10px;
	background: green;
}
/* 브라우저의 너비가 0~600 인 경우는 박스를 사라지게 하고 싶음.*/
@media (max-width:600px) {
	.box {
		display: none;
	}
}
</style>

</head>
<body>

<h3>반응형 웹</h3>

<p> 미디어 쿼리 : 각 미디어 메체에 따라 다른 스타일을 적용할 수 있게 만드는 것</p>

<div class="box"></div>
</body>
</html>


- max-width : 데스크탑의 가장 큰 화면 사이즈의 레이아웃을 기본으로 하고, 점차 축소하는 형태로 css 작성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- // 반응형 웹을 만들기 위해서 위의 줄이 꼭 필요 -->
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<style type="text/css">
* {
	padding: 0; margin: 0; box-sizing: border-box;
}

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

.container {
	width: 1200px; margin: 20px auto 10px;
	border: 3px solid black;
}

.header {
	width: 100%; background: #e4f7ba;
	padding: 20px;
	text-align: center;
}

.body-main:after {
	content: ""; clear: both; display: block;
}

.article {
	float: left; width: 75%; height: 500px; background: #eee;
	padding: 15px;
}

.side {
	float: left; width: 25%; height: 500px; background: #faf4c0;
}

.footer {
	width: 100%;
	background: #9575cd;
	padding: 20px;
	text-align: center;
}

/*
  - max-width : 데스크탑의 가장 큰 화면 사이즈의 레이아웃은 기본으로 하고, 점차 축소하는 형태로 css 작성
*/

/* 화면 너비 : 0~1200 - 데스크탑 */
@media (max-width:1200px) {
	.container { width: 95%; border: 3px solid red; }
}

/* 화면 너비 : 0~768 - 태블릿 */ 
@media (max-width:768px) {
	.container { width: 100%; border: 3px solid green; }
}

/* 화면 너비 : 0~480 - 스마트폰 옆으로 늘일 때 */
@media (max-width:480px) {
	.container { width: 100%; border: 3px solid blue; }
	.header { height: 300px }
	.article { float: none; width: 100%; height: 300px };
	.side { float: none; width: 100%; height: 300px; }
}

/* 화면 너비 : 0~320 - 스마트폰 기본 */
@media (max-width:320px) {
	.container { width: 100%; border: 3px solid gray; }
}
</style>

</head>
<body>

<div class="container">
	<div class="header">
		<h1>헤더입니다.</h1>
	</div>
	<div class="body-main">
		<div class="article">
			메인입니다.
		</div>
		<div class="side">
			사이드입니다.
		</div>
	</div>
	<div class="footer">
		<h3>푸터입니다.</h3>
	</div>
	
</div>

</body>
</html>

화면을 축소 함에 따라 테투리의 색이 변하는 것을 확인할 수 있다.


- min-width : 스마트폰 등 가장 작은 사이즈에서의 레이아웃을 기본으로 하고, 점차 확대되어가는 형태의 css

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- // 반응형 웹을 만들기 위해서 위의 줄이 꼭 필요 -->
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<style type="text/css">
* {
	padding: 0; margin: 0; box-sizing: border-box;
}

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

.container {
	width: 1200px; margin: 20px auto 10px;
	border: 3px solid black;
}

.header {
	width: 100%; background: #e4f7ba;
	padding: 20px;
	text-align: center;
}

.body-main:after {
	content: ""; clear: both; display: block;
}

.article {
	float: left; width: 75%; height: 500px; background: #eee;
	padding: 15px;
}

.side {
	float: left; width: 25%; height: 500px; background: #faf4c0;
}

.footer {
	width: 100%;
	background: #9575cd;
	padding: 20px;
	text-align: center;
}

/*
  - min-width : 스마트폰 등 가장 작은 사이즈에서의 레이아웃을 기본으로 하고, 점차 확대되어가는 형태의 css
*/

/* 화면 너비 : 320px 이상 */
@media (min-width:320px) {
	.container { width: 100%; border: 3px solid gray; }
	.header { height: 300px }
	.article { float: none; width: 100%; height: 300px };
	.side { float: none; width: 100%; height: 300px; }
}

/* 화면 너비 : 480px 이상 */
@media (min-width:480px) {
	.container { width: 100%; border: 3px solid blue; }
	.header { height: 100% }
	.article { float: left; width: 75%; height: 500px };
	.side { float: left; width: 25%; height: 500px; }
}

/* 화면 너비 : 768px 이상 */
@media (min-width:768px) {
	.container { width: 100%; border: 3px solid green; }
}

/* 화면 너비 : 1024px 이상 */
@media (min-width:1024px) {
	.container { width: 100%; border: 3px solid red; }
}

</style>

</head>
<body>

<div class="container">
	<div class="header">
		<h1>헤더입니다.</h1>
	</div>
	<div class="body-main">
		<div class="article">
			메인입니다.
		</div>
		<div class="side">
			사이드입니다.
		</div>
	</div>
	<div class="footer">
		<h3>푸터입니다.</h3>
	</div>
	
</div>

</body>
</html>

CSS파일을 따로 뺐을 때

@charset "UTF-8";

* {
	padding: 0; margin: 0; box-sizing: border-box;
}

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

header {
	padding: 15px; text-align: center;
}

nav {
	overflow: hidden; background: #b70202;
}

nav>a {
	float: left; color: #fff; text-align: center; padding: 15px 12px; text-decoration: none;
	display: block;
}

nav>a:hover {
	font-weight: 600;
}

nav:after {
	content: ""; clear: both; display: block;
}

main .left {
	float: left; width: 75%; background: #eee; min-height: 500px; padding: 15px;
}

main .right {
	float: left; width: 25%; background: #faf4c0; min-height: 500px; padding: 15px;
}

main:after {
	content: ""; clear: both; display: block;
}

footer {
	padding: 20px; text-align: center; background: #e4f7ba;
}
@charset "UTF-8";

nav>a {
	float: none;
}

main .left, main .right {
	width: 100%; padding: 0;
}

CSS파일을 연결해주는 link 태그 안에 media 속성을 이용한다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">

<link rel="stylesheet" href="desktop.css" type="text/css">
<link rel="stylesheet" href="mobile.css" media="(max-width:480px)" type="text/css">

</head>
<body>

<header>
	<h1>반응형 웹</h1>
</header>
<nav>
	<a href="#">홈</a>
	<a href="#">스터디</a>
	<a href="#">공지사항</a>
</nav>
<main>
	<article class="left">
		<h3>메인 화면</h3>
	</article>
	<article class="right">
		<h3>사이드</h3>
	</article>
</main>
<footer>
	<h3>footer 영역</h3>
</footer>
</body>
</html>


반응형 그리드 레이아웃 

- grid-template-columns: repeat(auto-fill, minmax(~)) 이용

<!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;
}

header {
	padding: 15px; text-align: center;
}

main {
	padding: 15px;
}

footer {
	padding: 15px;
	text-align: center;
}

.box {
	margin: 0 auto;
	padding: 0;
	list-style: none;
}

.box>li {
	background: #eee;
	height: 200px;
}

.grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
	grid-column-gap: 8px;
	grid-row-gap: 8px;
}

	
</style>
</head>
<body>

<header>
	<h1>Grid Layout</h1>
</header>

<main>
	<ul class="box grid">
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
		<li></li>
	</ul>
</main>

<footer>
	<h3>footer</h3>
</footer>
</body>
</html>

웹 스토리지 ?

- 웹 스토리지 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>

+ Recent posts