之前在某官网课程上看有关jQuery和bootstrap的相关教程,有一节课是教我们如何制作价格菜单的按钮以及总价问题
选中按钮,按钮样式会发生变化,右上角价格会自动运算
6个菜单的html结构差不多,先贴出一个菜单的html,如下:
<div class="col-xs-12 col-sm-4"><div class="panel panel-warning"><div class="panel-body"><span class="title">Southen Style</span><span class="desc">Darius Rucker</span><span class="price">$20.90</span></div><div class="panel-footer text-center"><div class="btn-group" data-toggle="buttons"><label class="btn btn-primary"><span class="glyphicon glyphicon-unchecked"></span><input type="checkbox" id="chk6" name="products" checked="checked"><label for="chk6">Not Selected</label></label></div></div></div></div>
javascript代码如下:
let checkOptions={//创建一个对象,可以在此代码块统一修改信息id:"",checkedGlyph:"glyphicon-check",unCheckedGlyph:"glyphicon-unchecked",checkedBtnClass:"btn-success",unCheckedBtnClass:"btn-primary",checkedText:"Selected",unCheckedText:"Not Selected"};$(document).ready(function () {$("[type='checkbox']").on('change', function () {if ($(this).prop('checked')) {setChecked($(this));} else {unChecked($(this));}caculateTotal($(this));});let checked=$("input:checked");//console.log("checked=="+checked);for (let i=0;i<checked.length;i++) {// console.log("checked["+i+"]=="+checked[i]);//setChecked(checked[i]);setChecked(checked);caculateTotal(checked[i]);}});function setChecked(ct1) {ct1.prev().removeClass(checkOptions.unCheckedGlyph).addClass(checkOptions.checkedGlyph).next().next().text(checkOptions.checkedText).parent().removeClass(checkOptions.unCheckedBtnClass).addClass(checkOptions.checkedBtnClass).addClass('active');}function unChecked(ct1) {ct1.prev().removeClass(checkOptions.checkedGlyph).addClass(checkOptions.unCheckedGlyph).next().next().text(checkOptions.unCheckedText).parent().removeClass(checkOptions.checkedBtnClass).removeClass("active").addClass(checkOptions.unCheckedBtnClass);}function caculateTotal(ct1) {let tt=$("#total");let total = tt.text();total=stripCurrency(total);let price=$(ct1).closest(".panel").find(".price").text();price=stripCurrency(price);if($(ct1).prop("checked")){total=parseFloat(total)+parseFloat(price);}else{total=parseFloat(total)-parseFloat(price);}tt.text(formatcurrency(total));}function stripCurrency(value){value=value.replace(/(\s|,|\$)/g ,"");//正则表达式value=parseFloat(value);return value;}function formatcurrency(value,decimals,decpoint,separator,symbol){decimals=(typeof decimals=='undefined' ? 2:decimals);//小数decpoint=(typeof decpoint=='undefined'? '.':decpoint);separator=(typeof separator=='undefined' ? ',':separator);symbol=(typeof symbol=='undefined' ? '$':symbol);let parts=value.toFixed(decimals).toString().split(decpoint);//toFixed(把数字转换为字符串,结果的小数点后有指定位数的数字)parts[0]=parts[0].replace(/\B(?=(?:\d{3})+(?!\d))/g,separator);//正则表达式return (symbol+parts.join(decpoint)).toLocaleString();}
各位父老乡亲同志们!有没有发现代码好像有点奇怪???
let checked=$("input:checked");//console.log("checked=="+checked);for (let i=0;i<checked.length;i++) {// console.log("checked["+i+"]=="+checked[i]);// setChecked(checked[i]);setChecked(checked);//为什么这段的checked不用checked[i]替换?就像下一行代码一样???caculateTotal(checked[i]);}
于是乎自以为是的我就加上去了,没想到!错误!
什么鬼东西?为什么下一行的代码也是用了【i】啊,
然后我就log一下checked和checked【i】分别代表了什么
嗯.....原来是我函数里面的对象搞错了,checked是jquery对象(类数组对象),他所返回的每个子集都是DOM对象
而jquery对象与DOM对象之间的方法都是独立的,不能jquery使用DOM的方法,相反亦然。
所以你只要在jquery对象后面再加个[index]就能转变为DOM对象
即
var $jqName=$("#idName"); //jquery对象var name = $jqName[0]; //dom对象 console.log(name.checked); //检测这个checkbox是否给选中
所以此例中,checked[i]返回的都是input这个DOM对象,它当然没有prev()这个函数了,只有jquery对象才内置有函数的,你看,caculateTotal(checked[i])之所以可以是因为这个函数里面他又用$(ct1)转化成了jquery对象,而我这个setChecked函数他就直接用ct1.prev()来表示
因为本例中函数内的方法都是jquery内置的函数,所以暂时考虑把对象都转化为jquery对象,有两种修改方法,一种是直接把要改的函数里的对象都换成类数组对象(保留setChecked(checked)),另一种就是把要改的函数里的对象都换成DOM对象,但是外面要用$()包围住(保留setChecked(checked[i]) )
方法一:jquery对象转化为DOM对象,我要把 setChecked(checked) 替换成 setChecked(checked[i]) 那么后面此函数内的ct1要换成$(ct1)才行得通,即
function setChecked(ct1) {$(ct1).prev().removeClass(checkOptions.unCheckedGlyph).addClass(checkOptions.checkedGlyph).next().next().text(checkOptions.checkedText).parent().removeClass(checkOptions.unCheckedBtnClass).addClass(checkOptions.checkedBtnClass).addClass('active');}function unChecked(ct1) {$(ct1).prev().removeClass(checkOptions.checkedGlyph).addClass(checkOptions.unCheckedGlyph).next().next().text(checkOptions.unCheckedText).parent().removeClass(checkOptions.checkedBtnClass).removeClass("active").addClass(checkOptions.unCheckedBtnClass);}
其实单看下面的代码中的this你也可以知道$("[type='checkbox']")这个jquery对象它只会返回DOM对象input,如果要利用返回值引用jquery内置的函数,还是要在本身加上$()才行
$("[type='checkbox']").on('change', function () {if ($(this).prop('checked')) {setChecked($(this));} else {unChecked($(this));}caculateTotal($(this));});
方法二:DOM对象转化为jquery对象,把caculateTotal(checked[i])换成caculateTotal(checked),代码就变成这样的了,不需要for循环了
let checkOptions={//创建一个对象,可以在此代码块统一修改信息id:"",checkedGlyph:"glyphicon-check",unCheckedGlyph:"glyphicon-unchecked",checkedBtnClass:"btn-success",unCheckedBtnClass:"btn-primary",checkedText:"Selected",unCheckedText:"Not Selected"};$(document).ready(function () {$("[type='checkbox']").on('change', function () {if ($(this).prop('checked')) {setChecked($(this));} else {unChecked($(this));}caculateTotal($(this));});let checked=$("input:checked");console.log("checked=="+checked);setChecked(checked);//改了这里噢噢噢噢caculateTotal(checked);/*for (let i=0;i<checked.length;i++) {console.log("checked["+i+"]=="+checked[i]);// setChecked(checked[i]);setChecked(checked);caculateTotal(checked[i]);}*/});function setChecked(ct1) {ct1.prev().removeClass(checkOptions.unCheckedGlyph).addClass(checkOptions.checkedGlyph).next().next().text(checkOptions.checkedText).parent().removeClass(checkOptions.unCheckedBtnClass).addClass(checkOptions.checkedBtnClass).addClass('active');}function unChecked(ct1) {ct1.prev().removeClass(checkOptions.checkedGlyph).addClass(checkOptions.unCheckedGlyph).next().next().text(checkOptions.unCheckedText).parent().removeClass(checkOptions.checkedBtnClass).removeClass("active").addClass(checkOptions.unCheckedBtnClass);}function caculateTotal(ct1) {let tt=$("#total");let total = tt.text();total=stripCurrency(total);let price=ct1.closest(".panel").find(".price").text();//这里也改了哦哦哦price=stripCurrency(price);if(ct1.prop("checked")){//这里也是改了哈哈哈total=parseFloat(total)+parseFloat(price);}else{total=parseFloat(total)-parseFloat(price);}tt.text(formatcurrency(total));}function stripCurrency(value){value=value.replace(/(\s|,|\$)/g ,"");value=parseFloat(value);return value;}function formatcurrency(value,decimals,decpoint,separator,symbol){decimals=(typeof decimals=='undefined' ? 2:decimals);//小数decpoint=(typeof decpoint=='undefined'? '.':decpoint);separator=(typeof separator=='undefined' ? ',':separator);symbol=(typeof symbol=='undefined' ? '$':symbol);let parts=value.toFixed(decimals).toString().split(decpoint);//toFixed(把数字转换为字符串,结果的小数点后有指定位数的数字)parts[0]=parts[0].replace(/\B(?=(?:\d{3})+(?!\d))/g,separator);return (symbol+parts.join(decpoint)).toLocaleString();}
不过还是有疑问,jquery这个类数组对象就可以不用for循环然后他自己就会遍历全身然后把相应的对象放入到正确的函数当中了?,比如说这例中的$(input:checked)作为参数放入函数中,之后所有的input:checked对象都套上了该套上的函数....嗯,有待思考啊这个问题(有空解决!!)
这篇文章可能会有点思路不清,不懂的小伙伴可以留言哦,我能解决的话一定解决!
后面有时间我会相应的介绍一下的正则表达式的一些规则哦,列一个知识清单哈哈哈