Как оттянуть свое.keyup () обработчик, пока пользователь не перестанет печатать?



у меня есть поле поиска. Прямо сейчас он ищет каждый ключ. Поэтому, если кто-то наберет "Windows", он выполнит поиск с помощью AJAX для каждого ключа: "W", "Wi", "Win", "Wind", "Windo", "Window", "Windows".



Я хочу иметь задержку, поэтому он ищет только тогда, когда пользователь перестает печатать на 200 мс.



нет опции для этого в и setTimeout, но это не сработало.



Как я могу это сделать?

628   24  

24 ответов:

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

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

использование:

$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000 );
});

для чего-то более сложного, посмотрите на jQuery Typewatch плагин.

если вы хотите выполнить поиск после завершения типа, используйте глобальную переменную для хранения таймаута, возвращенного из вашего setTimout позвоните и отмените его с помощью clearTimeout если это еще не произошло, чтобы он не запускал тайм-аут, кроме последнего keyup событие

var globalTimeout = null;  
$('#id').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
}   
function SearchFunc(){  
  globalTimeout = null;  
  //ajax code
}

или с анонимной функцией:

var globalTimeout = null;  
$('#id').keyup(function() {
  if (globalTimeout != null) {
    clearTimeout(globalTimeout);
  }
  globalTimeout = setTimeout(function() {
    globalTimeout = null;  

    //ajax code

  }, 200);  
}   

еще одно небольшое улучшение в ответе CMS. Чтобы легко разрешить отдельные задержки, вы можете использовать следующее:

function makeDelay(ms) {
    var timer = 0;
    return function(callback){
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
};

Если вы хотите повторно использовать ту же задержку, просто сделайте

var delay = makeDelay(250);
$(selector1).on('keyup', function() {delay(someCallback);});
$(selector2).on('keyup', function() {delay(someCallback);});

Если вы хотите, чтобы отдельные задержки, вы можете сделать

$(selector1).on('keyup', function() {makeDelay(250)(someCallback);});
$(selector2).on('keyup', function() {makeDelay(250)(someCallback);});

вы также можете посмотреть на подчеркивания.js, который предоставляет служебные методы, как debounce:

var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);

основываясь на ответе CMS, я сделал это:

поместите код ниже после включения jQuery:

/*
 * delayKeyup
 * http://code.azerti.net/javascript/jquery/delaykeyup.htm
 * Inspired by CMS in this post : http://stackoverflow.com/questions/1909441/jquery-keyup-delay
 * Written by Gaten
 * Exemple : $("#input").delayKeyup(function(){ alert("5 secondes passed from the last event keyup."); }, 5000);
 */
(function ($) {
    $.fn.delayKeyup = function(callback, ms){
        var timer = 0;
        $(this).keyup(function(){                   
            clearTimeout (timer);
            timer = setTimeout(callback, ms);
        });
        return $(this);
    };
})(jQuery);

и просто использовать, как это :

$('#input').delayKeyup(function(){ alert("5 secondes passed from the last event keyup."); }, 5000);

осторожно: переменная $(this) в функции, переданной в качестве параметра, не соответствует input

задержка вызовов нескольких функций с помощью меток

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

таким образом, в результате будет вызван только последний щелчок / действие, потому что эти запросы хранятся в очереди, которая после X миллисекунд вызывается, если в очереди нет другого запроса с той же меткой!

function delay_method(label,callback,time){
    if(typeof window.delayed_methods=="undefined"){window.delayed_methods={};}  
    delayed_methods[label]=Date.now();
    var t=delayed_methods[label];
    setTimeout(function(){ if(delayed_methods[label]!=t){return;}else{  callback();}}, time||500);
  }

вы можете установить свое собственное время задержки (его опционально, по умолчанию 500 мс). И отправьте свои аргументы функции в режиме "закрытия".

например, если вы хотите вызвать пыльник функция:

function send_ajax(id){console.log(id);}

чтобы предотвратить несколько запросов send_ajax, вы задерживаете их использование:

delay_method( "check date", function(){ send_ajax(2); } ,600);

каждый запрос, который использует метку "check date", будет инициирован только в том случае, если никакой другой запрос не будет выполнен в течение 600 миллисекунд. Этот аргумент является необязательным

независимость метки (вызов одной и той же целевой функции), но запустите оба:

delay_method("check date parallel", function(){send_ajax(2);});
delay_method("check date", function(){send_ajax(2);});

результаты в вызове же функция, но задерживает их независимо из-за того, что их метки отличаются

эта функция немного расширяет функцию из ответа Гатена, чтобы вернуть элемент:

$.fn.delayKeyup = function(callback, ms){
    var timer = 0;
    var el = $(this);
    $(this).keyup(function(){                   
    clearTimeout (timer);
    timer = setTimeout(function(){
        callback(el)
        }, ms);
    });
    return $(this);
};

$('#input').delayKeyup(function(el){
    //alert(el.val());
    // Here I need the input element (value for ajax call) for further process
},1000);

http://jsfiddle.net/Us9bu/2/

Я удивлен, что никто не упоминает о проблеме с несколькими входами в CMS очень хорошо обрезан.

в принципе, вы должны определить переменную задержки индивидуально для каждого входа. В противном случае, если sb помещает текст на первый вход и быстро переходит к другому входу и начинает печатать, обратный вызов для первого НЕ назовешь!

смотрите код ниже я пришел с на основе других ответов:

(function($) {
    /**
     * KeyUp with delay event setup
     * 
     * @link http://stackoverflow.com/questions/1909441/jquery-keyup-delay#answer-12581187
     * @param function callback
     * @param int ms
     */
    $.fn.delayKeyup = function(callback, ms){
            $(this).keyup(function( event ){
                var srcEl = event.currentTarget;
                if( srcEl.delayTimer )
                    clearTimeout (srcEl.delayTimer );
                srcEl.delayTimer = setTimeout(function(){ callback( $(srcEl) ); }, ms);
            });

        return $(this);
    };
})(jQuery);

Это решение сохраняет ссылку setTimeout внутри входная переменная delayTimer. Он также передает ссылку элемента на обратный вызов, как предложил fazzyx.

протестировано в IE6, 8 (comp - 7), 8 и Opera 12.11.

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

$('#searchText').on('keyup',function () {
    var searchValue = $(this).val();
    setTimeout(function(){
        if(searchValue == $('#searchText').val() && searchValue != null && searchValue != "") {
           // logic to fetch data based on searchValue
        }
        else if(searchValue == ''){
           // logic to load all the data
        }
    },300);
});

функция задержки для вызова на каждом keyup. jQuery 1.7.1 или выше требуется

jQuery.fn.keyupDelay = function( cb, delay ){
  if(delay == null){
    delay = 400;
  }
  var timer = 0;
  return $(this).on('keyup',function(){
    clearTimeout(timer);
    timer = setTimeout( cb , delay );
  });
}

использование: $('#searchBox').keyupDelay( cb );

Если кому-то нравится задерживать ту же функцию, и без внешней переменной он может использовать следующий скрипт:

function MyFunction() {

    //Delaying the function execute
    if (this.timer) {
        window.clearTimeout(this.timer);
    }
    this.timer = window.setTimeout(function() {

        //Execute the function code here...

    }, 500);
}

супер простой подход, предназначенный для запуска функции после того, как пользователь закончил вводить текстовое поле...

<script type="text/javascript">
$(document).ready(function(e) {
    var timeout;
    var delay = 2000;   // 2 seconds

    $('.text-input').keyup(function(e) {
        console.log("User started typing!");
        if(timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(function() {
            myFunction();
        }, delay);
    });

    function myFunction() {
        console.log("Executing function for user!");
    }
});
</script>

<textarea name="text-input" class="text-input"></textarea>

использовать

mytimeout = setTimeout( expression, timeout );

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

clearTimeout(mytimeout);

сбросит / очистит тайм-аут, чтобы он не запускал скрипт в выражении (например, отмена), пока он еще не был выполнен.

это решение по линии CMS, но решает несколько ключевых вопросов для меня:

  • поддерживает несколько входов, задержки могут выполняться одновременно.
  • игнорирует ключевые события, которые не изменили значение (например, Ctrl, Alt+Tab).
  • решает условие гонки (когда обратный вызов выполняется и значение уже изменено).
var delay = (function() {
    var timer = {}
      , values = {}
    return function(el) {
        var id = el.form.id + '.' + el.name
        return {
            enqueue: function(ms, cb) {
                if (values[id] == el.value) return
                if (!el.value) return
                var original = values[id] = el.value
                clearTimeout(timer[id])
                timer[id] = setTimeout(function() {
                    if (original != el.value) return // solves race condition
                    cb.apply(el)
                }, ms)
            }
        }
    }
}())

использование:

signup.key.addEventListener('keyup', function() {
    delay(this).enqueue(300, function() {
        console.log(this.value)
    })
})

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

вещи, чтобы иметь в виду:

  • уникальный идентификатор создается на основе идентификатора формы и имени ввода, поэтому они должны быть определены и уникальны, или вы можете настроить его в соответствии с вашей ситуацией.
  • задержка возвращает объект, который легко расширить для собственных нужд.
  • исходный элемент, используемый для задержки привязан к девайсу, так this работает, как ожидалось (как в Примере).
  • пустой значение игнорируется во второй проверке.
  • следи за в очередь, он ожидает миллисекунд сначала, я предпочитаю это, но вы можете переключить параметры, чтобы соответствовать setTimeout.

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

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

var delay = (function(){
    var timer = 0;
    return function(callback, ms){
      clearTimeout (timer);
      timer = setTimeout(callback, ms);
    };
})(); 

var duplicateFilter=(function(){
  var lastContent;
  return function(content,callback){
    content=$.trim(content);
    if(content!=lastContent){
      callback(content);
    }
    lastContent=content;
  };
})();

$("#some-input").on("keyup",function(ev){

  var self=this;
  delay(function(){
    duplicateFilter($(self).val(),function(c){
        //do sth...
        console.log(c);
    });
  }, 1000 );


})

основываясь на ответе CMS вот новый метод задержки, который сохраняет "это" в его использовании:

var delay = (function(){
  var timer = 0;
  return function(callback, ms, that){
    clearTimeout (timer);
    timer = setTimeout(callback.bind(that), ms);
  };
})();

использование:

$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000, this);
});

