21

我扩展了 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 '<strong>' + match + '</strong>';
            });
        },
        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;
        }
    });
};
4

3 回答 3

18

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

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/

于 2012-09-06T20:19:18.743 回答
0

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

$('.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 - 非常感谢您的回答!

于 2014-01-16T13:06:01.310 回答
0

@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;
            }
});

于 2015-03-18T12:28:23.790 回答