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 に答える