JS 웹 브라우저🧀

130605 단어 jsjs

HTML은 정보를 전달하고
CSS는 디자인을 담당하며
Javascript는 웹브라우저와 html을 제어합니다

HTML에 javascript 적용하기🎉

1) inline

태그에 직접 javascript를 작성하는 방식

<input type="button" onclick="alert('Hello world')" value="Hello world" />

2) script 태그

<script> </script> 태그 사이에 javascript 코드를 삽입하는 방식

<body>
	<script type="text/javascript">
  코드
	</script>
</body>

3) 외부 파일로 분리

javascript를 별도의 파일로 html과 분리해서 script 태그로 가져오는 방식

이 방법을 사용하면 정보제어의 구분이 더 명확해지고, 코드의 재활용성을 높이며 네트워크 측면에서도 캐쉬를 통해 속도향상과 전송량의 경량화 같은 장점이 있습니다

<body>
	<script type="text/javascript" src="script2.js"></script>
</body>

script 파일을 head에서 불러올 수도 있습니다

<head>
    <script src="script2.js"></script>
</head>

하지만 이럴경우 에러가 발생합니다
(웹 브라우저의 구성요소에 대한 로드가 아직 끝나지않아서 없는 요소에 대한 작업이 되버림)

그래서 head부분에 script파일을 불러올 경우 window.onload = function(){기존 js 코드 내용 } 코드를 추가해줘야합니다

일반적으로 script파일은 head보다는 페이지 하단에 위치시킵니다


Object 모델


브라우저의 구성요소들은 각각 객체화 되어있습니다

이 객체들을 javascript로 제어해서, 브라우저를 제어할 수 있게되는 것입니다
(객체가 가지는 속성, 메소드를 사용해 브라우저를 제어)

객체들은 서로 계층적인 관계로 구조화 되어있으며, BOMDOM은 이 구조를 구성하는 가장 큰 분류들입니다

위 구조에서처럼 documnet, window 등과 같이 브라우저는 각 요소에 접근할 수 있는 객체를 제공합니다

이 객체를 통해 이미 화면에 렌더링이 끝난 요소에 접근해 제어할 수 있습니다


Object 모델은 이 객체들을 구분해놓은 모델로, 각 구성요소들은 서로 계층적인 관계로 구조화되어있습니다

  • window객체 : 전역객체, window 제어를 위한 객체로서 존재한다

전역 객체기 때문에 window는 일반적으로 생략된다

  • JavaScript Core : javascript 언어 자체에 정의되어있는 객체(Object, Array, Function...)

  • BOM(Browser Object Model) : 웹 페이지의 내용을 제외한 브라우저의 각종 요소를 객체화 시킨 것

window의 속성(screen, location, frame...)에 속한 객체들

  • DOM(Document Object Model) : 웹 페이지의 내용을 제어하기 위한 객체들

window의 속성 중 document에 할당된 객체들

document 객체의 속성을 통해 문서 내용의 주요 요소들에 접근 할 수 있습니다

BOM, DOM, JSC 모두 window 객체의 속성들이지만, 그걸 개념적으로 나눠놓은 것을 Object 모델이라고 할 수 있습니다


BOM(Browser Object Model)

웹 브라우저의 창이나 프레임을 추상화해서 프로그래밍적으로 제어할 수 있도록 해주는 수단입니다

window객체의 속성과 메소드를 통해서 제어할 수 있습니다

window 객체💻

window는 모든 객체가 소속된 객체이고, 전역 객체이면서, 창과 프레임을 의미합니다

모든 객체는 window의 자식입니다

전역 변수,객체함수를 만드는 행위는 사실 window의 속성이나 메소드를 만드는 행위와 동일합니다

let a = 1;
window.a;

function(){
...
}
window.function();

사용자와 소통 : alert, confirm, prompt

JavaScript에서는 사용자의 입력을 받거나 정보를 전달하는 여러 수단을 제공합니다

이 메소드들은 window객체의 메소드 들이지만, window는 보통 생략됩니다

// alert : 경고창 / 정보를 제공하거나 디버깅 용도로 많이 사용됨
alert('hello world'); // == window.alert()

//confirm : 확인,취소의 선택을 제공하는 창을 띄운다
// 확안 - true , 취소 - false 를 return한다
confirm('ok?');

// prompt : 입력창 / 사용자로 부터 입력을 받은 내용을 return함
prompt('id?')

()안에는 전달하고자하는 정보를 작성합니다


Location 🌍

Location 객체는 문서의 주소와 관련된 객체로 마찬가지로 window 객체의 속성중 하나입니다

문서의 URL을 변경하거나 위치에 관련해서 여러 정보를 얻을 수 있습니다

//url 관련 정보
console.log(location.toString(), location.href);

//url을 의미에 따라 별도의 속성으로 제공하기도한다
console.log(location.protocol, location.host, location.port, location.pathname, location.search, location.hash);
//url 변경(리디렉션)
location.href = 'http://egoing.net'; //http://egoing.net으로 문서를 이동
location = 'http://egoing.net'; //동일한 효과

location.reload();//현제 문서를 리로드함

