(jquery/js) - получить текст из поля на keyup, но с задержкой для дальнейшего ввода

Привет всем. У меня есть форма, которая отправляется удаленно, когда различные элементы меняются. В поле поиска, в частности, я использую keyup для обнаружения, когда текст в поле изменяется. Проблема с этим заключается в том, что когда кто-то набирает "курица", то форма представляется семь раз, причем только последний подсчет.

что было бы лучше, если бы что-то вроде этого

  • обнаружен keyup-начало ожидания (для одного секунду)

  • обнаружен еще один ключ-перезапустить время ожидания

  • ожидание заканчивается-получить значение и отправить форму

прежде чем я уйду и закодирую свою собственную версию этого (я действительно бэкэнд-парень с небольшим js, я использую jquery для всего), есть ли уже существующее решение для этого? Кажется, это было бы общим требованием. Может быть, плагин jquery? если нет, то какой самый простой и лучший способ кодирования это?

спасибо, Макс

UPDATE-текущий код добавлен для Dan (ниже)

Dan - это может быть актуально. Один из плагинов jquery, который я использую на странице (tablesorter), требует этого файла - "tablesorter/jquery-latest.js", что, если включено, приводит к той же ошибке с вашим кодом, что и раньше:

jQuery ("input#search").данные ("timeout", null) не определены http://192.168.0.234/javascripts/main.Яш?1264084467 Линия 11

может быть, существует какой-то конфликт между различными определениями jquery? (или что-то)

$(document).ready(function() {
  //initiate the shadowbox player
//  Shadowbox.init({
//    players:  ['html', 'iframe']
//  });
}); 

jQuery(function(){
  jQuery('input#search')
    .data('timeout', null)
    .keyup(function(){
      jQuery(this).data('timeout', setTimeout(function(){
          var mytext = jQuery('input#search').val();
          submitQuizForm();
          jQuery('input#search').next().html(mytext);
        }, 2000)
     )
     .keydown(function(){
       clearTimeout(jQuery(this).data('timeout'));
     });
    });
});

function submitQuizForm(){
  form = jQuery("#searchQuizzes");
  jQuery.ajax({
    async:true, 
    data:jQuery.param(form.serializeArray()), 
    dataType:'script', 
    type:'get', 
    url:'/millionaire/millionaire_quizzes',
    success: function(msg){ 
     // $("#chooseQuizMainTable").trigger("update"); 
    }
  }); 
  return true;
}

5 ответов


Извините, я не тестировал это, и это немного с моей головы, но что-то в этом роде, надеюсь, сделает трюк. Измените 2000 на сколько миллисекунд вам нужно между сообщениями сервера

<input type="text" id="mytextbox" style="border: 1px solid" />
<span></span>

<script language="javascript" type="text/javascript">
    jQuery(function(){
      jQuery('#mytextbox')
        .data('timeout', null)
        .keyup(function(){
            clearTimeout(jQuery(this).data('timeout'));
            jQuery(this).data('timeout', setTimeout(submitQuizForm, 2000));
        });
    });
</script>

вот ваше необычное расширение jquery:

(function($){

$.widget("ui.onDelayedKeyup", {

    _init : function() {
        var self = this;
        $(this.element).keyup(function() {
            if(typeof(window['inputTimeout']) != "undefined"){
                window.clearTimeout(inputTimeout);
            }  
            var handler = self.options.handler;
            window['inputTimeout'] = window.setTimeout(function() {
                handler.call(self.element) }, self.options.delay);
        });
    },
    options: {
        handler: $.noop(),
        delay: 500
    }

});
})(jQuery);

используйте его так:

    $("input.filterField").onDelayedKeyup({
        handler: function() {
            if ($.trim($(this).val()).length > 0) {
                //reload my data store using the filter string.
            }
        }
    });

делает задержку по умолчанию.


в качестве обновления, я закончил с этим, который, кажется, работает хорошо:

function afterDelayedKeyup(selector, action, delay){
  jQuery(selector).keyup(function(){
    if(typeof(window['inputTimeout']) != "undefined"){
      clearTimeout(inputTimeout);
    }  
    inputTimeout = setTimeout(action, delay);
  });
}

затем я вызываю это со страницы в документе вопроса.готовый блок с

  afterDelayedKeyup('input#search',"submitQuizForm()",500)

было бы неплохо сделать новое событие jquery, которое использует эту логику, например .delayedKeyup идти рядом .keyup, поэтому я мог бы просто сказать что-то вроде этого для документа отдельной страницы.готовый блок.

  jQuery('input#search').delayedKeyup(function(){
    submitQuizForm();
  });

но я не знаю, как настроить jquery таким образом. Это хорошо. хотя домашнее задание.


хорошая работа, Макс, это было очень полезно для меня! Я сделал небольшое улучшение вашей функции, сделав ее более общей:

function afterDelayedEvent(eventtype, selector, action, delay) {
    $(selector).bind(eventtype, function() {
        if (typeof(window['inputTimeout']) != "undefined") {
            clearTimeout(inputTimeout);
        }
        inputTimeout = setTimeout(action, delay);
    });
}

таким образом, вы можете использовать его для любого типа событий, хотя keyup, вероятно, наиболее полезен здесь.


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

Я хотел пользовательское событие, которое работало так же, как существующие события jQuery, и ему нужно было работать с keypress + delete, backspace и enter.

вот мой плагин jQuery:

$.fn.typePause = function (dataObject, eventFunc)
    {
        if(typeof dataObject === 'function')
        {
            eventFunc = dataObject;
            dataObject = {};
        }
        if(typeof dataObject.milliseconds === 'undefined')
            dataObject.milliseconds = 500;
        $(this).data('timeout', null)
            .keypress(dataObject, function(e)
            {
                clearTimeout($(this).data('timeout'));
                $(this).data('timeout', setTimeout($.proxy(eventFunc, this, e), dataObject.milliseconds));
            })
            .keyup(dataObject, function(e)
            {
                var code = (e.keyCode ? e.keyCode : e.which);
                if(code == 8 || code == 46 || code == 13)
                    $(this).triggerHandler('keypress',dataObject);
            });
    }

Я $.proxy() сохранить контекст в этом случае, хотя может быть лучший способ сделать это, с точки зрения производительности.

чтобы использовать этот плагин, просто сделать:

$('#myElement').typePause(function(e){ /* do stuff */ });

или

$('#myElement').typePause({milliseconds: 500, [other data to pass to event]},function(e){ /* do stuff */ });