웹 요소의 스타일 속성에 접근할 때는 .style
예약어를 쓰고 CSS 속성을 적는다.
background-color, border-radius처럼 하이픈이 포함된 속성은 낙타 표기법으로 입력한다.
→ backgroundColor, borderRadius
document.querySelector("#heading").style.color = "white"
document.querySelector("#heading").style.backgroundColor = "gray"
document.querySelector("#heading").style.display = "block"
무엇을 화면에 표시하거나 감추려면 CSS 속성 중 display
or visibility
속성을 사용한다.
display : none
을 사용해 웹 요소를 화면에서 감추면 그 요소가 차지하던 공간도 사라지지만, visibility : hidden
을 사용해 웹 요소를 감추면 요소가 있던 공간은 빈 상태로 남아 있게 된다.
Ex) 사각형 위로 마우스 포인터를 올리면 초록색 원으로 바뀌고, 포인터를 치우면 원래 도형을 되돌아감
var Rect = document.querySelector("#rect")
Rect.addEventListener("mouseover",function(){
Rect.style.backgroundColor = "green"
Rect.style.backgroundRadius = "5o%"
})
Rect.addEventListener("mouseout",function(){
Rect.style.backgroundColor = "" // Rect 요소의 배경색 지우기
Rect.style.backgroundRadius = "" // Rect 요소의 테두리 둥글게 처리 안 함
})
Ex) display 속성을 사용해 상세 설명 링크 만들기
<div id = "desc">
<ul> ... </ul>
<a href = "#" id = "view">상세 설명 보기</a>
</div>
<div id = "detail">
<h2>상품 상세 정보</h2>
</div>
var isOpen = false // #detail 요소가 현재 화면에 표시된 상태인지 감춰진 상태인지를 저장할 변수
var view = document.querySelector("#view")
view.addEventListener("click",function(){
if(isOpen = false){
document.querySelector("#detail").style.display = "block"
View.innerText = "상세 설명 닫기"
isOpen = true
}
else{
document.querySelector("#detail").style.display = "none"
View.innerText = "상세 설명 보기"
isOpen = false
}
})
새로운 노드 추가 방법을 살펴보기 전 DOM 트리에 어떤 노드가 있었는지 복습해보자.
- 요소 노드 : 모든 HTML 태그
- 텍스트 노드 : 태그에서 사용하는 텍스트 내용
- 속성 노드 : 태그에 있는 속성
- 주석 노드
웹 문서의 요소는 단순히 태그만 있는게 아니라 속성과 내용을 함께 사용한다. 따라서 <h1>
,<p>
태그를 추가하고 싶다면 요소 노드뿐 아니라 태그 안에 있는 텍스트와 속성도 노드로 추가해야 한다.
새로운 노드를 만들거나 부모 노드에 연결할 때는 다음 메소드를 사용한다.
creatElement( )
: 새 요소를 만든다.creatTextNode( )
: 텍스트 내용이 있을 경우 텍스트 노드를 만든다.
appendChild( )
: 텍스트 노드를 요소 노드의 자식으로 추가한다.
방법1 :createAttribute( )
→setAttributeNode( )
or
방법2 :setAttribute( )
appendChild( )
: 새 요소 노드를 부모 노드에 추가한다.
var newP = document.creatElement("p")
var newText = document.creatTextNode("주문이 완료되었습니다.")
newP.appendChild(newText)
document.body.appendchild(newP)
// 방법1
var attr = document.creatAttribute("class")
attr.value = "accent"
newP.setAttributeNode(attr)
// 방법2 이게 더 간단하다!
newP.setAttribute("class","accent")
EX) 참가 신청 명단 프로그램 만들기
이름을 입력하고 신청 버튼을 누르면 그 정보는 서버로 넘겨져 DB에 저장된다. 서버에 저장되는 것과 동시에 웹 브라우저 화면에 신청 명단을 표시한다.
<body>
<div id = "container">
<h1>참가 신청</h1>
<form action = "">
<input type = "text" id = "userName" placeholder = "이름" required>
<button onclick = "newRegister();return false">신청</buttton>
<!-- button 태그에 return false를 추가하지 않으면 버튼을 눌렀을 때 빈 페이지로 넘어간다. -->
</form>
<hr>
<div id = "nameList"></div>
</div>
</body>
function newRegister(){
var newP = document.createElement("p")
var userName = document.querySelector("#userName") // 텍스트 필드 내용 가져오기
var newText = document.creatTextNode(userName.value)
newP.appendChild(newText)
var nameList = document.quertSelector("#namelist")
nameList.appendChild(newP)
userName.value = "" // 다시 이름 입력할 수 있게 텍스트 필드 비우기
}
추가한 노드의 순서를 바꾸거나 삭제하기 위해서는 DOM에서 노드를 다루기 위한 몇 가지 함수를 더 사용해야 한다.
querySelectorAll
<div id = "container">
<h1>참석자 명단</h1>
<div id = "nameList">
<p>홍길동 <span class = "del"> X </span></p>
<p>유현준 <span class = "del"> X </span></p>
<p>이상협 <span class = "del"> X </span></p>
</div>
</div>
querySelectorAll
을 사용해서 여러 개의 노드를 한 번에 가져오면 3개의 p노드가 한꺼번에 저장되는데 이를 노드 리스트라고 한다. 인덱스와 함께 값이 저장되고 length 속성을 사용할 수 있는 유사 배열 형태이다.
노드 리스트의 특정 위치에 접근할 때는 인덱스를 사용하면 된다.
document.querySelectorAll("p") // NodeList(3) [p,p,p]
document.querySelectorAll("p")[0] //<p> ... </p>
hasChildNodes
는 특정 노드에 자식 노드가 있는지 확인하는 함수이다. 자식 노드가 있다면 true, 없다면 false를 반환한다.
자식 노드가 있다면 childNodes
속성을 사용해 현재 노드의 자식 노드에 접근할 수 있다.
이때 요소 노드뿐만 아니라 태그와 태그 사이 줄바꿈도 빈 텍스트 노드인 자식 노드로 인식한다.
또한 주석 노드까지 접근할 수 있다. 밑의 예제에서는 <div>
태그 다음 줄바꿈, <P>
태그 사이 줄바꿈, </div>
앞에 줄바꿈을 빈 텍스트 노드로 인식하였다.
만약 요소 노드에만 접근한다면 children
속성을 사용하면 된다.
document.querySelectorAll("p")[0].hasChildNodes() // false
document.querySelector("#nameList").childNodes()
// NodeList(7) [text,p,text,p,text,p,text]
document.querySelector("#nameList").children()
//HTML Collection(3) [p,p,p]
자식 노드를 추가하는 appendChild
함수는 부모 노드에 자식 노드가 있을 경우 마지막 자식 노드로 추가된다. 하지만 insertBefore
함수를 사용하면 기준이 되는 노드를 정하고 그 앞에 자식 노드를 추가할 수 있다. 첫번째 인수는 추가하는 노드, 두번째 인수는 기준이 되는 노드이다.
var nameList = document.querySelector("#nameList")
namelist.insertBefore(nameList[2],nameList[0])
removeNode
는 부모 노드에서 자식 노드를 삭제하는 함수로 인수에는 자식 노드가 들어간다.
노드는 스스로 자신을 삭제할 수 없기 때문에 부모 노드에 접근 후 부모 노드에서 삭제해야 한다. 따라서 특정 노드를 삭제하기 위해선 그 노드의 부모 노드를 찾아야 한다. 부모 노드 정보를 가지고 있는 속성은 parentNode
로 현재 노드의 부모 요소를 반환한다.
var var firstDel = document.querySelectorAll(".del")[0]
var fistP = document.querySelectorAll("p")[0]
firstP.removeChild(firstDel) // 삭제된 노드 반환 <span class = "del"> X </span>
EX) 최근 입력한 이름이 명단 맨 위에 표시되고 삭제 기능이 추가된 참가 신청 명단 프로그램
function newRegister(){
var newP = document.createElement("p")
var userName = document.querySelector("#userName") // 텍스트 필드 내용 가져오기
var newText = document.creatTextNode(userName.value)
newP.appendChild(newText)
var delBttn = document.createElement("span")
var delText = document.creatTextNode("X")
delBttn.setAttribute("class","del")
delBttn.appendChild(delText)
newP.appendChild(delBttn)
var nameList = document.quertSelector("#namelist")
nameList.insertBefore(newP,nameList.children[0])
userName.value = "" // 다시 이름 입력할 수 있게 텍스트 필드 비우기
var removeBttns = document.quertSelectorAll(".del")
for (var i = 0; i < removeBttns.length; i++){
removeBttns[i].addEventListener("click", function(){
if (this.parentNode.parentNode){
this.parentNode.parentNode.removeChild(this.parentNode)}
})
}
}
이벤트리스너 안에서의
this
는e.currentTarget
과 같다.e.currentTarget
은 지금 이벤트가 동작하는 곳을 뜻한다. (즉, addEventListener 부착된 DOM 요소)
만약 이벤트리스너 안에서 콜백 함수를 쓴다면 콜백 함수의this
는window
를 가리킨다.