Navigator 🧭

Navigator객체는 현재 JavaScript가 실행되는 브라우저의 정보를 제공하는 객체입니다

주로 브라우저간 호환성을 위해서 사용됩니다 - 크로스브라우징/ 웹 표준

주요 속성은 다음과 같습니다

속성의미비고
appName웹브라우저의 이름IE는 Microsoft Internet Explorer, 파이어폭스, 크롬등은 Nescape
appVersion브라우저의 버전
userAgent브라우저가 서버측으로 전송하는 USER-AGENT HTTP 헤더의 내용appVersion과 유사
platform브라우저가 동작하고 있는 운영체제

객체에 관한 추가 속성은 console.dir(객체);로 모든 속성 열람이 가능합니다


창(window) 제어

대부분의 현대 브라우저는 탭을 지원하기 때문에 window.open() 메소드를 사용하면 새 창(탭)을 생성합니다

이때 open의 인자(파라미터)의 형태에 따라 작동하는 방식이 달라집니다

open을 사용하는 것은 JavaScript를 이용해 <a>태그를 구현하는 것과 유사합니다

//첫번째 인자에는 `문서의 url`이다
window.open('demo2.html');

//두번째 인자는 새 창의 이름이다
//이 인자를 생략하면 이름이 붙지 않은 새 창이 만들어진다

//_self는 스크립트가 실행되는 창을 의미한다
window.open('demo2.html', '_self');

// _blank는 새 창을 의미한다
window.open('demo2.html', '_blank');

//창에 이름을 붙일 수 있다
//open을 재실행 했을 때 동일한 이름의 창이 열려 있다면 그곳으로 문서가 로드된다
window.open('demo2.html', 'ot');

//세번재 인자는 새 창의 모양과 관련된 속성이 온다
window.open('demo2.html', '_blank', 'width=200, height=200, resizable=no');

//창을 닫음
window.close()

open 메소드는 실행되면 새로 열린 창의 정보를 담은 window객체를 return합니다

이 객체를 저장해놓으면 open을 통해 열린 창에 접근해 제어할 수 있습니다
win = window.open('demo2.html');

팝업 차단

웹 브라우저는 창을 열 때 JavaScript가 자동으로 실행되어 보안상의 문제가 발생하는 것을 방지합니다

브라우저는 같은 도메인일 경우에만 원격제어가 가능하게하고,
사용자의 상호작용(클릭...) 없이 창을 열려고 하면 팝업이 차단됩니다


DOM(Document Object Model)📄

DOM은 웹페이지(문서)를 JavaScript로 제어하기 위한 객체 모델을 말합니다

DOM은 코드가 브라우저/웹페이지와 상호작용하기 위한 표준 API라고 볼수 있습니다

window객체의 document 속성이 DOM에 해당됩니다


  • 요소(객체) 선택

문서를 제어하려면 제어의 대상이 되는 요소(객체)를 찾는게 먼저입니다

이를 위해서 document 객체의 여러 메소드들을 활용합니다
(메소드들은 클래스, 아이디, 태그 등 을 이용해 객체에 접근합니다)

메소드기능비고
document.getElementsByTagName특정 태그에 해당되는 객체결과를 nodelist라는 유사배열을 return합니다 (length나 인덱싱의 사용 가능)
document.getElementsByClassNameclass 속성의 값에 해당하는 객체
document.getElementByIdid 값에 해당하는 객체가장 우수한 성능을 가진다
document.querySelectorcss 선택자의 문법을 통해 선택선택자에 해당하는 첫번째 요소만 선택
document.querySelectorAllquerySelector와 유사선택자에 해당하는 모든 요소 선택

DOM TREE 🌴

Object Model에 따라서 HTML의 요소들은 객체로 취급되고, 각 객체는 관계된 HTML 요소들에 따라서 각각의 속성메소드를 가집니다

이러한 객체들은 부모, 자매의 관계들로 서로 얽혀서 하나의 계층구조를 형성하는데 이게 DOM TREE 입니다

각 객체들은 부모로부터 공통 속성을 내려받고, 각 요소의 특성에 따라 독립적인 속성을 가집니다

DOM의 메소드(getElement*)들로부터 받은 객체가 무엇인지 정확히 파악해야만 제어를 위한 적절한 메소드나 속성을 사용할 수 있습니다
(객체.constructor.name으로 어떤 객체인지 확인할 수 있습니다 )


Node 객체 🌱

Node는 DOM의 root 객체로, DOM의 모든 객체는 Node 객체를 상속 받습니다


주요 기능

Node 객체의 주요 기능은 다음과 같습니다

노드간의 관계

DOM의 요소들은 서로 부모, 자식, 혹은 형제자매 관계로 연결되어 있습니다

관계 API는 각 node가 다른 node와 연결된 정보를 보여주고, 이를 통해서 문서를 프로그래밍 적으로 탐색 가능하게 합니다

이때 빈칸과 같은 text도 DOM의 요소 중 하나입니다

