Получить текст из поля на клавиатуре, но с задержкой для дальнейшего ввода
У меня есть форма, которая отправляется удаленно, когда различные элементы меняются. В частности, в поле поиска я использую keyup, чтобы определить, когда изменяется текст в поле. Проблема в том, что когда кто-то печатает "курица", то форма отправляется семь раз, при этом учитывается только последний.
Что было бы лучше, это что-то вроде этого
-
обнаружен keyup - начало ожидания (на одну секунду)
-
обнаружен другой ключ - перезапустите время ожидания
-
ожидание заканчивается - получите значение и отправьте форму
прежде чем я уйду и напишу свою собственную версию этого (я действительно бэкэнд-парень с небольшим js, я использую jQuery для всего), есть ли уже существующее решение для этого? Кажется, это было бы общим требованием. Может быть плагин jQuery? Если нет, то какой самый простой и лучший способ кодировать это?
ОБНОВЛЕНИЕ - текущий код добавлен для Дана (ниже)
Дан - это может быть актуально. Один из плагинов jQuery, которые я использую на странице (TableSorter), требует этот файл - "tablesorter/jquery-latest.js", который, если он включен, приводит к той же ошибке с вашим кодом, что и раньше:
jQuery ("input # search"). data ("timeout", null) не определен http://192.168.0.234/javascripts/main.js? 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;
}
Ответы
Ответ 1
Жаль, что я не тестировал это, и это немного от меня, но что-то в этом направлении, надеюсь, сделает трюк. Измените 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>
Ответ 2
Здесь ваше фантастическое расширение 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.
}
}
});
Задержка по умолчанию занимает половину секунды.
Ответ 3
Как обновление, я закончил с этим, который, кажется, хорошо работает:
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 таким образом. Это хорошая домашняя задача, хотя.
Ответ 4
Хорошая работа, Макс, это было очень полезно для меня! Я сделал небольшое улучшение вашей функции, сделав ее более общей:
function afterDelayedEvent(eventtype, selector, action, delay) {
$(selector).bind(eventtype, function() {
if (typeof(window['inputTimeout']) != "undefined") {
clearTimeout(inputTimeout);
}
inputTimeout = setTimeout(action, delay);
});
}
Таким образом, вы можете использовать его для любого типа событий, хотя, возможно, наиболее полезным здесь является keyup.
Ответ 5
Я знаю, что это старо, но это был один из первых результатов, когда я искал, как сделать что-то подобное, поэтому, хотя я бы поделился своим решением. Я использовал комбинацию предоставленных ответов, чтобы получить то, что мне нужно.
Мне понадобилось настраиваемое событие, которое работало так же, как и существующие события 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 */ });