用于跟踪购物车可用性的Javascript数组/对象/哈希表
Javascript array/object/hash table to track cart availability
我不知道这是否可能,但似乎必须有一种更简单的方法来做到这一点。我现在有一辆t恤店的购物车。每件t恤都有3个下拉框,可在购买前进行选择:
样式:
- 美国服装
- 吉尔丹
尺寸:
- S
- M
- L
- XL
颜色:
- 蓝色
- 黑色
- 白色
- 灰色
并不是每种款式都有各种尺寸和颜色的组合,但除了购物车在页面上的布局之外,用户没有固定的方式可以先选择款式,然后选择尺寸而不强制选择,这将成为销售的障碍。
现在,当用户从任何下拉框中选择任何内容时,都会对服务器进行ajax调用,以计算其他下拉框应包含的内容,例如,如果用户首先选择Size(L),则颜色可能会变为蓝色和黑色,因为白色和灰色在Large中不可用,但更糟糕的是,白色可能可用,但仅在Gildan样式中可用。
无论如何,ajax调用有延迟,在数据连接不稳定的移动设备上可能特别慢。有没有一种方法可以用Javascript来实现这一点。在呈现页面之前,我知道所有的组合,我可以设置一个数组,但由于有两个以上的下拉框而丢失,最终会出现这种丑陋的混乱,即使这样,我也不知道如何执行实际的功能,因为可能会选择多个框:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var styles = { aa: 'American Apparel', gi: 'Gildan' };
var sizes = { s: 'Small', m: 'Medium', l: 'Large' };
var colours = { blue: 'Blue', black: 'Black', white: 'White', grey: 'Grey' };
var availability = {
aa: { size: ['s', 'm', 'l'], colour: ['blue', 'black', 'white', 'grey'] },
gi: { size: ['s', 'm'], colour: ['blue', 'black', 'white', 'grey'] },
s: { style: ['aa', 'gi'], colour: ['blue', 'black', 'white'] },
m: { style: ['aa', 'gi'], colour: ['black', 'white', 'grey'] },
l: { style: ['aa'], colour: ['blue', 'black', 'white', 'grey'] },
blue: { style: ['aa', 'gi'], size: ['s', 'l'] },
black: { style: ['aa', 'gi'], size: ['s', 'm', 'l'] },
white: { style: ['aa', 'gi'], size: ['s', 'm', 'l'] },
grey: { style: ['aa', 'gi'], size: ['m', 'l'] }
};
$(function()
{
addOptions('style', styles);
addOptions('size', sizes);
addOptions('colour', colours);
});
function addOptions(name, data)
{
$('select[name="' + name + '"]').empty();
$.each(data, function(value, description)
{
$('select[name="' + name + '"]').append('<option value="' + value + '">' + description + '</option>');
});
}
function updateOptions(select)
{
// Work out what has changed, and update select boxes?
}
</script>
</head>
<body>
<select name="style" onchange="updateOptions(this);"></select>
<select name="size" onchange="updateOptions(this);"></select>
<select name="colour" onchange="updateOptions(this);"></select>
</body>
</html>
有没有更有效的方法可以使用更智能的函数和/或哈希表来实现这一点?这可能不是唯一的三种选择,例如,商店也有枕头,它们有款式、材质、线数和颜色。每一组选项对产品来说都是唯一的,但在呈现页面之前,我知道它们是什么。
非常感谢。
构建数据的自然方法是使用多维数组(每个属性一个维度),其中的值为true或false。我在建模时考虑到了这个想法,但使用了关联数组(也就是JavaScript中的对象)。
数据:
var availability = {
'American Apparel' : {
'S' : {
'black' : true,
'green' : true
},
'M' : {
'black' : true,
'white' : true
}
},
'Gildan' : {
'M' : {
'black' : true
},
'XL' : {
'black' : true,
'white' : true,
'green' : true
}
}
};
现在,您只需要一个函数,在选择某些选项时返回可能的选项。初稿如下,但我相信它可以大幅度改进。如果设置了属性,则将值传递给函数,否则传递undefined。该函数返回一个具有3个数组的对象,这些数组指示用户选择的有效选项。结尾的用法示例。。
function pushIfNotIn(arr, item) {
if (arr.indexOf(item) === -1) arr.push(item);
}
function getAvailability(styleValue, sizeValue, colorValue) {
var av = {
style : [],
size : [],
color : []
};
for (var style in availability) {
if (styleValue === undefined || styleValue === style) {
for (var size in availability[style]) {
if (sizeValue === undefined || sizeValue === size) {
for (var color in availability[style][size]) {
if (colorValue === undefined || colorValue === color) {
if (availability[style][size][color]) {
pushIfNotIn(av.style, style);
pushIfNotIn(av.size, size);
pushIfNotIn(av.color, color);
}
}
}
}
}
}
}
return av;
}
console.log(getAvailability(undefined, 'M', undefined));
console.log(getAvailability('American Apparel', 'S', undefined));
console.log(getAvailability(undefined, 'M', 'black'));
console.log(getAvailability(undefined, 'M', 'green'));
console.log(getAvailability(undefined, undefined, 'green'));
演示:http://jsbin.com/uHAyirOX/1/edit
显然,可以从这个方法中推断出一个更通用的解决方案,在可用性对象中有可变数量的参数和更多级别。尽管如此,你还是有工作要做。
UPDATE:通用解决方案(以相同方式调用)
function pushIfNotIn(arr, item) {
if (!arr) arr = [];
if (arr.indexOf(item) === -1) arr.push(item);
return arr;
}
function getAvailability() {
var result = [];
~function getAvailabilityRecursive (level, availability, values) {
if (!values.length) return true;
var isAvailable = false;
var val = values[0];
values = values.slice(1);
for (var key in availability) {
if ((val === undefined || val === key) &&
(getAvailabilityRecursive(level+1, availability[key], values))){
result[level] = pushIfNotIn(result[level], key);
isAvailable = true;
}
}
return isAvailable;
}(0, availability, Array.prototype.slice.call(arguments));
return result;
}
演示:http://jsbin.com/uHAyirOX/3/edit
低技术方法,其优点对任何维护它的人来说都是显而易见的。
这可能是一个Ajax响应,简单明了:
var products = [
{ id: 101, style: 'aa', size: 's', colour: 'grey' },
{ id: 102, style: 'aa', size: 'm', colour: 'grey' },
{ id: 103, style: 'aa', size: 'l', colour: 'black' },
/* ... 500 more ... */
{ id: 604, style: 'gi', size: 'l', colour: 'blue' }
];
现在只需过滤客户端的数组暴力:
function Drilldown(items, properties) {
var self = this,
numItems = items.length,
numProps = properties.length;
self.setFilter = function (filterDef) {
var i, item, p, prop, pass, filter = filterDef || {};
self.items = [];
self.properties = {};
for (i = 0; i < numItems; i++) {
item = items[i];
pass = true;
for (p = 0; pass && p < numProps; p++) {
prop = properties[p];
pass = pass && (!filter[prop] || filter[prop] === item[prop]);
if (!self.properties.hasOwnProperty(prop)) {
self.properties[prop] = {};
}
if (!self.properties[prop].hasOwnProperty(item[prop])) {
self.properties[prop][item[prop]] = [];
}
}
if (pass) {
self.items.push(item);
for (p = 0; p < numProps; p++) {
prop = properties[p];
self.properties[prop][item[prop]].push(item);
}
}
}
};
self.setFilter();
}
用法:
var dd = new Drilldown(products, ['style', 'size', 'colour']);
dd.setFilter({size: 'l'});
/*
dd.items => [ array of size L products ]
dd.properties => {
style: {
aa: [ array of size L products in style 'aa' (1) ],
gi: [ array of size L products in style 'gi' (1) ]
},
size: {
s: [ array of size L products in size S (0) ],
m: [ array of size L products in size M (0) ],
l: [ array of size L products in size L (2) ]
},
colour: {
grey: [ array of size L products in Grey (0) ],
black: [ array of size L products in Black (1) ],
blue: [ array of size L products in Blue (1) ]
}
*/
dd.properties
包含所有属性组合。当然,有些条目将为空(数组长度为0),但所有条目都将存在。这使得对该对象进行索引变得简单。
我想我会做一些事情:
var items = {
'item1':{
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
},
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
}
},
'item2':{
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
},
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
}
}
}
第一个选择器(例如样式)可以指定下一个(颜色)的可用性,依此类推
在任何级别中,用户只能更改以下级别。
- 将数组对象传递到struts2中的操作类
- 如何使用jquery返回php-json数组对象
- 从其名称获取javascript数组对象
- 值未与数组对象绑定
- 如何按数组/对象值的倍数过滤对象数组
- 在表中显示数组对象
- 在数组对象中分组
- 将第二个或多个数组推送到数组对象 AngularJS 中
- 重新排列 JavaScript 数组/对象
- 键上的javascript数组对象过滤器
- handontable:在不更改数据数组/对象的情况下隐藏某些列
- 用于跟踪购物车可用性的Javascript数组/对象/哈希表
- 重建有角度的java脚本数组对象
- 对JSON数组对象进行排序
- 连接与数组对象相关的文本:方式和位置
- 哪些浏览器和版本支持将常见的类数组对象直接传递到fn.apply()
- 如何使用Handlebars循环数组对象和模板
- 是否可以引用JS数组/对象中的另一个元素
- Javascript中的名称索引-数组/对象
- 数组长度不等于数组对象