속성의미
Node.childNodes자식노드들을 유사배열에 담아서 리턴한다
Node.firstChild첫번째 자식노드
Node.lastChild마지막 자식노드
Node.nextSibling다음 형제 노드 - 같은 level에 있는 요소
Node.previousSibling이전 형제 노드
<body id="start">
<ul>
    <li><a href="./532">html</a></li> 
    <li><a href="./533">css</a></li>
    <li><a href="./534">JavaScript</a>
        <ul>
            <li><a href="./535">JavaScript Core</a></li>
            <li><a href="./536">DOM</a></li>
            <li><a href="./537">BOM</a></li>
        </ul>
    </li>
</ul>
<script>
let s = document.getElementById('start');
  
console.log(s.firstChild); // Text객체 - body와 ul 사이의 개행문자가 선택됨
  
let ul = s.firstChild.nextSibling
console.log(ul); // ul
console.log(ul.nextSibling); // Text객체 - ul과 script 사이의 개행문자
console.log(ul.nextSibling.nextSibling); // script
  
console.log(ul.childNodes); //text(개행), li, text, li, text, li, text
console.log(ul.childNodes[1]); // li(html)
console.log(ul.parentNode); // body
</script>
</body>

노드의 종류

node 객체는 모든 구성요소를 대표하는 객체이기 때문에, 각각의 구성요소가 어떤 카테고리에 속하는 것인지를 알려주는 식별자를 제공합니다

각 노드는 종류에 따라 정해진 상수가 있습니다

for(var name in Node){
   console.log(name, Node[name]);
}
/*
출력결과

ELEMENT_NODE 1 
ATTRIBUTE_NODE 2 
TEXT_NODE 3 
...
*/

Node.nodeType : node의 타입을 의미하며 요소의 카테고리를 알려줍니다

Node.nodeName : node의 이름 (태그명을 의미)같은 더 자세한 정보 를 알려줍니다


노드의 값

node 객체의 을 제공하는 API입니다

Node.nodeValue
Node.textContent


노드 추가/삭제

Node 객체에 자식을 추가,삭제하는 방법에 대한 API입니다

node를 추가하려면 먼저 생성을 해야하는데, 이 과정에 관여하는 객체는 node 객체가 아니라 documnet 객체입니다

그래서 documnet객체로 노드를 생성한 뒤에 node객체를 통해 배치하는 과정을 거칩니다

//노드 추가하는 과정
document.createElement(tagname);
//요소 노드 생성
document.createTextNode(data);
//텍스트 노드 생성

Node.appendChild(child);
// 노드의 마지막 자식으로 주어진 요소 추가
insertBefore(newElement, referenceElement);
// appendChild와 동작방법은 동일하지만 두번째 인자로 요소를 전달 했을 때 이것 앞에 요소가 추가


//노드 삭제
Node.removeChild(newElement, referenceElement);
//부모 요소에서 메소드를 호출해야한다


//노드 바꾸기
Node.replaceChild(newChild, oldChild);

문자열로 노드제어하기

API를 통해 노드를 제어하는 방법은 복잡하고 방대합니다(생성->추가)

그 과정을 조금더 편리하게해서 코드를 통해 노드를 관리하는 API가 있습니다

1) innerHTML

innerHTML문자열로 자식 노드를 만들 수 있는 기능을 제공하고, 자식 노드의 값을 읽어 올 수 있게 합니다

이때 문자열은 해석되어 html 요소로 들어가게 됩니다

var target = document.getElementById('target');
alert(target.innerHTML); //자식 요소가 렌더링되어 출력

//문자열로 자식 요소 변경
target.innerHTML = "<li>JavaScript Core</li><li>BOM</li><li>DOM</li>";

기존의 API를 통한 생성 -> 추가 과정을 단축할 수 있습니다

2) outerHTML

outerHTMLinnerHTML과 기능은 동일하지만 자식요소뿐만 아니라 선택된 요소 자신도 포함해서 처리합니다

3) innerText, outerText

innerText, outerText는 값을 읽을 때는 HTML 코드를 제외한 문자열을 리턴하고, 값을 변경할 때는 HTML요소가 아닌 문자열 그대로의 코드가 그대로 추가됩니다
(html 요소가 아니라 text 요소로서 문자열이 추가되는 것)

in,out의 의미는 inner/outerHTML과 동일 - 자기자신 포함여부

let target = document.getElementById('target');
alert(target.innerText); //자식요소에 해당하는 HTML 코드가 그대로 출력됨

//문자열로 자식 요소 변경
target.innerText = "<li>JavaScript Core</li><li>BOM</li><li>DOM</li>";

4) insertAdjacentHTML()

좀더 세밀하게 노드를 제어할 때 사용합니다

첫번째 인자로 beforebegin, afterbegin, beforeend, afterend의 4종류의 위치를 지정하는 값을 가질 수 있습니다

두번째 인자로는 추가할 요소를 문자열로 입력합니다

let target = document.getElementById('target');

target.insertAdjacentHTML('beforebegin','<h1>Client Side</h1>');

Element 객체 📂

Element 객체는 페이지의 요소를 추상화한 객체입니다

