- 本文是参考他人博客修改并添加自我理解的注释的一个文档,其他之处没有太多修改。通过本文让自己明白实现一个项目的思路。感觉这个博主的思路真的很清晰。值得借鉴
- html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link href="css/shop.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.11.0.js"></script>
</head>
<body onselectstart="return false;">
<template id="temp">
<tr>
<td>
<input type="checkbox" class="check">
</td>
<td>
<img src="./img/{src}">{txt}
</td>
<td>{price}</td>
<td>
<span class="reduce">-</span><input class="text" value="1"><span class="add">+</span>
</td>
<td>{subtotal}</td>
<td>
<span class="del">删除</span>
</td>
</tr>
</template>
<div class="box" id="box">
<table>
<thead>
<tr>
<th>
<label>
<input type="checkbox" class="checkAll check">全选
</label>
</th>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
</thead>
<tbody id="tbody">
</tbody>
</table>
<div class="bottom" id="bottom">
<aside>
</aside>
<label>
<input type="checkbox" class="checkAll">全选
</label>
<span class="delAll">全部删除</span>
<div>已选商品:
<span class="selected" id="num">3</span>件
</div>
<a href="#" class="show">显示或隐藏</a>
<div>合计:¥
<span class="total" id="total">7000</span>
</div>
<div class="js">结算</div>
</div>
</div>
<script type="text/javascript" src="js/shop1.js" ></script>
</body>
</html>
3.css代码:
body {
background-color: #bcdecf;
}
div.box {
width: 700px;
margin: 50px auto 0;
}
div.box table {
border-collapse: collapse;
width: inherit;
text-align: center;
background-color: #f6f6f6;
}
div.box table td,
div.box th {
border: 1px solid #999;
}
div.box th {
height: 40px;
}
div.box table tbody img {
height: 50px;
}
div.box table tbody tr span {
cursor: default;
}
div.box table tbody tr td:nth-child(2) img {
vertical-align: middle;
}
div.box table tbody tr td:nth-child(4) span {
display: inline-block;
width: 15px;
line-height: 30px;
background-color: #666;
color: #eee;
vertical-align: middle;
}
div.box table tbody tr td:nth-child(4) input {
width: 20px;
height: 20px;
outline: none;
vertical-align: middle;
text-align: center;
}
div.box table tbody tr td:nth-child(6) span {
padding: 4px 10px;
background-color: #cd4646;
color: white;
}
div.box div.bottom {
padding: 15px 0;
margin-top: 15px;
height: 25px;
background-color: white;
display: flex;
justify-content: space-between;
position: relative;
}
div.box div.bottom span.delAll {
cursor: default;
}
div.box div.bottom div.js {
padding: 0 6px;
background-color: #00A5FF;
color: white;
margin-right: 10px;
cursor: default;
}
div.box div.bottom aside div {
display: inline-block;
}
div.box div.bottom aside div span {
position: absolute;
width: 50px;
line-height: 20px;
padding: 0 5px;
background-color: rgba(255, 255, 255, .4);
color: #333;
font-size: 10px;
margin-left: -60px;
margin-top: 20px;
transform: rotate(30deg);
cursor: pointer;
}
div.box div.bottom aside img {
height: 60px;
vertical-align: middle;
}
div.box div.bottom aside {
position: absolute;
background-color: #0a74cb;
width: 100%;
top: -70px;
padding: 5px;
box-sizing: border-box;
display: none;
}
div.box div.bottom aside.on {
display: block;
}
div.box div.bottom aside:after {
position: absolute;
content: "";
border: 10px solid transparent;
border-top-color: #0a74cb;
bottom: -19px;
right: 280px;
}
div.box div.bottom a,
div.box div.bottom a:visited {
color: #0b97ff;
text-decoration: none;
}
js代码:
function $(exp) { //获取元素 #box
var el;
//对exp匹配以#开头的字符串,且匹配数字、字母、下划线、且以+结尾的字符串,如果存在该匹配,则返回true
if(/^#\w+$/.test(exp)) {
el = document.querySelector(exp);
} else {
el = document.querySelectorAll(exp);
}
return el;
}
var arr = []; /*表单的数据,以数组存储*/
arr[arr.length] = {
src: '1.jpg',
txt: 'Casio/卡西欧 EX-TR350',
price: 5999.88
};
arr[arr.length] = {
src: '2.jpg',
txt: 'Canon/佳能 PowerShot SX50 HS',
price: 3888.50
};
arr[arr.length] = {
src: '3.jpg',
txt: 'Sony/索尼 DSC-WX300',
price: 1428.50
};
arr[arr.length] = {
src: '4.jpg',
txt: 'Fujifilm/富士 instax mini 25',
price: 640.60
};
var temp = $('#temp').innerHTML;
var tbody = $('#tbody');
arr.forEach(function(el) { //把数据插入到HTML中 相当于初始化
tbody.innerHTML += temp.replace("{src}", el.src).replace("{txt}", el.txt).replace("{price}", el.price)
.replace("{subtotal}", el.price);
});
var trs = $('#tbody tr');
var box = $('#box');//$():调用上面的函数
var aside = $('#bottom aside')[0];
box.onclick = function(ev) {
//利用事件冒泡的原理,把事件添加给父级box
// var oEvent = ev || event; //意思是 ev 成立时 oEvent = event,否则 oEvent = ev
var e = ev || event;
//打印事件
console.log("即将打印数据");
console.log(e);
var target = e.target || e.srcElement; //获取当前点击对象
var cls = target.className;
if(cls.indexOf("check") != -1) cls = 'check';
switch(cls) {
case 'add': //添加商品数量
var tr = target.parentNode.parentNode; //找到点击过那一行
var tds = tr.cells;
target.previousSibling.value++; //数量那一栏的数字加一
tds[4].innerText = (tds[2].innerText * target.previousElementSibling.value).toFixed(2);
//修改小计里面的价格
break;
case 'reduce': //减少商品数量
//target:接受事件作用的DOM节点对象
var tr = target.parentNode.parentNode; //找到点击过那一行
//tr.cells:返回当前行的所有列<td>
var tds = tr.cells;
/*target.nextElementSibling.value:为<span>标签后面的<input>标签的值,target.nextElementSibling:当前标签的下一个兄弟标签*/
if(target.nextElementSibling.value != 1) target.nextElementSibling.value--;
//数量那一栏减一 tds[4]:即为数量那一栏 tds[2]:单价 target.nextElementSibling.value:数量
tds[4].innerText = (tds[2].innerText * target.nextElementSibling.value).toFixed(2);
//修改小计里面的价格
break;
case 'text': //直接修改数量那一栏input的值
var tr = target.parentNode.parentNode;
var tds = tr.cells;
target.onblur = function() { //失去焦点时执行
// this:表示触发当前事件的对象
tds[4].innerText = (tds[2].innerText * this.value).toFixed(2);
// this.onblur:对离开当前DOM节点触发的事件进行销毁
this.onblur = null; //销毁事件
};
break;
case 'del': //删除商品
var tr = target.parentNode.parentNode;
if(confirm('你确定要删除吗?'))
tbody.removeChild(tr);
break;
case 'check': //复选框选择商品
chk(target); //执行复选框函数
break;
case 'delAll': //删除全部商品
if(confirm('你确定要删除吗?'))
tbody.innerHTML = '';
break;
case 'show': //显示、隐藏商品
aside.classList.toggle('on');
break;
case 'cancel':
var index = target.getAttribute('data-index');
trs[index].cells[0].children[0].checked = false;
}
total(); //计算价格
};
var total_all = $('#total');
var num = $('#num');
total();
function total() { //计算价格
var sum = 0,
number = 0;
trs = $('tbody tr');
var str = "";
//i为索引,tr为对应 的索引的值
trs.forEach(
function(tr, i) {
//遍历每一行判断,将已选择商品添加到显示隐藏里面
var tds = tr.cells;
if(tds[0].children[0].checked) {
sum += parseFloat(tds[4].innerText);
number += parseInt(tds[3].children[1].value);
str += '<div><img src="images/${i+1}.jpg"><span class="cancel" data-index="${i}">取消选择</span></div>';
}
total_all.innerText = sum.toFixed(2);
num.innerText = number;
aside.innerHTML = str;
})
}
var checkAll = $('#box .checkAll');//为第一行和最后一行的最左边的复选框
function chk(target) { //复选框判断
var cls = target.className;
var flag = true;
if(cls === 'check') { //点击非全选复选框
/*当存在一个复选框未选中,全选框为false*/
for(var i = 0; i < trs.length; i++) {
// var trs = $('#tbody tr'); 获取所有tbody里面的所有行
var checkbox = trs[i].cells[0].children[0];//获取<td>里面的第一个<input>
if(!checkbox.checked) { //如果没有被选中
flag = false;
break
}
}
checkAll[0].checked = checkAll[1].checked = flag;
} else { //点击全选复选框,所有复选框的状态保持一致
for(var i = 0; i < trs.length; i++) {
var checkbox = trs[i].cells[0].children[0];
checkbox.checked = target.checked;
}
//checkAll:为第一行和最后一行的最左边的复选框
checkAll[0].checked = checkAll[1].checked = target.checked;//从右向左进行赋值
}
}