실행안될떄
괄호잘 닫혔는지확인
<></> 확인
오타확인
, . 구분 확인
chapter 07. 문서 객체 모델
section7-1 문서객체 조작하기
section7-2 이벤트 활용
DOMContentLoaded 이벤트를 사용한 문서 객체 조작과 다양한 이벤트의 사용 방법 이해
section07-1 문서객체 조작하기
- 문서객체모델(dom: document object model)
자바스크립트를 이용하여 웹 문서에 접근하고 제어할 수 있도록 객체를 사용해 문서를 체계적으로 정리하는 방법
- DOM Tree
- DOM트리 : 부모와 자식 구조로 표시
- 트리에서 갈라져 나가 항목을 노드라고 하며, html 노드를 루트 노드라고 한다.
DOM 구성 기본원칙
- 모든 HTML 태그는 요소(element) 노드입니다.
- HTML 태그에서 사용하는 텍스트 내용은 자식 노드인 텍스트(text)노드 입니다.
- HTML 태그에 있는 속성은 자식 노드인 속성(attribute) 노드입니다.
- 주석은 주석(comment) 노드 입니다.
-DOMContentLoaded 이벤트
웹브라우저가 문서 객체를 모두 읽고 나서 실행하는 이벤트
다음과 같이 코드를 구성하면 DOMContentLoaded 상태가 되었을 떄 콜백함수를 호출
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
//HTML 태그를 쉽게 만들 수 있는 콜백함수를 선언합니다.
const h1=(text) => `<h1>${text}</h1>`
</script>
<script>
document.body.innerHTML+=h1('1번째 스크립트 태그')
</script>
</head>
<body>
<script>
document.body.innerHTML+=h1('2번째 스크립트 태그')
</script>
<h1>
1번쨰 h1태그
</h1>
<script>
document.body.innerHTML+=h1('3번째 스크립트 태그')
</script>
<h1>2번째 h1 태그</h1>
</body>
</html>
문서객체가져오기
document.body 코드를 사용하여 문서의 body요소 읽기
document.head
document.body
document.title
querySelector
글자조작하기
문서객체.textContent 입력된 문자열을 그대로 기입
문서객체.innerHTML입력된 문자열을 HTML 형식으로 기입
속성조작하기
문서객체.setAttribute(속성 이름, 값) 값을 지정
문서객체.getAttribute (속성 이름) 값을 추출
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded', ()=> { //출력된다음에 마지막에 실행되게.싫으면 스크립트를 맨밑으로 뺴면됨
const rects= document.querySelectorAll('.rect') //class rect 인걸 다 선택
rects.forEach((rect,index)=>{ //각각다에 인덱스값 하나씩 집어넣음
const width = (index+1)*100
rect.setAttribute('src',src) //'src': 속성이름임 src: 값 = 변수임! 저걸 찾아서 'src'에다가 변수 src 값을 넣어주세요 라는뜻
})
})
</script>
</head>
<body>
<img class="rect">
<img class="rect">
<img class="rect">
<img class="rect">
</body>
</html>
문서객체.addEventListener (이벤트이름, 콜백함수) :addEventListener는 이벤트를 등록할때 사용
이떄 등록되는 이벤트는 DOMContentLoaded
(이벤트란 이벤트(Event)는 어떤 사건을 의미합니다. 브라우저에서의 사건이란 사용자가 "클릭을 했을 때", "스크롤을 했을 때", "무언가 입력했을 때" 등의 상호작용으로 인해 일어나는 사건을 의미)
DOMContentLoaded : DOM이 완성된 다음에 나를 실행한다= <body> 가 출력된 다음에 실행되게한다. 왜,, 완성된 다음에..?
스타일조작하기 (css -> 자바)
background-color backgroundColor
text-align textAlign
font-size fontSize
문서객체 생성하기
*document.createElement() 메소드 사용
document.createElement(문서객체이름)
*문서객체 트리구조
문서를 어떤 문서 아래에 추가할지 지정
부모객체.appendChild(자식객체)
+자바스크립트특징 : 부모객체를 선택할 수 있음
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=> {
//문서객체 생성하기
const header=document.createElement('h1')
//생성한 태그 조작하기
header.textContent='문서 객체 동적으로 생성하기'
header.setAttribute('data-custom','사용자 정의 속성') //(속성이름, 값)
header.style.color='white'
header.style.backgroundColor='black'
//h1 태그를 body 태그 아래에 추가하기
document.body.appendChild(header) //body를 부모로 추가
})
</script>
</head>
<body>
</body>
</html>
appendChild는 문서 객체를 이동할때도 사용
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
//문서객체 읽어들이고 생성하기
const divA=document.querySelector('#first') // id 속성이 first 인 div 태그를 선택
const divB=document.querySelector('#second') // id 속성이 second 인 div 태그를 선택
const h1=document.createElement('h1') //h1태그를 생성
h1.textContent='이동하는 h1태그'
//서로 번갈아가며 실행하는 함수를 구현합니다.
const toFirst=()=>{
divA.appendChild(h1)
setTimeout(toSecond,1000)
}
const toSecond=()=>{
divB.appendChild(h1)
setTimeout(toFirst,1000)
}
toFirst() //위에 두개가 함수이므로 누군가는 실행시켜줘야함. 이렇게 써서 실행!
})
</script>
</script>
</head>
<body>
<div id="first">
<h1>첫번쨰 div 내부</h1>
</div>
<hr>
<div id="second">
<h1>두번째 div 내부</h1>
</div>
</body>
</html>
+setTimeout 일정시간이 지난후에 실행
h1은 참조변수로 사용되어서 한놈이 움직이는거임(얕은복사)
*removeChild
부모객체.removeChild(자식객체)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
setTimeout(()=>{
const h1=document.querySelector('h1')
h1.parentNode.removeChild(h1) //h1 태그의 부모객체 body 태그에 접근하여 제거
//document.body.removeChild(h1) //h1.parentNode가 document.body 이므로, 이런 형태로도 제거할 수 있음
},3000)
})
</script>
</head>
<body>
<hr>
<h1>제거 대상 문서 객체</h1>
<hr>
</body>
</html>
*appendChild()
문서객체.parentnode.removeChild(자식객체) 이렇게 쓰면 parentnode 입력할 필요가 없음
이벤트설정하기
addEventListener() 메소드
문서객체.addEventListener (이벤트이름, 콜백함수)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
let counter=0
const h1= document.querySelector('h1')
h1.addEventListener('click',(event)=>{
counter++
h1.textContent=`클릭횟수:$(counter)`
})
})
</script>
<style>
h1{user-select:none;}
</style>
</head>
<body>
<h1>클릭횟수:0</h1>
</body>
</html>
DOMContentLoaded : DOM이 완성된 다음에 나를 실행한다
DOMContentLoaded이벤트는 html 페이지의 모든 문서 객체를 웹 브라우저가 읽어들였을때 발생시키는 이벤트
textContent 속성과 inner HTML 속성은 문서 객체 내부의 글자를 조작할때 사용하는 속성
이벤트 리스너는 이벤트가 발생할때 실행하는 함수를 의미
이벤트모델
표준이벤트모델 addEventListener
고전이벤트모델 :document.body.onkeyup 문서객체가 갖고있는 onㅇㅇ으로 시작하는 속성에 함수를 할당해서 이벤트를 연결
인라인이벤트모델 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
let counter=0 //변수
let isConnect= false //불값
const h1= document.querySelector('h1') //샐랙터
const p=document.querySelector('p')
const connectButton=document.querySelector('#connect') //버튼두개
const disconnectButton=document.querySelector('#disconnect')
const listener=event=>{
h1.textContent=`클릭 횟수: ${counter++}`
}
connectButton.addEventListener('click',()=>{
if(isConnect===false){
h1.addEventListener('click',listener)
p.textContent='이벤트 연결 상태: 연결'
isConnect=true
}
})
disconnectButton.addEventListener('click',()=>{
if(isConnect===true){
h1.removeEventListener('click',listener)
p.textContent='이벤트 연결 상태: 해제'
isConnect=false
}
})
})
</script>
<style>
h1{
/* 클릭을 여러번 했을때
글자가 선택되는 것을 막기 위한 스타일 */
user-select:none;
}
</style>
</head>
<body>
<h1>클릭횟수:0</h1>
<button id="connect">이벤트 연결</button>
<button id="disconnect">이벤트 제거</button>
<p> 이벤트 연결 상태: 해제</p>
</body>
</html>
키보드이벤트
keydown: 키가 눌릴떄 실행
keypress: 키가 눌릴때 실행이나 아시아권의 문자를 잘 처리하지 못함
keyup: 키보드에서 키가 떨어질 때 실행
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
//keyup 이용해서 마우스가 떨어지는 순간에
document.addEventListener('DOMContentLoaded',()=>{
const textarea =document.querySelector('textarea')
const h1=document.querySelector('h1')
textarea.addEventListener('keyup',(event)=>{
const length=textarea.value.length
h1.textContent= `글자수: ${length}`
})
})
</script>
</head>
<body>
<h1></h1>
<textarea></textarea>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
//별의 초기설정
const star=document.querySelector('h1')
star.style.position='absolute'
//별의 이동을 출력하는 기능
let [x,y]=[0,0]
const block=20
const print=() =>{
star.style.left=`${x*block}px`
star.style.top=`${y*block}px`
}
print()
//별을 이동하는 기능
const [left, up, right, down]=[37,38,39,40] //변수 한번에 집어넣기
document.body.addEventListener('keydown',(event)=>{
switch(event.keyCode){
case left:
x-=1
break
case up:
y-=1
break
case right:
x+=1
break
case down:
y+=1
break
}
print();
})
})
</script>
</head>
<body>
<h1>*</h1>
</body>
</html>
키보드 키 코드 사용하기
code 입력한키
keycode 입력한 키를 나타내는 숫자
이벤트발생객체
-이벤트리스너 내부에서 어떤 변수에 접근할 수 없는 경우
ex) 리스너함수 내부에서 텍스트에리어 변수에 접근할 수 없어 오류가 발생
문제해결: this 사용
글자입력양식이벤트
-인터넷에서 특정사이트에 가입할때 이메일과 전화번호 유효성 등을 검사
-일반적으로 이런 유효성 검사를 할 때에는 정규 표현식 regular expression을 사용
-이메일 형식 확인하기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
const input=document.querySelector('input')
const p=document.querySelector('p')
const isEmail=(value)=>{
//골뱅이를 갖고 있고 &&골뱅이 뒤에 점이 있다면
return(value.indexOf('@')>1)
&&(value.split('@')[1].indexOf('.')>1) //split('@')[1] : 골뱅이를 기준으로 split 복습하기 !!!!!!!!
}
input.addEventListener('keyup',(event)=>{
const value=event.currentTarget.value
if(isEmail(value)){
p.style.color='green'
p.textContent=`이메일 형식입니다.: ${value}`
} else{
p.style.color='red'
p.textContent=`이메일 형식이 아닙니다.: ${value}`
}
})
})
</script>
</head>
<body>
<input type="text">
<p></p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
let 현재값
let 변환상수 =10 //디폴트를 cm로 넣기 위해서 10넣음
const select=document.querySelector('select')
const input=document.querySelector('input')
const span=document.querySelector('span')
const calculate=() => {
span.textContent=(현재값*변환상수).toFixed(2)
}
select.addEventListener('change',(event)=> {
const option = event.currentTarget.options
const index=event.currentTarget.options.selectedIndex
변환상수=Number(options[index].value)
calculate()
})
input.addEventListener('keyup',
(event)=> {
현재값= Number(event.
currentTarget.value)
calculate()
})
})
</script>
</head>
<body>
<input type="text"> cm=
<span></span>
<select>
<option value="10">mm</option>
<option value="0.01">m</option>
<option value="0.393701">inch</option>
</select>
</body>
</html>
-드롭다운 목록 활용하기 :select 태그
-multiple select (+push 배열 추가)(+ toFIxed() 소숫점 몇째까지 표시)
-체크박스 이용하기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--1. 상태 2. 작동 -->
<script>
document.addEventListener('DOMContentLoaded',()=>{
let [timer, timerID]=[0,0]
const h1=document.querySelector('h1')
const checkbox= document.querySelector('input')
checkbox.addEventListener('change',(event)=>{
if(event.currentTarget.checked){
//체크상태
timerID=setInterval(()=>{
timer+=1
h1.textContent=`${timer}초`
},1000)
}else{
//체크해제상태
clearInterval(timerID)
}
})
})
</script>
</head>
<body>
<input type="checkbox">
<span>타이머 활성화</span>
<h1></h1>
</body>
</html>
-라디오버튼 이용하기
-기본이벤트막기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
const imgs= document.querySelectorAll('img')
imgs.forEach((img)=>{
img.addEventListener('contextmenu',(event)=>{
event.preventDefault()
})
})
})
</script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded',()=>{
let status=false
const checkbox=document.querySelector('input')
checkbox.addEventListener('change',(event)=>{
status=event.currentTarget.checked
})
const link=document.querySelector('a') //false 일떄 차단하는게 실행됨 = 차단됨
link.addEventListener('click',(event)=> {
if(!status){
event.preventDefault() //preventDefault
}
})
})
</script>
</head>
<body>
<input type="checkbox">
<span> 링크 활성화</span>
<br>
</body>
</html>