DOM은 HTML뿐만 아니라 XML, SVG, XUL 같은 마크업 형태의 언어를 제어하기위한 모델이기 때문에,
Element 객체마크업 언어의 일반적인 속성을 정의하고 각 언어에 대해서는 HTMLElement, SVGElement, XULElement 같은 객체를 통해 세부적인 내용을 정의하고있습니다


주요 기능

Element 객체의 주요 기능은 다음과 같습니다

식별자

문서 내에서 특정한 요소를 식별하기 위한 용도로 사용되는 API입니다

요소를 조회하기 위해서는 식별자가 필요합니다

HTML에서는 이름, id, class를 식별자로 사용하는데, 이 API는 이 식별자를 가져오거나 변경합니다

<ul>
    <li>html</li>
    <li>css</li>
    <li id="active" class="important current">JavaScript</li>
</ul>
<script>
	//Element.tagName
	document.getElementById('active').tagName;//tag명 조회
  
  	var active = document.getElementById('active');
  
	//Element.id
  	console.log(active.id); //id 조회
	active.id = 'deactive'; //id 변경
	console.log(active.id);
  
	//Element.className - 사용하기 불편해 실제론 classList 많이 사용
  	active.className = "important current";//class 값 변경
	console.log(active.className);
  	active.className += " readed";//class 추가시 빈칸을 두고 문자열 추가
  	
  	//Element.classList
  	console.log(active.classList.length , active.classList[0]);//배열 처럼 사용
  	active.classList.add(클래스); //추가
  	active.classList.remove(클래스); //삭제
  	active.classList.toggle(클래스); //있으면 없애고,없으면 만드는 기능 - toggle 기능
</script>

조회

요소의 하위 요소를 조회하는 API로 getElementsBy* 메소드를 통해 요소를 조회합니다

document 객체도 이 메소드를 사용하지만 탐색 범위가 다릅니다

document문서 전체를 대상으로 조회하고, Element해당 요소의 하위 요소만을 대상으로 조회합니다

<ul>
    <li class="marked">html</li>
    <li>css</li>
    <li id="active">JavaScript
        <ul>
            <li>JavaScript Core</li>
            <li class="marked">DOM</li>
            <li class="marked">BOM</li>
        </ul>
    </li>
</ul>

<script>
  	//document 객체 - html,DOM,BOM 출력
    var list = document.getElementsByClassName('marked');

    for(var i=0; i<list.length; i++){
        console.log(list[i].textContent);
    }                                

	//element 객체 - DOM, BOM 출력                               	
    var active = document.getElementById('active');                         
    var list = active.getElementsByClassName('marked');//active id요소의 하위 요소만 출력된다
    for(var i=0; i<list.length; i++){
        console.log(list[i].textContent);
    }

</script>

속성

엘리먼트의 속성을 알아내고 변경하는 API로 태그의 속성을 제어합니다

그 종류는 다음과 같습니다

메소드기능
Element.getAttribute(name)속성의 값을 가져온다
Element.setAttribute(name, value)속성의 값을 설정
Element.hasAttribute(name);속성의 존재여부를 확인
Element.removeAttribute(name);속성을 제거

HTML의 속성은 JavaScript 객체의 속성(attribute-메소드)이나 속성(property)를 통해 제어할 수 있습니다

//attribute 방식
var target = document.getElementById('target');
target.setAttribute('class', 'important');

//property 방식
target.className = 'important';

property 방식을 사용할 경우 실제 html 속성과 제오를 위해 사용되는 속성이 다른 경우가 있어서 주의해야합니다

예)
class <-> className
readonly <-> readOnly
rowspan <-> rowSpan
...


HTMLElement 객체

HTMLElementElement의 하위 객체로 그 자식으로 여러 요소에 해당하는 다양한 종류의 객체를 가집니다

let a = document.getElementById('active'); //#active id를 가지는 li태그
let b = document.getElementsByTagName('li');

//각 메소드가 리턴한 객체에대한 정보 출력
console.log(a.constructor.name); //객체 종류 - HTMLLIElement 
console.log(b.constructor.name); //객체 종류 - HTMLCollection

위 예제에선 메소드의 실행결과가 하나인 경우 HTMLLIELement, 복수인 경우 HTMLCollection(유사 배열)을 리턴하고있습니다

  • HTMLElement 하위 객체들

DOM을 통해 가져오는 객체는 HTMLElement에 해당하는 공통 속성이나 메소드를 가지지만, HTMLLIELement처럼 각 요소의 종류에 따라 객체의 종류(속성이나 메소드)가 조금씩 달라집니다

예시)
li태그 요소 -> HTMLLIElement
a태그 요소 -> HTMLAnchroElement
input태그 요소 -> HTMLInputElement
...

  • HTMLCollection

요소 선택의 결과가 여러 개일 경우 사용되는 객체입니다. 결과물은 유사배열로 배열과 사용방법이 비슷하지만 배열은 아닙니다(length, index 사용가능)

HTMLCollection의 목록은 collection을 생성한 뒤에는, collection 내의 요소에 변경이 있을 경우 별도의 작업없이도 자동으로 변경됩니다(자동 update)


Document 객체 📝

