(구체적인 언어적인 부분은 따로 정리 - 드림코딩님강의랑 같이 정리할 것!)
: 자바스크립트는 html를 프로그래밍적으로 제어한다.
:
2-1. inline방식
<!DOCTYPE html>
<html>
<body>
<input type="button" onclick="alert('Hello world')" value="Hello world" />
</body>
</html>
2-2. script를 내부문서에서 실행
<!DOCTYPE html>
<html>
<body>
<input type="button" id="hw" value="Hello world" />
<script type="text/javascript">
const hw = document.getElementById('hw');
hw.addEventListener('click', function(){
alert('Hello world');
})
</script>
</body>
</html>
2-3. 외부파일로 분리
<!DOCTYPE html>
<html>
<body>
<input type="button" id="hw" value="Hello world" />
<script type="text/javascript" src="script2.js"></script>
</body>
</html>
const hw = document.getElementById('hw');
hw.addEventListener('click', function(){
alert('Hello world');
})
2-4. script 파일은 위치에 따라 오류가 발생
script 파일은 head 태그 보다 페이지의 하단에 위치시키는 것이 더 좋은 방법이다.
: 웹브라우저의 구성요소들이 하나하나 객체화되어있는데 이것을 Object Model이라고 한다. 즉, html과 여러 브라우저의 요소들을 자바스크립트로 제어할 수 있게 객체로 만들어서 제어한다는 내용이다.
사진첨부
3-1. Window 객체
: 모든객체가 소속된 객체(전역객체) & 창이나 프레임을 의미
전역변수와 함수는 window객체의 프로퍼티와 메소드이다. 그리고 모든 객체는 window의 자식이고 Global객체라고 부를 수 있다.
3-2. JavaScript Core
: JavaScript 언어 자체에 정의되어 있는 객체
3-3. BOM
: Browser Object Model. 웹페이지의 내용을 제외한 브라우저의 각종 요소들을 객체화시킨것. 전역객체 Window의 프로퍼티에 속한 객체들
Location 객체 : 문서의 주소와 관련된 객체 -> url을 변경하고 문서의 위치와 관련해 다양한 정보를 얻을 수 있다.
💡 url 순서: location.protocol, location.host, location.port, location.pathname, location.search, location.hash
ex) https://opentutorials.org:80/module/1?id=1#hash
Navigator 객체 : 브라우저의 정보를 제공하는 객체이고, 호환성 문제 등을 위해서 사용
Navigator.appName -> 웹브라우저의 이름, Navigator.appVersion -> 브라우저의정보, Navigator.userAgent -> 브라우저가 서버측으로 전송하는 user-agent http 헤더의 내용, Navigator.platForm -> 브라우저가 동작하고 있는 운영체제에 대한 정보
💡 호환성 문제를 해결하기 위한 코드
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function () {
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}());
}
3-4. DOM
: Document Object Model. 웹페이지의 내용을 제어. Window의 프로퍼티에 할당된 document객체가 담당. (document객체의 프로퍼티는 문서 내의 주요 엘리먼트에 접근할 수 있는 객체와 메소드를 제공한다. ex - document.images, document.getElementByTagName())
HTMLElement: 실행결과 element가 하나 / HTMLCollection: 실행결과 element가 여러개(유사배열로 배열과 비슷한 방법을 가지고 있지만 배열은 아님)
DOM Tree
사진첨부
Element객체
: Element객체는 엘리먼트를 추상화한 객체.
사진첨부
Node 간의 관계정보 API
Node.childNodes, Node.firstChild, Node.lastChild, Node.nextSibling, Node.previousSibling
노드 종류 API
Node.nodeType : node의 타입
Node.nodeName : node의 이름(태그명)
// Node.nodeType을 의미하는 숫자
ELEMENT_NODE 1
ATTRIBUTE_NODE 2
TEXT_NODE 3
CDATA_SECTION_NODE 4
ENTITY_REFERENCE_NODE 5
ENTITY_NODE 6
PROCESSING_INSTRUCTION_NODE 7
COMMENT_NODE 8
DOCUMENT_NODE 9
DOCUMENT_TYPE_NODE 10
DOCUMENT_FRAGMENT_NODE 11
NOTATION_NODE 12
DOCUMENT_POSITION_DISCONNECTED 1
DOCUMENT_POSITION_PRECEDING 2
DOCUMENT_POSITION_FOLLOWING 4
DOCUMENT_POSITION_CONTAINS 8
DOCUMENT_POSITION_CONTAINED_BY 16
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32
노드 변경 API
-> 노드추가
: appendChild(child) - 노드의 마지막 자식으로 주어진 엘리먼트 추가됨
insertBefore(newElement, referenceElement) - referenceElement 앞에 newElement가 추가됨
-> 엘리먼트생성
: document.createElement(tagename) - 엘리먼트 노드를 추가 document.createTextNode(data) - 텍스트 노드를 추가
-> 노드제거 (참고사항 : 삭제대상의 부모 노드 객체에서 실행해야함)
: removeChild(child)
-> 노드 바꾸기
: replaceChild(newChild, oldChild)
문자열로 노드제어
-> innerHTML : 자식노드를 만들고, 그 값 또한 읽어올 수 있다. 코드를 포함해서 리턴.
-> outerHTML : 선택한 엘리먼트를 포함해서 처리된다. 코드를 포함해서 리턴.
-> innerText : innerHTML과 같지만 HTML코드를 제외한 문자열을 리턴한다.
-> outerText : outerHTML과 같지만 HTML코드를 제외한 문자열을 리턴한다.
-> insertAdjacentHTML : 좀 더 정교하게 문자열을 이용해서 노드를 변경하고 싶을때 사용.
(beforebegin, afterbegin, beforeend, afterend)
노드생성 API
-> creatElement()
-> createTextNode()
문서정보 API
-> title
-> URL
-> referrer
-> lastModified
값
-> data
-> nodeValue
조작
-> appendData()
-> deleteData()
-> insertData()
-> replaceData()
-> subStringData()
생성
-> document.createTextNode()
요소의 크기와 위치
사진첨부
: Element.getBoundingClientRect api를 이용하면 엘리먼트의 크기와 위치를 알 수 있다. (IE는 제공하지 않음) 그리고 top, right의 위치 기준은 엘리먼트의 부모가 아니라 뷰포트가 기준이 된다. (body기준)
알 수 있는 방법은 offsetParent 속성을 호출하면 되는데 만약 부모 중 css position 값이 static이면서 td, th, table 엘리먼트가 있으면 이 엘리먼트가 offsetParent가 된다.
그리고 테두리를 제외한 엘리먼트의 크기를 알려면 ClientWidth, ClientHeight를 사용한다.
스크롤에 따라서 달라지는 뷰포트의 좌표
: 뷰포트는 문서의 내용 중 사용자에게 보여주는 영역인데 앞서 말한것처럼 getBoundingClientRect은 viewport의 좌표를 사용한다. 그래서 스크롤을 하게되면 getBoundingClientRect의 정보는 달라지게 된다. 예를 들면 top의 정보가 200px이었는데 스크롤을 40px만큼 하게 되면 top은 160px이 된다.
그렇다면 문서의 좌표는 어떻게 알까? -> 뷰포트의 좌표에 스크롤 된 정보를 더하면 알 수 있다.(pageYOffset을 사용하면 스크롤의 정도를 알 수 있다)
-> 그럼 스크롤 값을 변경하는 것은 어떻게 할까? : scrollTo 프로퍼티를 이용하면 된다.
<input type="button" id="scrollBtn" value="scroll(0, 1000)" />
<script>
document.getElementById('scrollBtn').addEventListener('click', function(){
window.scrollTo(0, 1000); // 앞의 인수는 x값, 뒤의 인수는 y값
})
</script>
: 이벤트(event)는 어떤 사건을 의미한다. 브라우저에서의 사건이란 사용자가 클릭했을 때, 스크롤 했을 때, 등 '어떤 사건이 일어났을 때'를 의미한다.
<!DOCTYPE html>
<html>
<body>
<input type="button" onclick="alert(window.location)" value="alert(window.href)" />
<input type="button" onclick="window.open('bom.html')" value="window.open('bom.html')" />
</body>
</html>
onclick속성의 자바스크립트 코드는 사용자가 이버튼을 클릭했을 때가 실행된다. 즉, 개발자는 어떤 일이 발생했을 때 실행 되어야하는 코드를 등록하고, 브라우저는 그 등록된 코드를 실행한다. 이것을 이벤트 프로그래밍이라고 한다.
<input type="button" value="alert(window.href)" /
-> 이벤트 프로그래밍을 하기 위해서는 이벤트의 대상에 이벤트 핸들러를 등록해주면 된다. 웹브라우저에서는 크게 3가지의 종류의 등록방법을 제공한다.
<input type="button" onclick="alert('Hello world');" value="button" />
<input type="button" id="target" value="button" />
<script>
var t = document.getElementById('target');
t.onclick = function(){
alert('Hello world');
}
</script>
-> 그리고 이벤트가 실행된 맥락의 정보가 필요할때는 이벤트객체를 사용한다. 이벤트객체는 이벤트가 실행될때 이벤트 핸들러의 인자로 전달된다. (ie8 이하 버전에서는 이벤트 객체를 핸들러의 인자가 아니라 전역객체의 event 프로퍼티로 제공하고, target 프로퍼티도 지원하지 않는다.)
<body>
<input type="button" id="target" value="button" />
<script>
var t = document.getElementById('target');
t.onclick = function(event){
alert('Hello world, '+event.target.value)
}
</script>
// 크로스브라우정 이슈문제를 위한 참고_ 이벤트를 전달하는 방식(ie8 이하 버전)
<input type="button" id="target" value="button" />
<script>
var t = document.getElementById('target');
t.onclick = function(event){
var event = event || window.event;
var target = event.target || event.srcElement;
alert('Hello world, '+target.value)
}
</script>
<input type="button" id="target1" value="button1" />
<input type="button" id="target2" value="button2" />
<script>
var t1 = document.getElementById('target1');
var t2 = document.getElementById('target2');
function btn_listener(event){
switch(event.target.id){
case 'target1':
alert(1);
break;
case 'target2':
alert(2);
break;
}
}
t1.addEventListener('click', btn_listener);
t2.addEventListener('click', btn_listener);
</script>
: 중첩되어 있는 태그들에게 이벤트가 등록되어 있을 때의 처리되는 과정.
<p>
<a href="http://opentutorials.org" onclick="if(document.getElementById('prevent').checked) return false;">opentutorials</a>
</p>
<p>
<form action="http://opentutorials.org" onsubmit="if(document.getElementById('prevent').checked) return false;">
<input type="submit" />
</form>
</p>
<p>
<label>prevent event on</label><input id="prevent" type="checkbox" name="eventprevent" value="on" />
</p>
<p>
<a href="http://opentutorials.org">opentutorials</a>
</p>
<p>
<form action="http://opentutorials.org">
<input type="submit" />
</form>
</p>
<script>
document.querySelector('a').onclick = function(event){
if(document.getElementById('prevent').checked)
return false;
};
document.querySelector('form').onclick = function(event){
if(document.getElementById('prevent').checked)
return false;
};
</script>
<p>
<label>prevent event on</label><input id="prevent" type="checkbox" name="eventprevent" value="on" />
</p>
<p>
<a href="http://opentutorials.org">opentutorials</a>
</p>
<p>
<form action="http://opentutorials.org">
<input type="submit" />
</form>
</p>
<script>
document.querySelector('a').addEventListener('click', function(event){
if(document.getElementById('prevent').checked)
event.preventDefault();
});
document.querySelector('form').addEventListener('submit', function(event){
if(document.getElementById('prevent').checked)
event.preventDefault();
});
</script>
: 자바스크립트를 이용해 웹브라우저의 통신 기능을 사용
-> JSON API
1. JSON.parse() : 인자로 전달된 문자열을 자바스크립트의 데이터로 변환한다.
2. JSON.stringify() : 인자로 전달된 자바스크립트의 데이터를 문자열로 변환한다.
ex) 서버에서 JSON 데이터 가져오기
// time.php
<?php
$timezones = ["Asia/Seoul", "America/New_York"];
echo implode(',', $timezones);
?>
// 결과 : Asia/Seoul,America/New_York
<p id="timezones"></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
var xhr = new XMLHttpRequest();
xhr.open('GET', './time2.php');
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
var _tzs = xhr.responseText;
var tzs = JSON.parse(_tzs);
// 서버에 전송한 JSON 데이터를 JavaScript의 배열로 만들 수 있다.
var _str = '';
for(var i = 0; i< tzs.length; i++){
_str += '<li>'+tzs[i]+'</li>';
}
_str = '<ul>'+_str+'</ul>';
document.querySelector('#timezones').innerHTML = _str;
}
}
xhr.send();
});
</script>
ex) 서버로 JSON 데이터 전송하기
<p>time : <span id="time"></span></p>
<select id="timezone">
<option value="Asia/Seoul">asia/seoul</option>
<option value="America/New_York">America/New_York</option>
</select>
<select id="format">
<option value="Y-m-d H:i:s">Y-m-d H:i:s</option>
<option value="Y-m-d">Y-m-d</option>
</select>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
var xhr = new XMLHttpRequest();
xhr.open('POST', './time3.php');
xhr.onreadystatechange = function(){
document.querySelector('#time').innerHTML = xhr.responseText;
}
var data = new Object();
data.timezone = document.getElementById('timezone').value;
data.format = document.getElementById('format').value;
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
});
</script>
<?php
$data = json_decode(file_get_contents('php://input'), true);
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone($data['timezone']));
echo $d1->format($data['format']);
?>
ex)
// time.php
// 현재 시간을 출력
<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone("asia/seoul"));
echo $d1->format('H:i:s');
?>
// demo1.html
// time.php에 접속해서 현재 시간을 페이지에 표시한다.
<p>time : <span id="time"></span></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
var xhr = new XMLHttpRequest();
// XMLHttpRequest 객체를 생성한다.
xhr.open('GET', './time.php');
// 접속하려는 대상을 지정한다.
// 첫번째 인자는 form태그의 method이고 GET/POST방식을 주로 사용한다.
// 두번째 인자는 접속하고자 하는 서버쪽 리소스의 주소로 form태그의 action에 해당한다.
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
document.querySelector('#time').innerHTML = xhr.responseText;
}
}
// onreadystatechange 이벤트는 서버와의 통신이 끝났을 때 호출되는 이벤트이다.
// readyState는 통신의 형재상태를 알려주는데 4는 통신이 완료되었음을 의미하고
// status는 통신의 결과를 의미하는데 200은 통신이 성공했음을 의미한다.
// responseText 프로퍼티는 서버에서 전송한 데이터를 담고 있다.
xhr.send();
});
</script>