我不知道这是否可能,但似乎必须有一种更简单的方法来做到这一点。我目前有一个T恤商店的购物车。每件T恤在购买前都有3个下拉框供选择:
风格:
尺寸:
颜色
并非每种尺寸和颜色组合都可以使用每种款式,但除了购物车在页面上的布局方式外,用户没有固定的方式首先选择款式,然后在不强制它的情况下选择款式,这将是一个障碍出售。
现在,当用户从任何下拉框中选择任何内容时,会向服务器发出ajax调用以计算其他下拉框应包含的内容,例如,如果用户首先选择Size(L),颜色可能会变为蓝色和黑色,因为白色和灰色不适用于大号,但比白色可能更差,但只有吉尔丹风格。
无论如何,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>
使用更智能的功能和/或哈希表是否有更有效的方法?这些可能不是唯一的三个选项,例如商店也有枕头,它们有款式,材质,线数和颜色。每组选项对于产品都是唯一的,但我知道在呈现页面之前它们是什么。
谢谢你。
答案 0 :(得分:1)
构造数据的自然方式是使用多维数组(每个属性的一个维度),其中值为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'));
DEMO:http://jsbin.com/uHAyirOX/1/edit
显然,可以从此方法推断出更通用的解决方案,在可用性对象中具有可变数量的参数和更多级别。不过,你还有一些工作要做。
更新:通用解决方案(以相同方式调用)
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;
}
答案 1 :(得分:1)
低技术方法,对于任何维护它的人来说都是显而易见的。
这可能是一个简单明了的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),但所有条目都是那里。这使得直接索引到这个对象。
答案 2 :(得分:0)
我想我会做一些事情:
var items = {
'item1':{
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
},
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
}
},
'item2':{
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
},
'level1' : {
'level2' : {},
'level2' : {'level3' :{}}
}
}
}
第一个选择器(例如Style)可以指示下一个(Color)的可用性,等等。
在任何级别,用户只能更改以下级别。