노드 이동
부모 노드, 자식 노드 선택
기능 | 설명 |
childNodes | 모든 자식 노드 선택 (단, 노드에 생략된 text도 포함) |
children | 모든 자식 노드 선택 |
parentElement | 부모 노드 선택 |
nextElementSibling | 다음 형제 노드 선택 |
previousElementSibling | 이전 형제 노드 선택 |
firstChild | 첫번째 자식 노드 선택 |
lastChild | 마지막 자식 노드 선택 |
부모, 자식 노드 선택을 다음의 웹 화면을 기준으로 해보자!
이동 | 번호 | 이름 | 내용 | 날짜 |
---|---|---|---|---|
1 | 홍길자 | 안녕! | 2019-01-01 | |
2 | 이순신 | 반가워 | 2019-02-01 | |
3 | 이순신 | 반가워 | 2019-02-01 | |
4 | 이순신 | 반가워 | 2019-02-01 | |
5 | 이순신 | 반가워 | 2019-02-01 |
✅ parentElement
<tbody class="table">
<tr>
<td><button onclick="down(this)">↓</button><button onclick="up(this)">↑</button></td>
<td>1</td>
<td>홍길자</td>
<td>안녕!</td>
<td>2019-01-01</td>
</tr>
<tr>
<td><button onclick="down(this)">↓</button><button onclick="up(this)">↑</button></td>
<td>2</td>
<td>이순신</td>
<td>반가워</td>
<td>2019-02-01</td>
</tr>
....중략
<script>
function down(x){
// console.log(x); //자신 태그
// console.dir(x); // 현재 상태에서 사용할 수 있는 함수를 보여주는 사전
console.log(x.parentNode); // 부모 태그 ( 공백이 있다면, 공백을 선택 )
//x는 버튼 태그를 받는 매개변수로 부모 도는 tr
console.log(x.parentElement); // 부모 태그 ( 순수한 태그의 형태만 선택 )
//순수한 태그만을 추출하는 parentElement를 사용하는 게 좋다
}
</script>
✅ nextElementSibling & previousElementSibling ( 형제 노드 )
console.log(x.parentElement.nextElementSibling); // 태그의 부모 요소의 다음 형제 노드 출력 => <td>1</td>
console.log(x.parentElement.nextElementSibling.nextElementSibling); // <td>홍길자</td>
console.log(x.previousElementSibling); // 이전형제 => 현재 없음 : null
✅firstElementChild & lastElementChild & children ( 자식 노드 )
console.log(x.parentElement.parentElement.firstElementChild); // tr기준 첫번쨰 자식 태그
console.log(x.parentElement.parentElement.lastElementChild); // tr기준 마지막 자식 태그
console.log(x.parentElement.parentElement.children); // 모든 자식 태그 >> 배열로 출력
console.log(x.parentElement.parentElement.children[2]); // 모든 자식 태그 중 3번째 태그(배열이라서 인덱스로 호출 가능)
✅ 노드 이동시키는 방법
insertBefore ( 삽입 노드, 기준 노드 ) - 기준노드 앞에 삽입노드 추가
⭐ insertBefore은 부모태그를 기준으로 실행되기 때문에 부모태그를 반드시 얻어야 한다
⬇️ 아래로 이동시키기
var current = x.parentElement.parentElement; // 버튼의 부모행 => tr
var next = current.nextElementSibling; // tr의 다음 형제 노드
// 확실하지 않으면 콘솔창으로 출력해보기
console.log(current);
console.log(next);
if ( next == null ){
alert("마지막 행 입니다");
return; //함수종료
}
//insertBefore는 동작시킬 부모태그를 얻는다
var table = document.querySelector(".table");
table.insertBefore(next, current); //current앞에 next를 넣는다
⬆️ 위로 이동시키기
//up 바튼을 생성해보자
function up(y){
var current = y.parentElement.parentElement; //tr
var previous = current.previousElementSibling; // tr 기준 이전 형제 노드
if ( previous == null ){
alert("첫번째 행 입니다");
return; //함수종료
}
console.log(current);
console.log(previous);
var table = document.querySelector(".table");
table.insertBefore(current, previous);
}
노드 삭제
<body>
<button button="type" id="delOne">하나씩 삭제</button>
<button button="type" id="del">일괄 삭제</button>
<table>
<thead>
<th><input type="checkbox" class="allCheck"></th>
<th>번호</th>
<th>이름</th>
<th>내용</th>
<th>날짜</th>
</thead>
<tbody class="table">
<tr>
<td><input type="checkbox" class="check"></td>
<td>1</td>
<td>홍길자</td>
<td>안녕!</td>
<td>2019-01-01</td>
</tr>
<tr>
<td><input type="checkbox" class="check"></td>
<td>2</td>
<td>김길자</td>
<td>안녕!</td>
<td>2019-01-01</td>
</tr>
<tr>
<td><input type="checkbox" class="check"></td>
<td>3</td>
<td>이길자</td>
<td>안녕!</td>
<td>2019-01-01</td>
</tr>
<tr>
<td><input type="checkbox" class="check"></td>
<td>4</td>
<td>고길자</td>
<td>안녕!</td>
<td>2019-01-01</td>
</tr>
</tbody>
removeChild ( ) - 자식 태그를 하나씩 삭제하기
//하나씩 삭제 removeChild
var delOne = document.getElementById("delOne");
delOne.onclick = function() {
var table = document.querySelector(".table"); // tr의 부모요소
console.log(table.firstElementChild); //첫번째 요소
console.log(table.children[0]); //배열 => 첫번쨰 요소
table.removeChild(table.firstElementChild);
// table.removeChild();
}
remove ( ) - 노드 자체를 모두 삭제
//일괄삭제 remove
var del = document.getElementById("del");
del.onclick = function(){
var table = document.querySelector(".table tr");
var check = document.querySelectorAll(".check");//체크 박스 전부 가져오기
if(confirm("정말 삭제하시겠습니까?") == false){
return;
}
console.log(check);
console.log(check.length);
for ( var i = 0; i < check.length; i++ ){
console.log(i);
if(check[i].checked){
check[i].parentElement.parentElement.remove(); //tr삭제
}
}
}
그런데 말입니다..! getElementByClassName으로 체크박스 태그를 가지고 오면 다음과 같은 문제가 발생한다
var check = document.getElementsByClassName("check"); //체크 박스 전부 가져오기
일괄삭제를 했을 때, 2번 3번 모두 삭제되는 것이 아니라 하나씩 지워지는 현상이 발생한다.
이러한 현상은 왜 이러나는 것일까?
getElementByClassName, querySelector 모두 태그를 클래스 이름으로 지정했을 떄 가지고 올 수 있는데 말이다.
그건 getElementByClassName이 태그를 가지고 올 때 컬렉션으로 가지고 오는데, 이는 삭제할 때 문제가 발생할 수 있다.
컬렉션을 삭제하게 되면, 해당하는 요소가 지워지면서 다음의 요소가 지워진 요소 자리로 인덱스가 당겨지면서 요소도 당겨지기 때문이다 . 따라서 삭제할 때는 getElementByClassName보다는 querySelector를 사용하는 것이 좋다
그러면 이번에 전체 선택 기능을 만들어볼까나?
// 전체 선택 vs 전체 삭제
var allCheck = document.querySelector(".allCheck");
var check = document.querySelectorAll(".check") ;//체크 박스 전부 가져오기
allCheck.onclick = function(){
if(allCheck.checked){
for(var i = 0; i < check.length; i++ ){
check[i].checked = true;
}
}else{
for(var i = 0; i < check.length; i++ ){
check[i].checked = false;
}
}
}
전체 선택을 하기 위해서는 위의 사진에서 빨간색으로 표시한 부분에 해당하는 태그에 접근해야 한다
var allCheck = document.querySelector(".allCheck");
그래서 클래스 이름이 allCheck인 체크박스 태그를 가지고 와야 한다
var check = document.querySelectorAll(".check"); //체크 박스 전부 가져오기
그리고 각각의 체크 박스가 모두 체크되어야 하기 때문에 즉, 반복문을 통해 checked 속성을 줘야 하기 때문에
각각의 체크박스에 해당하는 태그들도 가지고 와야 한다
allCheck.onclick = function(){
if(allCheck.checked){
for(var i = 0; i < check.length; i++ ){
check[i].checked = true;
}
그런 다음 allCheck 태그가 클릭과 동시에 allCheck 태그가 checked속성이 true였을 때, 모든 태그들이 선택되어야 하기 때문에 반복문을 통해 checked 속성을 true로 만들어주면 된다 ( 모두 선택 )
}else{
for(var i = 0; i < check.length; i++ ){
check[i].checked = false;
}
}
}
태그가 checked 속성이 false 였을 때는 모든 태그들이 false가 될 수 있도록 조건을 설정해주었다 ( 선택 모두 해제 )
클래스 속성 제어하기
클래스 속성 제어하는 대표적인 함수들
1️⃣ add ( )
2️⃣ remove ( )
3️⃣ contains ( )
4️⃣ toggle ( )
className & classList
✅ className - 클래스명
✅ classList - 클래스명을 배열로 얻을 수 있음
<button id="btn" class="btn btn-default">버튼</button>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
//태그에 속성변경-->
//console.log(btn.class); //클래스는 키워드라 안 됨
// console.dir(btn);
console.log(btn.className); //클래스명을 얻음
console.log(btn.classList); //클래스명을 배열로 얻음
}
</script>
cosole.log ( btn.className );
console.log ( btn.classList );
1️⃣ add ( )
btn.classList.add("newBtn"); //클래스명 추가
2️⃣ remove ( )
btn.classList.remove("btn-default"); //클래스명 삭제
3️⃣ contains ( )
if(btn.classList.contains("btn")){
console.log("btn클래스 존재함");
}
클래스명에 "btn"이 존재하는지(포함되어 있는지)에 따라 결과값을 다르게 출력하도록 조건문을 설정하였다
4️⃣ toggle ( )
toggle( )의 기능은 하나의 기능을 on/off 모두 할 수 있게끔 즉, 하나의 태그로 두 가지의 기능을 할 수 있게끔 해준다
btn.classList.toggle("aaa"); //있으면 제거, 없으면 추가
btn(버튼) 태그의 classList(클래스명)에 "aaa"가 없으면 추가
btn(버튼) 태그의 classList(클래스명)에 "aaa"가 있으면 제거
좀 더 자세하게 토글의 기능에 대해 알아볼까?
👩💻 토글의 기능을 직관적으로 확인하기 위해 직접 기능을 작성
<hr>
<h3>하나의 버튼으로 두가지 작업을 처리하기(toggle)</h3>
<button class="toggle" id="toggle">토글버튼</button>
<!-- id는 고유하기 때문에 식별하기 용이 => 이벤트 걸어주기 -->
<script>
var toggle = document.getElementById("toggle");
toggle.onclick = function(){
//토글의 기능 직접 작성
if(toggle.classList.contains("add")){ //add가 포함되어 있다면
toggle.style.color = "black"; //색상 변경
toggle.classList.remove("add"); //클래스 제거
} else {
toggle.style.color="blue";
toggle.classList.add("add");
}
}
</script>
default값 - 폰트 색깔 : 검정, 클래스명 : toggle
"add"가 포함되어 있다면, 폰트 색깔은 검정으로 하고 classList에서 "add"는 지워줘
"add"가 포함되어 있지 않다면, 폰트 색깔은 파란색으로 바꾸고 classList에 "add"를 추가해
👩💻 똑같은 기능을 토글을 사용해서 구현
toggle.onclick = function(){
toggle.classList.toggle("add");
console.log(toggle);
}
실습을 통해 클래스 속성을 제어해보자! 그럼 이해가 잘 될 거야!
< style >
<title>Document</title>
<style type="text/css">
.center {
text-align: center;
}
.content {
overflow: hidden;
border: 1px solid #777;
}
.content,
.content .left,
.content .right {
width: 50%;
margin: 0 auto;
box-sizing: border-box;
padding: 5px;
}
.content .right,
.content .left {
float:left;
}
.left .inner,
.right .inner {
border: 1px solid #777;
height: 300px;
}
img {
width: 100%;
height: 100%;
}
</style>
</head>
< 태그 >
<body>
<header>
<div class="center">
<h2>토글형태 활용하기</h2>
<button id="btn1" class="dark">어둡게보기</button>
<button id="btn2" class="name">이름보기</button>
<!--추가-->
<hr>
</div>
</header>
<section>
<div class="content">
<div class="left">
<div class="inner"><img src="profile.png"></div>
</div>
<div class="right">
<div class="inner">
<p class="info" style="display:none;">홍길자<br>20세<br>능력단위<br>Java, Oracle, JSP, CSS, Javascript</p>
<p class="dict">자바스크립트는 객체 기반의 스크립트 프로그래밍 언어이다. 이 언어는 웹 브라우저 내에서 주로 사용하며, 다른 응용 프로그램의 내장 객체에도 접근할 수 있는 기능을 가지고 있다. 또한 Node.js와 같은 런타임 환경과 같이 서버 사이드 네트워크 프로그래밍에도 사용되고 있다</p>
<a href="https://www.naver.com">위키백과</a>
</div>
</div>
</div>
</section>
< script >
<script>
//body 얻는 법
//1. var body = document.querySelector("body");
//2. var body = document.body;
var body = document.body;
var all = document.querySelectorAll("p, a, h2");
var btn1 = document.getElementById("btn1");
btn1.onclick = function(){
//x클래스
if(btn1.classList.contains("x")){
btn1.innerHTML = "어둡게보기"; // 버튼
body.style.backgroundColor = "white"; // 배경 색상
for(var i = 0; i < all.length; i++){ // 폰트 색상
all[i].style.color = "black";
}
btn1.classList.remove("x");
}else{
btn1.innerHTML = "밝게보기"; // 버튼
body.style.backgroundColor = "black"; // 배경 색상
for(var i = 0; i < all.length; i++){ // 폰트 색상
all[i].style.color = "white";
}
btn1.classList.add("x");
}
}
var btn2 = document.getElementById("btn2");
var info = document.querySelector(".info");
var dict = document.querySelector(".dict");
btn2.onclick = function(){
if(btn2.classList.contains("x")){
btn2.classList.remove("x"); //클래스명 삭제
btn2.innerHTML = "내용보기";
info.style.display="none";
dict.style.display = "block";
}else{
btn2.classList.add("x"); //클래스명 추가
btn2.innerHTML = "이름보기";
info.style.display="block";
dict.style.display = "none";
}
}
</script>
위의 실습 코드를 자세하게 뜯어보자면...
btn1(밝게 보기)를 클릭했을 때, 함수 실행
btn1.onclick = function(){
//x클래스
if(btn1.classList.contains("x")){
btn1.innerHTML = "어둡게보기"; // 버튼
body.style.backgroundColor = "white"; // 배경 색상
"밝게 보기"에 대한 기능이 실행해야 하기 때문에 누름과 동시에 버튼 태그의 사잇값은 "어둡게 보기"로 바꿔야 한다
그리고 웹 페이지의 색상을 하얀 색으로 바꿔야 하기 때문에 body태그를 가지고 와서 body의 스타일 속성의 backgroundColor를 white로 바꿔준다
✅ body는 다음과 같이 2가지 방법으로 불러올 수 있다
//body 얻는 법
1. var body = document.querySelector("body");
2. var body = document.body;
그런 다음 폰트의 색상을 black으로 바꿔주려고 한다
var all = document.querySelectorAll("p, a, h2");
for(var i = 0; i < all.length; i++){ // 폰트 색상
all[i].style.color = "black";
}
그런데 폰트을 색상을 바꿔주려고 하다보니 글이 모두 다른 태그에 담겨 있어서 모든 태그를 불러와야 하는 문제가
발생했다. 물론 모든 태그를 각각 불러와서 폰트의 색상을 바꿀 수 있지만 위의 코드처럼 한 번에 불러서 바꿔줄 수 있다.
배열로 불러오기 때문에 반복문을 돌려 색상을 바꿔주면 된다.
btn1.classList.remove("x");
이제 모두 바꾸었으면, "x"를 지워서 해당 버튼이 "어둡게 보기" 기능을 할 수 있도록 만들어준다
이제 반대의 경우도 똑같이 작성해주면 된다
btn1(어둡게 보기)를 눌렀을 때, 함수 실행
}else{
btn1.innerHTML = "밝게보기"; // 버튼
body.style.backgroundColor = "black"; // 배경 색상
for(var i = 0; i < all.length; i++){ // 폰트 색상
all[i].style.color = "white";
}
btn1.classList.add("x");
}
}
위에서처럼 ( btn1 클래스명에 "x"가 포함되어 있지 않아야 한다 ) btn1(어둡게 보기)기능을 함과 동시에 btn1의
사잇값은 "밝게 보기"로 바뀌어야 하고 body 태그의 style 속성에서 배경 색상은 black으로 바꿔주고 폰트의 색상도 white로 바꾸어준다.
일련의 과정이 모두 끝나고 나면 "밝게 보기"의 기능을 할 수 있도록 btn1의 클래스명에 "x"를 추가해준다.
이제 다음 기능도 똑같은 방법으로 진행하면 된다
var btn2 = document.getElementById("btn2");
var info = document.querySelector(".info");
var dict = document.querySelector(".dict");
btn2.onclick = function(){
if(btn2.classList.contains("x")){
btn2.classList.remove("x"); //클래스명 삭제
btn2.innerHTML = "내용보기";
info.style.display="none";
dict.style.display = "block";
}else{
btn2.classList.add("x"); //클래스명 추가
btn2.innerHTML = "이름보기";
info.style.display="block";
dict.style.display = "none";
}
}
단 위의 기능의 경우 스타일 속성의 display을 사용해 글의 내용을 보이게 했다가 안 보이게 했다가 해야 한다는 점에 차이점이 있지만 이 또한 한 번 알면 쉽게 할 수 있다!
해당 태그를 안 보이게 하고 싶다면, 해당 태그.style.display = "none";
해당 태그를 보이게 하고 싶다면, 해당 태그.style.display = "block";
'JavaScript' 카테고리의 다른 글
[JavaScript] ES6문법 - 클래스, 클래스 상속 (0) | 2023.01.13 |
---|---|
[JavaScript] 여러 태그에 한번에 이벤트 걸기 가능...? (0) | 2023.01.03 |
[JavaScript] this 연산자 정복해보자 (0) | 2023.01.01 |
[JavaScript] 자바스크립트 이벤트핸들러 (0) | 2022.12.29 |
[JavaScript] 자바스크립트를 시작하며.. (0) | 2022.12.28 |