Получить текст из поля при нажатии клавиши, но с задержкой для дальнейшего ввода

StackOverflow https://stackoverflow.com/questions/2101259

Вопрос

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

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

  • Обнаружена клавиатура - начните ждать (в течение одной секунды)

  • обнаружена другая клавиша – перезапустите время ожидания

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

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

ОБНОВЛЕНИЕ — добавлен текущий код для Дэна (ниже)

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

jquery ("input#search"). Data ("Timeout", NULL) не определен http‍: //192.168.0.234/javascripts/main.js? 12640844467 Строка 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;
}
Это было полезно?

Решение

Извините, я не проверял это, и это немного не в моей голове, но, надеюсь, что-то в этом роде должно помочь.Измените 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);
  });
}

Затем я вызываю это из блока document.ready рассматриваемой страницы с помощью

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

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

  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);
    });
}

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

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

Мне нужно было создать собственное событие, которое работало бы так же, как существующие события jQuery, и оно должно было работать с keypress + удалить, вернуться на пробел и ввести.

Вот мой плагин 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 */ });    
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top