[ 열혈강의 No More Copy & Paste 자바스크립트 ]
(http://book.naver.com/bookdb/book_detail.nhn?bid=6983102)
7. DOM Script
서론
DOM
문서 객체 모델, document object modelDOM Script
html문서에 접근하고 그 안의 내용물을 마음대로 바꾸거나 새로운 객체를 직접 만들어 문서의 원하는 부위에 삽입할 수 있고 삭제도 할 수 있는 것도큐먼트(document) 객체
DOM 최 상위 객체로 window 객체 안에 가장 커다란 단위의 객체 중 하나
HTML문서 자체를 document라고 칭한다고 보면 됨엘리먼트(element) 객체
태그로 만들어진 모든 요소를 엘리먼트라고 부름(div, span, table 등등)애트리뷰트(attribute)
엘리먼트가 가진 속성 (id, name, class 등등)노드(node)
객체를 상징하는 표현
엘리먼트, 애트리뷰트, 엘리먼트 내부의 글 내용도 모두 노드API
API는 자신이 가진 명령이나 정보와 같은 리소스를 외부에서 접근할 수 있도록 해주는 일종의 통로(P193)
문서(document) 객체
개요
- 문서에 엘리먼트를 만들거나 찾을 수 있도록 도와주기도 하고 location이나 history 객체도 함께 가지고 있음
- document 객체는 window 객체에 포함되며 특정한 엘리먼트들을 포함하고 있음
- 주로 문서 유형(document type)이나 색상, 포맷과 같은 문서 정보 접근하는 방법을 제공
document 객체의 속성
- P194 표 7-1 참고
document 객체의 메서드 (P196 표 7-2)
- open(): 새로운 문서 작성을 시작(새로운 document가 생성됨)
createAttribute(): 속성 노드를 생성
1
2
3
4
5
6<div id="app" hi="안녕"></div>
<script>
document.createAttribute('hi');
var app = document.getElementById('app');
app.getAttribute('hi') // -> '안녕'
</script>close(): 새로운 문서 작성을 종료
- createDocumentFragment(): document 객체 참조를 위한 조각을 생성한다
createElement(): 엘리먼트 생성
1
2
3
4var jbBtn = document.createElement( 'button' );
var jbBtnText = document.createTextNode( 'Click' );
jbBtn.appendChild( jbBtnText );
document.body.appendChild( jbBtn );createElementNS(): 네임 스페이스를 참조하는 새로운 엘리먼트를 생성
(참고 - https://developer.mozilla.org/ko/docs/Web/API/Document/createElementNS)createEvent(): 새로운 이벤트를 생성, 이벤트를 정의하는 오래된 기법으로 잘 사용되지 않는 것으로 보임, IE에선 사용 불가
createRange(): 편집할 수 있는 범위를 지정하는 새로운 range(위치/범위) 객체를 생성
( https://developer.mozilla.org/ko/docs/Web/API/Document/createRange )createTextNode(): 새로운 텍스트 노드를 생성한다
1
2
3EX> var apps = document.getElementById('app');
var textNode = document.createTextNode('text node'); // #app에 문자 text node가 추가 됨
apps.appendChild(txtNode);execCommand(): 문서에서 사용 가능한 명령을 실행시킨다.
getElementById(): id속성이 일치하는 하나의 엘리먼트를 반환
getElementByName(): name속성이 일치하는 엘리먼트들을 반환
getElementByTagName(): 태그 이름이 일치하는 엘리먼트들을 반환
getElementByTagNameNS(): 태그 이름과 네임스페이스가 일치하는 엘리먼트들을 반환
write(): 문서에 내용을 추가
whiteln(): 문서에 내용을 추가하고 줄 바꿈을 한다
P197 window.open을 이용한 새창 예제 (HTML)
1
2
3<!-- HTML -->
<button id="btnFunc1" type="button">func1(팝업창 출력)</button>
<br><br>P197 window.open을 이용한 새창 예제 (JS)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// func1
function func1() {
// 팝업 윈도우 설정 window.open(url, name, properties);
var popWin = window.open('', 'popwin', 'width=400, height=300');
// 팝업 윈도우의 document를 변수에 할당
var popDoc = popWin.document;
// 팝업 윈도우의 document를 open
popDoc.open();
// 팝업 윈도우의 document내에 내용 추가
popDoc.write('<html><head><title>popup</title></head>');
popDoc.write('<body bgcolor="gold">');
popDoc.write('<p align="center"><b>팝업 창 입니다.</b></p>');
popDoc.write('</body></html>');
// 팝업 윈도우의 document를 close
popDoc.close();
}
// event bind
document.getElementById('btnFunc1').addEventListener('click', func1);
HTML 객체 만들기
태그 직접 써넣기
- 앞서 해본 방식(document.write)으로 엘리먼트를 넣으면 브라우저가 해석하여 추가하는 것으로 엘리먼트를 만드는 것이 아님
DOM API 이용하기
document객체가 제공하는 속성과 메서드를 이용하여 엘리먼트 만들기
1
2
3EX> var element = document.createElement('태그 명');
var attr = document.createAttribute('속성 명');
var textNode = document.createTextNode('내용');엘리먼트 만들기 예(html)
1
2
3
4
5<div id="func2">
<button id="btnFunc2-1" type="button">func2-1</button>
<button id="btnFunc2-2" type="button">func2-3</button>
<div id="textFunc2"></div>
</div>엘리먼트 만들기 예(js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25var func2 = {
createTag1: function () {
// 엘리먼트 생성
var element = document.createElement('div');
// 속성(어트리뷰트) style 생성
var attribute = document.createAttribute('style');
// 속성 값 선언
attribute.nodeValue = 'background:#eee;width:100px;height:100px;';
// 엘리먼트에 속성 적용
element.setAttributeNode(attribute);
// 엘리먼트를 body 하위에 추가
document.getElementById('textFunc2').appendChild(element);
},
createTag2: function () {
// 엘리먼트 생성
var element = document.createElement('div');
// 속성 선언 및 적용(createTag1와 사용 방법 비교)
element.setAttribute('style', 'background:#aaa;width:100px;height:100px;');
// 엘리먼트를 body하위에 추가
document.getElementById('textFunc2').appendChild(element);
}
};
document.getElementById('btnFunc2-1').addEventListener('click', func2.createTag1);
document.getElementById('btnFunc2-2').addEventListener('click', func2.createTag2);
객체 가져오기
특정 대상 가져오기
getElementsByTagName
태그 이름으로 엘리먼트를 가져 옴 (여러개의 엘리먼트 동시 선택 가능)getElementById == $(‘#element’)
아이디를 통해서 엘리먼트를 가져오라는 의미
id를 통해 가져오기 때문에 1개의 엘리먼트 만을 반환1
2var element = document.getElementById('app');
element.style.backgroundColor = 'red';getElementsByName() == $(‘:[name=name]’)
name 속성을 통해 엘리먼트를 가져오라는 의미
선택된 대상을 배열의 형태로 반환(즉 여러개의 엘리먼트가 동시에 선택될 수 있음)- getElementsByClassName() == $(‘.class’)
class 속성을 통해 엘리먼트를 가져오라는 의미
선택된 대상을 배열의 형태로 반환(즉 여러개의 엘리먼트가 동시에 선택될 수 있음) document.querySelector()
CSS선택자로 엘리먼트를 가져오라는 의미
선택된 엘리먼트 1개만을 반환하며 다수 인경우 첫번째 대상만 가져옴
일치하는 엘리먼트를 찾지 못한 경우 null을 반환
ie8 미만에서 지원되지 않음1
document.querySelector('body #fWrap');
document.querySelectorAll()
기본 적으로는 querySelector와 동일
차이점 모든 엘리먼트를 가져 온다는 점
다수의 선택자를 입력해야하는 경우 컴마로 구분하여 사용1
document.querySelectorAll('body, html, #fWrap');
자식 노드 찾기
childNodes
메서드가 아닌 프로퍼티
선택된 대상의 하위 노드를 배열로 반환
상위 대상이 배열의 형태인 경우 아래와 같이 사용해야하는 점을 주의1
2var ele = document.querySelectorAll('li');
ele[0].childNodesfirstChild, lastChild
첫 번째 자식와 마지막 자식 노드는 쉽게 선택할 수 있도록 프로퍼티가 존재1
2
3var ele = document.querySelectorAll('li');
ele.firstChild
ele.lastChild
부모 노드 찾기
- parentElement, parentNode
바로 윗 부모 1개를 반환하는 프로퍼티
이름은 다르나 용도는 같은 것으로 보임
형제 노드 찾기
- previousSibling, nextSibling
각각 이전, 다음 형재를 선택하는 프로퍼티
기타
document.all
document 내 모든 엘리먼트document.forms
document 내 모든 form 엘리먼트document.images
document 내 모든 img 엘리먼트document.links
document 내 모든 a 엘리먼트document.scripts
document 내 모든 script 엘리먼트document.styleSheets
document 내 모든 link 또는 style 엘리먼트
참고
복수의 대상을 반환하는 항목은 뒤에 s가 추가 됨
1
getElementsByClassName('class');
복수의 대상을 반환하는 메서드, 속성은 배열의 형태로 전달
선택된 엘리먼트의 자식 엘리먼트를 가져 오기의 다른 예
1
2var parent = document.getElementById('parent');
var child = parent.getElementsByClassName('child');
엘리먼트(element) 객체
엘리먼트 객체의 속성
- P221 표7-4 참고
엘리먼트 객체의 메서드(P222 표7-5)
addEventListener(‘이벤트 명’, ‘함수’, ‘캡쳐 사용 여부’)
이벤트 발생 시 실행할 함수를 등록1
2
3
4document.getElementById('btnFunc1').addEventListener('click', func1);
document.getElementById('btnFunc1').addEventListener('click', function(){
alert('click');
});appendChild()
node의 하위 객체의 가장 마지막에 추가blur()
주시 대상 설정(focus)을 해제(즉 focus 해제)click()
대상에 클릭 이벤트를 발생 (onClick과 다른 점 주의)cloneNode()
노드의 복사본을 만들어서 반환1
2var ele = document.getElementById('fWrap');
var copy = ele.cloneNode(true);dispatchEvent(이벤트)
이벤트가 발생했다는 것을 알림- focus()
주시 대상으로 설정(focus 설정) getAttribute(‘속성명’)
속성 값을 반환1
2
3<button id="navInvite" type="button" data-name="type_invite" class="active"></button>
var nav = document.getElementById('navInvite');
nav.getAttribute('data-name'); -> 'type_invite'getAttributeNS(‘속성이름’, ‘NS’)
속성 이름과 네임스페이스를 가진 속성 값을 받아 옴getAttributeNode(‘속성이름’)
속성 이름에 해당하는 속성 객체를 받아 온다
( 받아 온 값은 각각 .name, .value로 확인 가능 )getAttributeNodeNS()
속성 이름과 네임 스페이스를 가진 속성 객체를 받아 옴hasAttribute()
속성을 가졌는지 boolean 값으로 반환hasAttributeNS()
속성과 네임스페이스를 가졌는지 boolean 값으로 반환hasAttributes()
속성을 하나라도 가졌는지 boolean 값으로 반환hasChildNodes()
하위 객체를 하나라도 가졌는지 boolean 값으로 반환insertBefore(삽입할 객체, 하위 기준 객체)
하위 기준 객체 바로 앞에 객체를 삽입 한다 (https://www.w3schools.com/jsref/met_node_insertbefore.asp)normalize()
하위 객체중 비어 있는 노드를 지우거나 텍스트 노도를 합치는 등의 정규화를 시킴removeAttribute(‘속성이름’)
속성 이름에 해당하는 속성을 제거removeAttributeNS(‘속성이름’, ‘네임스페이스’)
속성 이름과 네임스페이스에 해당하는 속성을 제거removeAttributeNode(속성 객체)
해당 속성 객체를 지움removeChild(객체)
하위 객체 중 정보로 전달 받은 객체를 지움removeEventListener(‘이벤트명’, 실행되는 함수, 캡쳐 사용 여부)
이벤트 이름에 등록된 실행되는 함수를 삭제replaceChild(대체할 객체, 대체될 자식 객체)
대체될 자식 객체를 지우고 대체할 객체를 그 자리에 삽입scrollIntoView(위쪽 기준인지 아닌지)
엘리먼트가 화면에 보이도록 스크롤을 이동1
2
3var btn = document.getElementById('button');
btn.scrollIntoView(true); -> 선택된 대상이 가장 윗쪽에 위치하도록 스크롤 이동
btn.scrollIntoView(false); -> 선택된 대상이 가장 아랫 쪽에 위치하도록 스크롤 이동setAttribute(‘속성이름’, ‘속성 값’) == $(‘element’).attr(‘속성이름’, ‘속성 값’)
새 속성을 추가하거나 현재 속성을 대체setAttributeNS(‘NS’, ‘속성이름’, ‘속성 값’)
네임 스페이스를 갖는 속성을 추가하거나 네임 스페이스와 속성 이름이 같은 속성을 대체setAttributeNode(속성 객체)
새 속성을 추가하거나 현재 속성을 대체setAttributeNodeNS(속성 객체)
네임 스페이스를 갖는 새 속성을 추가하거나 현재 속성을 대체
관련된 객체 찾기
- 부모 자식 노드
parent.node: 부모 노드
childNodes: 자식 노드 부모 자식 노드 예(html)
1
2
3<button id="btnFunc3" type="button">
<span>func3 - 부모 자식노드</span>
</button>부모 자식 노드 예(js)
1
2
3
4
5
6
7
8document.getElementById('btnFunc3').addEventListener('click', function () {
var parent = this.parentNode;
var child = this.childNodes;
console.log('[parent Node]');
console.log(parent);
console.log('[child Nodes]');
console.log(child);
});속성(attribute) 객체
setAttribute()속성(attribute) 객체 예(html)
1
2
3
4<div id="func4">
<input id="inpFunc4" type="text" value="기본 값">
<button id="btnFunc4" type="button">func4 - 속성변경</button>
</div>속성(attribute) 객체 예(js)
1
2
3
4
5
6document.getElementById('btnFunc4').addEventListener('click', function () {
var inp = document.getElementById('inpFunc4');
console.log('변경 전 type 속성은 '+inp.getAttribute('type'));
inp.setAttribute('type', 'password');
console.log('변경 후 type 속성은 '+inp.getAttribute('type'));
});
엘리먼트에 자식 노드 삽입하기
appendChild: 대상 엘리먼트 자식 뒤로 추가
insertBefore: 대상 엘리먼트의 자식 위치를 지정하여 교체엘리먼트에 자식 노드 삽입하기 예(html)
1
2
3
4
5
6
7
8
9
10
11<div id="func5">
<button id="btnFunc5-1" type="button">func5-1 자식 노드 삽입(append)</button>
/
<button id="btnFunc5-2" type="button">func5-2 자식 노드 삽입(insertBefore)</button>
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>엘리먼트에 자식 노드 삽입하기 예(js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36var func5 = {
comm: function (idx) {
var listEle = document.createElement('li');
listEle.textContent = idx;
return listEle;
},
comm2: function (idx) {
// 문자열 형태로 생성은 불가
var targetEle = '<li>'+idx+'</li>';
// 가져다 쓰는건 가능
var targetEle2 = document.getElementsByTagName('li')[0].cloneNode(true); // 매개변수가 true인 경우 하위 내용도 함께 복사
targetEle2.textContent = idx;
return targetEle2
},
btn1: function () {
var targetEle = document.getElementsByClassName('list')[0];
var targetList = targetEle.getElementsByTagName('li');
var insertList = func5.comm( parseInt(targetList[targetList.length-1].textContent) + 1);
//var insertList = func5.comm2( parseInt(targetList[targetList.length-1].textContent) + 1);
targetEle.appendChild(insertList);
},
btn2: function () {
var targetEle = document.getElementsByClassName('list')[0];
var targetList = targetEle.getElementsByTagName('li');
//var insertList = func5.comm(targetList[0].textContent - 1);
var insertList = func5.comm2(targetList[0].textContent - 1);
targetEle.insertBefore(insertList, targetList[0]);
}
};
document.getElementById('btnFunc5-1').addEventListener('click', func5.btn1);
document.getElementById('btnFunc5-2').addEventListener('click', func5.btn2);
내용물 바꿔치기
innerHTML
선택된 엘리먼트에 변수의 형태로 입력1
2
3var test = document.getElementById('#func6');
text.innerHTML = '내용을 교체합니다';
text.innerHTML+= '내용을 추가 합니다';innerHTML 예(html)
1
2
3
4
5
6
7<div id="func6">
<input id="inpFunc6" type="text" placeholder="내용을 입력해 주세요">
<button id="btnFunc6" type="button">func6 내용 물 바꿔치기(innerHTML)</button>
<p id="textFunc6">
내용이 음슴미다
</p>
</div>innerHTML 객체 예(js)
1
2
3
4
5
6document.getElementById('btnFunc6').addEventListener('click', function () {
var targetInp = document.getElementById('inpFunc6');
var targetText = document.getElementById('textFunc6');
targetText.innerHTML = targetInp.value;
});innerHTML 사용 시 완전한 문자열을 최소화하여 추가하는 것을 권장(html)
1
2
3
4<div id="func7">
<button id="btnFunc7" type="button">func7 innerHTML 사용 최소화</button>
<p id="textFunc7"></p>
</div>innerHTML 사용 시 완전한 문자열을 최소화하여 추가하는 것을 권장(js)
1
2
3
4
5
6
7
8
9document.getElementById('btnFunc7').addEventListener('click', function () {
var targetText = document.getElementById('textFunc7');
var content1 = '<a href="http://www.naver.com"';
var content2 = '> 네이버 링크<';
var content3 = '/a>';
var setCont = content1 + content2 + content3;
targetText.innerHTML = setCont;
});
removeChild(): 자식 노드를 제거
removeChild 예 (html)
1
2
3
4
5
6
7
8
9<div id="func8">
<button id="btnFunc8" type="button">func8 자식 노드 삭제</button>
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>removeChild 예 (js)
1
2
3
4
5
6
7// func8
document.getElementById('btnFunc8').addEventListener('click', function () {
var targetEle = document.getElementsByClassName('list')[1];
var targetList = targetEle.childNodes;
targetEle.removeChild(targetList[1]);
});
replaceChild(추가할 항목, 삭제될 대상)
replaceChild 예(html)
1
2
3
4
5
6
7
8
9<div id="func9">
<button id="btnFunc9" type="button">func9 자식 노드 교체(1 -> 20)</button>
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>replaceChild 예(js)
1
2
3
4
5
6
7
8document.getElementById('btnFunc9').addEventListener('click', function () {
var targetEle = document.getElementsByClassName('list')[2];
var targetList = targetEle.getElementsByTagName('li');
var cloneList = targetList[0].cloneNode(false);
cloneList.textContent = '20';
targetEle.replaceChild(cloneList, targetList[0]);
});