использовать bindWithDelay jQuery плагин:

element.bindWithDelay(eventType, [ eventData ], handler(eventObject), timeout, throttle)
var globalTimeout = null;  
$('#search').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
});
function SearchFunc(){  
  globalTimeout = null;  
  console.log('Search: '+$('#search').val());
  //ajax code
};

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

эта функция получает объект поля ввода, помещенный в ваш код

function fieldKeyup(obj){
    //  what you want this to do

} // fieldKeyup

это фактическая функция delayCall, заботится о нескольких полях ввода

function delayCall(obj,ms,fn){
    return $(obj).each(function(){
    if ( typeof this.timer == 'undefined' ) {
       // Define an array to keep track of all fields needed delays
       // This is in order to make this a multiple delay handling     
          function
        this.timer = new Array();
    }
    var obj = this;
    if (this.timer[obj.id]){
        clearTimeout(this.timer[obj.id]);
        delete(this.timer[obj.id]);
    }

    this.timer[obj.id] = setTimeout(function(){
        fn(obj);}, ms);
    });
}; // delayCall

использование:

$("#username").on("keyup",function(){
    delayCall($(this),500,fieldKeyup);
});

объединение CMS ответ С Мигель один дает надежное решение, позволяющее одновременные задержки.

var delay = (function(){
    var timers = {};
    return function (callback, ms, label) {
        label = label || 'defaultTimer';
        clearTimeout(timers[label] || 0);
        timers[label] = setTimeout(callback, ms);
    };
})();

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

