Dom + jsDOMScript의 위치에 따른 실행Document APIElement APIEvent + js브라우저에서 발생하는 EventEventHandler 설정AJAX(Asynchronous Javascript and XML)AJAX request 보내기XMLHttpRequest 의 readyStatereadyState와 status 활용하여 response에 접근JSON(JavaScript Object Notation)익명함수, 즉시 호출예외처리[실습] 이미지 갤러리 만들기
Dom + js
DOM
- javascript 언어에서 document 객체를 통해 html 문서에 접근할 수 있는데, 그 이유는 html이DOM(Document Object Model - 객체 )에 의해 기술되기 때문임.
<html> <head> ... </head> <body> </body> </html>


- 컴퓨터가 문서를 잘 처리할 수 있도록 문서에 대한 구조를 약속한 것임
document.children[0] -> html 태그 document.children[0].children[0] -> html 안에 head document.children[0].children[1] -> body
Script의 위치에 따른 실행
- 브라우저는 HTML 문서를 읽으면서 script tag를 실행함
- HTML 문서 Element 파싱 보다 스크립트가 먼저 실행되면 접근되지 않음
- 페이지의 상단의 script 에서 이후 파싱될 Element에 접근하고 싶다면 document.onload 등의 eventhandler로 실행되도록 해야 함
- async, defer 속성을 이용하면 스크립트의 실행과 문서의 로딩을 동시에 진행할 수 있음(비 동기적)
Document API
엘리먼트 선택, 추가, 삭제 api
- document.getElementBy~ : 단일 엘리먼트를 선택하는 메소드
- document.getElementsBy~ : 다중 엘리먼트 선택 메소드
- document.querySselector : css selector를 기반으로 엘리먼트 선택
- document.createElement()
- 해당하는 Element api
- appendChild
- removeChild
- insertBefore(element, element) : 첫번째 element를 두번째 element 전에 삽입
- cloneNode() 호출된 element를 복사해서 반환
Element API
.innerHTML 속성
- 엘리먼트 안의 HTML코드를 변경
.innerText 속성
- 엘리먼트 안의 텍스트를 변경
.style 속성
- css를 변경 가능
getAttribute 메소드
- element의 속성의 값을 얻어옴
- 하나의 인자 : attribute 이름을 받음
- 직접 객체에 동기화되지 않는 속성(예 : src 속성) 에 대해서도 접근이 가능
setAttribute 메소드
- element의 속성의 값을 설정함
- 두개의 인자 : attribute 이름, 설정할 속성의 값을 받음
- 직접 객체에 동기화되지 않는 속성에 대해서도 값 설정이 가능
.value 속성
Event + js
- setTimeout(function, time) → timerId 반환
- clearTimeout(timerId) : timerId를 인자로 받아 예약되어 있던 function 호출 취소
- setInterval(function, time) → timerId : time시간이 경과할 때마다 function 함수를 콜백
- clearInterval(timerId)
브라우저에서 발생하는 Event
- form Event : HTML 문서의 form element에 변화가 생기거나 submit버튼을 누르는 경우 등의 상황에서 발생
- window Event : 페이지가 모두 로드되었을 때 발생하는 onload event 등이 있음
- mouse Event
- key Event
EventHandler 설정
- Tag 의 속성에 event handler 코드를 추가
- onEvent 속성 사용 ( onclick, onchange, onkeydown, ... )
<h1 onclick="console.log('clicked');">..</h1> <input type="text" onchange="console.log('changed');" onkeydown="console.log('typed');">
- property에 직접 Handler 설정
- Element의
"on"+"이벤트"
의 속성에 메소드를 직접 지정
document.getElementById("form1").onsubmit = function eventHandler(){ console.log("from property"); return false; // 브라우저의 submit 처리 비활성}
- addEventListener 메소드
document.getElementById("form1").addEventListener( "submit", function eventHandler(){ console.log("from addEventListener"); return false; } );
AJAX(Asynchronous Javascript and XML)
- 브라우저에서 페이지를 이동하지 않고 자바스크립트를 통해 HTTP Requeset를 보내고 그 응답을 받아 처리할 수 있는 기술
- 사용자에게 더 나은 사용 경험 제공. 대부분 웹사이트에서 사용함
AJAX request 보내기
<html> <script> var req = new XMLHttpRequest(); // http 요청을 만들 수 있는 새로운 객체 생성 req.open("GET", "./data.txt"); // http request method와 URL 설정 req.send(); // 요청 전송 // console.log(req.response) -> undefined </script> </html>
- 위와 같이 응답을 보내면 req.response에 response의 응답값이 저장됨. 그러나 비동기 방식으로 요청되는 것이기 때문에 script에서 바로 접근하면 undefined가 뜨고 callback 식으로 접근해야함
XMLHttpRequest 의 readyState
var req = new XMLHttpRequest(); req2.readyState; -> 0 req2.open("GET", "./data.txt"); req2.readyState; -> 1 req2.send(); // response의 header를 받으면 2, response의 body를 받으면 3 req2.readyState; -> 4 // 최종적으로 4 req2.onreadystatechange = function a(){ console.log(this.readyState, this.status); // this.status 는 http 상태 코드를 나타냄 }// 이벤트 핸들러
- 0 : open 메소드 호출 전
- 1: open 메소드 호출 후
- 2 : 보낸 요청에 대해 응답에 헤더가 수신된 후
- 3 : 응답 메세지에 바디 부분이 수신 중 일 때
- 4: 모든 응답이 완료되었을 때
readyState와 status 활용하여 response에 접근
<html> <head> <meta charset="utf-8"> <script> var req = new XMLHttpRequest(); req.addEventListener("readystatechange", function call(){ console.log(this.readyState, this.status); if(this.readyState == 4 && this.status==0){ console.log(this.response); }}); // or req.onreadystatechange = function call(){}; req.open("GET", "./data.txt"); req.send(); </script> </head> <body> AJAX </body> </html>
JSON(JavaScript Object Notation)
- 자바스크립트의 객체를 문자열로 표현하는 방법
var arr=["문자열", 3.14, true, null, undefined, function a(){console.log("method")}]; var t = JSON.stringify(arr); // '["문자열",3.14,true,null,null,null]' JSON.parse(t); // ['문자열', 3.14, true, null, null, null] var obj = {"str": "문자열", "num": 3.14, "boolean":true, "null":null, "undefined":undefined, "method": function a(){console.log("method")}}; JSON.stringify(obj) '{"str":"문자열","num":3.14,"boolean":true,"null":null}' // 마찬가지로 undefined와 method는 날라간것을 확인가능함
- JSON은 객체의 데이터 만을 문자열 화 하기 때문에 undefined와 메서드는 포함시키지 않음
익명함수, 즉시 호출
var sum = 0; for(var i= 1; i<=50; i++){ sum += i; } (function a(){ for(var i=1; i<=5; i++){ console.log(i); })(); // 즉시 함수 호출 (function(){ for(var i=1; i<=5; i++){ console.log(i); })(); // 익명 함수 호출 -> parameter로 넘길 때 특히 편함 for(; i<=100; i++){ sum+= i; } console.log(sum); // 익명함수 사용 예제 setTimeout(function(){ // body }, 3000);
예외처리
try{ console.log("aaa"); throw "error"; console.log("bbb"); } catch(e){ console.log("catch error : ", e); } finally{ console.log(" always executed"); }
- 에러 발생시키기 : throw 명령 사용 (문자열, 숫자, 객체 등 javascript object를 자유롭게 활용 가능함)
[실습] 이미지 갤러리 만들기
var req = new XMLHttpRequest(); req.open("GET", "static/image_list.json"); req.onreadystatechange = function () { if (this.readyState == 4) { var data = JSON.parse(this.response); for (var i = 0; i < data.length; i++) { var div = document.createElement("div"); div.setAttribute("class", "image"); div.onclick = function () { this.classList.toggle("image-selected"); // toggle을 활용하면 해당 클래스가 존재하면 제거, 없으면 추가해줌 } div.onmouseover = function () { var element = this; this.timerId = setTimeout(function () { element.classList.add("image-magnified"); // 이 function안에서 this에 접근하면 window 오브젝트를 가리키게 됨. 따라서 // 클로져를 활용하여 바깥에서 element를 정의해서 접근하도록 함 }, 1000); } div.onmouseout = function () { this.classList.remove("image-magnified"); clearTimeout(this.timerId); // clearTimeout을 통해 onmouseover를 실행하기 전에 onmouseout이 // 실행되는 상황을 방지함 } // div 의 onmouseover 와 onmouseout 에 callback function을 // 위치 시킴으로 image 확대 기능을 구현하였음 var img = document.createElement("img"); img.setAttribute("src", data[i]); div.appendChild(img); document.body.appendChild(div); } } } req.send(); function selectAll(input) { var images = document.getElementsByClassName("image"); for (var i = 0; i < images.length; i++) { if (input.value == "Unselect All") { images[i].classList.remove("image-selected"); } else { images[i].classList.add("image-selected"); } } if (input.value == "Unselect All") { input.value = "Select All"; } else { input.value = "Unselect All"; } } function slideShow(button) { var images = document.getElementsByClassName("image"); var idx = 0; images[idx].classList.add("image-magnified"); var timerId = setInterval(function () { images[idx].classList.remove("image-magnified"); idx++; if (idx < images.length) { images[idx].classList.add("image-magnified"); } else { clearInterval(timerId); } }, 2000); }
<html> <head> <link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}"> <script src="{{url_for('static', filename='gallery.js')}}"></script> </head> <body style="overflow:scroll"> <input type="button" value="Select All" onclick="selectAll(this);"> <input type="button" value="Slide Show" onclick="slideShow(this);"> <hr> </body> </html>