Element를 CRUD 해볼 것이다.
우선 입력할 창을 만들어 입력한 값을 받아온다.
< 노드를 생성 >
이번에는 입력한 값을 출력하는 노드를 생성한다.
입력누르면 div태그가 늘어남
< 값 넣고 초기화하기 >
값을 넣으면 넣은 값들이 밑에 출력되면서 입력창은 초기화 된다.
'ㅁㅁㅁㅁ'을 제일 먼저 입력함
넣을 때 마다 class가 추가된다.
< 넣은 값이 처음으로 출력되게 함 >
apppend는 나중에 친 값이 맨 밑에 출력되지만 ( containerEl.appendChild(divEl); )
prepend는 나중에 친 값이 맨 위로 출력되도록 한다. ( containerEl.prependChild(divEl); )
'ㅇㅇㅇ' 을 제일 마지막에 입력함
< 삭제 >
휴지통을 클릭하면 삭제되는 것을 해볼 것이다.
구글아이콘에 들어가 delete 아이콘을 가져왔다.
그리고 가져온 google icon 을 등록한다.
값을 입력한 뒤 휴지통을 누르게 되면 해당 값이 삭제 되는 것을 볼 수 있다.
선택한 삭제 값이 나오는 것을 볼 수 있다.
< 엔터 적용 >
입력버튼을 누르지 않고 엔터를 눌러도 값이 들어가는 것을 적용해본다. ( 'keydown' )
엔터는 아스키코드로 13번이므로 event.keyCode==13 을 해주면 된다.
이렇게 위에 코드를 복사 붙여넣기 해도 되지만 코드중복이므로 함수를 사용할 것이다
< 함수 사용해서 연결시킴 >
createNode()를 만들어서 위에 중복 코드를 삭제한 뒤 입력시켜 준다.
< 유효성검사 >
내용을 입력하면 들어가고
내용을 입력하지 않고 입력하면 뜨지 않는다.
if else 를 사용한다.
< 내용 입력했을 때 >
< 내용 입력하지 않았을 때 >
< 드래그 이벤트 >
이번에는 드래그 이벤트를 추가해 볼 것이다.
먼저 드랍하기 전의 좌표를 저장한다.
그리고 function createNode()안에 드래그 이벤트를 입력한다.
이렇게 a, b, c, d 순서로 입력하여 출력된 것이 드래그를 하여 순서를 바꿀 수 있다.
콘솔창에는 이렇게 dragstart event 와 drop event 가 나타나게 된다.
< 전체 코드 >
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- GOOGLE ICON -->
<style>
.material-symbols-outlined {
font-variation-settings:
'FILL' 0,
'wght' 400,
'GRAD' 0,
'opsz' 24;
font-size:1rem;
}
.draggable--style{
background-color:gray;
opacity: .5;
}
.drop--style{
background-color:white;
opacity: 1;
}
</style>
</head>
<body>
<input type="text" class="inputEl"><span> | </span><button class="btn">입력</button>
<hr>
<div class="container">
</div>
<script>
const inputEl = document.querySelector(".inputEl");
const btnEl = document.querySelector(".btn");
const containerEl = document.querySelector('.container');
btnEl.addEventListener('click',function(){
createNode()
})
inputEl.addEventListener('keydown',function(event){
console.log(event.keyCode);
if(event.keyCode==13){
createNode()
}
})
function isValid(value){
//console.log(typeof value);
if(value==="")
return false;
return true;
}
let beforeEl = null; //드랍 이전 El 저장
let beforeYpos = null; //드랍 이전 El의 Y좌표 저장
function createNode(){
const contents = inputEl.value; //input value 가져오기
const result = isValid(contents);
if(result){
console.log("clicked..value : ",contents);
const divEl = document.createElement('div') //div태그 생성
divEl.setAttribute('style','width:300px;height : 40px;border:1px solid;padding:2px;margin:2px;')
//----------------------
//드래그이벤트 추가
//----------------------
divEl.setAttribute('draggable',true); //drag가능상태로 요소 설정
divEl.addEventListener('dragstart',function(event){
console.log('dragstart event',event);
console.log('dragstart target',event.target);
beforeYpos= event.pageY;
beforeEl = event.target;
})
divEl.addEventListener('dragover',function(event){
event.preventDefault();
//console.log(event);
})
divEl.addEventListener('drop',function(event){
event.preventDefault();
console.log('drop event',event);
console.log('drop target',event.target)
if(beforeYpos<event.pageY) //위에서 아래로 이동
{
beforeEl.before(event.target);
}
else //아래서 위로 이동
{
beforeEl.after(event.target);
}
})
//----------------------
divEl.innerHTML=contents; //input value 를 div의 content에 넣기
const delEl = document.createElement('span');
delEl.classList.add('material-symbols-outlined'); //google icon class 등록
delEl.innerHTML='delete'; //google icon name 지정
delEl.setAttribute('style','cursor:pointer');
delEl.addEventListener('click',function(){
console.log('clicked..');
//부모노드 찾기
const parentEl = delEl.parentNode;
console.log(parentEl);
//부모노드 삭제
parentEl.remove();
})
divEl.appendChild(delEl); //divEl의 자식으로 연결
//containerEl.appendChild(divEl); //container의 자식으로 연결(마지막)
containerEl.prepend(divEl); //container의 자식으로 연결(첫노드로연결)
inputEl.value=""; //input value 초기화
}
else{
alert("내용을 입력하세요..");
inputEl.value="";
}
}
</script>
</body>
</html>
< CRUD 연습하기 >
// form의 기본기능은 비활성화합니다 ( 답 : initial-scale=1.0 )
// 입력버튼을 눌렀을때 table의 tbody에 입력된 (이름/나이/주소/삭제버튼)이 생성될수 있도록합니다
// 입력된 노드의 이름/나이/주소를 수정할수 있도록합니다.
// 특정행의 삭제버튼을 클릭했을때 해당 행이 삭제 될수 있도록 합니다.
// 특정행의 위치를 위로이동/아래로 이동이 가능하도록 합니다(나중에)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- GOOGLE ICON -->
<style>
*{
font-size: 1rem;
}
.material-symbols-outlined {
font-variation-settings:
'FILL' 0,
'wght' 300,
'GRAD' 0,
'opsz' 24;
font-size:1.5rem;
}
input{
height : 35px;
}
.btn{
width : 75px;
height : 35px;
border-radius: 5px;
background-color: white;
cursor: pointer;
}
th,td{
width:50px;
height : 35px;
border : 1px solid;
margin : 2px;
}
th:nth-child(3),
td:nth-child(3)
{
width : 700px;
}
.container{
border: 1px solid;
display: flex;
}
</style>
</head>
<body>
<form action="" name="joinForm" onsubmit="return false">
<input name="username" placeholder="이름을 입력하세요" >
<input name="age" placeholder="나이를 입력하세요">
<input name="address" placeholder="주소를 입력하세요">
<button class="btn">입력</button>
</form>
<hr>
<table>
<thead>
<tr>
<th>이름</th>
<th>나이</th>
<th>주소</th>
<th>삭제</th>
</tr>
</thead>
<tbody>
<div class="container">
<div class="d1"></div>
<div class="d2"></div>
<div class="d3"></div>
<div class="d4"></div>
</div>
</tbody>
</table>
</div>
<script>
// form의 기본기능은 비활성화합니다
//입력버튼을 눌렀을때 table의 tbody에 입력된 (이름/나이/주소/삭제버튼)이 생성될수 있도록합니다
//입력된 노드의 이름/나이/주소를 수정할수 있도록합니다.
//특정행의 삭제버튼을 클릭했을때 해당 행이 삭제 될수 있도록 합니다.
//특정행의 위치를 위로이동/아래로 이동이 가능하도록 합니다(나중에)
const btnEl = document.querySelector('.btn');
const formEl = document.joinForm;
const usernameEl = formEl.username;
const ageEl = formEl.age;
const addressEl = formEl.address;
const tableBodyEl = document.querySelector('table tbody');
btnEl.addEventListener('click', function(){
if(isValid()){
createNode();
}
else{
alert("다시 입력하세요..");
}
//초기화 시키는 작업
usernameEl.value='';
ageEl.value='';
addressEl.value='';
})
function isValid(){
return !(isNaN(ageEl.value)); // 숫자가 아니면 true / 숫자면 false
}
function createNode(){
const tr = document.createElement('tr'); //tr생성
const td1 = document.createElement('td'); //td생성
td1.innerHTML = usernameEl.value;
const td2 = document.createElement('td');
td2.innerHTML = ageEl.value;
const td3 = document.createElement('td');
td3.innerHTML = addressEl.value;
const td4 = document.createElement('td');
const delEl = document.createElement('span');
delEl.classList.add('material-symbols-outlined');
delEl.innerHTML='delete';
delEl.setAttribute('style', 'cursor:pointer');
delEl.addEventListener('click', function(){
const parentEl = delEl.parentNode.parentNode;
console.log(parentEl);
parentEl.remove();
})
td4.appendChild(delEl);
//tr -> td연결
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
//tbody - td 연결
tableBodyEl.appendChild(tr)
}
</script>
</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>
<!-- GOOGLE ICON -->
<style>
*{
font-size: 1rem;
}
.material-symbols-outlined {
font-variation-settings:
'FILL' 0,
'wght' 300,
'GRAD' 0,
'opsz' 24;
font-size:1.5rem;
}
input{
height : 35px;
}
.btn{
width : 75px;
height : 35px;
border-radius: 5px;
background-color: white;
cursor: pointer;
}
th,td{
width:50px;
height : 35px;
border : 1px solid;
margin : 2px;
}
th:nth-child(3),
td:nth-child(3)
{
width : 700px;
}
.container{
border: 1px solid;
display: flex;
}
</style>
</head>
<body>
<form action="" name="joinForm" onsubmit="return false">
<input name="username" placeholder="이름을 입력하세요" >
<input name="age" placeholder="나이를 입력하세요">
<input name="address" placeholder="주소를 입력하세요">
<button class="btn">입력</button>
</form>
<hr>
<table>
<thead>
<tr>
<th>이름</th>
<th>나이</th>
<th>주소</th>
<th>삭제</th>
</tr>
</thead>
<tbody>
<div class="container">
<div class="d1"></div>
<div class="d2"></div>
<div class="d3"></div>
<div class="d4"></div>
</div>
</tbody>
</table>
</div>
<script>
// form의 기본기능은 비활성화합니다
//입력버튼을 눌렀을때 table의 tbody에 입력된 (이름/나이/주소/삭제버튼)이 생성될수 있도록합니다
//입력된 노드의 이름/나이/주소를 수정할수 있도록합니다.
//특정행의 삭제버튼을 클릭했을때 해당 행이 삭제 될수 있도록 합니다.
//특정행의 위치를 위로이동/아래로 이동이 가능하도록 합니다(나중에)
const btnEl = document.querySelector('.btn');
const formEl = document.joinForm;
const usernameEl = formEl.username;
const ageEl = formEl.age;
const addressEl = formEl.address;
const tableBodyEl = document.querySelector('table tbody');
btnEl.addEventListener('click', function(){
if(isValid()){
createNode();
}
else{
alert("다시 입력하세요..");
}
//초기화 시키는 작업
usernameEl.value='';
ageEl.value='';
addressEl.value='';
})
function isValid(){
return !(isNaN(ageEl.value)); // 숫자가 아니면 true / 숫자면 false
}
let td01_id_val=0; // 전역변수
function createNode(){
td01_id_val++;
const tr = document.createElement('tr'); //tr생성
tr.setAttribute('draggable',true); //드래그 가능하도록
const td1 = document.createElement('td'); //td생성
//--------------------
// 라벨 체크 시 이름 변경 가능하도록
// --------------------
const chk1 = document.createElement('input');
chk1.setAttribute('type','checkbox');
chk1.setAttribute('id',`name_id_01_${td01_id_val}`);
chk1.style.display="none"; //체크박스 숨기기
const chk1_label = document.createElement('label');
chk1_label.setAttribute('for',`name_id_01_${td01_id_val}`);
chk1_label.setAttribute('style','display:block; position:relative;')
const input1 = document.createElement('input');
input1.value = usernameEl.value;
input1.setAttribute('disabled',true);
input1.setAttribute('style','position:relative; z-index:-1;');
chk1.addEventListener('change',function(){
const inputEl = chk1.nextSibling.firstChild;
if(event.target.checked){
inputEl.style.zIndex=1; //수정 가능하도록 index를 올려줌
inputEl.disabled=false;
}
else{
inputEl.disabled=true;
}
});
input1.addEventListener('keydown',function(event){
if(event.keyCode==13){
input1.setAttribute('style','position:relative; z-index:-1;');
input1.setAttribute('disabled',true);
const chkEl = input1.parentNode.previousSibling;
chkEl.checked=false;
} // enter 치면 원래대로 돌림
})
td1.append(input1);
input1.addEventListener('dblclick',function(){
// input1.setAttribute('disabled',false);
})
chk1_label.appendChild(input1);
td1.append(chk1);
td1.append(chk1_label);
// ------------------------
const td2 = document.createElement('td');
td2.innerHTML = ageEl.value;
const td3 = document.createElement('td');
td3.innerHTML = addressEl.value;
const td4 = document.createElement('td');
const delEl = document.createElement('span');
delEl.classList.add('material-symbols-outlined');
delEl.innerHTML='delete';
delEl.setAttribute('style', 'cursor:pointer');
delEl.addEventListener('click', function(){
const parentEl = delEl.parentNode.parentNode;
console.log(parentEl);
parentEl.remove();
})
td4.appendChild(delEl);
//tr -> td연결
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
//tbody - td 연결
tableBodyEl.appendChild(tr)
}
</script>
</body>
</html>
더블 클릭하면 이름을 변경할 수 있고 enter를 치면 변경한 값이 들어가게 된다.
참고 : https://fonts.google.com/icons?selected=Material+Symbols+Outlined:delete:FILL@0;wght@400;GRAD@0;opsz@24&icon.query=trash