Document 객체는 DOM의 시작점이면서 문서 전체를 의미하는 node이기도 합니다

실제 사용될 때는 하위 객체인 HTMLDocument 객체가 주로 사용됩니다

//document 객체의 자식으로는 Doctype과 html(문서 전체)이 있다
console.log(window.document.childNodes[0]);//Doctype
console.log(window.document.childNodes[1]);//html

주요 기능은 다음과 같습니다
  • 노드 생성 API

createElement()
createTextNode()

  • 문서 정보 제공 API

title, URL, referrer, lastModified


Text 객체

text 노드에 대한 DOM 객체로 CharcterData를 상속받습니다

DOM에서 공백이나 줄바꿈(개행)도 텍스트 노드입니다


주요 기능은 다음과 같습니다

  • 노드의 값

Text 객체에는 DOM에서 실질적인 값들이 저장됩니다. 그 값들을 이 속성들로 확인할 수 있습니다

data, nodeValue

  • 노드 조작
target.appendData(text); //target 객체에 text 추가

target.deleteData(시작지점,종료지점); //0부터 시작해 범위를 지정

target.insertData(시작지점, text); //삽입할 위치와 텍스트를 입력

target.replaceData(시작지점, 종료지점, text); //지정된 범위를 텍스트로 대체

//정보중 일부만 가져온다
target.substringData(시작지점, 종료지점); //객체의 데이터를 시작지점~종료지점까지 가공
  • 노드 생성

docuemnt.createTextNode()


이벤트(Event)🎈

이벤트는 어떤 사건을 의미하고, 사용자가 어떠한 행동을 했을 를 기준으로 등록된 코드를 실행하게 하는 방식을 이벤트 프로그래밍(event driven programming)이라고합니다

이 이벤트에 참여하는 여러 대상이 있습니다

event target : 이벤트가 일어날 객체
event type : 이벤트의 종류 - click, scroll, mousemove 등 다양한 종류가 있다
event handler : 이벤트가 발생했을 때 동작하는 코드(함수)


이벤트 등록

이벤트 프로그래밍을 위해서는 그 대상에 이벤트 핸들러(event handler)를 등록해줘야합니다

그 등록 방법은 다음과 같습니다

1) inline

이벤트를 이벤트 대상의 태그 속성으로 지정하는 것입니다

<input type="button" onclick="alert('Hello world');" value="button" />

이때 이벤드 대상(event target)this를 통해 참조할 수 있습니다

태그에 이벤트가 포함되기 때문에 이벤트 대상을 찾기 편리합니다

2) 프로퍼티 리스너(Property Listener)

이벤트 대상에 해당하는 객체의 프로퍼티(속성)로 이벤트를 등록하는 방법입니다

<input type="button" id="target" value="button" />
<script>
    var t = document.getElementById('target');
    t.onclick = function(){ //onclick이라는 속성의 값으로 이벤트를 등록
        alert('Hello world');
    }
</script>

이벤트 객체(event)

이벤트는 실행된 맥락의 정보를 전달하는 객체입니다

이벤트 객체는 이벤트 실행시 핸들러에게 인자로서 전달됩니다

전달된 event객체에서는 이벤트에 관련된 다양한 정보를 얻을 수 있습니다

...
t.onclick = function(event){
...

3) addEventListener()

addEventListener는 이벤트를 등록하는 방법중가장 권장되는 방식입니다

일반적으로 target.addEventListener(type, listener[, options]);의 형태로 사용됩니다

<input type="button" id="target" value="button" />
<script>
    var t = document.getElementById('target');
    t.addEventListener('click', function(event){
        alert('Hello world, '+event.target.value);//value=button
    });
  	
  	//addEventListener가 동작하지 않는 경우 대신 사용하는 메소드
  	t.attachEvent('onclick', function(event){
        alert('Hello world, '+event.target.value);
    })
</script>

addEventListener는 하나의 대상에 같은 타입의 이벤트에 대해서 리스너 여러 개를 추가할 수 있습니다

기능 테스트

예를 들어 addEventListenerie8이하에서는 동작하지 않기 때문에 attachEvent 메소드를 사용해야한다

이럴 경우 객체의 메소드가 존재하는지 확인하고 환경에 따라 다르게 동작하도록 기능 테스트를 적용하면 된다

if(객체.메소드) 코드로 객체에 메소드가 존재하는지 확인할 수 있다


기본 이벤트 관리

웹 브라우저의 요소들은 사용자가 작성한 이벤트 외에도 기본 이벤트들을 가지고 있습니다

예)
텍스트 필드에 포커스를 준 상태에서 키보드를 입력하면 텍스트가 입력
폼에서 submit 버튼을 누르면 데이터가 전송
...

이런 기본 이벤트 들은 사용자 지정 이벤트로 취소시킬 수 있습니다

이벤트의 리턴값이 false 일 때 기본 동작이 취소됩니다

<!--inline 방식-->
<form action="http://opentutorials.org" onsubmit="return false;">//retrun값이 false
	<input type="submit" />
</form>

<!--property 방식-->
<script>
document.querySelector('form').onclick = function(event){
	return false; //retrun값이 false
};
</script>

