JavaScript DOM API
API 란?
Application Programming Interface 의 약자로 어플리케이션을 프로그래밍할 수 있는 접점을 의미합니다.
API 는 응용 프로그램에서 사용할 수 있도록 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스로 애플리케이션을
프로그래밍 하기위해 미리만들어 놓은 기능의 집합으로 자주 사용되는 기능을 미리 만들어놨다가 필요할때 가져다 쓸수있도록
하기에 프로그래밍 작업시 효율성과 편의성을 제공합니다.
DOM 이란?
Document Object Model(문서 객체 모델)은 HTML, XML 문서의 프로그래밍 interface 입니다.
DOM 은 문서의 구조화된 표현을 제공하여, 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공하며,
그들이 문서 구조, 스타일, 내용 등을 변경할 수 있게 돕습니다.
DOM 은 구조화된 nodes 와 property 와 method 를 갖고 있는 objects 로 문서를 표현합니다.
이들은 웹 페이지를 스크립트 혹은 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당합니다.
DOM Tree
트리는 여러 데이터가 계층 구조 안에서 서로 연결된 형태를 나타날 때 사용됩니다.
트리는 노드로 구성되어 있는데 노드란?
- 노드(node) - 트리 안에 들어있는 각 항목을 말합니다.
다음은 노드의 종류입니다.
-
문서 노드 (Document Node) - 트리의 최상위에 존재하며 각각 요소,어트리뷰트,텍스트 노드에 접근하려면 문서 노드를 통해야 합니다.
즉 DOM Tree 에 접근하기 위한 시작점(entry point)입니다. -
요소 노드 (Element Node) - 요소 노드는 HTML 요소를 표현합니다. HTML 요소는 중첩에 의해 부자 관계를 가지며, 이 부자 관계를 통해 정보를 구조화합니다.
따라서 요소노드는 문서의 구조를 서술한다고 말 할수 있습니다. 어트리뷰트, 텍스트 노드에 접근하려면 먼저 요소 노드를 찾아 접근해야 합니다.
모든 요소 노드는 요소별 특성을 표현하기 위해 HTMLElement 객체를 상속한 객체로 구성됩니다.- 자식 노드 (child node) - 노드는 여러 자식 노드를 가질 수 있습니다.
- 부모 노드 (parent node) - 노드 A 가 노드 B 를 자식으로 갖고 있다면, 노드 A 를 노드 B 의 ‘부모 노드’라고 부릅니다.
- 뿌리 노드 (root node) - 트리의 가장 상층부에 있는 노드를 말합니다.
- 잎 노드 (leaf node) - 자식 노드가 없는 노드를 말합니다.
- 조상 노드 (ancestor node) - 노드 A 의 자식을 따라 내려갔을 때 노드 B 에 도달할 수 있다면, 노드 A 를 노드 B 의 조상 노드라고 부릅니다.
- 자손 노드 (descendant node) - 노드 A 가 노드 B 의 조상 노드일 때, 노드 B 를 노드 A 의 자손 노드라고 부릅니다.
- 형제 노드 (sibling node) - 같은 부모 노드를 갖는 다른 노드를 보고 형제 노드라고 부릅니다.
-
어트리뷰트 노드 (Attribute Node) - 어트리뷰트 노드는 HTML 요소의 어트리뷰트를 표현합니다.
어트리뷰트 노드는 해당 어트리뷰트가 지정된 요소의 자식이 아니라 해당 요소의 일부로 표현됩니다.
따라서 해댱 요소 노드를 찾아 접근하면 어트리뷰트의 참조, 수정할 수 있습니다. -
텍스트 노드 (Text Node) - 텍스트 노드는 HTML 요소의 텍스트를 표현합니다. 텍스트 노드는 요소 노드의 자식이며 자신의 자식 노드를 가질 수 없습니다.
즉 텍스트 노드는 DOM tree 의 최종단입니다.
다음은 아주 간단한 형태의 Node
를 구현한 예입니다.
class Node {
constructor(content, children = []) {
this.content = content;
this.children = children;
}
}
const tree = new Node("hello", [
new Node("world"),
new Node("and"),
new Node("fun", [new Node("javascript!")])
]);
function traverse(node) {
console.log(node.content);
for (let child of node.children) {
traverse(child);
}
}
traverse(tree);
// hello world and fun javascript!
트리는 계층 구조를 나타내기 위해, 또한 계층 구조를 통해 알고리즘의 효율을 높이고자 할 때 널리 사용됩니다.
Event Reference
대표적인 이벤트들을 소개합니다.
https://developer.mozilla.org/en-US/docs/Web/Events
Web API
자바스크립트로 웹용 코드를 작성할 때 사용할 수 있는 API 가 많이 있습니다. 다음 사이트는 웹 앱이나 사이트를 개발할 때 사용할 수 있는 모든 인터페이스(즉, 객체유형) 목록이 있습니다. https://developer.mozilla.org/en-US/docs/Web/API
엘리먼트 선택하기
요소 노드(Element Node)를 선택하는 방법은 다음과 같습니다.
document.querySelector
- document 안에 해당하는 요소를 선택합니다.
// 사용방법
document.querySelector("CSS 선택자");
document.querySelectorAll
- document 안에 해당하는 요소를 모두 선택합니다.
// 사용방법
document.querySelectorAll("CSS 선택자");
el.querySelector
- 요소 안에 해당하는 요소를 선택합니다.
// 사용방법
body.querySelector("CSS 선택자");
el.closest
- Element.closest () 메서드는 매개 변수에 지정된 선택기와 일치하는 현재 요소 (또는 현재 요소 자체)의 가장 가까운 조상을 반환합니다.
그러한 조상이 존재하지 않는 경우, null 를 돌려줍니다.
<article>
<div id="div-01">Here is div-01
<div id="div-02">Here is div-02
<div id="div-03">Here is div-03</div>
</div>
</div>
</article>
// 사용 방법
let el = document.querySelector("#div-03");
let r1 = el.closest("#div-02");
// id가 div-02인 요소를 반환합니다. (div-03이 자식이기에 CSS를 적용하면 같이 적용됩니다.)
let r2 = el.closest("div div");
// div의 div인 가장 가까운 조상을 반환합니다. div-03이 반환됩니다.
let r3 = el.closest("article > div");
// div이면서 부모 article이 있는 가장 가까운 상위 항목을 반환합니다. div-01이 반환됩니다.
let r4 = el.closest(":not(div)");
// div가 아닌 가장 가까운 조상을 반환합니다. 여기에 outmost article이 있습니다.
el.matches
- Element.matches () 메서드는 요소가 지정된 선택자 문자열로 선택되는 경우 true 를 반환하고, 그렇지 않으면 false 를 반환합니다.
그렇지 않은 경우는 false 를 리턴합니다.
<ul id="birds">
<li>Orange-winged parrot</li>
<li class="endangered">Philippine eagle</li>
<li>Great white pelican</li>
</ul>
let birds = document.querySelectorAll("li"); // document의 모든 li요소를 선택하여 변수 birds에 값으로 대입
for (let i = 0; i < birds.length; i++) {
// i가 0일때부터 birds.length(3)까지 i++
if (birds[i].matches(".endangered")) {
// 만약 birds[i]가 endangered라는 클래스 네임을 갖고 있을 경우
console.log("The " + birds[i].textContent + " is endangered!"); // 해당 구문 출력
}
}
// 결과 : The Philippine eagle is endangered!
엘리먼트 내용 조작하기
el.textContent
- 요소의 텍스트 콘텐츠를 취득 또는 변경한다. 이때 마크업은 무시됩니다.
textContent 를 통해 요소에 새로운 텍스트를 할당하면 텍스트를 변경할 수 있습니다.
이때 순수한 텍스트만 지정해야 하며 마크업을 포함시키면 문자열로 인식되어 그대로 출력됩니다.
const text = element.textContent;
element.textContent = "this is some sample text";
el.innerHTML
- 해당 요소의 모든 자식 요소를 포함하는 모든 콘텐츠를 하나의 문자열로 취득할 수 있습니다.
이 문자열은 마크업을 포함합니다.
const content = element.innerHTML;
element.innerHTML = htmlString;
여기서 잠깐!!
HTML 콘텐츠를 조작(Manipulation)하기 위해 위와 같은 프로퍼티 또는 메소드를 사용할 수 있습니다.
하지만 마크업이 포함된 콘텐츠를 추가하는 행위는 크로스 스크립팅 공격(XSS: Cross-Site Scripting Attacks)에 취약하므로 주의가 필요합니다.
가급적 텍스트 노드를 다룰때는 마크업이 무시되는 textContent 를 사용하는 것이 좋습니다.
그렇다면 크로스 스크립팅 공격이란?
// 크로스 스크립팅 공격 사례
// 스크립트 태그를 추가하여 자바스크립트가 실행되도록 합니다.
// HTML5에서 innerHTML로 삽입된 <script> 코드는 실행되지 않습니다.
// 크롬, 파이어폭스 등의 브라우저나 최신 브라우저 환경에서는 작동하지 않을 수도 있습니다.
elem.innerHTML = '<script>alert("XSS!")</script>';
// 에러 이벤트를 발생시켜 스크립트가 실행되도록 합니다.
// 크롬에서도 실행됩니다!
elem.innerHTML = '<img src="#" onerror="alert(\'XSS\')">';
// 자바스크립트 링크 공격
// 링크 태그로 자바스크립트를 실행시킵니다.
elem.innerHTML = '<a href="javascript:alert("XSS")">XSS</a>';
SQL injection(데이터베이스 조회를 통한 공격)과 함께 웹 상에서 가장 기초적인 취약점 공격 방법의 일종으로,
악의적인 사용자가 공격하려는 사이트에 스크립트를 넣는 기법을 말합니다.
공격에 성공하면 사이트에 접속한 사용자는 삽입된 코드를 실행하게 되며,
보통 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰등의 민감한 정보를 탈취합니다.
엘리먼트 어트리뷰트 조작하기
el.hasAttribute
- Element.hasAttribute () 메서드는 지정된 요소에 지정된 특성이 있는지 여부를 나타내는 부울 값을 반환합니다.
// 작성 방법
let result = element.hasAttribute("CSS 선택자");
// 사용 방법
let foo = document.querySelector("#foo");
if (foo.hasAttribute("bar")) {
// 부울 값을 반환하므로 조건문으로 활용할 수 있습니다.
// do something
}
el.getAttribute
- getAttribute ()는 요소의 지정된 속성 값을 반환합니다.
지정된 속성이 존재하지 않는 경우, 반환되는 값은 null 또는 ‘‘(공 문자열)가 됩니다.
// 작성 방법
let attribute = element.getAttribute("어트리뷰트 이름");
// 사용 방법
let div1 = document.querySelector("#div1");
let align = div1.getAttribute("align");
alert(align); // shows the value of align for the element with id="div1"
el.setAttribute
- 지정된 요소의 속성 값을 설정합니다. 속성이 이미 존재하면 값이 갱신됩니다.
그렇지 않으면 새로운 속성이 지정된 이름과 값으로 추가됩니다.
속성의 현재 값을 가져 오려면 getAttribute ()를 사용하고, 속성을 삭제하려면, removeAttribute ()를 사용하도록 합니다.
<button>Hello World</button>
const b = document.querySelector("button");
b.setAttribute("name", "helloButton");
b.setAttribute("disabled", "");
el.removeAttribute
- removeAttribute 는 지정된 요소에서 속성을 제거합니다.
// <div id="div1" align="left" width="200px">
document.querySelector("#div1").removeAttribute("align");
// align 속성을 제거시켰으므로 다음과 같이 출력됩니다.
// <div id="div1" width="200px">
엘리먼트 클래스 조작하기
el.classList
- Element.classList 는 요소의 클래스 속성에 대한 라이브 DOMTokenList 컬렉션을 반환하는 읽기 전용 속성입니다.
classList 를 사용하는 것은 element.className 을 통해 요소의 클래스 목록에 공백으로 구분 된 문자열로 액세스하는 편리한 대안입니다.
// div는 class = 'foo bar'인 요소에 대한 객체 참조입니다.
div.classList.remove("foo");
div.classList.add("anotherclass");
// visible이 설정되어있으면 제거하고, 그렇지 않으면 추가합니다.
div.classList.toggle("visible");
// i가 10보다 작으면 visible을 추가/제거합니다.
div.classList.toggle("visible", i < 10);
// foo라는 값을 포함하고 있으면 경고창을 켭니다.
alert(div.classList.contains("foo"));
// 여러 클래스를 더하거나 제거할수 있습니다.
div.classList.add("foo", "bar", "baz");
div.classList.remove("foo", "bar", "baz");
// 스프레드 문법을 이용하여 추가 제거도 가능합ㄴ디ㅏ.
let cls = ["foo", "bar"];
div.classList.add(...cls);
div.classList.remove(...cls);
// foo를 bar로 대체합니다.
div.classList.replace("foo", "bar");
-
el.classList.add
- 지정된 클래스 값을 추가합니다. 이러한 클래스가 이미 요소의 속성에 존재하면 무시됩니다. -
el.classList.remove
- 지정된 클래스 값을 제거합니다. 존재하지 않는 클래스를 제거해도 오류가 발생하지 않습니다. -
el.classList.contains
- 요소의 클래스 속성에 지정된 클래스 값이 있는지 확인합니다. -
el.classList.toggle
- 인수가 하나 뿐인 경우 : 클래스 값을 토글합니다.
즉, 클래스가 존재하면 그것을 제거하고 false 를 반환하고 그렇지 않으면 false 를 반환하고 추가 한 다음 true 를 반환합니다.
두 번째 인수가있는 경우 : 두 번째 인수가 true 로 평가되면 지정된 클래스 값을 추가하고, false 로 평가하면 제거합니다. -
el.classList.replace
- 기존 클래스를 새 클래스로 바꿉니다. -
el.classList.item
- 콜렉션의 인덱스에 의해 클래스 값을 돌려줍니다.
인라인 스타일 조작하기
el.style
- HTMLElement.style 속성은 요소의 인라인 스타일을 가져 오거나 설정하는 데 사용됩니다.
가져 오는 동안 요소의 인라인 스타일 속성에 정의 된 특성에 할당 된 값을 사용하여 해당 요소의 모든 스타일 속성 목록을 포함하는 CSSStyleDeclaration 개체를 반환합니다.
style 속성은 style 속성을 통해 설정된 인라인 스타일 선언과 같은 CSS 캐스케이드에서 동일한 (가장 높은) 우선 순위를 가집니다.
// 여러 style 설정을 한줄로 할 수 있습니다.
elt.style.cssText = "color: blue; border: 1px solid black";
// 위처럼 뿐만 아니라 아래처럼도 style 적용을 할 수 있습ㄴ디ㅏ.
elt.setAttribute("style", "color:red; border: 1px solid blue;");
elt.style.color = "blue"; // 다른 인라인 스타일 값을 변경하지 않고 특정 스타일을 설정합니다.
이벤트 리스너
el.addEventListener
- EventTarget.addEventListener () 메서드는 지정된 EventListener 호환 객체를
호출 한 EventTarget 의 지정된 이벤트 유형에 대한 이벤트 리스너 목록에 추가합니다.
이벤트 대상은 문서의 요소, 문서 자체, 창 또는 이벤트를 지원하는 기타 객체 (예 : XMLHttpRequest) 일 수 있습니다.
// 작성 방법
target.addEventListener(type, listener[, options]);
target.addEventListener(type, listener[, useCapture]);
target.addEventListener(type, listener[, useCapture, wantsUntrusted ]);
// Gecko/Mozilla only (크롬, 파이어폭스, 사파리)
// ie의 경우 addEventListenter를 지원하지 않으며 attachevent로 이벤트를 추가해야 합니다.
// 사용 방법
function modifyText() {
let t2 = document.querySelector("#t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
}
}
// add event listener to table
let el = document.querySelector("#outside");
el.addEventListener("click", modifyText, false);
el.removeEventListener
- EventTarget.removeEventListener () 메서드는
EventTarget.addEventListener ()를 사용하여 이전에 등록한 이벤트 리스너를 EventTarget 에서 제거합니다.
제거 할 이벤트 리스너는 이벤트 유형, 이벤트 리스너 함수 자체 및 일치하는 프로세스에 영향을 줄 수있는 다양한 옵션 옵션의 조합을 사용하여 식별됩니다
// 작성 방법
target.removeEventListener(type, listener[, options]);
target.removeEventListener(type, listener[, useCapture]);
// 사용 방법
element.removeEventListener("mousedown", handleMouseDown, false); // Fails
element.removeEventListener("mousedown", handleMouseDown, true); // Succeeds
DOM 노드 생성하기
// 작성 방법
let element = document.createElement(tagName[, options]);
// 사용 방법
document.body.onload = addElement;
function addElement () {
// div 요소를 만들어 newDiv에 값으로 대입합니다.
let newDiv = document.createElement("div");
// Hi there and greetings!이라는 텍스트노드를 만들어 newContent에 값으로 대입합니다.
let newContent = document.createTextNode("Hi there and greetings!");
// newDiv에 텍스트 노드를 추가합니다.
newDiv.appendChild(newContent);
// 새로 생성 된 요소와 그 내용을 DOM에 추가합니다.
let currentDiv = document.querySelectro("#div1");
document.body.insertBefore(newDiv, currentDiv);
}
-
document.createElement
- HTML 문서에서 document.createElement () 메서드는
tagName 으로 지정된 HTML 요소를 만들거나 tagName 이 인식되지 않으면 HTMLUnknownElement 를 만듭니다. -
document.createTextNode
- 새로운 Text 노드를 작성합니다. -
el.cloneNode
- Node.cloneNode () 메서드는 메서드가 호출 된 노드의 복제본을 반환합니다.
// 작성 방법
let dupNode = node.cloneNode([deep]);
// 노드의 아이도 복제 할 필요가있는 경우는 true, 지정된 노드만을 복제하는 경우는 false 지정해줍니다.
// 사용 방법
let p = document.querySelector("#para1");
let p_prime = p.cloneNode(true);
DOM 트리 조작하기
el.appendChild
- Node.appendChild () 메소드는 지정된 부모 노드의 자식 목록 끝에 노드를 추가합니다. 지정된 자식이 문서의 기존 노드에 대한 참조 인 경우 appendChild ()는 현재 위치에서 새 위치로 이동합니다. 다른 노드에 노드를 추가하기 전에 부모 노드에서 노드를 제거하지 않아도됩니다. 이는 노드가 문서의 두 지점에 동시에 있을 수 없음을 의미합니다. 따라서 노드에 이미 상위가 있는 경우 노드를 먼저 제거 한 다음 새 위치에 추가합니다.
// 작성 방법
let aChild = element.appendChild(aChild);
// 사용 방법
let p = document.createElement("p");
document.body.appendChild(p);
el.insertBefore
- Node.insertBefore () 메서드는 지정된 부모 노드의 자식으로 참조 노드 앞에 노드를 삽입합니다. 지정된 자식이 문서의 기존 노드에 대한 참조 인 경우 insertBefore ()가 현재 위치에서 새 위치로 이동합니다 (다른 노드에 노드를 추가하기 전에 부모 노드에서 노드를 제거 할 필요가 없습니다) 이는 노드가 문서의 두 지점에 동시에 있을 수 없음을 의미합니다. 따라서 노드에 이미 상위가 있는 경우 노드를 먼저 제거 한 다음 새 위치에 삽입합니다
// 작성 방법
let insertedNode = parentNode.insertBefore(newNode, referenceNode);
// 사용 방법
<div id="parentElement">
<span id="childElement">foo bar</span>
</div>;
// span 요소를 만들어 newNode에 값으로 대입합니다.
const newNode = document.createElement("span");
// 부모 노드에 대한 참조를 얻습니다.
const parentDiv = document.getElementById("childElement").parentNode;
// 테스트 케이스 시작 [1] : Exist a childElement -> 모두 올바르게 작동합니다.
const sp2 = document.getElementById("childElement");
parentDiv.insertBefore(newNode, sp2);
// 테스트 케이스 [ 1 ] 종료
// 테스트 케이스 시작 [2] : childElement는 유형이 정의되지 않았습니다.
const sp2 = undefined; // ID가 'childElement'인 노드가 존재하지 않습니다.
parentDiv.insertBefore(newNode, sp2); // 입력 노드에 대한 암시적 동적 캐스트
// 테스트 케이스 [ 2 ] 종료
// 테스트 케이스 시작 [3] : childElement는 'undefined'(string) 유형입니다.
const sp2 = "undefined"; // id가 'childElement'인 노드가 존재하지 않습니다.
parentDiv.insertBefore(newNode, sp2); // '유형 오류 : 잘못된 인수' 생성
// 테스트 케이스 [ 3 ] 종료
el.replaceChild
- Node.replaceChild () 메서드는 지정된 노드의 한 자식 노드를 다른 노드로 바꿉니다.
// 작성 방법
replacedNode = parentNode.replaceChild(newChild, oldChild);
// 사용 방법
// <div>
// <span id="childSpan">foo bar</span>
// </div>
const sp1 = document.createElement("span");
sp1.id = "newSpan";
const sp1_content = document.createTextNode("new replacement span element.");
sp1.appendChild(sp1_content);
const sp2 = document.getElementById("childSpan");
const parentDiv = sp2.parentNode;
// sp2를 sp1로 대체 합니다.
parentDiv.replaceChild(sp1, sp2);
// result:
// <div>
// <span id="newSpan">new replacement span element.</span>
// </div>
el.removeChild
- Node.removeChild () 메서드는 DOM 에서 자식 노드를 제거합니다. 삭제 된 노드를 돌려줍니다.
// 작성 방법
const oldChild = node.removeChild(child);
OR;
node.removeChild(child);
// 사용 방법
const d = document.getElementById("top");
const d_nested = document.getElementById("nested");
const throwawayNode = d.removeChild(d_nested);
dataset
el.dataset
- HTMLElement.dataset 속성은 읽기 또는 쓰기 모드에서 HTML 또는 DOM 의 요소에
설정된 모든 사용자 지정 데이터 특성 (data- *)에 대한 액세스를 허용합니다.
이것은 DOMString 의 맵이며 각 사용자 정의 데이터 속성에 대해 하나의 항목입니다.
데이터 셋 속성 자체는 읽을 수는 있지만 직접 쓰는 것은 아닙니다.
대신 모든 쓰기는 데이터 속성을 나타내는 ‘특성’에 있어야합니다.
HTML 데이터 속성과 해당 DOM dataset.property 는 같은 이름을 공유하지 않지만 항상 비슷합니다.
// 사용 및 작성 방법
<div data-index="hello" data-name="moong2" name="hwan"></div>
노드 간 관계
el.childNodes
- Node.childNodes 읽기 전용 속성은 첫 번째 자식 노드에 인덱스 0 이 할당 된 주어진 요소의 자식 노드의 라이브 컬렉션을 반환합니다.el.firstChild
- Node.firstChild 읽기 전용 속성은 트리에서 노드의 첫 번째 자식을 반환하거나 노드에 자식이없는 경우 null 을 반환합니다.
노드가 Document 인 경우 직접 자식 목록에서 첫 번째 노드를 반환합니다.el.lastChild
- Node.lastChild 읽기 전용 속성은 노드의 마지막 자식을 반환합니다.
상위 요소가 요소이면 하위 요소는 일반적으로 요소 노드, 텍스트 노드 또는 주석 노드입니다. 자식 요소가 없으면 null 을 반환합니다.el.previousSibling
- Node.previousSibling 읽기 전용 속성은 부모의 childNodes 목록에서
지정된 노드 바로 앞에있는 노드를 반환하거나 지정된 노드가 해당 목록의 첫 번째 노드이면 null 을 반환합니다.el.nextSibling
- Node.nextSibling 읽기 전용 속성은 부모의 childNodes 목록에 지정된 노드
바로 다음에있는 노드를 반환하거나 지정된 노드가 해당 목록의 마지막 노드이면 null 을 반환합니다.el.parentNode
- Node.parentNode 읽기 전용 속성은 DOM 트리에서 지정된 노드의 부모를 반환합니다.el.offsetParent
- HTMLElement.offsetParent 읽기 전용 속성은 요소를 포함하는 위치에 가장 가까운 (포함 계층에서 가장 가까운) 객체에 대한 참조를 반환합니다.
요소가 배치되지 않은 경우 가장 가까운 테이블, 표 셀 또는 루트 요소 (표준 준수 모드의 html, 기본 렌더링 모드의 본문)가 offsetParent 에 의해 반환됩니다.
엘리먼트 크기 및 위치
el.getBoundingClientRect()
- Element.getBoundingClientRect () 메소드는 뷰포트를 기준으로 요소의 크기와 위치를 반환합니다.el.offsetHeight / el.offsetWidth
- HTMLElement.offsetHeight/offsetWidth 읽기 전용 속성은
수직,수평 패딩과 테두리를 포함한 요소의 높이를 정수로 나타낸 것입니다.el.clientHeight / el.clientWidth
- Element.clientHeight/clientWidth 읽기 전용 속성은
CSS 또는 인라인 레이아웃 상자가없는 요소에 대해 0 입니다.
그렇지 않으면 패딩을 포함하여 요소의 내부 높이/폭이 픽셀이지만 수평/수직 스크롤 막대 높이, 테두리 또는 여백은 포함되지 않습니다.el.scrollHeight / el.scrollWidth
- Element.scrollHeight/scrollWidth 읽기 전용 속성은 오버플로로 인해
화면에 표시되지 않는 내용을 포함하여 요소 콘텐츠의 높이/너비를 측정 한 것입니다.el.offsetTop / el.offsetLeft
- HTMLElement.offsetTop/offsetLeft 읽기 전용 속성은
offsetParent 노드의 맨 위/왼쪽을 기준으로 현재 요소의 거리를 반환합니다.el.scrollTop / el.scrollLeft
- Element.scrollTop/scrollLEft 속성은 요소의 내용이 세로/왼쪽으로 스크롤되는 픽셀 수를 가져 오거나 설정합니다.el.clientTop / el.clientLeft
- 요소의 위/왼쪽 테두리 너비 (픽셀 단위)입니다. 요소의 정수 속성 인 읽기 전용 속성입니다.
이벤트 전파
- 버블링이 일어나는 이벤트도 있고, 일어나지 않는 이벤트도 있습니다. (submit, focus, blur, change 등)
이벤트 객체
event.target
- 이벤트를 전달한 객체에 대한 참조입니다.
이벤트의 버블 링 또는 캡처 단계에서 이벤트 핸들러가 호출 될 때 event.currentTarget 과 다릅니다.
// list 생성
let ul = document.createElement("ul");
document.body.appendChild(ul);
let li1 = document.createElement("li");
let li2 = document.createElement("li");
ul.appendChild(li1);
ul.appendChild(li2);
function hide(e) {
// e.target은 클릭 된 요소를 참조합니다.
// 이것은 이 컨텍스트에서 부모를 참조하는 e.currentTarget과 다릅니다.
e.target.style.visibility = "hidden";
}
// Listener를 목록에 첨부하십시오.
// 각 li를 클릭하면 실행됩니다.
ul.addEventListener("click", hide, false);
event.currentTarget
- 이벤트가 DOM 을 통과 할 때 이벤트의 현재 대상을 식별합니다.
이벤트가 발생한 요소를 식별하는 event.target 과는 달리 이벤트 핸들러가 연결된 요소를 항상 참조합니다.
function hide(e) {
e.currentTarget.style.visibility = "hidden";
console.log(e.currentTarget);
// 이 함수가 이벤트 핸들러로 사용될 때 : this === e.currentTarget
}
let ps = document.getElementsByTagName("p");
for (let i = 0; i < ps.length; i++) {
// 콘솔에서 클릭된 p요소를 출력합니다.
ps[i].addEventListener("click", hide, false);
}
// body 추력
document.body.addEventListener("click", hide, false);
// 주위를 클릭하면 단락을 사라지게합니다.
event.stopPropagation()
- 캡처 및 버블 링 단계에서 현재 이벤트의 추가 전파를 방지합니다.
// 사용 방법 - 사용할 이벤트의 메소드처럼 사용하도록 합니다.
event.stopPropagation();
event.preventDefault()
- 이벤트 인터페이스의 preventDefault () 메서드는 사용자 에이전트에게
이벤트가 명시적으로 처리되지 않으면 기본 동작을 정상적으로 수행해서는 안됩니다.
해당 이벤트 리스너 중 하나가 stopPropagation () 또는 stopImmediatePropagation ()을
호출하지 않는 한 이벤트는 평소와 같이 전파를 계속하며,이 중 하나는 전달을 즉시 중단합니다.
function checkName(evt) {
var charCode = evt.charCode;
if (charCode != 0) {
if (charCode < 97 || charCode > 122) {
evt.preventDefault();
displayWarning(
"Please use lowercase letters only." +
"\n" +
"charCode: " +
charCode +
"\n"
);
}
}
}
폼 이벤트
change
- 폼의 값이 변경될때마다 발생하는 이벤트입니다.
// 사용 방법
document.querySelector("select").addEventListener("change", e => {
alert(e.target.value);
});
input
- 텍스트 필드에 거는 이벤트로 한글자가 입력될 때마다 일어나는 이벤트입니다.
// 사용 방법
document.querySelector(".name").addEventListener("input", e => {
document.querySelector(".named").textContent = e.target.value;
});
focus
- 포커스가 특정엘리먼트에 도달했을 때 발생하는 이벤트입니다.
nameEl.addEventListener("focus", e => {
console.log("focus");
});
blur
- 특정엘리먼트에 포커스되었던 것이 빠져나올 때 발생하는 이벤트입니다. (focus 의 반대되는 역할)
nameEl.addEventListener("blur", e => {
console.log("blur");
});
submit
- 제출 이벤트는 양식이 제출되면 시작됩니다.
submit 은 button 또는 submit 입력이 아닌 form 요소에서만 시작됩니다.
폼에서는 Enter 를 치면 전송이 되는 기능이 있습니다.
이는 편리할 수도 있지만 거추장스러울 수도 있습니다.
Enter 를 눌렀을 때 제출이 안되게 하고 싶다면 키보드 이벤트를 이용하여 엔터키를 눌렀을 때,
preventDefault()를 이용하여 이벤트가 발생안되게 하면 됩니다.
<!--
과거에는 html에서 type 어트리뷰트로 submitd을 통해 전송했으나
전송과 동시에 새로고침 혹은 주소변경되는 이슈로 최근에는 쓰지 않는다.-->
<input type="submit" value="전송">
// 대신 submit 이벤트를 사용한다.
const formEl = document.querySelector("form");
formEl.addEventListener("submit", e => {
e.preventDefault();
alert(e.target.elements.gender.value);
alert(e.target.elements.name.value);
});
마우스 이벤트
click / dblclick
- click 이벤트는 포인팅 장치 버튼 (일반적으로 마우스의 기본 버튼)이 단일 요소에서 한 번/두 번 클릭 될 때 발생합니다.
document.querySelector("a").addEventListener("click", e => {
alert("링크가 클릭되었습니다.");
e.preventDefault();
});
mouseover / mouseout
- mouseover/mouseout 이벤트는 포인팅 장치를 수신기가 연결된 요소 위로 이동하거나 해당 자식 중 하나 위로 이동하면/벗어나면 시작됩니다.
const boxEl = document.querySelector(".box");
boxEl.addEventListener("mouseover", e => {
console.log("mouseover");
});
boxEl.addEventListener("mouseout", e => {
console.log("mouseout");
});
mousedown / mouseup
- mousedown 이벤트는 요소에서 포인팅 장치 버튼을 누르면/놓이면 시작됩니다.
// 드래그 앤 드롭을 구현하고자 할 때 mousedown / mouseup을 씁니다.
const boxEl = document.querySelector(".box");
boxEl.addEventListener("mousedown", e => {
console.log("mousedown");
});
boxEl.addEventListener("mouseup", e => {
console.log("mouseup");
});
mousemove
- mousemove 이벤트는 포인팅 장치 (일반적으로 마우스)가 요소 위로 이동 될 때 발생합니다.
// 요소위에서 조금이라도 움직이면 mousemove는 발생합니다.
let count = 0;
boxEl.addEventListener("mousemove", e => {
console.log(`mousemove : ${count++}`);
});
[mousedown, mouseup, mousemove 를 이용한 drag&drop 구현]
const boxEl = document.querySelector(".box");
let dragging = false;
let originalOffset;
let originalMousePos;
document.addEventListener("mousemove", e => {
if (dragging) {
const newTop = `${originalOffset.top + (e.clientY - originalMousePos.y)}px`;
const newLeft = `${originalOffset.left +
(e.clientX - originalMousePos.x)}px`;
boxEl.style.top = newTop;
boxEl.style.left = newLeft;
}
console.log(`x:${e.clientX}, y:${e.clientY}`);
});
boxEl.addEventListener("mousedown", e => {
dragging = true;
originalOffset = {
top: boxEl.offsetTop,
left: boxEl.offsetLeft
};
originalMousePos = {
x: e.clientX,
y: e.clientY
};
});
boxEl.addEventListener("mouseup", e => {
dragging = false;
});
키보드 이벤트
-
keydown
- keydown 이벤트는 키를 누르면 시작됩니다. keypress 이벤트와 달리, keydown 이벤트는 문자 값을 생성하는 키와 문자 값을 생성하지 않는 키에 대해 실행됩니다. -
keyup
- keyup 이벤트는 키를 놓을 때 발생합니다.
const inputEl = document.querySelector("input");
inputEl.addEventListener("keydown", e => {
console.log("keydown");
});
inputEl.addEventListener("keyup", e => {
console.log("keyup");
});
스크롤 이벤트
scroll
- 스크롤 이벤트는 문서 뷰나 요소가 스크롤 될 때 발생합니다.
document.addEventListener("click", e => {
console.log("scroll" + window.scrollY);
});
2. Today I Found Out
하루동안 연산자 심화 공부와 DOM을 공부하였는데
중요한 부분이라서 조금 더 시간을 갖고 공부를 하였습니다.
DOM트리 그림을 보면서 하나하나 이해하려고 노력하였고,
그 결과 오늘 공부한 것까지 이해를 할 수 있었습니다.
오늘 공부한 것을 정리해보면서 생각해보니
그간 독학으로 공부하면서 혼란스러웠던 부분이
상당부분 정리가 되었음을 체감할 수 있었습니다.
앞으로도 계속 열심히 해야겠습니다.
3. refer
https://github.com/fds9/fds-dom-api
https://devdocs.io/dom/node
http://poiemaweb.com/js-dom