扩展bootstrap-typeahead以获取对象而不是字符串

我扩展了bootstrap-typeahead以获取对象而不是字符串。
它有效,但我想知道这是做事情的正确方法。

谢谢。

参考:
http://twitter.github.com/bootstrap/javascript.html#typeahead http://twitter.github.com/bootstrap/assets/js/bootstrap-typeahead.js

_.extend($.fn.typeahead.Constructor.prototype, { render: function (items) { var that = this; items = $(items).map(function (i, item) { i = $(that.options.item) .attr('data-value', item[that.options.display]) .attr('data-id', item.id); i.find('a').html(that.highlighter(item)); return i[0]; }); items.first().addClass('active'); this.$menu.html(items); return this; }, select: function () { var val = this.$menu.find('.active').attr('data-value'), id = this.$menu.find('.active').attr('data-id'); this.$element .val(this.updater(val, id)) .change(); return this.hide() } }); return function (element, options) { var getSource = function () { return { id: 2, full_name: 'first_name last_name' }; }; element.typeahead({ minLength: 3, source: getSource, display: 'full_name', sorter: function (items) { var beginswith = [], caseSensitive = [], caseInsensitive = [], item, itemDisplayed; while (item = items.shift()) { itemDisplayed = item[this.options.display]; if (!itemDisplayed.toLowerCase().indexOf(this.query.toLowerCase())) { beginswith.push(item); } else if (~itemDisplayed.indexOf(this.query)) { caseSensitive.push(item); } else { caseInsensitive.push(item); } } return beginswith.concat(caseSensitive, caseInsensitive); }, highlighter: function (item) { var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); return item[this.options.display].replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { return '' + match + ''; }); }, matcher: function (item) { var value = item[this.options.display]; return { value: ~value.toLowerCase().indexOf(this.query.toLowerCase()), id: item.id }; }, updater: function (item, userId) { options.hiddenInputElement.val(userId); return item; } }); }; 

我建议不要重写原型(这会影响你可以使用自动完成器的所有地方,而不仅仅是以下function)。
这段代码应该有效:

 var getSource = function () { var users = new Backbone.Collection([ { first_name: 'primo', last_name: 'ultimo', id: 1 }, { first_name: 'altro_primo', last_name: 'altro_ultimo', id: 2 } ]).models; return _.map(users, function (user) { return { id: user.get('id'), full_name: user.get('first_name') + ' ' + user.get('last_name'), // these functions allows Bootstrap typehead to use this item in places where it was expecting a string toString: function () { return JSON.stringify(this); }, toLowerCase: function () { return this.full_name.toLowerCase(); }, indexOf: function (string) { return String.prototype.indexOf.apply(this.full_name, arguments); }, replace: function (string) { return String.prototype.replace.apply(this.full_name, arguments); } }; }); }; $('.full_name').typeahead({ minLength: 3, source: getSource(), display: 'full_name', updater: function (itemString) { var item = JSON.parse(itemString); $('.id').val(item.id); return item.full_name; } }); 

演示: http : //jsfiddle.net/hyxMh/48/

除了@AntoJs的回答,这里是一个ajax版本(只是’source’部分):

 $('.full_name').typeahead({ /* ... */ source: function(query,process){ $.ajax({ url: 'your_url_here', data: {term: query, additional_data: 'some_data'}, success: function(data){ process($.map(data, function(user){ return { id: user.id, full_name: user.first_name + ' ' + user.last_name, toString: function () { return JSON.stringify(this); }, toLowerCase: function () { return this.full_name.toLowerCase(); }, indexOf: function (string) { return String.prototype.indexOf.apply(this.full_name, arguments); }, replace: function (string) { return String.prototype.replace.apply(this.full_name, arguments); } } })); } }); }, /* ... */ }); 

顺便说一下:@AntoJs – 非常感谢您的回答!

@ antonjs的回答对我不起作用,我收到了以下错误

TypeError:item.substr不是函数

所以使用jQuery v2.1.3和bootstrap3-typeahead.js v3.1.0以下内容适用于我

 var getSource = function () { var users = new Backbone.Collection([ { first_name: 'primo', last_name: 'ultimo', id: 1 }, { first_name: 'altro_primo', last_name: 'altro_ultimo', id: 2 } ]).models; return _.map(users, function (user) { return { id: user.get('id'), full_name: user.get('first_name') + ' ' + user.get('last_name'), // these functions allows Bootstrap typehead to use this item in places where it was expecting a string toString: function () { return JSON.stringify(this); }, toLowerCase: function () { return this.full_name.toLowerCase(); }, indexOf: function (string) { return String.prototype.indexOf.apply(this.full_name, arguments); }, replace: function (string) { return String.prototype.replace.apply(this.full_name, arguments); }, substr: function(start, len){ return this.full_name.substr(start, len); } }; }); }; $('.full_name').typeahead({ minLength: 3, source: getSource(), display: 'full_name', updater: function (itemString) { var item = JSON.parse(itemString); $('.id').val(item.id); return item.full_name; } });