$('input.group1').keyup(function() {
    delay(function(){
        alert('Time elapsed!');
    }, 1000, 'firstAction');
});

$('input.group2').keyup(function() {
    delay(function(){
        alert('Time elapsed!');
    }, 1000, '2ndAction');
});

посмотри автозаполнение плагин. Я знаю, что он позволяет указать задержку или минимальное количество символов. Даже если вы не используете плагин, Просмотр кода даст вам некоторые идеи о том, как реализовать его самостоятельно.

Ну, я также сделал кусок кода для ограничения высокочастотного ajax-запроса, вызванного Keyup / Keydown. Проверьте это:

https://github.com/raincious/jQueue

сделайте свой запрос следующим образом:

var q = new jQueue(function(type, name, callback) {
    return $.post("/api/account/user_existed/", {Method: type, Value: name}).done(callback);
}, 'Flush', 1500); // Make sure use Flush mode.

и привязать событие, как это:

$('#field-username').keyup(function() {
    q.run('Username', this.val(), function() { /* calling back */ });
});

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

    var timeOutVar
$(selector).on('keyup', function() {

                    clearTimeout(timeOutVar);
                    timeOutVar= setTimeout(function(){ console.log("Hello"); }, 500);
                });

С ES6 можно использовать стрелка функция синтаксис как хорошо.

В этом примере кода задержки keyup событие для 400 мс после того, как пользователи закончат набирать перед вызовом searchFunc сделать запрос.

const searchbar = document.getElementById('searchBar');
const searchFunc = // any function

// wait ms (milliseconds) after user stops typing to execute func
const delayKeyUp = (() => {
    let timer = null;
    const delay = (func, ms) => {
        timer ? clearTimeout(timer): null
        timer = setTimeout(func, ms)
    }
    return delay
})();

searchbar.addEventListener('keyup', (e) => {
    const query = e.target.value;
    delayKeyUp(() => {searchFunc(query)}, 400);
})

Comments

    Ничего не найдено.