我正在使用twitter typeahead
来显示适用于我的类别建议。
问题在于子类别的显示。如果是category has sub-categories
then expand/collapse icon
与建议一起显示,如果用户选择其中一个子类别必须在其下方显示,我已经成功显示部分但是cannot update the dataset
的类型,以便当用户选择时一个子类别应该在输入中显示。 Please use keyboard on Jsfiddle because i have tried only in keypress
。以下是我的json数组
JSFIDDLE here
[{
"id": "38",
"value": "Entertaintment",
"parent_id": "27",
"children": "1",
"childCategories": [{
"id": "28",
"value": "Movies",
"parent_id": "38"
}, {
"id": "29",
"value": "Sports",
"parent_id": "38"
}]
}, {
"id": "40",
"value": "eeen",
"parent_id": "27",
"children": "1",
"childCategories": [{
"id": "41",
"value": "een child 1",
"parent_id": "40"
}]
}, {
"id": "41",
"value": "een child 1",
"parent_id": "40",
"children": "0",
"childCategories": false
}]
我尝试了以下内容:
_onEnterKeyed: function onEnterKeyed(type, $e) {
var cursorDatum, topSuggestionDatum;
cursorDatum = this.dropdown.getDatumForCursor();
topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();
//My custom condition, if category has children show sub-categories below
if (cursorDatum.raw && cursorDatum.raw.children == "1") {
//below line is my failed try
//this.dropdown.updateChild('',cursorDatum.raw.childCategories,false);
var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;
var childHTML='';
$('.ttchild').remove();
//adding the sub-categories to dropdown
$.each(cursorDatum.raw.childCategories,function(i,v){
childHTML += '<div class="tt-suggestion ttchild"><div class="suggestions"><span>'+this.value+'</span></div></div>';
});
$(childHTML).insertAfter('.tt-cursor');
return;
}
if (cursorDatum) {
this._select(cursorDatum);
$e.preventDefault();
}
else if (this.autoselect && topSuggestionDatum) {
this._select(topSuggestionDatum);
$e.preventDefault();
}
},
//This is my custom function trying to update the dataset, but i know its totally wrong.
updateChild: function updateChild(query,childs) {
var that = this;
this.query = query;
this.canceled = false;
this.source(query, render);
function render(childs) {
if (!that.canceled && query === that.query) {
that._render(query, childs);
}
}
},
JSFIDDLE here
例如:娱乐类别有子类别电影和体育。
希望任何人都能帮助我......
答案 0 :(得分:2)
编辑v.2
我再次refactored,现在它完美无缺。
我删除了之前的修改并重构了onEnterKeyed
函数,如下所示
var dataSet = this.dropdown.datasets[0];
// childHTML is replaced by childDom
// var childHTML='';
var childDom = $('<div></div>');
$('.ttchild').remove();
$.each(cursorDatum.raw.childCategories,function(i,v){
var div = $('<div class="tt-suggestion ttchild"></div>');
div.append('<div class="suggestions"><span>'+this.value+'</span></div>');
var suggestion = v;
// TODO console log this is duplicated from dataset
var datasetKey = "ttDataset", valueKey = "ttValue", datumKey = "ttDatum";
// this is what makes it show in the input box
// set these data for the child element.
div.data(datasetKey, dataSet.name);
div.data(valueKey, dataSet.displayFn(suggestion));
div.data(datumKey, suggestion);
childDom.append(div);
});
// childHtml is replaced by childDom
$('.tt-cursor').append(childDom.children());
已弃用编辑v.1
我refactored我的解决方案,现在按预期工作。
我删除了之前的修改,并在getSuggestionNode
方法中添加了这一行。
for (var key in suggestion.childCategories) {
var value = suggestion.childCategories[key];
$el.append(getSuggestionNode(value));
}
在以下不推荐使用
我solved你的问题,虽然你需要改进。
// I added this line
// add the child nodes to the suggestions.
suggestions = suggestions.reduce(function(res, num) { res.push(num); for (var i=0;i<num.children;i++) res.push(num.childCategories[i]); return res; }, [])
// nodes are calculated based on suggestions
// but child nodes are not added to suggestions so their data is not set (see below line)
nodes = _.map(suggestions, getSuggestionNode);
// inside the suggestions.map function
// here .data sets the necessary values required to render the input on cursor change.
// since child nodes are not mapped they are ignored.
$el = $(html.suggestion).append(that.templates.suggestion(suggestion))
.data(datasetKey, that.name)
.data(valueKey, that.displayFn(suggestion))
.data(datumKey, suggestion);
所以你不需要自定义updateChild
功能,虽然我不知道你如何实现下拉菜单,但这个解决方案会将孩子添加到下拉列表并立即显示,按Enter键进入父节点。你应该自己配置它。
答案 1 :(得分:1)
您可以将每个childCategories
组视为自己的数据源。然后使用Multiple Datasets范例自动为子项应用标题。
$.typeahead(options, [*datasets])
的第二个参数采用一组数据集。我们可以将每组子元素转换为它自己的数据集,如下所示:
var dataSources = [];
$.each(movies, function(index, movieItem) {
if (movieItem.childCategories) {
var bloodhoundEngine = createBlounhoud(movieItem.childCategories, 'value');
var dataSource = {
name: movieItem.value,
displayKey: 'value',
source: bloodhoundEngine.ttAdapter(),
templates: {
header: '<h3 class="typeahead-group">' + movieItem.value + '</h3>'
}
};
dataSources.push(dataSource);
}
});
请注意,我们已为此数据源中的项目定义了标头模板。我们可以这样设计:
.typeahead-group {
margin: 0 20px 5px 10px;
padding: 3px 0;
border-bottom: 1px solid #ccc;
}
不属于子组的元素都可以作为单个ungrouped
数据源的一部分添加:
var ungrouped = [];
$.each(movies, function(index, movieItem) {
if (!movieItem.childCategories) {
ungrouped.push(movieItem);
}
});
function addUngroupedItems() {
var bloodhoundEngine = createBlounhoud(ungrouped, 'value');
var dataSource = {
name: 'ungrouped',
displayKey: 'value',
source: bloodhoundEngine.ttAdapter()
};
// add to first position of array so it doesn't look like it's part of the group above it
dataSources.unshift(dataSource);
};
此解决方案的优点是,在框架内工作时,可以最低限度地覆盖现有的先行和血腥代码,以提供分组功能。
此外,它为用户提供了一个直观的用户界面,用户可能知道他们正在寻找的子项目名称的名称,但并不想点击每个类别来查找它。大多数本地搜索都可以轻松搜索所有字段。
除了:我会尽量避免直接修改源代码。这使您很难看到自己进行了哪些修改。相反,尝试将CDN用于整个库并在其上面编写插件或包装器。这将使未来的修订更加容易。