автозаполнение jquery: получить новые значения, когда они будут выполнены

У меня есть текстовое поле автозаполнения jquery (multiple: true), используемое для установки категорий для элемента, почти так же, как теги stackoverflow.

Источник автозаполнения - это список объектов с переопределением formatItem для правильного отображения.

Я пытаюсь вытащить из него два списка: один список идентификаторов выбранных категорий (массив целых чисел) и список любых введенных ими «новых» категорий, которых не было в исходном списке. Вот что я пробовал:

var categories = [];
var newCategoryNames = [];

var collectData = function(event, itemData, formatted) {
    if (itemData == null)
    {
        // no match -- new category
        newCategoryNames[newCategoryNames.length] = formatted;
    }
    else
    {
        categories[categories.length] = itemData.iCategoryID;
    }
};
$('#txtCategories').result(collectData).search().unbind('result');

Это отлично работает для уже существующих категорий (предложение "else"), но не работает для новых элементов (предложение "if"). Это связано с тем, что в этом случае значение itemData не только передается в null, но и форматированный параметр также имеет значение null. Я думал, что это все равно будет передаваться как введенный пользователем текст, но, видимо, нет.

Так что я могу сделать? Этот обратный вызов вызывается для несоответствующего элемента, но, похоже, он не дает мне никакой информации, которая скажет мне, чем на самом деле был этот несовпадающий элемент.


person Clyde    schedule 25.06.2009    source источник


Ответы (3)


Как вы можете заставить срабатывать событие result, когда для параметра multiple установлено значение true и пользователь вводит запись, которой нет в существующем списке? На моей тестовой странице я не смог этого сделать.

В любом случае, я отлаживал исходный код плагина автозаполнения и обнаружил, что он не обрабатывает сценарий, в котором у вас есть «multiple = true», «mustmatch = false» и типы пользователей в записи, которая не принадлежит вашему списку автозаполнения.

Вот отладочная информация:

Существует код, который проверяет нажатие клавиши пользователем, если это ЗАПЯТАЯ или ваш multipleSeparator, он запускает метод selectCurrent ().

        // matches also semicolon
        case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
        case KEY.TAB:
        case KEY.RETURN:
            if( selectCurrent() ) {
                // stop default to prevent a form submit, Opera needs special handling
                event.preventDefault();
                blockSubmit = true;
                return false;
            }
            break;

Так выглядит метод selectCurrent. Он пытается получить текущее выбранное значение. Здесь объект выбора - это раскрывающийся список «автозаполнение», созданный плагином. Если пользователь ввел слово, которого нет в списке, возвращается false, и событие result не срабатывает.

function selectCurrent() {
    var selected = select.selected();

    if( !selected ) //selected is NULL if user types in comma after typing a word which doesn't belong in the list. And that is why I was surprised that your result event was even triggered.
        return false;

    var v = selected.result;
    previousValue = v;

    if ( options.multiple ) {
        var words = trimWords($input.val());
        if ( words.length > 1 ) {
            v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
        }
        v += options.multipleSeparator;
    }

    $input.val(v);
    hideResultsNow();
    $input.trigger("result", [selected.data, selected.value]);
    return true;
}

Чтобы исправить это, вы должны проверить options.multiple. Вот последний код, который все сделает правильно:

function getLastWord()
{
    var words = trimWords($input.val());
    return words[words.length - 1];
};

function selectCurrent() {
    var selected = select.selected();

    //options.multiple BUGFIX START

    //We don't have to check for options.mustMatch because the 'select' component
    //already handles it.
    if(! selected && options.multiple)
    {
        var lastWord = getLastWord();
        //Below code is similar to how the Cache component generates the data.
        selected = {
                        data : lastWord,                            
                        value : options.formatMatch(lastWord, -1, options.data.length),
                        result : options.formatResult && options.formatResult(lastWord) || lastWord

        };
    }
    //options.multiple BUGFIX END

    if( !selected )
        return false;

    var v = selected.result;
    previousValue = v;

    if ( options.multiple ) {
        var words = trimWords($input.val());
        if ( words.length > 1 ) {
            v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
        }
        v += options.multipleSeparator;
    }

    $input.val(v);
    hideResultsNow();
    $input.trigger("result", [selected.data, selected.value]);
    return true;
}

Таким образом, вы можете изменить свою версию плагина Autocomplete или получить значение текстового поля и выполнить синтаксический анализ самостоятельно.

person SolutionYogi    schedule 15.07.2009
comment
Я закончил тем, что просто проанализировал себя (на самом деле это просто разделение на разделительный символ, а затем поиск строки в списке). Но спасибо это очень интересно - person Clyde; 15.07.2009

В худшем случае вы должны сами получить значение из ввода:

if (itemData == null)
{
    // no match -- new category
    newCategoryNames[newCategoryNames.length] = event.target.value;
}
person Prestaul    schedule 25.06.2009
comment
К сожалению, event.target.value содержит только полное содержимое текстового поля. Если бы я собирался использовать это, я мог бы полностью обойти весь этот код и попробовать разделить $ ('# txtbox'). Val (); Но я надеялся использовать уже существующий код в автозаполнении для сопоставления отображаемых значений и идентификаторов. - person Clyde; 29.06.2009

1) В моем случае, как вы получите идентификатор выбранного элемента или его присутствие в текстовом поле после выбора. Идентификатор не должен отображаться в выбранном списке, он должен быть прикреплен сзади к каждому значению списка. 2) Содержит ли автозаполнение jquery структуру списка из нескольких столбцов (например: я хочу: ItemCode, Name, Desc, в котором поиск основан на коде элемента).

person Community    schedule 30.07.2009