js实现购物车(源码)
首先是页面布局html+css部分
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>演示</title>
<link rel="stylesheet" href="css/style.css">
<script type="text/javascript" src="js/demo.js"></script>
</head>
<body>
<table id="cartTable">
<thead>
<tr>
<th><label><input class="check-all check" type="checkbox"/> 全选<label></th>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td class="checkbox"><input class="check-one check" type="checkbox"/></td>
<td class="goods"><img src="data:images/1.jpg" alt=""/><span>Casio/卡西欧 EX-TR350</span></td>
<td class="price">5999.88</td>
<td class="count"><span class="reduce"></span><input class="count-input" type="text" value="1"/><span class="add">+</span></td>
<td class="subtotal">5999.88</td>
<td class="operation"><span class="delete">删除<span></td>
</tr>
<tr>
<td class="checkbox"><input class="check-one check" type="checkbox"/></td>
<td class="goods"><img src="data:images/2.jpg" alt=""/><span>Casio/卡西欧 EX-TR350</span></td>
<td class="price">5999.88</td>
<td class="count"><span class="reduce"></span><input class="count-input" type="text" value="1"/><span class="add">+</span></td>
<td class="subtotal">5999.88</td>
<td class="operation"><span class="delete">删除<span></td>
</tr>
<tr>
<td class="checkbox"><input class="check-one check" type="checkbox"/></td>
<td class="goods"><img src="data:images/3.jpg" alt=""/><span>Casio/卡西欧 EX-TR350</span></td>
<td class="price">5999.88</td>
<td class="count"><span class="reduce"></span><input class="count-input" type="text" value="1"/><span class="add">+</span></td>
<td class="subtotal">5999.88</td>
<td class="operation"><span class="delete">删除<span></td>
</tr>
<tr>
<td class="checkbox"><input class="check-one check" type="checkbox"/></td>
<td class="goods"><img src="data:images/4.jpg" alt=""/><span>Casio/卡西欧 EX-TR350</span></td>
<td class="price">5999.88</td>
<td class="count"><span class="reduce"></span><input class="count-input" type="text" value="1"/><span class="add">+</span></td>
<td class="subtotal">5999.88</td>
<td class="operation"><span class="delete">删除<span></td>
</tr>
</tbody>
</table>
<div class="foot" id="foot">
<label class="f1 select-all"><input type="checkbox" class="check-all check"/> 全选</label>
<a class="f1 delete" id="deleteAll" href="javascript:;">删除</a>
<div class="fr closing">结算</div>
<div class="fr total">合计:¥<span id="priceTotal">0.00</span></div>
<div class="fr selected" id="selected">已选商品<span id="selectedTotal">0</span>件<span class="arrow up">︽</span><span class="arrow down">︾</span></div>
<div class="selected-view">
<div id="selectedViewList" class="clearfix">
<div><img src="data:images/1.jpg"><span>取消选择</span></div>
</div>
<span class="arrow">◆<span>◆</span></span>
</div>
</body>
</html>
//***************************************************
* {
margin: 0;
padding: 0;
}
a {
color: #666;
text-decoration: none;
}
body {
padding: 20px;
color: #666;
}
.fl{
float: left;
}
.fr {
float: right;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 0;
text-align: center;
width: 937px;
}
th, td {
border: 1px solid #CADEFF;
}
th {
background: #e2f2ff;
border-top: 3px solid #a7cbff;
height: 30px;
}
td {
padding: 10px;
color: #444;
}
tbody tr:hover {
background: RGB(238,246,255);
}
.checkbox {
width: 60px;
}
.goods {
width: 300px;
}
.goods span {
width: 180px;
margin-top: 20px;
text-align: left;
float: left;
}
.price {
width: 130px;
}
.count {
width: 90px;
}
.count .add, .count input, .count .reduce {
float: left;
margin-right: -1px;
position: relative;
z-index: 0;
}
.count .add, .count .reduce {
height: 23px;
width: 17px;
border: 1px solid #e5e5e5;
background: #f0f0f0;
text-align: center;
line-height: 23px;
color: #444;
}
.count .add:hover, .count .reduce:hover {
color: #f50;
z-index: 3;
border-color: #f60;
cursor: pointer;
}
.count input {
width: 50px;
height: 15px;
line-height: 15px;
border: 1px solid #aaa;
color: #343434;
text-align: center;
padding: 4px 0;
background-color: #fff;
z-index: 2;
}
.subtotal {
width: 150px;
color: red;
font-weight: bold;
}
.operation {
width: 80px;
}
.operation span:hover, a:hover {
cursor: pointer;
color: red;
text-decoration: underline;
}
img {
width: 100px;
height: 80px;
/*border: 1px solid #ccc;*/
margin-right: 10px;
float: left;
}
.foot {
width: 935px;
margin-top: 10px;
color: #666;
height: 48px;
border: 1px solid #c8c8c8;
background-color: #eaeaea;
background-image:linear-gradient(RGB(241,241,241),RGB(226,226,226));
position: relative;
z-index: 8;
}
.foot div, .foot a {
line-height: 48px;
height: 48px;
}
.foot .select-all {
width: 100px;
height: 48px;
line-height: 48px;
padding-left: 5px;
color: #666;
}
.foot .closing {
border-left: 1px solid #c8c8c8;
width: 100px;
text-align: center;
color: #000;
font-weight: bold;
background: RGB(238,238,238);
cursor: pointer;
}
.foot .total{
margin: 0 20px;
cursor: pointer;
}
.foot #priceTotal, .foot #selectedTotal {
color: red;
font-family: "Microsoft Yahei";
font-weight: bold;
}
.foot .selected {
cursor: pointer;
}
.foot .selected .arrow {
position: relative;
top:-3px;
margin-left: 3px;
}
.foot .selected .down {
position: relative;
top:3px;
display: none;
}
.show .selected .down {
display: inline;
}
.show .selected .up {
display: none;
}
.foot .selected:hover .arrow {
color: red;
}
.foot .selected-view {
width: 935px;
border: 1px solid #c8c8c8;
position: absolute;
height: auto;
background: #ffffff;
z-index: 9;
bottom: 48px;
left: -1px;
display:none;
}
.show .selected-view {
display: block;
}
.foot .selected-view div{
height: auto;
}
.foot .selected-view .arrow {
font-size: 16px;
line-height: 100%;
color:#c8c8c8;
position: absolute;
right: 330px;
bottom: -9px;
}
.foot .selected-view .arrow span {
color: #ffffff;
position: absolute;
left: 0px;
bottom: 1px;
}
#selectedViewList {
padding: 20px;
margin-bottom: -20px;
}
#selectedViewList div{
display: inline-block;
position: relative;
width: 100px;
height: 80px;
border: 1px solid #ccc;
margin: 10px;
}
#selectedViewList div span {
display: none;
color: #ffffff;
font-size: 12px;
position: absolute;
top: 0px;
right: 0px;
width: 60px;
height: 18px;
line-height: 18px;
text-align: center;
background: RGBA(0,0,0,.5);
cursor: pointer;
}
#selectedViewList div:hover span {
display: block;
}
//js部分
/**
* Created by double
*/
window.onload = function (){
if(!document.getElementsByClassName)
document.getElementsByClassName = function(cls){
var ret = [];
var els = document.getElementsByTagName('*');
for(var i = 0, len = els.length; i < len; i++){
if(els[i].className === cls
||els[i].className.indexOf(cls) >=0
||els[i].className.indexOf(' ' + cls) >=0
||els[i].className.indexOf(' ' + cls + ' ') >=0){
ret.push(els[i]);
}
}
return ret;
}
var table = document.getElementById('cartTable'); // 购物车表格
var selectInputs = document.getElementsByClassName('check'); // 所有勾选框
var checkAllInputs = document.getElementsByClassName('check-all') // 全选框
var tr = table.children[1].rows; //行
var selectedTotal = document.getElementById('selectedTotal'); //已选商品数目容器
var priceTotal = document.getElementById('priceTotal'); //总计
var deleteAll = document.getElementById('deleteAll'); // 删除全部按钮
var selectedViewList = document.getElementById('selectedViewList'); //浮层已选商品列表容器
var selected = document.getElementById('selected'); //已选商品
var foot = document.getElementById('foot');
// 更新总数和总价格,已选浮层
function getTotal(){
var selected = 0,price = 0, html = '';
for(var i = 0; i < tr.length; i++){
if(tr[i].getElementsByTagName('input')[0].checked){
tr[i].className = 'on';
selected += parseInt(tr[i].getElementsByTagName('input')[1].value);
price += parseFloat(tr[i].getElementsByTagName('td')[4].innerHTML);
html += '<div><img src="'+tr[i].getElementsByTagName('img')[0].src+'"><span class="del" index="'+i+'">取消选择</span></div>';// 添加图片到弹出层已选商品列表容器
}
else{
tr[i].className = '';
}
}
selectedTotal.innerHTML = selected; // 已选数目
priceTotal.innerHTML = price.toFixed(2); // 总价
selectedViewList.innerHTML = html;
if (selected==0) {
foot.className = 'foot';
}
}
// 计算单行价格
function getSubtotal(tr) {
var cells = tr.cells;
var price = cells[2]; //单价
var subtotal = cells[4]; //小计td
var countInput = tr.getElementsByTagName('input')[1]; //数目input
var span = tr.getElementsByTagName('span')[1]; //-号
//写入HTML
subtotal.innerHTML = (parseInt(countInput.value) * parseFloat(price.innerHTML)).toFixed(2);
//如果数目只有一个,把-号去掉
if (countInput.value == 1) {
span.innerHTML = '';
}else{
span.innerHTML = '-';
}
}
// 点击选择框
for(var i = 0; i < selectInputs.length; i++ ){
selectInputs[i].onclick = function () {
if (this.className.indexOf('check-all') >= 0) { //如果是全选,则吧所有的选择框选中
for (var j = 0; j < selectInputs.length; j++) {
selectInputs[j].checked = this.checked;
}
}
if (!this.checked) { //只要有一个未勾选,则取消全选框的选中状态
for (var i = 0; i < checkAllInputs.length; i++) {
checkAllInputs[i].checked = false;
}
}
getTotal();//选完更新总计
}
}
// 显示已选商品弹层
selected.onclick = function () {
if (selectedTotal.innerHTML != 0) {
foot.className = (foot.className == 'foot' ? 'foot show' : 'foot');
}
}
//已选商品弹层中的取消选择按钮
selectedViewList.onclick = function (e) {
var e = e || window.event;
var el = e.srcElement;
if (el.className=='del') {
var input = tr[el.getAttribute('index')].getElementsByTagName('input')[0]
input.checked = false;
input.onclick();
}
}
//为每行元素添加事件
for(var i = 0; i < tr.length; i++){
//将点击事件绑定到tr元素
tr[i].onclick = function(e){
var e = e || window.event;
var el = e.target || e.srcElement; //通过事件对象的target属性获取触发元素
var cls = el.className; //触发元素的class
var countInout = this.getElementsByTagName('input')[1]; // 数目input
var value = parseInt(countInout.value); //数目
//通过判断触发元素的class确定用户点击了哪个元素
switch(cls){
case 'add'://点击了加号
countInout.value = value + 1;
getSubtotal(this);
break;
case 'reduce':
if (value > 1) {
countInout.value = value - 1;
getSubtotal(this);
}
break;
case 'delete': //点击了删除
var conf = confirm('确定删除此商品吗?');
if (conf) {
this.parentNode.removeChild(this);
}
break;
}
getTotal();
}
// 给数目输入框绑定keyup事件
tr[i].getElementsByTagName('input')[1].onkeyup = function () {
var val = parseInt(this.value);
if(isNaN(val) || val <=0){
val = 1;
}
if(this.value != val){
this.value = val;
}
getSubtotal(this.parentNode.praentNode);//更新小计
getTotal();//更新总数
}
// 点击全部删除
deleteAll.onclick = function () {
if(selectedTotal.innerHTML !=0) {
var conf = confirm('确定删除所选商品吗?');
if(conf){
for(var i = 0; i < tr.length; i++){
// 如果被选中,就删除相应的行
if(tr[i].getElementsByTagName('input')[0].checked){
tr[i].parentNode.removeChild(tr[i]);//删除节点
i--;//回退下标位置
}
}
}
}
else{
alert('请选择商品!');
}
getTotal(); //更新总数
}
// 默认全选
checkAllInputs[0].checked = true;
checkAllInputs[0].onclick();
}
}
js实现购物车(源码)的更多相关文章
- PureMVC(JS版)源码解析:总结
PureMVC源码中设计到的11个类已经全部解析完了,回首想想,花了一周的时间做的这点事情还是挺值得的,自己的文字组织表达能力和对pureMVC的理解也在写博客的过程中得到了些提升.我也是第一次写系列 ...
- PureMVC(JS版)源码解析
PureMVC(JS版)源码解析:总结 PureMVC源码中设计到的11个类已经全部解析完了,回首想想,花了一周的时间做的这点事情还是挺值得的,自己的文字组织表达能力和对pureMVC的理解也在写 ...
- Vue.js 2.0源码解析之前端渲染篇
一.前言 Vue.js框架是目前比较火的MVVM框架之一,简单易上手的学习曲线,友好的官方文档,配套的构建工具,让Vue.js在2016大放异彩,大有赶超React之势.前不久Vue.js 2.0正式 ...
- 从发布订阅模式入手读懂Node.js的EventEmitter源码
前面一篇文章setTimeout和setImmediate到底谁先执行,本文让你彻底理解Event Loop详细讲解了浏览器和Node.js的异步API及其底层原理Event Loop.本文会讲一下不 ...
- 基于wke封装的duilib的webkit浏览器控件,可以c++与js互交,源码及demo下载地址
转载请说明原出处,谢谢~~ 前些日子用wke内核封装了duilib的webkit浏览器控件,好多群里朋友私聊我希望可以我公布源码,今天把这个控件的源码和使用demo公布.其实这个控件封装起来没什么难度 ...
- PureMVC(JS版)源码解析(二):Notification类
上篇博客,我们已经就PureMVC的设计模式进行的分析,这篇博文主要分析Notification(消息)类的实现. 通过Notification的构造函数可以看出,PureMVC中的Notificat ...
- 深入理解 Node.js 中 EventEmitter源码分析(3.0.0版本)
events模块对外提供了一个 EventEmitter 对象,即:events.EventEmitter. EventEmitter 是NodeJS的核心模块events中的类,用于对NodeJS中 ...
- js调试系列: 源码定位与调试[基础篇]
js调试系列目录: - 如果看了1, 2两篇,你对控制台应该有一个初步了解了,今天我们来个简单的调试.昨天留的三个课后练习,差不多就是今天要讲的内容.我们先来处理第一个问题:1. 查看文章下方 推荐 ...
- html5shiv.js分析-读源码之javascript系列
xiaolingzi 发表于 2012-05-31 23:42:29 首先,我们先了解一下html5shiv.js是什么. html5shiv.js是一套实现让ie低版本等浏览器支持html5标签的解 ...
随机推荐
- js方式实现页面加遮罩效果
有时候在页面上执行查询的时候由于数据量很大,需要较长时间,所以就需要在等待结果期间不可以操作页面,那么可以使用如下代码给页面添加遮罩效果: $.messager.progress({ title: ' ...
- css 只改变父元素的透明度,不改变子元素透明度rgba+opacity
给元素加透明度时,通常写法为:opacity:0.5,filter:alpha(opacity=50); 我们通常也会遇到,在给父元素背景设置透明度时,子元素内容继承了父元素的透明度. 如何让子元素脱 ...
- sso单点登录研究
iframe跨域通信的通用解决方案http://www.alloyteam.com/2012/08/lightweight-solution-for-an-iframe-cross-domain-co ...
- centos5.5 快速安装mysql
安装MySQL. [root@sample ~]# yum -y install mysql-server ← 安装MySQL[root@sample ~]# yum -y install php-m ...
- Makefile 使用小结
Makefile的基本格式 #目标:依赖(条件) # 命令 #all: add.c sub.c dive.c mul.c main.c # gcc add.c sub.c div.c mul.c ma ...
- 简单集成高大上的ImagePicker无标题文章
简单集成高大上的ImagePicker无标题文章 现在是个项目就要有图片上传所以下面介绍一下简单高端的图片选择器 感谢读者的细心发现bug,最近bug已经修复(github更新)所以对文章部分内容 ...
- vue项目中,main.js,App.vue,index.html如何调用
1.main.js是我们的入口文件,主要作用是初始化vue实例,并引入所需要的插件 2.App.vue是我们的主组件,所有页面都是在App.vue下进行切换的.其实你也可以理解为所有的路由也是App. ...
- SAP ECC6安装系列四:安装过程详解
原作者博客 http://www.cnblogs.com/Michael_z/ ======================================== 续接上篇,我们终于按下了 “Next” ...
- 关于Context
Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄.很多方法需要通过 C ...
- Makefile 12——改善编译效率
从Makefile的角度看,一个可以改善编译效率的地方与其中的隐式规则有关.为了了解make的隐式规则,我们把之前的simple项目的Makefile做一点更改,删除生成.o文件的规则(与隐式规则相对 ...