Как правильно перехватить событие onchange или onkeyup для динамически вставляемого элемента ввода? - PullRequest
1 голос
/ 01 апреля 2012

У меня есть немного JavaScript, который собирает некоторый HTML для меня и вставляет его в div.Я использую jQuery 1.7.2 для этого теста.

Я заинтересован в том, чтобы прикрепить пользовательский обработчик события изменения или keyup к текстовому полю input с именем gene_autocomplete_field.

Вот что я пробовал до сих пор.

Следующая функция создает HTML, который вставляется в div с именем gene_container:

function buildGeneContainerHTML(count, arr) {
    var html = "";
    // ...
    html += "<input type='text' size='20' value='' id='gene_autocomplete_field' name='gene_autocomplete_field' placeholder='Enter gene name...' /><br/>";
    // ...
    return html;
}

// ...
$('#gene_container').html( buildGeneContainerHTML(count, geneNameArr) );

В моем вызовеHTML, я извлекаю gene_autocomplete_field из элемента gene_container, а затем перезаписываю обработчик событий keyup для gene_autocomplete_field:

<script>
    $(document).ready(function() {
        $("#gene_container input:[name=gene_autocomplete_field]").live('keyup', function(event) {
            refreshGenePicker($("#gene_container input:[name=gene_autocomplete_field]").val());
        });
    });
</script>

Когда я изменяю текст в gene_autocomplete_field,refreshGenePicker() Функция просто отправляет предупреждение:

function refreshGenePicker(val) {
    alert(val);
}

Результат

Если я наберу любую букву в элемент gene_autocomplete_field, обработчик события, кажется, вызывает alert(val) бесконечное количество раз.Я получаю одно предупреждение за другим, и браузер переходит в диалоговые окна.Возвращенное значение верное, но я волнуюсь, что refreshGenePicker() вызывается снова и снова.Я не думаю, что это неправильное поведение.

Вопросы

  • Как правильно перехватить событие keyup один раз, чтобы я мог толькообрабатывать изменение содержимого в поле автозаполнения один раз?
  • Есть ли другое событие, которое я должен использовать для этой цели?

ОБНОВЛЕНИЕ

Получается, что больше, чем простоkeyCode из 13 (Return / Enter) может быть проблемой - нажатие Control, Alt, Esc или других специальных символов вызовет событие (но будет бессимптомным, поскольку проблема бесконечного цикла идет).Имена генов, по которым я фильтрую, не содержат метасимволов.Поэтому я использовал буквенно-цифровой тест обнаружения , чтобы отфильтровать не алфавитно-цифровые символы от дальнейшей обработки события, включая ключ Return:

if (!alphaNumericCheck(event.keyCode)) return;

Ответы [ 3 ]

5 голосов
/ 01 апреля 2012

alert вызывается бесконечно много раз, потому что вы используете клавишу «Ввод» для подтверждения / отклонения предупреждения.Вместо этого используйте .on('change').Это предотвратит вызов refreshGenePicker при использовании ввода в alert.

Однако событие 'change' будет срабатывать только в том случае, если элемент ввода теряет фокус.Если вы хотите использовать refreshGenePicker для каждой клавиши, используйте вместо этого следующий подход:

$("#gene_container input:[name=gene_autocomplete_field]").live('keyup', function(event) {
    if(event.keyCode === 13) // filter ENTER
        return;
    refreshGenePicker($("#gene_container input:[name=gene_autocomplete_field]").val());
});

Это отфильтрует все входящие события ввода keyup ( jsFiddle demo ).Также переключитесь на .on и сбросьте .live.

EDIT : обратите внимание, что есть больше возможностей отклонить модальный alert, такой как escape или spaceключ.Вы должны добавить проверку внутри refreshGenePicker, действительно ли значение изменилось .

1 голос
/ 01 апреля 2012

Вы действительно должны использовать .on(), если вы используете jQuery> 1.7.

Проверьте the perftest .

А также зацените мой вопрос: .

Также при тестировании на равных вы действительно должны добавить кавычки вокруг него :

input:[name='gene_autocomplete_field']

Чтобы ответить на реальный вопрос :). Это не должно вести себя так с кодом, который вы представили. Может быть, что-то еще не так. Можете ли вы установить jsfiddle с проблемой?

Проверьте мое демо и, возможно, вы увидите, что не так с вашим кодом:

function refreshGenePicker(value) {
    console.log('keyup! Value is now: ' + value);
}

(function($) {
    var someHtml = '<input type="text" name="gene_autocomplete_field">';
    $('body').append(someHtml);

    $('body').on('keyup', 'input[name="gene_autocomplete_field"]', function(e) {
        refreshGenePicker($(this).val());
    });
})(jQuery);​
0 голосов
/ 01 апреля 2012
$(document).ready(function() {
    $('#test').html('<input id="text" />');
    $('#text').keyup(function() {
        console.log($(this).val());
    });
});​

Это работает просто отлично. Поскольку у вас есть второй блок кода в тегах <script>, возможно, вы запускаете его более одного раза, что приводит к тому, что он связывается более одного раза и выдает более одного предупреждения каждый раз, когда он связан. Конечно, вы могли бы использовать .unbind() для этого ввода перед добавлением keyup, но я думаю, что гораздо лучшим решением было бы сгруппировать весь код в один $(document).ready();, чтобы гарантировать, что вы связываете объект только один раз.

http://jsfiddle.net/Ka7Ty/2/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...