6 글 보임 - 1 에서 6 까지 (총 6 중에서)
-
글쓴이글
-
2023년 3월 23일 13:34 #73324
김진선참가자검색기능을 통해 나온 상품목록을 drag해서 장바구니에 넣으면 1개씩이 아니라 2개씩 들어가게 되네요. 콘솔로 확인해 보니 이벤트가 2번씩 발생하더라구요. '담기'버튼으로 넣으면 1개씩 잘 들어가는데 drag만 하면 2개씩 들어가는 이유를 전혀 모르겠습니다..ㅠ,.ㅠ
//=========================== //상품진열기능 //===========================
const productList = document.querySelector('.product-list'); const cartList = document.querySelector('.cart-list'); const purchase = document.querySelector('.purchase'); const totalPrice = document.querySelector('#final-price'); const modal1 = document.querySelector('.modal1'); const modal2 = document.querySelector('.modal2'); const search = document.querySelector('#search');
let products = []; let cart = [];
//=========================== //상품진열기능 //===========================
fetch('./data/store.json') .then((res) => res.json()) .then((data) => { products = data.products;
for (let i = 0; i < products.length; i++) { const template = ` <li class="item" draggable="true" data-id='${products[i].id}'> <div class="image"> <img " src="./images/${products[i].photo}" alt="${products[i].title}"> </div> <div class="item-title">${products[i].title}</div> <div class="item-brand">${products[i].brand}</div> <div class="item-price">가격:<span>${products[i].price}</span></div> <button class="btn btn-primary btn-dark" type="submit" id="addProduct">담기</button> </li> `;
productList.insertAdjacentHTML('beforeend', template); }
//======================== //담기버튼 클릭 //======================== productList.addEventListener('click', function (e) { checkDuplId(e);
//담기버튼 누를 때 마다 장바구니 박스에 let cart 안에 있던 {} 갯수만큼 html 생성
cartList.innerHTML = ''; cart.forEach((a) => { const template = ` <li class="item" draggable="true" data-id='${a.id}'> <div class="image"> <img " src="./images/${a.photo}" alt="${a.title}"> </div> <div class="item-title">${a.title}</div> <div class="item-brand">${a.brand}</div> <div class="item-price">가격:<span>${a.price}</span></div> <input type="number" value="${a.count}" class="item-count w-100"> </li> `; cartList.insertAdjacentHTML('beforeend', template); });
//총가격 계산해서 표기해주는 기능 calculatePrice();
//input값 조절해도 총가격 계산해서 표기해줘야될듯 document.querySelectorAll('.item-count').forEach((a) => { a.addEventListener('input', () => { calculatePrice(); }); }); });
//=================== //.item 드래그로 장바구니에 추가기능 //===================
dragItems(); });
//======================== //담기버튼 누르면 일어날 일들 //========================
function checkDuplId(e) { let productId;
if (e.target.id === 'addProduct') { //지금누른 상품번호 productId = e.target.parentElement.dataset.id; }
// arr.findIndex(callback), 반환 타입 number, 없다면 -1 // 담기버튼 누를 때 let cart = [] 에 상품을 {} 형태로 보관부터하고 // let cart에 상품이 이미있는지 찾고 없으면 let cart에 {}추가, 있으면 수량만 ++;
let arrNum = cart.findIndex((a) => { return a.id == productId; });
if (arrNum == -1) { let curItem = products.find((a) => { return a.id == productId; }); curItem.count = 1; cart.push(curItem); } else { cart[arrNum].count++; } }
//=================== //.item 드래그로 장바구니에 추가기능 //===================
function dragItems() { const items = document.querySelectorAll('.item');
items.forEach((item) => { item.addEventListener('dragstart', (e) => { e.dataTransfer.setData('id', e.target.dataset.id); }); }); cartList.addEventListener('dragover', (e) => { e.preventDefault(); }); cartList.addEventListener('drop', (e) => { let productId = e.dataTransfer.getData('id');
//여기서 장바구니 추가기능 똑같이 만들면 되는데 //귀찮아서 그냥 $('.add')버튼 강제 클릭으로 대체함 document.querySelectorAll('#addProduct')[productId].click(); }); }
//=========================== // 최종가격 계산 //===========================
function calculatePrice() { const itemPrice = document.querySelectorAll('.item-price span'); const itemCount = document.querySelectorAll('.item-count');
let finalPrice = 0;
for (let i = 0; i < itemCount.length; i++) { let price = itemPrice[i].innerText; let count = itemCount[i].value; finalPrice += parseFloat(price * count); }
totalPrice.innerHTML = `${finalPrice}`; }
//=========================== //주문 누르면 뜨는 모달창, 영수증 기능 //===========================
//최하단 주문버튼 누르면 모달창1 띄우는 기능 purchase.addEventListener('click', (e) => { if (e.target.id === 'buy-btn') { document.querySelector('.modal1').style.display = 'block'; } else if (e.target.id === 'clear-btn') { cartList.innerHTML = ''; cart = []; totalPrice.innerHTML = ''; } });
//모달창1에 뭐 입력하면 전역변수에 저장해둠 let fullname = ''; let phone = '';
modal1.addEventListener('input', (e) => { if (e.target.id === 'name') { fullname = document.querySelector('#name').value; } else if (e.target.id === 'phone') { phone = document.querySelector('#phone').value; } });
//모달창1의 완료버튼 누르면 모달창2 (영수증) 보여줌 //거기안엔 canvas태그로 그림그려줌 modal1.addEventListener('click', (e) => { if (e.target.id === 'receipt') { modal1.style.display = 'none'; modal2.style.display = 'block';
let canvas = document.querySelector('#canvas'); let c = canvas.getContext('2d'); c.font = '16px dotum'; c.fillText('구매자: ' + fullname, 20, 30); c.fillText('연락처: ' + phone, 20, 60); c.fillText('--------------------------------------', 20, 90); cart.forEach((a, i) => { c.fillText(`${a.title}`, 20, 120 + i * 30); c.fillText(`${a.count}`, 220, 120 + i * 30); c.fillText(`${a.price}`, 280, 120 + i * 30); }); c.fillText( '--------------------------------------', 20, 120 + cart.length * 30 ); c.fillText('총 구매가격: ', 20, 150 + cart.length * 30); c.fillText(`${totalPrice.innerText}`, 280, 150 + cart.length * 30);
//상품명들 보여주려면 장바구니 상품만큼 c.fillText() 하면 되겠군요 } else if (e.target.className === 'close') { modal1.style.display = 'none'; } });
modal2.addEventListener('click', function (e) { if (e.target.className === 'close') { modal2.style.display = 'none'; } });
//=========================== //검색기능 //===========================
search.addEventListener('keyup', function (e) { let keyword;
if (e.key === 'Enter') { keyword = search.value;
//지금입력한 글자가 제목에 있으면 let products에서 검색어있는 것만 남기기 let newProducts = products.filter((a) => { return a.title.includes(keyword) || a.brand.includes(keyword); });
productList.innerHTML = ''; if (newProducts.length === 0) { productList.innerHTML = '찾으시는 상품이 없습니다.'; }
newProducts.forEach((a) => { const template = ` <li class="item" draggable="true" data-id='${a.id}'> <div class="image"> <img " src="./images/${a.photo}" alt="${a.title}"> </div> <div class="item-title">${a.title}</div> <div class="item-brand">${a.brand}</div> <div class="item-price">가격:<span>${a.price}</span></div> <button class="btn btn-primary btn-dark" type="submit" id="addProduct">담기</button> </li> `;
productList.insertAdjacentHTML('beforeend', template); });
dragItems(); } changeKeyword(keyword); });
function changeKeyword(keyword) { const title = document.querySelectorAll('.item-title'); const brand = document.querySelectorAll('.item-brand');
title.forEach((a) => { a.innerHTML = a.innerHTML.replaceAll( keyword, `<span style="background : yellow">${keyword}</span>` ); });
brand.forEach((a) => { a.innerHTML = a.innerHTML.replaceAll( keyword, `<span style="background : yellow">${keyword}</span>` ); }); }
2023년 3월 23일 19:57 #73367
codingapple키 마스터curItem 변수도 cart변수에 집어넣기 전에 출력도 해봅시다 2번출력되는게 수상해보이는데 이벤트리스너도 2번실행되는건 아닌가 확인합시다
2023년 3월 24일 10:33 #73429
김진선참가자애플코딩님 drop이벤트리스트너가 2번 실행되는걸 확인했고 왜 2번실해되나 봤더니 아무래도 이벤트 버블링문제 같았습니다. e.stopPropagation()을 사용했더니 여전히 2번 실행되어서 e.stopImmediatePropagation()을 사용했더니 1번만 실행되네요. 솔직히 아직도 왜 이러는지 딱 이해는 안가네요..ㅠ,ㅠ cartList.addEventListener('drop', (e) => { e.stopImmediatePropagation(); let productId = e.dataTransfer.getData('id'); document.querySelectorAll('#addProduct')[productId].click(); });
-
글쓴이글
6 글 보임 - 1 에서 6 까지 (총 6 중에서)
- 답변은 로그인 후 가능합니다.