在客户购买商品的时候,若这个商品存在多种”规格”(SKU),就需要客户手动选择自己想要的哪款。当时并不是每种我们都有库存, 所有就需要提供提供一个筛选功能,当客户选中一个条件的时候,需要设置其他条件中的一些值不可选。 这样就能保证不论客户怎么选择,到最后的选择都是有库存的”规格”(SKU)
开始之前先定义几种术语
属性集: 一个商品全部属性的集合
属性: 商品中的 尺码 颜色 就是两个属性
属性值: 尺码、颜色可有多个值 比如 衣服的尺码:S M XL 衣服的颜色:黑色 白色 蓝色 其中 XL 黑色就是属性值
SKU: Stock Keeping Uint(库存量单位) 由属性值组合而成(这些属性值属于不通的属性)如 一件衣服 (XL,白色) 它能确定商品的 唯一性 ,同一款式的衣服 可能有不通的颜色和大小 ,把颜色大小限制住,就能确定这件‘商品’了。
为了简化 我们虚拟出一个的商品, 下面是它的属性集和SKU:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var keys = { 'attr1':['10','11'], 'attr2':['20','21','22','23'], 'attr3':['30','31','32'], 'attr4':['40','41'] }; /*num是库存*/ var sku_list=[ {'attrs':'10|20|30|40','num':120}, {'attrs':'10|21|30|40','num':10}, {'attrs':'10|22|30|40','num':28}, {'attrs':'10|22|31|41','num':220}, {'attrs':'10|22|32|40','num':130}, {'attrs':'11|23|32|41','num':120}, ]; |
为选择之前是这种显示状态
1 2 3 4 5 |
attr1 10 11 attr2 20 21 22 23 attr3 30 31 32 attr4 40 41 |
attr1-attr4中有 2x4x3x2=42种组合,但是有库存的只有上面6种组合
我们要做的就是,在选择某一个属性的时候,把其他为选择的属性中的一些值设置为block(锁定状态) 因为它们和已选属性的组合是没有库存的(有库存的只有上面6种)
比如:
选择 10 和 21后, 有库存的SKU(组合) 只有
1 2 |
{'attrs':'10|21|30|40','num':10}, |
attr3中的31
32
以及attr4中的 41
就要设置为block
1 2 3 4 5 |
attr1 *10* 11 attr2 20 *21* 22 23 attr3 30 -31- -32- attr4 40 -41- |
总结1:在所有库存组合(sku_list)
中筛选出包含选中属性值(10,21)
的组合(10|21|30|40)
, 未选的属性(attr3、attr4)
中的所有属性值若不在这个组合
中就设置为block
还有一个问题,在已选属性(attr1,attr2)
中 , 我可以把21
换成20
或22
; 因为 10|21
10|22
也是一种可行组合(有库存),10|23
不可行,所以需要20
、22
也可选,23
设置为block
或者21
不变,修改attr1中的属性值 11|21
不可行,11
设置block。
1 2 3 4 5 |
attr1 *10* -11- attr2 20 *21* 22 -23- attr3 30 -31- -32- attr4 40 -41- |
总结2: 已选属性
(attr1,attr2) 中任意一个属性(attr1)的属性值(10,11), 若不能和其他属性
(attr2)中的选中属性值(21)
组合成有效(有库存)组合, 则设置该属性(11)
为block
好了,接下来就是根据上面总结的两条,来进行程序的实现 点击 商品SKU选择DEMO 可查看demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <title>商品SKU选择DEMO</title> </head> <body> <style type="text/css"> ul,li{ padding:0px; margin:0px;} #panel{ width:500px; margin:30px auto;} .goods_attr{ overflow:hidden;} .goods_attr .label {font: 12px/30px '宋体';color: #777;width: 50px;;padding-right: 10px;float: left; display:block;} .goods_attr ul {float:left;width:300px;} .goods_attr li{color:#333;overflow:hidden;position:relative;float:left;text-align:center; vertical-align:middle; border:1px solid #999;text-indent:0; cursor:pointer} .goods_attr li.b{border:1px dotted #CCC;color:#DDD; pointer:none;} .goods_attr li.b img {opacity:0.4;} .goods_attr li.sel{ border:1px solid #c80a28;color:#333;} .goods_attr li.text{margin:5px 10px 5px 0; height:23px;line-height:23px;text-indent:0;padding:0 23px;font-style:normal;} .goods_attr li.img{ margin-right:10px;width:35px;height:35px; line-height:35px;text-align:center;} </style> <div id="panel"> <div id="panel_sku_list"><pre></pre></div> <div id="panel_sel"> </div> </div> <script src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script> <script type="text/javascript"> /* 属性集 下面一共有4个属性 属性item1 下面有 2个属性值 分别是 10,11 (举个常见的例子 属性尺码 下有 S M L XL 4个属性值 ) */ var keys = { 'attr1':['10','11'], 'attr2':['20','21','22','23'], 'attr3':['30','31','32'], 'attr4':['40','41'] }; //SKU,Stock Keeping Uint(库存量单位) var sku_list=[ {'attrs':'10|20|30|40','num':120}, {'attrs':'10|21|30|40','num':10}, {'attrs':'10|22|30|40','num':28}, {'attrs':'10|22|31|41','num':220}, {'attrs':'10|22|32|40','num':130}, {'attrs':'11|23|32|41','num':120}, ]; /**init start */ //显示html结构 function show_attr_item(){ var html=''; for(k in keys){ html+='<div class="goods_attr" > <span class="label">'+k+'</span>'; html+='<ul>' for(k2 in keys[k]){ _attr_id=keys[k][k2]; html+='<li class="text" val="'+_attr_id+'" >'; html+='<span>'+_attr_id+'</span>'; html+='<s></s>'; html+='</li>' } html+='</ul>'; html+='</div>'; } $('#panel_sel').html(html); } //显示数据 function show_data(sku_list){ var str=""; for( k in sku_list){ str+=sku_list[k]['attrs']+"\t"+sku_list[k]['num']+"\n"; } $('#panel_sku_list pre').html(str); } show_data(sku_list); show_attr_item() /**init end */ //获取所有包含指定节点的路线 function filterProduct(ids){ var result=[]; $(sku_list).each(function(k,v){ _attr='|'+v['attrs']+'|'; _all_ids_in=true; for( k in ids){ if(_attr.indexOf('|'+ids[k]+'|')==-1){ _all_ids_in=false; break; } } if(_all_ids_in){ result.push(v); } }); return result; } //获取 经过已选节点 所有线路上的全部节点 // 根据已经选择得属性值,得到余下还能选择的属性值 function filterAttrs(ids){ var products=filterProduct(ids); //console.log(products); var result=[]; $(products).each(function(k,v){ result=result.concat(v['attrs'].split('|')); }); return result; } //已选择的节点数组 function _getSelAttrId(){ var list=[]; $('.goods_attr li.sel').each(function(){ list.push($(this).attr('val')); }); return list; } $('.goods_attr li').click(function(){ if($(this).hasClass('b')){ return ;//被锁定了 } if($(this).hasClass('sel')){ $(this).removeClass('sel'); }else{ $(this).siblings().removeClass('sel'); $(this).addClass('sel'); } var select_ids=_getSelAttrId(); //已经选择了的规格 var $_sel_goods_attr=$('li.sel').parents('.goods_attr'); // step 1 var all_ids=filterAttrs(select_ids); //获取未选择的 var $other_notsel_attr=$('.goods_attr').not($_sel_goods_attr); //设置为选择属性中的不可选节点 $other_notsel_attr.each(function(){ set_block($(this),all_ids); }); //step 2 //设置已选节点的同级节点是否可选 $_sel_goods_attr.each(function(){ update_2($(this)); }); }); function update_2($goods_attr){ // 若该属性值 $li 是未选中状态的话,设置同级的其他属性是否可选 var select_ids=_getSelAttrId(); var $li=$goods_attr.find('li.sel'); var select_ids2=del_array_val(select_ids,$li.attr('val')); var all_ids=filterAttrs(select_ids2); set_block($goods_attr,all_ids); } function set_block($goods_attr,all_ids){ //根据 $goods_attr下的所有节点是否在可选节点中(all_ids) 来设置可选状态 $goods_attr.find('li').each(function(k2,li2){ if($.inArray($(li2).attr('val'),all_ids)==-1){ $(li2).addClass('b'); }else{ $(li2).removeClass('b'); } }); } function del_array_val(arr,val){ //去除 数组 arr中的 val ,返回一个新数组 var a=[]; for(k in arr){ if(arr[k]!=val){ a.push(arr[k]); } } return a; } </script> </body> </html> |