이벤트 리스너를 사용할 경우에는 이벤트 객체의 preventDefault 메소드를 사용합니다

<!--addEventListener 방식-->
document.querySelector('form').addEventListener('submit', function(event){
	event.preventDefault();
});

이벤트 전파

HTML은 여러 태그들이 중첩되어 부모 자식관계로 얽혀있습니다

이때 특정 태그에서 발생하는 이벤트중첩되어있는 태그들 모두가 대상이 될 수 있습니다

특정 태그에서 이벤트가 발생했을 때 중첩된 태그들에 이벤트가 등록되어있을 경우, 각 이벤트가 처리되는 방식들을 정의한게 버블링캡쳐링입니다

더 자세히

캡쳐링(Capturing) 📷

이벤트가 부모에서 발생해서 자식으로 전파되는 방식으로, 리스너를 추가할 때 별도로 true 옵션을 줘야합니다

false(default 값) : 핸들러는 버블링 단계에서 동작
true : 핸들러는 캡처링 단계에서 동작

<html>
    <head>
        <style>
            html{border:5px solid red;padding:30px;}
            body{border:5px solid green;padding:30px;}
            fieldset{border:5px solid blue;padding:30px;}
            input{border:5px solid black;padding:30px;}
        </style>
    </head>
    <body>
        <fieldset>
            <legend>event propagation</legend>
            <input type="button" id="target" value="target">          
        </fieldset>
        <script>
        function handler(event){
            var phases = ['capturing', 'target', 'bubbling']
            console.log(event.target.nodeName, this.nodeName, phases[event.eventPhase-1]);
        }
        /*
        출력 결과 - 이벤트 주체 / 핸들러 함수가 호출된 요소/ 페이즈
        INPUT HTML capturing
		INPUT BODY capturing
		INPUT FIELDSET capturing
		INPUT INPUT target  
        */
          
        //리스너 추가
        document.getElementById('target').addEventListener('click', handler, true);//캡쳐링 옵션을 true로 설정
        document.querySelector('fieldset').addEventListener('click', handler, true);
        document.querySelector('body').addEventListener('click', handler, true);
        document.querySelector('html').addEventListener('click', handler, true);
        </script>
    </body>
</html>

ie 낮은 버전에서는 작동하지 않기 때문에 많이 사용하지는 않습니다


버블링(Bubbling) 🧼

자식부터 부모로 이벤트가 전파되는 것을 버블링이라고 합니다

버블링은 거의 모든 요소, 브라우저에 대해서 동작합니다

...
document.getElementById('target').addEventListener('click', handler);
...

버블링은 중간에 멈출 수도 있습니다. 이벤트 개체의 event.stopPropagation()메소드를 사용하면 됩니다

멈추고자 하는 리스너의 핸들러에서 메소드를 사용하면, 사용된 대상 이후의 리스너 작동을 중지시킵니다


이벤트 타입


form

  • submit

form 태그에서 정보를 서버로 전송하는 명령인 submit을 할때 발생하는 이벤트입니다

<form id="target" action="result.html">
	...
</form>
<script>
var t = document.getElementById('target');
  
t.addEventListener('submit', function(event){
	...
});
</script>
  • change

change는 폼 컨트롤의 값이 변경 되었을 때 발생하는 이벤트입니다

t.addEventListener('change', function(event){
    document.getElementById('result').innerHTML=event.target.value;
});
  • blur, focus

focus는 요소에 포커스(강조)가 생겼을 때, blur은 포커스가 사라졌을 때 발생하는 이벤트입니다

<base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title> 태그를 제외하고 모든 태그에서 발생합니다

t.addEventListener('blur', function(event){
    ...
});
t.addEventListener('focus', function(event){
    ... 
});

문서 로딩

웹 페이지를 프로그래밍으로 제어하려면 각 요소에대한 처리가 끝나야합니다

이 처리의 진행 상황에 대해 알려주는 이벤트가 load, DOMContentLoaded입니다

<head>
    <script>
      	//페이지의 로드가 완료되면 이 이벤트가 발생한다
        window.addEventListener('load', function(){
            var t = document.getElementById('target');
            console.log(t);
        })
      
      	window.addEventListener('DOMContentLoaded', function(){
			console.log('DOMContentLoaded');
       	})
    </script>
</head>
<body>
    <p id="target">Hello</p>
</body>

load는 문서내 이미지, 스크립트를 포함한 모든 리소스의 다운로드가 마무리된 뒤에 실행되기 때문에 구동이 너무 느려질 위험성이 있습니다

DOMContentLoaded는 문서에 스크립트 작업을 할 수 있을 때 바로 실행되기 때문에 이미지 같은 리소스의 준비를 기다리지 않습니다


마우스

마우스나 키보드와 관련된 이벤트들입니다

