Twitter Bootstrap typeahead: получить контекст/вызывающий элемент с `this` - программирование
Подтвердить что ты не робот

Twitter Bootstrap typeahead: получить контекст/вызывающий элемент с `this`

Я использую Typeahead компонент Twitter Bootstrap 2.1.1 и jQuery 1.8.1

Я пытаюсь получить доступ к элементу текстового поля из функции typeahead updater. Вот мой текущий код, который отлично работает:

$('#client-search').typeahead({
    source: function (query, process) {
        $.get(url, { query: query }, function (data) {
            labels = [];
            mapped = {};
            $.each(data, function(i,item) {
                mapped[item.label] = item.value;
                labels.push(item.label);
            });
            process(labels);
        });
    }
    ,updater: function (item) {
        $('#client-id').val(mapped[item]);
        return item;
    }
    ,items: 10
    ,minLength: 2
});

У меня есть много поисковых полей typeahead на той же странице. В каждом окне поиска есть id #xxx-search и соответствующий скрытый ввод с id #xxx-id. Я хотел бы повторно использовать один и тот же код для всего, выполнив что-то вроде этого:

$('#client-search, #endClient-search, #other-search').typeahead({

    ...

    ,updater: function (item) {
        var target = $(this).attr('id').split('-')[0] + '-id';
        $('#'+target).val(mapped[item]);
        return item;
    }

    ...

Я думал, что this будет ссылаться на используемый элемент текстового поля, но, видимо, нет, потому что я получаю ошибку undefined в firebug:

$(this).attr("id") is undefined

Когда я использую this вместо $(this), я получаю:

this.attr is not a function

Может кто-нибудь помочь сделать эту работу?


ОБНОВЛЕНИЕ: ОТВЕТ И БОЛЬШЕ!

Благодаря ответу benedict_w ниже, это не только отлично работает сейчас, но я также сделал это намного лучше с точки зрения повторного использования.

Вот как выглядит мой <input>:

<input type="text" autocomplete="off"
    id="client-search"
    data-typeahead-url="/path/to/json"
    data-typeahead-target="client-id">
<input type="hidden" id="client-id" name="client-id">

Обратите внимание, как окно поиска ссылается на скрытый идентификатор. Здесь новый js:

$(':input[data-typeahead-url]').each(function(){
    var $this = $(this);
    $this.typeahead({
        source: function (query, process) {
            $.get($this.attr('data-typeahead-url'), { query: query }, function (data) {
                labels = [];
                mapped = {};
                $.each(data, function(i,item) {
                    mapped[item.label] = item.value;
                    labels.push(item.label);
                });
                process(labels);
            });
        }
        ,updater: function (item) {
            $('#'+$this.attr('data-typeahead-target')).val(mapped[item]);
            return item;
        }
        ,items: 10
        ,minLength: 2
    });
});
4b9b3361

Ответ 1

Вы находитесь внутри другой функции, поэтому вам нужно сохранить ссылку на элемент во внешнем закрытии, тогда ее можно передать в обработчик события внутреннего закрытия. Вы можете сделать это с помощью вызова $.each() для циклического переключения селектора, сохраняющего ссылку на элемент (это) каждый раз - например,

$('#client-search, #endClient-search, #other-search').each(function() {
    var $this = $(this);
    $this.typeahead({
        ...

        ,updater: function (item) {
            var target = $this.attr('id').split('-')[0] + '-id';
            $('#'+target).val(mapped[item]);
            return item;
        }
        ...
     });

Ответ 2

Принятый ответ является хорошим, но просто хотел поделиться альтернативой, которая фактически не требует внешнего закрытия. Я использую bootstrap v2.3.1, и вход доступен вам от this.$element.

Например:

$(':input[data-typeahead-url]').typeahead({
    source: function (query, process) {
        $.get(this.$element.attr('data-typeahead-url'), { query: query }, function (data) {
            labels = [];
            mapped = {};
            $.each(data, function(i,item) {
                mapped[item.label] = item.value;
                labels.push(item.label);
            });
            process(labels);
        });
    }
    ,updater: function (item) {
        $('#'+this.$element.attr('data-typeahead-target')).val(mapped[item]);
        return item;
    }
    ,items: 10
    ,minLength: 2
});