标签:
可能题目的表述不是特别清晰,具体有一下截图看这会比较明显
页面上的功能描述
1. 当页面加载完成后,需要根据不同规格的商品刷新出对应规格商品的价格,
2.重置默认数量,这个功能在input标签中设置默认的value值即可,或者添加一个js函数,重置对应class集合中的值,这个不多说,比较简单,
3.点击添加购物车,需要把例如上图中的不同规格中的商品能全部添加到购物车
解题思路,
要求1,这个任务比较简单,由于这种方式,后台里的商品规格选项必须用单选按钮来做,否则页面效果不容易实现
具体要实现什么样式自己来定义,我的代码如下
1 <style> 2 .text-align{ text-align: center;} 3 #table_title li div{border: 1px solid red; font-size: 18px; font-weight: bold;} 4 </style> 5 <!--备注,由于需求限制这里只对单选的单选按钮做出控制--> 6 <!--更改的购买流程开始--> 7 <div> 8 <!-- {* 开始循环所有可选属性 *} --> 9 <!-- {foreach from=$specification item=spec key=spec_key} --> 10 11 <!--不用了屏蔽掉--> 12 <div class="te" style="disply:none;">{$spec.name}</div> 13 <!--不用了屏蔽掉--> 14 15 <ul id="table_title" style="width:100%;"> 16 <li> 17 <div class="f_l text-align" style="width: 50%;">Description</div> 18 <div class="f_l text-align" style="width: 12%;">TF Model</div> 19 <div class="f_l text-align" style="width: 12%;">Availability</div> 20 <div class="f_l text-align" style="width: 12%;">Price</div> 21 <div class="f_l text-align" style="width: 12%;">Quantity</div> 22 <div class="clear"></div> 23 </li> 24 </ul> 25 26 <!-- {* 判断属性是复选还是单选 *} --> 27 <!-- {if $spec.attr_type eq 1} --> <!--$spec.attr_type eq 1 是单选--> 28 <!-- {if $cfg.goodsattr_style eq 1} --> <!--单选按钮--> 29 30 <ul style="width:100%;"> 31 <!--{foreach from=$spec.values item=value key=key} --> 32 <li class="noprivate" style="border:0px;"> 33 <div class="f_l" style="width: 50%;"> 34 {$value.label} 35 <input style="display:none" class="spec_value" id="spec_value_{$value.id}" type="radio" name="spec_{$spec_key}" value="{$value.id}" {if $key eq 0}checked{/if} /> 36 </div> 37 <div class="f_l text-align" style="width: 12%;">1212</div> 38 <div class="f_l text-align" style="width: 12%;">Availability</div> 39 <div class="f_l text-align" style="width: 12%;"> 40 <font id="price_{$value.id}">{$goods.shop_price_formated}</font> 41 </div> 42 <div class="f_l text-align" style="width: 12%;"> 43 <font id="plus"> 44 <var onclick="goods_cut(this);" class="imgl"><img src="images/classjj.gif"></var> 45 <input name="number" type="text" id="number" class="inum" value="1" size="4" onblur="changePrice();get_shipping_list(forms[‘ECS_FORMBUY‘],{$goods.goods_id});"/> 46 <var onclick="goods_add(this);" class="imgr"><img src="images/classj.gif"></var> 47 </font> 48 </div> 49 <div class="clear"></div> 50 <input type="hidden" class="hidNum" name="hidNum" value="1"> 51 </li> 52 <!-- {/foreach} --> 53 </ul> 54 <input type="hidden" name="spec_list" value="{$key}" /> 55 <!-- {else} --><!--下拉菜单--> 56 <select name="spec_{$spec_key}" onchange="changePrice()"> 57 <!-- {foreach from=$spec.values item=value key=key} --> 58 <option label="{$value.label}" value="{$value.id}">{$value.label} {if $value.price gt 0}{$lang.plus}{elseif $value.price lt 0}{$lang.minus}{/if}{if $value.price neq 0}{$value.format_price}{/if}</option> 59 <!-- {/foreach} --> 60 </select> 61 <input type="hidden" name="spec_list" value="{$key}" /> 62 <!-- {/if} --> 63 <!-- {else} --> <!--多选--> 64 <!-- {foreach from=$spec.values item=value key=key} --> 65 <label for="spec_value_{$value.id}"> 66 <input type="checkbox" name="spec_{$spec_key}" value="{$value.id}" id="spec_value_{$value.id}" onclick="changePrice()" /> 67 {$value.label} [{if $value.price gt 0}{$lang.plus}{elseif $value.price lt 0}{$lang.minus}{/if} {$value.format_price|abs}] </label><br /> 68 <!-- {/foreach} --> 69 <input type="hidden" name="spec_list" value="{$key}" /> 70 <!-- {/if} --> 71 <!-- {/foreach} --> 72 <!-- {* 结束循环可选属性 *} --> 73 </div> 74 75 <!--更改的购买流程结束--> 76 <div class="blank"></div>
由于空间编辑器可能识别代码不是很好,建议复制出去看
这样上面的样式就出来了
这里去观察原版的ecshop中,对于价格的刷新是利用了一个changePrice2函数来做ajax,所以这里我们根据已有的结构
<!--{foreach from=$spec.values item=value key=key} --> <li class="noprivate" style="border:0px;"> <div class="f_l" style="width: 50%;"> {$value.label}<input style="display:none" class="spec_value" id="spec_value_{$value.id}" type="radio" name="spec_{$spec_key}" value="{$value.id}" {if $key eq 0}checked{/if} /> </div> <div class="f_l text-align" style="width: 12%;">1212</div> <div class="f_l text-align" style="width: 12%;">Availability</div> <div class="f_l text-align" style="width: 12%;"> <font id="price_{$value.id}">{$goods.shop_price_formated}</font> </div> <div class="f_l text-align" style="width: 12%;"> <font id="plus"> <var onclick="goods_cut(this);" class="imgl"><img src="images/classjj.gif"></var> <input name="number" type="text" id="number" class="inum" value="1" size="4" onblur="changePrice();get_shipping_list(forms[‘ECS_FORMBUY‘],{$goods.goods_id});"/> <var onclick="goods_add(this);" class="imgr"><img src="images/classj.gif"></var> </font> </div> <div class="clear"></div> <input type="hidden" class="hidNum" name="hidNum" value="1"> </li> <!-- {/foreach} --> <!--{foreach from=$spec.values item=value key=key} --> <li class="noprivate" style="border:0px;"> <div class="f_l" style="width: 50%;"> {$value.label}<input style="display:none" class="spec_value" id="spec_value_{$value.id}" type="radio" name="spec_{$spec_key}" value="{$value.id}" {if $key eq 0}checked{/if} /> </div> <div class="f_l text-align" style="width: 12%;">1212</div> <div class="f_l text-align" style="width: 12%;">Availability</div> <div class="f_l text-align" style="width: 12%;"> <font id="price_{$value.id}">{$goods.shop_price_formated}</font> </div> <div class="f_l text-align" style="width: 12%;"> <font id="plus"> <var onclick="goods_cut(this);" class="imgl"><img src="images/classjj.gif"></var> <input name="number" type="text" id="number" class="inum" value="1" size="4" onblur="changePrice();get_shipping_list(forms[‘ECS_FORMBUY‘],{$goods.goods_id});"/> <var onclick="goods_add(this);" class="imgr"><img src="images/classj.gif"></var> </font> </div> <div class="clear"></div> <input type="hidden" class="hidNum" name="hidNum" value="1"> </li> <!-- {/foreach} -->
这里循环的是li
添加几个函数
function noprivate(good_id){ var noprivate = document.getElementsByClassName("noprivate"); //alert(noprivate.length); for(i = 0; i < noprivate.length; i++){ changePrice2(noprivate[i]); } } /* * 专门用于处理页面初始化完成后,对于属性列表中的价格处理 * 仿照上面的changePrice函数来写 */ function changePrice2(divElement){ var attr_arr = divElement.getElementsByClassName(‘spec_value‘); var inum_arr = divElement.getElementsByClassName(‘hidNum‘); var attr = attr_arr[0].value; var inum = inum_arr[0].value; Ajax.call(‘goods.php‘, ‘act=price&id=‘ + {$goods_id} + ‘&attr=‘ + attr + ‘&number=‘ + inum, changePriceResponse2, ‘GET‘, ‘JSON‘); } function changePriceResponse2(res){ if (res.err_msg.length > 0) { alert(res.err_msg); } else { // document.forms[‘ECS_FORMBUY‘].elements[‘number‘].value = res.qty; // // if (document.getElementById(‘ECS_GOODS_AMOUNT‘)) // document.getElementById(‘ECS_GOODS_AMOUNT‘).innerHTML = res.result; document.getElementById(‘price_‘ + res.attr).innerHTML = res.result; } }
noprivate 的参数根据页面变量来var goods_id = {$goods_id};也就是商品的id
这样做ajax循环,就可以刷新出每种规格的商品的价格了
还有一个就是加减商品数量,这里比较简单,稍微改造一下原函数就可以了
function goods_cut(obj){ var inum_arr = obj.parentNode.getElementsByClassName(‘inum‘); var inum = inum_arr[0]; var new_num=inum.value; if(isNaN(new_num)){alert(‘请输入数字‘);return false} var Num = parseInt(new_num); if(Num>0)Num=Num-1; inum.value=Num; } function goods_add(obj){ var inum_arr = obj.parentNode.getElementsByClassName(‘inum‘); var inum = inum_arr[0]; var new_num=inum.value; var new_num=inum.value; if(isNaN(new_num)){alert(‘请输入数字‘);return false} var Num = parseInt(new_num); Num=Num+1; inum.value=Num; }
下一步就是要根据不同规格商品的不同购买数量来提交到购物车,查看原函数可知,原本提交到购物撤是要在页面中查找商品的属性,然后来提交,这里只做了一个属性,所以会比较简单,如果是多个属性,看看原函数怎么弄的就行
当要提交的时候,根据用户需求,可能不是所有规格都会有一个数量》0 所以这里只要提交商品数量大于0的那些行即可
所以把提交到购物车按钮点击事件的函数换一下
对应的函数如下
function check_car(good_id){ //获得被循环的li元素的集合 var noprivate = document.getElementsByClassName("noprivate"); var z = 0; var rei = new Array(); //循环这个集合 for(i = 0; i < noprivate.length; i++){ var inum_arr = noprivate[i].getElementsByClassName(‘inum‘); //得到某一行的选定的数量 var inum = inum_arr[0].value; //如果数量大于零,那么就将这个行的行号存入数组中,用z变量来记录总共需要提交的行数 if(inum > 0){ rei[z] = i; z++; } } //alert(rei); //这里来提交到购物车用上面的z来控制循环次数 for(y = 0; y < z; y++){ //rei[y] 里面存的是一个行号,这一行一定是购物数量大于0的, //noprivate[x]变量就是集合中的具体某一个,不多废话了 var x = rei[y]; //如果条件成立,说明这是最后一次提交到购物车的操作,就传递给addToCart2一个(1) if((y+1) == z){ addToCart2(1, noprivate[x], good_id); } else{ addToCart2(0, noprivate[x], good_id); } } }
再来看addToCart2这个函数,也是要稍微改造一下的
/* * * 使用与本站的添加商品到购物车 */ function addToCart2(check_good, divElement, goodsId, parentId) { var attr_arr = divElement.getElementsByClassName(‘spec_value‘); var inum_arr = divElement.getElementsByClassName(‘inum‘); var attr = attr_arr[0].value; var inum = inum_arr[0].value; var goods = new Object(); var spec_arr = new Array(); //var fittings_arr = new Array();//这个变量好像原版里也没有用到。 var number = 0; //var formBuy = document.forms[‘ECS_FORMBUY‘]; var quick = 0; //这里的处理逻辑需要改变,如果某一个属性的购买数量大于0,那么就做ajax提交,否则就不提交到购物车,所以goods.quick 可以直接设置为1, if(parseInt(inum) > 0){ number = parseInt(inum); spec_arr = attr; quick = 1; goods.quick = quick; goods.spec = spec_arr; goods.goods_id = goodsId; goods.number = number; goods.parent = (typeof(parentId) == "undefined") ? 0 : parseInt(parentId); if(check_good == 1){ Ajax.call(‘flow.php?step=add_to_cart‘, ‘goods=‘ + goods.toJSONString(), addToCartResponse, ‘POST‘, ‘JSON‘); } else if(check_good == 0){ Ajax.call(‘flow.php?step=add_to_cart‘, ‘goods=‘ + goods.toJSONString(), function(res){return 2;}, ‘POST‘, ‘JSON‘); } } }
把这个函数对比一下原函数找一下区别把,就是查找属性的时候不太一样,再有就是最后的ajax提交,的返回不同,如果是最后一次才用addToCartResponse作为回调函数,其他情况用一个匿名函数function(res){return 2;},这里我返回2,其实无所谓,就是不写都没事,主要是让客户端程序不要有操作就可以了,
再来看看回调函数
/* * * 处理添加商品到购物车的反馈信息 */ function addToCartResponse(result) { if (result.error > 0) { // 如果需要缺货登记,跳转 if (result.error == 2) { if (confirm(result.message)) { location.href = ‘user.php?act=add_booking&id=‘ + result.goods_id + ‘&spec=‘ + result.product_spec; } } // 没选规格,弹出属性选择框 else if (result.error == 6) { openSpeDiv(result.message, result.goods_id, result.parent); } else { alert(result.message); } } else { //这里会更新屏幕上面的购物车数据 var cartInfo = document.getElementById(‘ECS_CARTINFO‘); var cart_url = ‘flow.php?step=cart‘; //这里我屏蔽了,再下面会用到,其中result.content; 中的content元素在php文件中 //是这么定义的$result[‘content‘] = insert_cart_info();至于insert_cart_info函数的作用自己看咯 // if (cartInfo) // { // cartInfo.innerHTML = result.content; // } if (result.one_step_buy == ‘1‘) { location.href = cart_url; } else { switch(result.confirm_type) { case ‘1‘ : //如果成功了就会进入到这里原函数中只是调用了opencartDiv(,,,,....)这个函数, //为什么用下面的ajax下面会解释 Ajax.call( ‘flow.php?step=re_select_cart‘, ‘goods_id=‘ + result.goods_id, function(result){ if (cartInfo) { cartInfo.innerHTML = result.content; } opencartDiv(result.shop_price,result.goods_name,result.goods_thumb,result.goods_brief,result.goods_id,result.goods_price,result.goods_number); }, ‘POST‘, ‘JSON‘); //opencartDiv(result.shop_price,result.goods_name,result.goods_thumb,result.goods_brief,result.goods_id,result.goods_price,result.goods_number); break; case ‘2‘ : if (!confirm(result.message)) location.href = cart_url; break; case ‘3‘ : location.href = cart_url; break; default : break; } } } }
if(check_good == 1){ Ajax.call(‘flow.php?step=add_to_cart‘, ‘goods=‘ + goods.toJSONString(), addToCartResponse, ‘POST‘, ‘JSON‘); } else if(check_good == 0){ Ajax.call(‘flow.php?step=add_to_cart‘, ‘goods=‘ + goods.toJSONString(), function(res){return 2;}, ‘POST‘, ‘JSON‘); }
这里按照道理来说是最后一个属性提交后才会调用ajax,但是在实际中可能存在一个线程问题,就是前面的ajax还没有执行完成,后面的ajax请求已经来了,所以前面的可能被服务器挂起,这样当最后调用回调函数的时候,调用的数据就不是应该有的最后一次的执行结果,
又由于js本身没有一个合适的休眠函数,好像就算是休眠也不见得很好用,所以这里在回调函数中,判断执行成功后重新发起一次ajax请求,重新获得页面上想要的数据所以
case ‘1‘ :
Ajax.call(
‘flow.php?step=re_select_cart‘,
‘goods_id=‘ + result.goods_id, //要记得传递商品的id,这个id是从当前的回调数据中取得
function(result){
if (cartInfo)
{
cartInfo.innerHTML = result.content;
}
opencartDiv(result.shop_price,result.goods_name,result.goods_thumb,result.goods_brief,result.goods_id,result.goods_price,result.goods_number);
},
‘POST‘,
‘JSON‘);
//opencartDiv(result.shop_price,result.goods_name,result.goods_thumb,result.goods_brief,result.goods_id,result.goods_price,result.goods_number);
break;
case ‘1’ 内部的这个ajax请求就诞生了
对应的php代码 flow.php文件中找到$_REQUEST[‘step‘] == ‘add_to_cart‘
在这个代码段的下面添加一段查询代码
elseif($_REQUEST[‘step‘] == ‘re_select_cart‘)
{
//加载json类,ecshop里面都没有用php自带的json函数,可能是由于历史原因
include_once(‘includes/cls_json.php‘);
$goods_id = $_REQUEST[‘goods_id‘];//接收参数
$json = new JSON;//实例化json类
$rows = $GLOBALS[‘db‘]->getRow("select
goods_brief,shop_price,goods_name,goods_thumb,promote_price from
".$GLOBALS[‘ecs‘]->table(‘goods‘)." where goods_id=".$goods_id);
$result[‘shop_price‘] = price_format($rows[‘shop_price‘]);
$result[‘goods_name‘] = $rows[‘goods_name‘];
$result[‘goods_thumb‘] = $rows[‘goods_thumb‘];
$result[‘goods_brief‘] = $rows[‘goods_brief‘];
if ($rows[‘promote_price‘] > 0)
{
$result[‘shop_price‘] = price_format($rows[‘promote_price‘]);
}
else
{
$result[‘shop_price‘] = price_format($rows[‘shop_price‘]);
}
$result[‘goods_id‘] = $goods_id;
$sql = ‘SELECT SUM(goods_number) AS number, SUM(goods_price * goods_number) AS amount‘ .
‘ FROM ‘ . $GLOBALS[‘ecs‘]->table(‘cart‘) .
" WHERE session_id = ‘" . SESS_ID . "‘ AND rec_type = ‘" . CART_GENERAL_GOODS . "‘";
$rowss = $GLOBALS[‘db‘]->GetRow($sql);
$result[‘goods_price‘] = price_format($rowss[‘amount‘]);
$result[‘goods_number‘] = $rowss[‘number‘];
$result[‘confirm_type‘] = !empty($_CFG[‘cart_confirm‘]) ? $_CFG[‘cart_confirm‘] : 2;
//这里要重新执行一边$result[‘content‘] = insert_cart_info(); //这个数据是提供给给页面头部里的购物车数据
$result[‘content‘] = insert_cart_info();
die($json->encode($result));
}
到这这个功能算是完成,后面的就是一些页面上的美化工作,这个功能做了一天半才完全搞定,有点慢了
标签:
原文地址:http://www.cnblogs.com/azhw/p/4379044.html