JavaScript
1. 모달 띄우기 버튼 클릭 시 모달창 활성화, 모달창 닫기 버튼 클릭시 비활성화
변수명에 element 저장
const modal = document.querySelector('.modal');
const overlay = document.querySelector('.overlay');
const btn_modal = document.querySelector('#btn-modal');
const btn_close = document.querySelector('.btn-close');
const close_elements = [btn_close, overlay];
https://print-blue.tistory.com/186
[Javascript] Element.classList 속성, 자바스크립트로 클래스 추가/제거 하기
Element.classList 속성다양한 메서드를 통해 클래스를 간편하게 제어할 수 있다 !classList 자체는 읽기 전용 속성이지만 add() 와 remove() 메서드를 이용해 변형할 수 있다 ! 1. add()classList.add('클래스명')
print-blue.tistory.com
[ 모달 : 활성화 ]
1-1. btn_modal(모달창 띄우기 버튼) 클릭 했을 때 이벤트 설정
btn_modal.addEventListener('click', () => { // 콜백함수
modal.classList.add('active'); // modal 에 active 클래스를 추가
overlay.classList.add('active') ; // overlay 에 active 클래스를 추가
});
[ 모달 : 비활성화 ]
1-2. btn_close(모달창 x 버튼) or overlay(버튼 외) 클릭 했을 때 이벤트 설정
btn_close.addEventListener('click', () => {
modal.classList.remove('active'); // modal 에 active 클래스를 제거
overlay.classList.remove('active') ; // overlay 에 active 클래스를 제거
});
overlay.addEventListener('click', () => {
modal.classList.remove('active'); // modal 에 active 클래스를 제거
overlay.classList.remove('active') ; // overlay 에 active 클래스를 제거
});
이렇게 코드 작성하면 작동은 되지만 중복된 코드가 보인다 ! 함수로 btn_close 와 overlay 속성을 합쳐주자
const close_elements = [btn_close, overlay];
close_elements.forEach(element => {
console.log('element >>', element)
});
const close_elements = [btn_close, overlay];
close_elements.forEach(element => {
element.addEventListener('click', () => {
modal.classList.remove('active'); // modal 에 active 클래스를 제거
overlay.classList.remove('active'); // overlay 에 active 클래스를 제거
})
});
이렇게 되면 ! 모달창 x 버튼을 클릭해도, 모달창 이외에 overlay 를 클릭해도 !
modal 과 overlay 에 active 클래스 제거가 되면서 잘 된다 !
1-3. 모달창에 텍스트(이메일) 입력 후 닫고 다시 열었을 때 텍스트 초기화
const inputData = document.querySelector("input[type='email']");
const modal_input = document.querySelector('.modal input');
// [모달창 활성화]
btn_modal.addEventListener('click', () => {
modal.classList.add('active');
overlay.classList.add('active') ;
modal_input.value = null; // 모달창 입력값 비우기
});
2. 상품명 입력 후 등록
변수명에 element 저장
const form = document.querySelector('form');
const sign_up = document.querySelector('.sign-up');
const input = document.querySelector('input');
const ul = document.querySelector('ul');
text box(상품명 입력창)에 입력 후, 등록 버튼 클릭하면 항목(li) 추가
form 은 text 입력 후 엔터를 치면 기본적으로 submit 이 되는데,
현재 form 태그에 action 을 설정을 안해서 티가 안날 뿐 페이지 요청을 하게 된다.
하지만 ! server 에 페이지 요청 하고 싶지 않기 때문에 자바스크립트를 사용해서 요청하지 않을 것 !
자바스크립트에 perventDefault() 를 사용해서 refresch (새로고침) 방지 즉, submit 기능을 삭제한다.
form.addEventListener('submit', (event) => { // submit : 엔터를 치면
console.log('입력했다 !!');
});
페이지 요청을 했고 현재 페이지가 요청되면서 새로 고침이 됐기 때문에 콘솔창에 log 가 안뜬다 !
1) li element 를 생성
form.addEventListener('submit', (event) => { // submit : 엔터를 치면
// 1) refresch(새로 고침) 방지
event.preventDefault();
console.log('입력했다 !!');
});
새고 고침 방지와 submit 기능을 삭제 했기 때문에 페이지 요청 하지 않아 새로 고침 되지 않기 때문에
콘솔창에 log 가 잘 뜬다 !
그럼 이제 li element 를 생성 -> li element 에 content 추가 -> ul 의 자식 li element 추가 해보자
2-1) li element 를 생성
form.addEventListener('submit', (event) => { // submit : 엔터를 치면
// 1) refresch(새로 고침) 방지
event.preventDefault();
console.log('입력했다 !!');
// 2-1) li element 생성
const li = document.createElement('li');
console.log(li);
});
2-2) li element 에 content 추가
form.addEventListener('submit', (event) => { // submit : 엔터를 치면
// 1) refresch(새로 고침) 방지
event.preventDefault();
console.log('입력했다 !!');
// 2-1) li element 생성
const li = document.createElement('li');
console.log(li);
// 2-2) li element 에 content 추가
console.log(input.value);
li.innerText = input.value;
});
2-3) ul 의 자식 li element 추가
form.addEventListener('submit', (event) => { // submit : 엔터를 치면
// 1) refresch(새로 고침) 방지
event.preventDefault();
console.log('입력했다 !!');
// 2-1) li element 생성
const li = document.createElement('li');
console.log(li);
// 2-2) li element 에 content 추가
console.log(input.value);
li.innerText = input.value;
});
3) input(텍스트 박스)에 입력된 문자열 삭제
form.addEventListener('submit', (event) => { // submit : 엔터를 치면
// 1) refresch(새로 고침) 방지
event.preventDefault();
console.log('입력했다 !!');
// 2-1) li element 생성
const li = document.createElement('li');
console.log(li);
// 2-2) li element 에 content 추가
console.log(input.value);
li.innerText = input.value;
// 3) input(텍스트 박스)에 입력된 문자열 삭제
input.value = '';
input.value = null;
});
지금까지의 전체 코드 !
// 변수명에 element 저장
// 1
const modal = document.querySelector('.modal');
const overlay = document.querySelector('.overlay');
const btn_modal = document.querySelector('#btn-modal');
const btn_close = document.querySelector('.btn-close');
const close_elements = [btn_close, overlay];
// 2
const form = document.querySelector('form');
const sign_up = document.querySelector('.sign-up');
const input = document.querySelector('input');
const ul = document.querySelector('ul');
// 1. 모달 띄우기 버튼 클릭 시 모달창 활성화, 모달창 닫기 버튼 클릭시 비활성화
[모달 : 활성화]
1-1. btn_modal(모달창 띄우기 버튼) 클릭 했을 때 이벤트 설정
btn_modal.addEventListener('click', () => { // 콜백함수
modal.classList.add('active'); // modal 에 active 클래스를 추가
overlay.classList.add('active') ; // overlay 에 active 클래스를 추가
});
[모달 : 비활성화]
1-2. btn_close(모달창 x 버튼) or overay(버튼 외) 클릭 했을 때 이벤트 설정
close_elements.forEach(element => {
element.addEventListener('click', () => {
modal.classList.remove('active'); // modal 에 active 클래스를 제거
overlay.classList.remove('active'); // overlay 에 active 클래스를 제거
})
});
1-3. 모달창에 텍스트(이메일) 입력 후 닫고 다시 열었을 때 텍스트 초기화
// 코드 복붙하기
2. 상품명 입력 후 등록
[구현 1]
text box(상품명 입력창)에 입력 후, 등록 버튼 클릭하면 항목(li) 추가
form.addEventListener('submit', (event) => { // submit : 엔터를 치면
// 1) refresch(새로 고침) 방지
event.preventDefault();
// 2-1) li element 생성
const li = document.createElement('li');
// 2-2) li element 에 content 추가
li.innerText = input.value;
// 2-3) ul 의 자식 li element 추가
ul.appendChild(li);
// 3) input(텍스트 박스)에 입력된 문자열 삭제
input.value = '';
});
구현된 코드 리팩토링 !
현재 코드에서 기능이 많아지면서 분리하는게 좋겠다 생각 들어서 리팩토링 들어갑니당
listener, handle 그리고 li 기능을 분리할 것 !
명확한 기능이 있는 경우 따로 빼주는 것이 좋은데, 다른 작업하면서 또 쓸 수 있기 때문이다 !
input.value 보다는 호출할 때 매개변수를 그니까 li 에 content 를 넣어주는 거니까 이렇게 코드 작성하는 것이 추후 작업할 때 편하다
const addLi = (content) => {
const li = document.createElement('li');
li.innerText = content;
ul.appendChild(li);
}
보통 무슨 handler 인지 지정해주면 좋지만, 하나만 있어서 그냥 handler 라 지정 !
근데 코드를 막 작성하는 것이 아니라 생각을 하고 ! 순서대로 해야된다.
일단 새로 고침 후 li 추가 한 다음에 텍스트 박스에 입력된 문자열을 삭제해줘야한다.
const handler = (event) => {
event.preventDefault();
addLi(input.value);
input.value = '';
}
근데 또 ! 여기서 또 생각해야할 점은
사용자가 텍스트를 입력하지 않고 엔터를 쳤을 때도 li 를 추가하기 때문에 이것 또한 방지 해야한다.
const handler = (event) => {
event.preventDefault();
if (input.value !== '') { // type 비교까지 하기 위해 사용
addLi(input.value);
input.value = '';
}
}
form.addEventListener('submit', handler);
하지만 !! form 전체보다는 등록 버튼에 등록하는 것이 명확하다.
// form.addEventListener('submit', handler);
sign_up.addEventListener('click', handler);
지금까지의 전체 코드 !
[구현 2] refactoring
위 코드 분리 : listener, handler, li 기능 분리
[함수] li 추가 기능
const addLi = (content) => {
const li = document.createElement('li');
li.innerText = content;
ul.appendChild(li);
}
[handler]
const handler = (event) => {
event.preventDefault();
if (input.value !== '') { // type 비교까지 하기 위해 사용
addLi(input.value);
}
input.value = '';
}
[listener]
form.addEventListener('submit', handler);
sign_up.addEventListener('click', handler);
리팩토링한 코드에 기능 추가 !
1. 삭제버튼
1-1. li element 가 추가되면, 삭제 버튼도 같이 추가
li 가 생성되면서 ul 에 자식으로 들어오고, button 이 생성되면서 li 자식으로 들어오는 형태 !
근데 여기서 li content 에 button 을 추가될건데 그냥 content 보다는 span 으로 감싸는 것이 좋다 !
// [함수] li 추가 기능
const addLi = (content) => {
const li = document.createElement('li');
ul.appendChild(li);
// span element 생성 후 추가
const span_content = document.createElement('span');
span_content.innerText = content;
// 삭제 버튼 생성 후 추가
const btn_cross = document.createElement('button');
// li 자식으로 span, button 한 번에 추가
li.append(span_content, btn_cross); // 순서대로 들어옴
}
1-2. 삭제 버튼을 클릭하면, li element 삭제
// 삭제 기능
const deleteLi = () => {
console.log('삭제 버튼 클릭됨 !');
}
// [함수] li 추가 기능
const addLi = (content) => {
const li = document.createElement('li');
ul.appendChild(li);
// span element 생성 후 추가
const span_content = document.createElement('span');
span_content.innerText = content;
// 삭제 버튼 생성 후 추가
const btn_cross = document.createElement('button');
// 삭제 버튼 : listener 에 handler 등록
btn_cross.addEventListener('click', deleteLi)
// li 자식으로 span, button 한 번에 추가
li.append(span_content, btn_cross); // 순서대로 들어옴
}
근데 삭제 기능을 만들 때도 ! 무작정 삭제가 아닌 해당 li 만 삭제 해야된다.
// 삭제 기능
const deleteLi = (event) => {
console.log('삭제 버튼 클릭됨 !');
console.log(event.target.parentElement);
const target = event.target.parentElement; // 삭제하고자 하는 element 만 삭제
target.remove();
}
// [함수] li 추가 기능
const addLi = (content) => {
const li = document.createElement('li');
ul.appendChild(li);
// span element 생성 후 추가
const span_content = document.createElement('span');
span_content.innerText = content;
// 삭제 버튼 생성 후 추가
const btn_cross = document.createElement('button');
// 삭제 버튼 : listener 에 handler 등록
btn_cross.addEventListener('click', deleteLi); // li button 클릭하면 이 코드 실행
// li 자식으로 span, button 한 번에 추가
li.append(span_content, btn_cross); // 순서대로 들어옴
}
2. local storage
https://print-blue.tistory.com/187
개발자 도구 [Application]-[web local storage] 저장하기/가져오기
웹 브라우저는 Application 에 web local storage 에 정보가 남아있는데, 여기서 가져올 것 ! 가져오는 함수가 있음 !단점 : 다른 웹 브라우저 사용시 보여지지 않음 [저장하기 / 가져오기]localStorage.s
print-blue.tistory.com
2-1. li content 를 web local storage 에 저장
key 값은 하나로 하고 value 에 상품들을 넣어줄건데
각 상품마다 특정 구분도 해줄 거임(생성날짜+시간)
현재 프로젝트에서는 key 값으로 쓸만한게 없어서 Date.now() 로 사용할 것 !
// [handler]
let li_items = [];
const handler = (event) => {
event.preventDefault();
if (input.value !== '') { // type 비교까지 하기 위해 사용
const li_item = { // 2-1) li content 를 web local storage 에 저장
id : Date.now(),
content : input.value,
};
// console.log(li_item);
li_items.push(li_item);
// addLi(input.value);
addLi(li_item.content);
}
input.value = '';
}
addLi(li_item.content);
값 가져오는 거 잊지 않기 !
그럼 다시 코드를 수정해줘야한다 . . .
// 삭제 기능 -> 변경사항 없음
const deleteLi = (event) => {
console.log('삭제 버튼 클릭됨 !');
const target = event.target.parentElement; // 삭제하고자 하는 element 만 삭제
target.remove();
}
// [함수] li 추가 기능
const addLi = (li_item) => { // content -> li_item 수정
const li = document.createElement('li');
ul.appendChild(li);
// span element 생성 후 추가
const span_content = document.createElement('span');
span_content.innerText = li_item.content; // content -> li_item 수정
// 삭제 버튼 생성 후 추가
const btn_cross = document.createElement('button');
// 삭제 버튼 : listener 에 handler 등록
btn_cross.addEventListener('click', deleteLi); // li button 클릭하면 이 코드 실행
// li 자식으로 span, button 한 번에 추가
li.append(span_content, btn_cross); // 순서대로 들어옴
}
// [handler]
let li_items = [];
const handler = (event) => {
event.preventDefault();
if (input.value !== '') { // type 비교까지 하기 위해 사용
const li_item = { // 2-1) li content 를 web local storage 에 저장
id : Date.now(),
content : input.value,
};
li_items.push(li_item);
addLi(li_item); // input.value -> li_item 변경
}
input.value = '';
}
그럼 이제 상품을 추가할 때마다 새롭게 저장되어야 한다.
local storage 에 저장하는 함수를 만들어보자 !
배열 안에 객체가 들어있고, 직렬화해주자
// 삭제 기능
const deleteLi = (event) => {
console.log('삭제 버튼 클릭됨 !');
const target = event.target.parentElement; // 삭제하고자 하는 element 만 삭제
target.remove();
}
// [함수] li 추가 기능
const addLi = (li_item) => {
const li = document.createElement('li');
ul.appendChild(li);
// span element 생성 후 추가
const span_content = document.createElement('span');
span_content.innerText = li_item.content;
// 삭제 버튼 생성 후 추가
const btn_cross = document.createElement('button');
// 삭제 버튼 : listener 에 handler 등록
btn_cross.addEventListener('click', deleteLi); // li button 클릭하면 이 코드 실행
// li 자식으로 span, button 한 번에 추가
li.append(span_content, btn_cross); // 순서대로 들어옴
// local storage 에 저장된 요소 삭제할 때
// 기준으로 사용될 id 지정
li.id = li_item.id;
console.log('매개변수 li_item >>', li_item);
}
// [handler]
let li_items = [];
// local storage 에 저장하는 함수
const storage_save = () => {
localStorage.setItem('li_items', JSON.stringify(li_items)); // 배열안에 객체가 들어가 있고, 직렬화 해주기
};
const handler = (event) => {
event.preventDefault();
if (input.value !== '') { // type 비교까지 하기 위해 사용
const li_item = { // li content 를 web local storage 에 저장
id : Date.now(),
content : input.value,
};
li_items.push(li_item);
// addLi(input.value);
addLi(li_item);
storage_save();
}
input.value = '';
}
2-2. 삭제 버튼 클릭하면, web browser 에 저장된 데이터 삭제
// 삭제 기능
const deleteLi = (event) => {
console.log('삭제 버튼 클릭됨 !');
const target = event.target.parentElement; // 삭제하고자 하는 element 만 삭제
// 삭제 버튼 클릭된 element id 확인
console.log(target.id);
target.remove();
}
// 삭제 버튼 클릭된 element 제외한 나머지 추출
li_items = li_items.filter((item) => {
console.log('item >> ', item);
console.log('item.id > > ', item.id);
console.log('item.id type> > ', typeof item.id);
console.log('target.id >>', target.id);
console.log('target.id type> > ', typeof target.id);
});
순회를 하면서 다시 시간이 찍히기 때문에 id 값이 다른 것 !
li_items = li_items.filter((item) => {
console.log('item >> ', item);
console.log('item.id > > ', item.id);
console.log('item.id type> > ', typeof item.id);
console.log('target.id >>', target.id);
console.log('target.id type> >> ', typeof target.id);
console.log('item.id != target.id >> ', item.id != target.id);
return item.id != target.id;
});
배열에 삭제된 아이디 제외하고 잘 담아왔는데 확인
// 삭제 버튼 클릭된 element 제외한 나머지 추출
li_items = li_items.filter((item) => {
console.log('item >> ', item);
console.log('item.id > > ', item.id);
console.log('item.id type> > ', typeof item.id);
console.log('target.id >>', target.id);
console.log('target.id type> >> ', typeof target.id);
console.log('item.id != target.id >> ', item.id != target.id);
return item.id != target.id;
});
console.log('삭제 후 li_items >> ', li_items);
target.remove();
이제 로컬 스토리지에 반영하자 . . .
const deleteLi = (event) => {
console.log('삭제 버튼 클릭됨 !');
const target = event.target.parentElement; // 삭제하고자 하는 element 만 삭제
// 삭제 버튼 클릭된 element id 확인
console.log(target.id);
// 삭제 버튼 클릭된 element 제외한 나머지 추출
li_items = li_items.filter((item) => {
console.log('item >> ', item);
console.log('item.id > > ', item.id);
console.log('item.id type> > ', typeof item.id);
console.log('target.id >>', target.id);
console.log('target.id type> >> ', typeof target.id);
console.log('item.id != target.id >> ', item.id != target.id);
return item.id != target.id;
});
console.log('삭제 후 li_items >> ', li_items);
target.remove();
// local storage 에 저장
storage_save();
}
3) 새로 고침해도 local storage 에 있는 값들 보여지게 하기
새로 고침 된다는 것은 HTML 도 CSS 도 JS 도 다시 코드를 읽는다.
새로 고침해도 ! 저장된 값이 있는 경우 보여지게 하는 작업을 초기화 작업이라고 한다
페이지가 로드 될 때, 로컬 스토리지에 저장된 데이터 가져와보자
const init = () => {
const local_storage_data = JSON.parse(localStorage.getItem('li_items'));
console.log('local_storage_data >> ', local_storage_data);
console.log('[전] li_items >> ', li_items);
li_items = local_storage_data
console.log('[후] li_items >> ', li_items);
};
init();
현재 로컬 스토리지는 2개 저장되어 있다
아까 li 추가 기능을 따로 함수에 만들었으니까 써먹자 !
이러면 새로 고침해도 ! 저장된 값이 보여질 거다
const init = () => {
const local_storage_data = JSON.parse(localStorage.getItem('li_items'));
console.log('local_storage_data >> ', local_storage_data);
console.log('[전] li_items >> ', li_items);
li_items = local_storage_data
console.log('[후] li_items >> ', li_items);
// li 추가
li_items.forEach(value => addLi(value));
};
근데 또 문제가 있음
만약 로컬 스토리지에 아무것도 저장된 것이 없으면 에러가 발생함
배열 형태에서 타입이 변환이 되니까 막 코드 작성하면 안된다 ㅠ
https://print-blue.tistory.com/188
자바스크립트 논리값 확인하기
console.log('>');console.log('null : ', Boolean(null));console.log('0 : ', Boolean(0));console.log('-5 : ', Boolean(-5));console.log('빈 배열 [] : ', Boolean([]));console.log('빈 객체 [] : ', Boolean({}));
print-blue.tistory.com
local_storag_data 가 있을 때 없을 때 조건문 걸어서 저장하자
const init = () => {
const local_storage_data = JSON.parse(localStorage.getItem('li_items'));
console.log('local_storage_data >> ', local_storage_data);
if(local_storage_data) {
console.log('[전] li_items >> ', li_items);
console.log('[전] li_items type >> ', typeof li_items);
li_items = local_storage_data
console.log('[후] li_items >> ', li_items);
console.log('[후] li_items type >> ', typeof li_items);
// li 추가
li_items.forEach(value => addLi(value));
}
};
init();
그럼 모든 기능 끝 !
그럼 완성 코드 !
const modal = document.querySelector('.modal');
const overlay = document.querySelector('.overlay');
const btn_modal = document.querySelector('#btn-modal');
const btn_close = document.querySelector('.btn-close');
const close_elements = [btn_close, overlay];
const form = document.querySelector('form');
const sign_up = document.querySelector('.sign-up');
const input = document.querySelector('input');
const ul = document.querySelector('ul');
// 1
// [모달창 활성화]
btn_modal.addEventListener('click', () => {
modal.classList.add('active');
overlay.classList.add('active') ;
});
// [모달창 비활성화]
close_elements.forEach(element => {
element.addEventListener('click', () => {
modal.classList.remove('active');
overlay.classList.remove('active');
})
});
// [모달창 텍스트 초기화]
// 2
// [삭제 기능]
const deleteLi = (event) => {
const target = event.target.parentElement;
li_items = li_items.filter((item) => {
return item.id != target.id;
});
target.remove();
storage_save();
}
// [li 추가]
const addLi = (li_item) => {
const li = document.createElement('li');
ul.appendChild(li);
const span_content = document.createElement('span');
span_content.innerText = li_item.content;
const btn_cross = document.createElement('button');
btn_cross.addEventListener('click', deleteLi);
li.append(span_content, btn_cross);
li.id = li_item.id;
}
// [handler]
let li_items = [];
const storage_save = () => {
localStorage.setItem('li_items', JSON.stringify(li_items));
};
const handler = (event) => {
event.preventDefault();
if (input.value !== '') {
const li_item = {
id : Date.now(),
content : input.value,
};
li_items.push(li_item);
addLi(li_item);
storage_save();
}
input.value = '';
}
// [listener]
sign_up.addEventListener('click', handler);
// [초기화 작업]
const init = () => {
const local_storage_data = JSON.parse(localStorage.getItem('li_items'));
if(local_storage_data) {
li_items = local_storage_data
li_items.forEach(value => addLi(value));
}
};
init();
'Language > HTML & CSS & JavaScript' 카테고리의 다른 글
[JavaScript] 정규표현식 (0) | 2024.06.03 |
---|---|
[Javascript] Javascript 에서 내장 타입과 native (0) | 2024.05.31 |
[Javascript] 논리값 확인하기 (0) | 2024.05.29 |
[Javascript] Element.classList 속성, 자바스크립트로 클래스 추가/제거 하기 (0) | 2024.05.29 |
[프로젝트] 행복한 마켓 - 1. HTML, CSS 설정 (0) | 2024.05.29 |