이벤트 타입감지하는 움직임
click클릭했을 때 발생하는 이벤트
dblclick더블클릭을 했을 때 발생하는 이벤트
mousedown마우스를 누를 때 발생
mouseup마우스버튼을 땔 때 발생
mousemove마우스를 움직일 때
mouseover마우스가 엘리먼트에 진입할 때 발생
mouseout마우스가 엘리먼트에서 빠져나갈 때 발생
contextmenu컨텍스트 메뉴가 실행될 때 발생
event.shiftKeyshift키 눌러짐 감지
event.altKeyalt키 눌러짐 감지
event.ctrlKeyctrl키 눌러짐 감지
event.clientX/clientY마우스 포인터의 위치

jQuery🔨

jQuery는 JavaScript 라이브러리로, DOM의 내용을 내부에 숨기고 보다 쉽게 페이지를 조작 할 수 있도록 돕는 도구입니다

DOM을 기반으로 제작된 것이고, 더 편리한 문서 제어를 가능하게 해줍니다


jQuery를 사용하기 위해서는 HTML에 jQuery를 로드해줘야합니다

직접 파일을 저장해 사용하거나, CDN을 통해 불러올 수도 있습니다

//CDN 방식
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

//이 코드로 감싸주는게 이상적인 jQuery사용법이다
jQuery( document ).ready(function( $ ) {
	코드내용
}

더 자세히


jQuery 기본 양식

//기본 양식
$("css 선택자").메소드();

$() 는 jQuery의 함수입니다. 이 함수는 전달된 인자(css 선택자)를 바탕으로 jQuery객체를 return 합니다

이 객체는 선택자에 해당하는 요소 를 제어하는 다양한 메소드들을 가지고 있습니다

//동일한 기능을 DOM과 jQuery로 구현했을 때의 코드 차이

//DOM
var lis = document.getElementsByTagName('li');
for(var i=0; i&lt;lis.length; i++){
    lis[i].style.color='red';   
  
//jQuery
$('li').css('color', 'red');

위 예시처럼 jQuery를 활용하면 코드가 더 간단해지고 명확해집니다


jQuery 객체

jQuery객체는 jQuery 함수의 리턴값으로, 선택한요소에 대한 처리작업을 속성(메소드)으로 가지는 객체입니다

jQuery 객체는 암시적 반복을 수행하는 특성을 가집니다. DOM과 다르게 jQuery 객체의 메소드를 실행하면 선택된 모든 요소에 대해 동시에 작업이 처리됩니다

암시적 반복

jQuery 객체의 특성으로 값을 설정할 때만 동작합니다. 값을 조회할 때는 첫번째 값만 반환하고 종료됩니다

jQuery 객체의 메소드들은 암시적 반복을 통해 선택된 모든 항목에 대해 작업을 수행합니다

체이닝(chainig)

체이닝은 선택된 요소에 대해 계속 이어서 연속적으로 작업을 처리하는 방법입니다

예시) $('li').css('color', 'red').css('background-color','blue')...;

jQuery 객체에는 선택자에 따라서 조회된 요소가 저장되어있습니다

이 요소들은 객체에 일종의 유사배열 형태로 저장되어있기 때문에, 배열처럼 저장된 DOM 요소를 가져올 수 있습니다

<ul>
    <li>html</li>
    <li>css</li>
    <li>JavaScript</li>
</ul>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
  	//배열과 같은 특성 사용
    console.log($('li').length);
    console.log($('li')[0]);
  
    var li = $('li');
    for(var i=0; i<li.length; i++){
        console.log(li[i]);                                                   
    }
	
	//map함수와 같이 사용할 수 도 있다 - 순회하면서 각 항목에대해 함수를 호출           
    li.map(function(index, elem){
        console.log(index, elem);
        $(elem).css('color', 'red');
    })               
</script>

위 예시에서 사용한 css외에도 객체에서 사용 가능한 다양한 메소드가 있습니다


Node 객체 기능 in jQuery

node의 변경 기능을 jQuery로 구현하는 기능은 Manipulation 카테고리에 해당됩니다


  • node 추가

추가와 관련된 주요 메소드는 4가지로, 각 메소드가 node를 추가하는 방식은 다음 그림과 같습니다

<div class="target">
    content1
</div>
 
<div class="target">
    content2
</div>
 
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('.target').before('<div>before</div>');
    $('.target').after('<div>after</div>');
    $('.target').prepend('<div>prepend</div>');
    $('.target').append('<div>append</div>');
</script>

추가 메소드의 인자로 특정 노드를 선택하면 그 요소를 jQuery객체의 자식으로 이동시키는 효과가 있습니다

$('#target1').append($('#source'));

  • node 제거

node의 제거는 removeempty 메소드를 통해 이루어집니다

remove : 선택된 요소 삭제
empty : 요소의 텍스트 노드 삭제

$('#target1').remove();
$('#target2').empty();

  • node 바꾸기

node의 교체는 replaceAllreplaceWith을 통해 이뤄진다

replaceAll: 제어 대상을 인자로 전달
replaceWith: 제어 대상을 먼저 지정

인자의 위치 차이입니다

$('<div>replaceAll</div>').replaceAll('#target1');
$('#target2').replaceWith('<div>replaceWith</div>');

clone 메소드를 교체 메소드에 더해서 노드를 복사 할 수도 있습니다

$('#source').clone().replaceAll('#target1');

$('#target2').replaceWith($('#source').clone());

$('#source').clone()으로 대체할 노드를 복제합니다


Element 객체 기능 in jQuery

Element의 API기능을 jQuery에서 구현하는 방법들입니다

  • 속성제어

기존의 Element의 메소드가 jQuery에서는 다음과 같이 대체되어 사용됩니다

setAttribute, getAttribute -> attr : 속성 조회 및 변경
removeAttribute -> removeAttr : 속성 제거

<a id="target" href="http://opentutorials.org">opentutorials</a>

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

<script>
	var t = $('#target');
  
  	//attr=attribute 방식
	console.log(t.attr('href')); //속성 값 조회
	t.attr('title', 'opentutorials.org'); // 속성 값 설정
	t.removeAttr('title'); //속성을 제거
  	
  	//prop=property 방식 - 가져오는 값이 약간 달라진다
  	t.prop('href')
</script>

jQuery에서는 property 방식으로 속성을 제어할 때 Element에서 실제 요소의 속성명과 property가 달라서 불편했던 것과 달리 내부적으로 보정해줍니다
(웹표준, 크로스 브라우징에 관련된 부분을 알아서 처리해줍니다)

//property 방식
target.className = 'important';

// 모두 클래스를 수정한다
$('#t1').prop('className', 'important'); 
$('#t2').prop('class', 'current');  

  • 조회범위 제한

Element에서는 조회의 범위가 객체의 선택된 요소의 하위 요소로 제한됬었습니다

jQuery에서는 find메소드 혹은 css 선택자 문법으로 범위 제한을 구현합니다

<ul>
    <li class="marked">html</li>
    <li>css</li>
    <li id="active">JavaScript
        <ul>
            <li>JavaScript Core</li>
            <li class="marked">DOM</li>
            <li class="marked">BOM</li>
        </ul>
    </li>
</ul>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
  	//selector context : 선택자 문법으로 요소 제한
    $( ".marked", "#active").css( "background-color", "red" );
  
  	//.find() : jQuery 객체 내에서 요소를 조회
  	$( "#active").find('.marked').css( "background-color", "red" );
</script>

find는 객체의 연결고리(chain)을 끊지 않고 작업 대상을 변경할 때 사용합니다

$('#active').css('color','blue').find('.marked').css( "background-color", "red" );

하지만 find를 너무 복잡하게 사용하면 유지보수가 어려워집니다


이벤트 in jQuery

jQuery는 이벤트 관련해서도 편리한 기능을 제공합니다

이벤트를 순수하게 구현하는 것에 비해 코드 분량을 줄여주고, 크로스 브라우징 또한 알아서 처리해줍니다

    // 순수하게 DOM으로 구현했을 때
    var target = document.getElementById('pure');
    if(target.addEventListener){
        target.addEventListener('click', function(event){
            alert('pure');
        });
    } else {
        target.attachEvent('onclick', function(event){
            alert('pure');
        });
    }
 
    // jQuery를 사용했을 때
    $('#jquery').on('click', function(event){
        alert('jQuery');
    })

jQuery는 이벤트를 구현하기 위해 on API를 사용합니다

on의 기본 문법은 다음과 같습니다

.on( events [, selector ] [, data ], handler(eventObject) )

event : 등록하고자 하는 이벤트 타입을 지정한다. (예: "click")

selector : 이벤트가 설치된 요소의 하위 요소를 이벤트 대상으로함

//ul태그가 아니라 그 하위의 a,li태그가 이벤트의 대상이된다
$('ul').on('click','a, li', function(event){ 
        console.log(this.tagName);
    })

data : 이벤트가 실행될 때 핸들러로 전달될 데이터를 설정함
handler : 이벤트 핸들러 함수


Late Binding

jQuery는 존재하지 않는 엘리먼트에도 이벤트를 등록할 수 있는 기능인 late binding을 제공합니다

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('body').on('click','a, li', function(event){
        console.log(this.tagName);
    })
</script>
<ul>
    <li><a href="#">HTML</a></li>
    <li><a href="#">CSS</a></li>
    <li><a href="#">JavaScript</a></li>
</ul>

이미 존재하는 body 태그처럼 sciprt 로드 이전에도 이미 존재하는 태그를 기준으로 그 하위요소에 이벤트를 등록하면, 이후 요소가 생성된 뒤에 이벤트가 설치됩니다


다중 바인딩

하나의 요소에 여러 개의 이벤트 타입을 동시에 등록하는 방법입니다

//하나의 요소에 여러 이벤트 타입 동시 등록
$('#target').on('focus blur', function(e){//빈칸으로 이벤트 구분
        $('#status').html(e.type);
})

//여러 이베트 타입 등록후 다른 핸들러를 실행하는 경우
$('#target').on({
	'focus' : function(e){
	}, 
	'blur' : function(e){
	}
})

이벤트 제거

이벤트 제거에는 off 메소드를 사용합니다

$('#target').off('focus blur', handler);
    console.log(32);

출처 및 참고

https://opentutorials.org/course/1375
https://web.stanford.edu/class/cs98si/slides/the-document-object-model.html

좋은 웹페이지 즐겨찾기