September 18th 2018
Javascript와 DOM을 이용해 웹브라우저 상의 HTML과 text content를 변경하는 법을 알아보겠습니다.
querySelector 또는 getElementById 등으로 요소를 선택해 변수에 할당하면, 해당 요소에 접근하기 위해 그 요소를 할당한 변수를 사용할 수 있습니다.
// Example
const card = document.querySelector('.card-1');
// 'Card-1'이라는 class명을 가진 요소를 변수 'card'를 이용해 접근할 수 있음.
목차 - HTML 요소 내부의 HTML - HTML 요소 내부의 text content 다루기 - HTML 요소 생성하기 - 웹페이지 상의 content 삭제하기 - 요소 스타일 변경하기 - class 이용하기
** 위와는 별도로, 드물게 사용하는 outerHTML이란 속성이 있습니다. outerHTML은 자식요소 뿐만 아니라 요소 자체까지 포함한 HTML markup을 나타냅니다.
// 요소에 text 설정하기 element.textContent = 'This is new text.';
주의할 점은 자식요소가 있는 요소에 text content 값을 새로 설정하면, 그 안의 자식요소들 또한 모두 없어지고 새로 설정한 text node만 남습니다.
textContent method로 값에 아래과 같이 html tag를 포함해도 html tag도 string으로 간주하여 표기합니다. 위와 같이 웹의 요소에 html tag와 함께 새로운 text 값으로 변경하고 싶을 때 innerHTML을 사용할 수 있습니다.
```javascript
// <h1 id='test1'>Ice Cream Flavors</h1>
const myElement = document.querySelector('#test');
myElement.textContent = 'The <strong>Greatest</strong> Ice Cream Flavors';
// 브라우저에 'The <strong>Greatest</strong> Ice Cream Flavors'로 출력;
myElement.innerHTML = 'The <strong>Greatest</strong> Ice Cream Flavors';
// 브라우저에 Greatest만 굵게 표시된 'The Greatest Ice Cream Flavors'로 출력;
innerText역시 textContent와 동일하게 요소의 text 내용을 가져오고 설정할 수 있습니다. 하지만, 둘 사이에 차이점이 있습니다. innerText는 화면상에 보이는 text의 모습을 값으로 가져옵니다.
- 요소 안의 일부 text가 css에 의해 화면에 보이지 않을 때, innerText는 이러한 text는 제외한 text를 값으로 가져옵니다. - innerText는 화면상에 출력된 text의 대소문자 역시 구분하여 값으로 반환합니다.
// 위 요소에 text를 추가함. heading.textContent = 'new text here!';
<br>
#### 생성한 HTML 요소 웹페이지에 추가하기
생성한 html 요소를 appendChild method를 이용해 웹페이지에 추가할 수 있습니다.
##### .appendChild()
\- Syntax : element.appendChild(aChild);
\- 메소드를 호출한 요소의 맨 마지막 자리에 인자로 전달받은 요소를 추가합니다.
\- <u>인수로 전달된 요소가 페이지 상 존재하는 요소일 경우, 그 요소가 복사되는 것이 아니고 이동을 함.</U>
\- method를 호출하기 위해서는 document 객체 내부의 요소가 필요함. document 객체 자체에서는 호출할 수 없음. (ex, document.appendChild(aElement) -> error)
##### .createTextNode()
createElement와 마찬가지로, createTextNode method는 textNode를 생성하고, 이를 웹페이지에 추가할 수 있습니다.
```javascript
const myPara = document.createElement('p');
const textOfPara = document.createTextNode('This is text!');
myPara.appendChild(textOfPara);
document.body.appendChild(myPara);
위의 내용은 myPara의 textContent 속성을 이용해 구현할 수도 있습니다. 그리고 textContent를 이용하는 방법이 빠르고 쉽습니다.
appendChild method를 사용하면 인수로 받은 요소를 호출한 요소의 맨 마지막 자리에만 추가할 수 있습니다. insertAdjacentHTML method를 사용하면 원하는 자리에 전달받은 요소를 추가할 수 있습니다.
- Syntax: element.insertAdjacentHTML(position, string); - position parameters : - 'beforebegin': Before the element itself. - 'afterbegin': Just inside the element, before its first child. - 'beforeend': Just inside the element, after its last child. - 'afterend': After the element itself.
<!-- beforebegin -->
<p>
<!-- afterbegin -->
foo
<!-- beforeend -->
</p>
<!-- afterend -->
removeChild()로 자식 요소를 삭제할 수 있습니다. appendChild()와 유사하게 부모 요소와 삭제할 자식 요소를 이용해 해당 메서드를 사용할 수 있습니다. - Syntax : parent.removeChild(child); - 반환값 : 삭제한 자식 요소
removeChild method를 이용해 요소를 삭제하기 위해서는, 먼저 부모 요소로 접근을 해야합니다. 하지만 부모 요소의 접근 없이 remove 메서드를 사용해 요소 자신을 삭제할 수 있습니다.
aElement.remove();
// 요소 자신을 삭제함.
removeChild로 첫번째 자식 요소를 삭제하고 싶을 때 firstChild 또는 firstElementChild()를 사용할 수 있습니다. 하지만, firstChild는 html에서 tag와 tag사이의 whitespace(textNode)가 있는 경우, 해당 whitespace까지 자식요소로 간주하기 때문에 결과에 차이가 발생할 수 있습니다.
<div class="parent">
<div class="child" />
</div>;
document.querySelector('.parent').firstChild; // -> #text
document.querySelector('.parent').firstElementChild; // -> <div class='child'></div>
요소의 style 속성으로 스타일을 변경할 수 있습니다.
const heading = document.querySelector('h1');
heading.style.color = 'red';
heading.style.fontSize = '20rem';
위의 방법으로는 한번에 하나의 속성만 변경이 가능합니다. style.cssText 속성을 사용하면, 여러 스타일을 한번에 변경할 수 있습니다. cssText의 값으로는 css file에서 쓰는 방식 그대로 코드를 작성해야 합니다. (ex, font-size not fontSize)
const heading = document.querySelector('h1');
heading.style.cssText = 'color: red; font-size: 20rem;';
또다른 방법으로 setAttribute method에 첫 인수로 'style'를 건네서 스타일을 변경할 수 있습니다.
const heading = document.querySelector('h1');
heading.setAttribute('style', 'color: red; font-size: 20rem;');
const heading = document.querySelector('h1'); heading.className; // -> 'main-heading row'를 반환함 heading.className = 'main-heading' // -> 기존의 class 명을 모두 삭제 후 새로운 값만 할당함.
className 속성으로 특정 class를 추가하거나 삭제 하려면, split을 사용해 배열로 바꾸고 for loop난 pop, push 등의 메소드를 사용해 class를 수정하고 다시 className = something 으로 값을 할당해야 합니다.
classList 속성을 사용하면, 이 긴 과정을 줄일 수 있습니다.
##### classList property
classList 속성은 class를 공란으로 나눈 DOMTokenList를 반환합니다. classList 속성은 읽기 전용이지만, add(), remove() 등의 method를 이용해 수정할 수 있습니다. 속성이 없거나, 속성의 값이 없으면 length가 0인 DOMTokenList를 반환합니다.
**classList의 methods**
\- add(string [, string [,..]]) : 인수로 전달한 값을 class에 추가함. 만약 기존에 있는 class명을 전달한 경우는 중복되서 추가하지 않음.
\- remove(string [,string[,..]]) : 인수로 전달한 값을 class에서 삭제함. <u>존재하지 않는 값을 전달한다고 해서 error가 발생하지 않음.</u>
\- item(number) : index값에 해당하는 class명을 반환함.
\- toggle(string [, force]) :
\- 첫 인수만 전달한 경우 : list에 class명이 존재하면, class명을 삭제하고 false를 반환함. 존재하지 않는다면, class명을 추가하고 true를 반환함.
\- 두개의 인수를 전달한 경우 : 두번째 인수가 true일 경우, class명을 추가함. 두번째 인수가 false인 경우, class명을 삭제함.
\- contains(string) : 특정 class명이 있는지 여부를 boolean 값으로 반환함.
\- replace( oldClass, newClass) : 기존의 class를 새로운 class로 변경함.