卡了一天多,但這樣下去會耽誤太多,所以先記錄一下趕快繼續往下走
需求:
在訂單頁面放了 Modal · Bootstrap ,想要在按商品刪除跳出這個 modal,按確定就是確定刪除這條商品,按取消則是不會刪除這條商品,但由於商品列是從首頁取資料再動態產生,所以 javascript 都是使用監聽事件,e.target
來抓
狀況一
如果整個 model 是放在 forEach 裡面,並且 target 是跳出 model 的確認鍵
if (target.classList.contains('btn-primary'))
我把它放在跟刪除同一層
cart.jsp 檔案
<div class="goods">
<c:forEach var="row" items="${cart}">
<div class="row order_list">
<div class="col-5 center-vertical justify-content-start">
<img class="order_goods_img" src="/img/${row.goodsimg}"/>
<p class="order_goods_name">${row.goodsname}</p>
</div>
<div class="col center-vertical">
<span id="price_${row.goodsid}">${row.price}</span>
</div>
<div class="col center-vertical">
<div class="center-vertical amount">
<button class="amount_btn minus_btn" type="button">-</button>
<div class="order_amount" name="quantity_${row.goodsid}"
onblur="calc(${row.goodsid}, this)">${row.quantity}</div>
<button class="amount_btn add_btn" type="button">+</button>
</div>
</div>
<div class="col center-vertical">
<span class="order_price_total" id="subtotal_${row.goodsid}">${row.price * row.quantity}</span>
</div>
<div class="col center-vertical">
<button class="del_btn" type="button" data-toggle="modal" data-target="#staticBackdrop">刪除
</button>
<!-- 跳出刪除 alert -->
<div class="modal fade" id="staticBackdrop" data-backdrop="static" data-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">確定刪除 ? </h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
確定要將此商品刪除 ?
</div>
<div class="modal-footer">
<button type="button" id="cel" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" id="delDetermine" class="btn btn-primary" data-dismiss="modal">確定刪除</button>
</div>
</div>
</div>
</div>
</div>
</div>
</c:forEach>
</div>
order.js 檔案
document.querySelector('.container').addEventListener('click', (e) => {
const {target} = e;
total = document.getElementById("total").innerText;
/* -----------------刪除商品項目-----------------------*/
if (target.classList.contains('btn-primary')) {
const totalDel = target.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.children[3].children[0].innerText
console.log(totalDel)
document.getElementById('total').innerText = parseInt(total) - parseInt(totalDel);
target.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.remove();
}
/* -----------------改變商品數量-----------------------*/
if (target.classList.contains('add_btn')) {
var count = target.parentNode.children[1].innerText;
var price = target.parentNode.parentNode.parentNode.children[1].innerText;
target.parentNode.children[1].innerText = ++count;
var subtotle1 = target.parentNode.children[1].innerText
target.parentNode.parentNode.parentNode.children[3].children[0].innerText = subtotle1 * price;
total = parseInt(total) + parseInt(price);
document.getElementById('total').innerText = total;
}
if (target.classList.contains('minus_btn')) {
var count = target.parentNode.children[1].innerText;
var price = target.parentNode.parentNode.parentNode.children[1].innerText;
if (count > 0) {
target.parentNode.children[1].innerText = --count;
var subtotle1 = target.parentNode.children[1].innerText;
target.parentNode.parentNode.parentNode.children[3].children[0].innerText = subtotle1 * price;
total = parseInt(total) - parseInt(price);
document.getElementById('total').innerText = total;
}
}
});
不管按哪一條商品的刪除,都只會刪除第一項商品列
也沒辦法這樣寫
if (target.classList.contains('del_btn')) {
const totalDel = target.parentNode.parentNode.children[3].children[0].innerText
if (target.classList.contains('btn-primary')) {
document.getElementById('total').innerText = parseInt(total) - parseInt(totalDel);
target.parentNode.parentNode.remove();
}
}
因為當按下 del_btn
,自然是不會同時按下 btn-primary
,所以裡面的 if 判斷都是 false ,因此無法執行裡面的程式
狀況二
在('btn-primary') 再多設監聽,並且整個 model 是放在 forEach 外面
不過 model 是放在 forEach 外或內好像影響不大
cart.jsp 檔案
<form action="controller" method="post">
<!-- 跳出結帳 alert -->
<div class="modal fade" id="checkAccounts" data-backdrop="static" data-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">結帳</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
確定將訂單結帳 ?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary delCommodity">確定</button>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row order_list center-vertical">
<div class="col-5 justify-content-start">
商品
</div>
<div class="col center-vertical">
單價
</div>
<div class="col center-vertical">
數量
</div>
<div class="col center-vertical">
總計
</div>
<div class="col center-vertical">
操作
</div>
</div>
<div class="goods">
<c:forEach var="row" items="${cart}">
<div class="row order_list">
<div class="col-5 center-vertical justify-content-start">
<img class="order_goods_img" src="/img/${row.goodsimg}"/>
<p class="order_goods_name">${row.goodsname}</p>
</div>
<div class="col center-vertical">
<span id="price_${row.goodsid}">${row.price}</span>
</div>
<div class="col center-vertical">
<div class="center-vertical amount">
<button class="amount_btn minus_btn" type="button">-</button>
<div class="order_amount" name="quantity_${row.goodsid}"
onblur="calc(${row.goodsid}, this)">${row.quantity}</div>
<button class="amount_btn add_btn" type="button">+</button>
</div>
</div>
<div class="col center-vertical">
<span class="order_price_total" id="subtotal_${row.goodsid}">${row.price * row.quantity}</span>
</div>
<div class="col center-vertical">
<button class="del_btn" type="button" data-toggle="modal" data-target="#staticBackdrop">刪除
</button>
<!-- 跳出刪除 alert -->
<div class="modal fade" id="staticBackdrop" data-backdrop="static" data-keyboard="false"
tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">確定刪除 ? </h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
確定要將此商品刪除 ?
</div>
<div class="modal-footer">
<button type="button" id="cel" class="btn btn-secondary" data-dismiss="modal">
取消
</button>
<button type="button" id="delDetermine" class="btn btn-primary"
data-dismiss="modal">確定刪除
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</c:forEach>
</div>
</div>
<footer class="footer_block">
<div class="settle_accounts_block">
<div class="sub_total">
<div>商品總金額</div>
<span class="total_price" id="total">${total}</span>
<input class="settle_accounts_btn" type="button" value="結帳" data-toggle="modal"
data-target="#checkAccounts">
</div>
</div>
</footer>
</form>
order.js 檔案
document.querySelector('.container').addEventListener('click', (e) => {
const {target} = e;
total = document.getElementById("total").innerText;
/* -----------------刪除商品項目-----------------------*/
if (target.classList.contains('del_btn')) {
const totalDel = target.parentNode.parentNode.children[3].children[0].innerText
document.querySelector('#delDetermine').addEventListener('click', (e) => {
document.getElementById('total').innerText = parseInt(total) - parseInt(totalDel);
target.parentNode.parentNode.remove();
console.log(target.parentNode.parentNode)
});
}
......後面不貼了
按確認都是沒問題的,因為總金額重新計算,節點也刪除
但問題在於,如果按了取消,當下的確就取消沒再動作,但當我按了其他商品列的刪除+確認,會連帶之前取消的商品也一併跟著刪除,所以也就是只要我按了刪除鍵,target 都是被記錄下來,
原先三項商品,按了三次取消鍵
第四次按另外一項商品的刪除確認鍵
原本預計是跑一次 console.log(target.parentNode.parentNode)
Orz
阻止事件傳遞
如果加上 e.stopImmediatePropagation()
連帶 Modal · Bootstrap 都會被擋掉一些,但的確監聽只剩一次,後面不會繼續聽下去,但是他先執行刪除的也是第一個 target (也就是剛剛按取消的那個),而我要的卻是最後面的 target
e.stopPropagation()
沒用,因為都是同一層,事件還是會被執行。
原本想說既然都會被記錄下來,那我選擇最後一次 target 做刪除,前面有多少個就不管她,結果不知道記錄在那邊,也不是 event 的父節點,所以沒辦法用索引子來選取
也想過點完後就移除監聽事件,也是失敗
document.querySelector('.del_btn').removeEventListener('onmouseup', (e) => {
console.log('ok')
});