产品详情页配送送信息联动的实现逻辑
2016-01-13 08:38
429 查看
功能图如下:
需要实现选择运送国家时,相应的运送方式随着改变,同时运送价格也改变
后台返回的部分数据如下:
{ "jsonrpc":"2.0", "id":null, "result":{ "delivery_info":{ "1":[//对应的country id { // country支持的运送方式 "delivery_price":44.5, "delivery_name":"邮政挂号小包" } ], "235":[ { "delivery_price":18.1, "delivery_name":"邮政挂号小包" }, { "delivery_price":31, "delivery_name":"线上e邮宝" }, { "delivery_price":31, "delivery_name":"线下e 邮宝" } ], }, "countries":[ [ 235,//country id "美国" // country 名 ], [ 233, "英国" ], [ 3, "Afghanistan, Islamic State of" ], [ 6, "Albania" ], ] } }
国家下拉列表的实现:
将countries字段循环绑定到下拉列表上,xml对应的如下:<div t-attf-class="form-group col-lg-6 col-md-6 product_shipping" id="product_shipping" > <label class="control-label" for="shipping_country_id">运至</label> <button type="button" name="product_shipping_country_id" class="btn btn-default dropdown-toggle country_ul" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" value="United States" ng-click="search()"> <span class="cty-name" id="s_cty-name">United Status</span> <span class="caret" id="s_caret"></span> </button> <div class="btn_search btn-default dropdown-toggle search_country"> <input type="text" id="s_country" style="border:none;" placeholder="搜索(国家名)" ng-model="product_query.value"/> </div> //国家下拉列表 <ul class="dropdown-menu dp-menu-ul" aria-labelledby="dropdownMenu2" > <li ng-repeat="country in countries | filter:product_query.value"> <a href="javascript:;" value="{{country[0]}}" data-index= "{{$index}}" data-delivery-fee="{{delivery_info[country[0]]}}" ng-bind="country[1]"></a> </li> </ul> </div>效果图如下:
为了要显示所选择的国家对应的运送方式,可以从后台返回的数据delivery_info中找到当前国家的id对应的运送信息和价格。
$scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]];$scope.curSelectedIndexTop记录当前选中的是countries中的第几个国家,之所以需要该字段来记录,是因为在后面改变商品数量,重新获得运送信息和价格时,仍然需要保证是上次所选中的国家。
运送方式对应的xml文件内容如下:
<div class="product_shipping_fee col-lg-6 col-md-6 product_shipping" id="deli-mf"> <label class="control-label label-txt" for="">运送方式</label> <div class="shipping_fee_type"> <button type="button" class="btn btn-default dropdown-toggle transport_ul" id="dropdownMenu-ship" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" ng-click="delivultoggle()"> <span class="cty-name" id="s_deliv-name">The Poste</span> <span class="caret" id="s_deliv-caret"></span> </button> <ul class="dp-menu-ul dp-ship-ls" aria-labelledby="dropdownMenu-ship" ng-show="showdelivul"> <li ng-repeat="delivery in transportInfo"> <a href="javascript:;" ng-bind="delivery.delivery_name" data-price="{{delivery.delivery_price}}" data-index="{{$index}}"></a> </li> </ul> </div>
</div>
同样需要一个字段来记录当前选中的配送方式,从而获得对应的运送价格
$scope.shipMethodIndex $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price;
运送价格对应的xml文件内容如下:
<div class="product_shipping_fee col-lg-6 col-md-6 product_shipping pst-wp"> <lable class="control-label label-price">运送价格</lable> <div class="price"> <span>¥</span> <span ng-bind="ship_price"></span> <a href="#" data-toggle="tooltip" data-placement="top" title="含国内邮费+打包费共计3元"><i class="glyphicon glyphicon-question-sign"></i> </a> </div> </div>
那么当选择不同的国家时,对应的运送信息和价格如何随着改变呢?
我在每个国家对应的a标签中设置了data-index,记录它是第几个国家,同时,将该国家的运送信息绑定到data-delivery-fee上。这样当点击选择不同的国家时,改变transportInfo和curSelectedIndexTop。
<a href="javascript:;" value="{{country[0]}}" data-index= "{{$index}}" data-delivery-fee="{{delivery_info[country[0]]}}" ng-bind="country[1]"></a> scope.transportInfo = $(this).data('delivery-fee'); scope.curSelectedIndexTop = parseInt($(this).data('index'));//记录当前选中的是哪个国家此外,改变运送国家时,将当前的运输方式默认设置为默认第一个:
$('#s_deliv-name').text(scope.transportInfo[0].delivery_name); scope.ship_price = scope.transportInfo[0].delivery_price;当改变运输方式时,让运输价格随着改变,实现逻辑和改变运送国家让运输信息随着改变一样
<a href="javascript:;" ng-bind="delivery.delivery_name" data-price="{{delivery.delivery_price}}" data-index="{{$index}}"></a>
以上便是大致的联动逻辑。那么当改变商品数量时如何使得对应的价格随着更新呢?
触发商品数量改变的点击事件时,重新向后台发送请求取得数据。
$scope.delivery_info = data.delivery_info; $scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]]; if($scope.transportInfo.length) { $('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name); $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price; }
这里会利用记录的$scope.curSelectedIndexTop,$scope.shipMethodIndex仍然显示之前选中的国家。
因为在页面中有两个地方需要展示运输信息,所以逻辑相比于单个来说会麻烦一些,之前碰到的问题是,改变其中一个总是时不时的影响另一个,所以需要不同的变量来保存格式的国家和运送信息,
我这里的定义变量如下:
* $scope.delivery_info = data.delivery_info; 商品详情部分 所有国家的运送信息 * $scope.delivery_info_ship; 运送信息部分 所有国家的运送信息 * $scope.transportInfo; 商品详情部分 当前所选国家对应运送信息 * $scope.deliveryDetail; 运送信息部分 当前所选国家对应运送信息 * $scope.curSelectedIndexTop; 商品详情部分 记录当前选中的country * $scope.curSelectedIndex;运送信息部分 记录当前选中的country * $scope.shipMethodIndex; 商品详情部分 记录当前选中的运输方式此外,我利用了index来区分当前到底在改变商品详情部分还是运送信息部分的数量。
//数量改变时的请求处理完整的js代码如下:
//产品详情部分数量改变
if(parseInt($elem.data('index')) === 0) {
$scope.delivery_info = data.delivery_info; $scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]]; if($scope.transportInfo.length) { $('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name); $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price; }
}//配送信息部分数量改变
else if(parseInt($elem.data('index')) === 1) {
$scope.delivery_info_ship = data.delivery_info;
$scope.deliveryDetail = $scope.delivery_info_ship[$scope.countries[$scope.curSelectedIndex][0]];
}
//angular.module('product.description');
/**
* $scope.delivery_info = data.delivery_info; 商品详情部分 所有国家的运送信息 * $scope.delivery_info_ship; 运送信息部分 所有国家的运送信息 * $scope.transportInfo; 商品详情部分 当前所选国家对应运送信息 * $scope.deliveryDetail; 运送信息部分 当前所选国家对应运送信息 * $scope.curSelectedIndexTop; 商品详情部分 记录当前选中的country * $scope.curSelectedIndex;运送信息部分 记录当前选中的country * $scope.shipMethodIndex; 商品详情部分 记录当前选中的运输方式
页面初始化和每次商品数量改变时发送请求,得到新的数据,将每个国家对应的运输信息绑定到对应的a标签中,
改变国家时取出对应的信息,然后改变显示的运输方式和价格。
注意区分 [商品详情部分] 的运送信息 和 [运送信息部分] 的运送信息,改变其中一个的数量时不能影响另一个的运送信息
*/
var app= angular.module('product.description', ["ui.bootstrap", "ngSanitize","highcharts-ng"]);
app.controller('desController', function ($scope, $sce, $log, $http, $location) {
$scope.product_template_id = parseInt($('#product_comments_li').data('id'), 10);
$scope.product_description_images = [];
$scope.curSelectedIndexTop = 0;
$scope.curSelectedIndex = 0;
$scope.shipMethodIndex = 0;
$scope.init = true;
$scope.description_html ='';
$scope.extractCountry = function($elem){
var jsonp = {
jsonrpc: "2.0",
method: "call",
params: {
quantity: parseInt($elem.val())
}
};
if(jsonp.params.quantity <= 0) {
jsonp.params.quantity = 1;
$elem.val(1);
}
$http.post('/shop/product/country/'+ $scope.product_template_id ,jsonp)
.success(function(data){
data = data.result;
$scope.countries = data.countries;
//页面初始化
if($scope.init) {
//产品详情部分的delivery_info,包含所有国家的运送信息
$scope.delivery_info = data.delivery_info;
//配送信息部分的delivery_info,包含所有国家的运送信息
$scope.delivery_info_ship = data.delivery_info;
//当前所选国家对应的运输信息
$scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]];
$scope.deliveryDetail = $scope.delivery_info_ship[$scope.countries[$scope.curSelectedIndex][0]];
//初始化选中的国家,运输方式,价格
$('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name);
$('#s_cty-name_btm').text($scope.countries[$scope.curSelectedIndex][1]);
$('#s_cty-name').text($scope.countries[$scope.curSelectedIndexTop][1]);
$scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price;
$scope.init = false;
}else {
//数量改变时的请求处理
//产品详情部分数量改变
if(parseInt($elem.data('index')) === 0) {
$scope.delivery_info = data.delivery_info; $scope.transportInfo = $scope.delivery_info[$scope.countries[$scope.curSelectedIndexTop][0]]; if($scope.transportInfo.length) { $('#s_deliv-name').text($scope.transportInfo[$scope.shipMethodIndex].delivery_name); $scope.ship_price = $scope.transportInfo[$scope.shipMethodIndex].delivery_price; }
}//配送信息部分数量改变
else if(parseInt($elem.data('index')) === 1) {
$scope.delivery_info_ship = data.delivery_info;
$scope.deliveryDetail = $scope.delivery_info_ship[$scope.countries[$scope.curSelectedIndex][0]];
}
}
})
};
if($scope.product_template_id && $scope.product_template_id > 0) {
// $('.search_country').css('display','block');
// $('.dropdown-menu').css('display','block');
$('.dp-ship-ls').css('display','block');
$scope.extractCountry($('#product_quantity'));
}
$scope.extractDescription = function(){
var $description = $('#product_full_description'),
url;
if($description.data('add-need-desc')){
url = $description.data('url');
$http.post("/desc/", {
'url' : url
}).success(function (data) {
if(data.status == 200){
$description.html('<div class="description_table">'+data.table+'</div>');
$description.append(data.desc);
}
});
}
};
$scope.zip_dataPackage = function(){
var uuid=$('#epic-buy').data('uuid');
//console.log(uuid);
var form2 = document.createElement("form"),
input = document.createElement("input");
form2.id = "data_package_form";
form2.name = "data_package_form";
// 添加到 body 中
document.body.appendChild(form2);
// 创建一个输入
// 设置相应参数
input.type = "text";
input.name = "uuid";
input.value = uuid;
// 将该输入框插入到 form 中
form2.appendChild(input);
// form 的提交方式
form2.method = "GET";
// form 提交路径
form2.action = "/tornado/get/packet";
//event.preventDefault()
// 对该 form 执行提交
form2.submit();
// 删除该 form
document.body.removeChild(form2);
};
$scope.comments = [];
$scope.comments_count = 0;
$scope.currentPage = 2;
$scope.totalItems = 100;
$scope.itemsPerPage = 5;
$scope.showProductDetail=true;
$scope.showComments=false;
$scope.showShippingInfo=false;
$scope.showTrend=false;
$scope.text = "";
$scope.currentPage = 1;
$scope.items_per_page = 5;
$scope.extractDescription();
$scope.get_comments();
//$scope.zip_images();
$scope.toProductDetail = function() {
$scope.showProductDetail=true;
$scope.showComments=false;
$scope.showShippingInfo=false;
$scope.showTrend=false;
};
$scope.toComments = function() {
$scope.showProductDetail=false;
$scope.showComments=true;
$scope.showShippingInfo=false;
$scope.showTrend=false;
};
$scope.toShippingInfo = function() {
$('.shipping_info').css('display','block');
$scope.showProductDetail=false;
$scope.showComments=false;
$scope.showShippingInfo=true;
$scope.showTrend=false;
};
$scope.toTrend = function() {
$scope.showProductDetail=false;
$scope.showComments=false;
$scope.showShippingInfo=false;
$scope.showTrend=true;
};
$scope.get_trend = function () {
if(document.getElementById('product_trend_li'))
{
trend = JSON.parse(document.getElementById('product_trend_li').dataset['trend']);
var sales_trend = trend;
$scope.chartConfig.series[0].data = sales_trend.measures.sales_quantity;
$scope.chartConfig.xAxis[0].categories = sales_trend.dimension;
$scope.chartConfig.title.text = trend.name;
$scope.chartConfig.subtitle.text = "该产品过去三个月的销量趋势(wish平台目前只能抓取评价数目趋势)" ;
}
};
$scope.get_trend();
$scope.product_query = {
value : ''
};
$scope.showCtyMenu = false;
$scope.search = function(){
var state = $('.product_shipping .search_country').css('display');
if(state == "none")
{
$('.product_shipping .search_country').css('display', 'block');
$('.product_shipping .dropdown-menu').show();
}
else
{
$('.product_shipping .search_country').css('display', 'none');
$('.product_shipping .dropdown-menu').hide();
}
$scope.product_query.value = "";//每次点击下拉时重置query的值
};
$scope.visible = false;
$scope.showdelivul = false;
$scope.showtoggle = function() {
$scope.visible = !$scope.visible;
$scope.product_query.value = "";
};
$scope.delivultoggle = function() {
$scope.showdelivul = !$scope.showdelivul;
};
});
app.directive('wrapDirective',function() {
return {
restrict: 'AE',
scope: false,
link: function(scope,elements) {
$(elements[0]).on('click',function(ev) {
if(ev.toElement !=$('#dropdownMenu2')[0]&&ev.toElement !=$('#s_country')[0]
&&ev.toElement !=$('#s_cty-name')[0]&&ev.toElement !=$('#s_caret')[0]){
$('.product_shipping .search_country').css('display', 'none');
$('.product_shipping .dropdown-menu').hide();
scope.$apply();
}
if(ev.toElement !== $('#dropdownMenu3')[0] && ev.toElement !== $('#s_country_btm')[0]
&& ev.toElement !== $('#s_cty-name_btm')[0]&&ev.toElement !== $('#s_caret_btm')[0]){
scope.visible = false;
scope.$apply();
}
if(ev.toElement !== $('#dropdownMenu-ship')[0] && ev.toElement !== $('#s_deliv-name')[0]
&&ev.toElement !== $('#s_deliv-caret')[0]) {
scope.showdelivul = false;
scope.$apply();
}
})
//商品详情部分 监听商品数量变化
.on('change','#product_quantity', function() {
if(scope.product_template_id && scope.product_template_id > 0) {
scope.extractCountry($(this));
}
})
// 商品详情部分 监听改变商品数量的按钮点击事件
.on('click', 'span.change_product_number', function (ev) {
ev.preventDefault();
var $link = $(ev.currentTarget);
var $input = $link.parent().find("input");
var min = parseFloat($input.data("min") || 1);
var max = parseFloat($input.data("max") || Infinity);
var quantity = ($link.has(".fa-minus").length ? -1 : 1) + parseFloat($input.val(),10);
$input.val(quantity > min ? (quantity < max ? quantity : max) : min);
$('input[name="'+$input.attr("name")+'"]').val(quantity > min ? (quantity < max ? quantity : max) : min);
if(scope.product_template_id && scope.product_template_id > 0) {
scope.extractCountry($('#product_quantity'));
}
return false;
})
}
}
})
.directive('shippingCountry', function() {
return {
restrict: 'AE',
scope: false,
link: function(scope,elements) { //运送信息部分 国家选择事件
$(elements[0]).on('click','.dp-menu-wp li a',function() {
var ctyname = $.trim($(this).text());
scope.curSelectedIndex = parseInt($(this).data('index'));
$('#s_cty-name_btm').text(ctyname);
scope.visible = false;
scope.deliveryDetail = $(this).data('delivery-fee');
//检查数据有没有更新
scope.$apply();
})
}
}
})
.directive('numChange',function() {
return {
restrict: 'AE',
scope: false,
link: function(scope,elements) { //运送信息部分,商品数量改变事件
$(elements[0]).on('change', function() {
if(scope.product_template_id && scope.product_template_id > 0) {
scope.extractCountry($(this));
//若在这里执行更新,每次获得的是上一次请求的数据
//scope.deliveryDetail = scope.delivery_info[scope.countries[scope.curSelectedIndex][0]];
//scope.$apply();
}
})
}
}
})
.directive('prodetailDir',function() {
return {
restrict: 'AE',
scope: false,
link: function(scope,elements) { //商品详情部分 选择国家事件
$(elements[0]).on('click','.dropdown-menu li a', function() {
$('.dp-ship-ls').css('display','block');
scope.transportInfo = $(this).data('delivery-fee');
scope.curSelectedIndexTop = parseInt($(this).data('index'));
//改变运送国家时,将当前的运输方式设置为默认第一个
if(scope.transportInfo.length) {
$('#s_deliv-name').text(scope.transportInfo[0].delivery_name); scope.ship_price = scope.transportInfo[0].delivery_price;
} else {
$('#s_deliv-name').text('暂不支持运送');
$('.dp-ship-ls').css('display','none');
scope.ship_price = 0.00;
}
scope.shipMethodIndex = 0;
$('#dropdownMenu2').find('.cty-name').text($.trim($(this).text()));
if($(this).attr('delivery-fee')){
$('#dropdownMenu2').attr('delivery-fee', parseFloat($(this).attr('delivery-fee')));
} else {
$('#dropdownMenu2').attr('delivery-fee', 0);
}
$('#dropdownMenu2').val($.trim($(this).text())).change();
$('.product_shipping .search_country').css('display', 'none');
$('.product_shipping .dropdown-menu').hide();
if($(this).attr('delivery-fee')){
$('#dropdownMenu2').attr('delivery-fee', parseFloat($(this).attr('delivery-fee')));
} else {
$('#dropdownMenu2').attr('delivery-fee', 0);
}
$('#dropdownMenu2').val($.trim($(this).text())).change();
// $('.product_shipping .search_country').css('display', 'none');
// $('.product_shipping .dropdown-menu').hide();
// $scope.showCtyMenu = false;
scope.$apply();
})
//商品详情部分 选择运输方式事件
.on('click','.dp-ship-ls li a', function() {
scope.visible = false;
var shipname = $.trim($(this).text());
scope.shipMethodIndex = parseInt($(this).data('index'));
$('#s_deliv-name').text(shipname);
scope.ship_price = $(this).data('price');
})
}
}
});
相关文章推荐
- Javascript 中Ajax同步和异步的说明
- android 属性动画
- KVO通知中心
- linux 命令 —— netstat
- 一边是马云,一边是星云
- ubuntu下resolv.conf文件的自动覆盖问题
- C语言实现通用数据结构的高效设计
- angular + browserify + gulp + bower + less
- 常规功能和模块自定义系统 (cfcmms)—032开发日志(用GoJS来绘制模块关系图)
- 关于android的2.2与4.4的文件读取的一点发现
- 物联网技术趋势预测
- windows安装程序无法将windows配置为在此计算机的硬件上运行
- UDP发送和接收
- 两个移动web开发在线测试工具
- 嵌入式Linux学习小结
- zabbix监控打印机
- 数据库字段命名 --工作备忘2016/1/12
- iOS开发-模板方法模式
- C#打开文件对话框
- 内存管理细节1