How to trigger an onkeyup event that's delayed until a user pauses their typing?

后端 未结 7 743
生来不讨喜
生来不讨喜 2020-11-29 03:16

I have a textarea where people enter some text (naturally), and I want to make it so that an AJAX request is made every now and then to get some suggestions regarding what t

相关标签:
7条回答
  • 2020-11-29 03:48

    If you are using this functionality alot around the site and don't want to keep track of all of the setTimeout refs etc then i packaged this up into a plugin available here.

    The plugin adds a few options to the normal $.ajax method for buffering and canceling previous ajax calls.

    0 讨论(0)
  • 2020-11-29 03:50

    What you're looking for is called debouncing. Here is a generic algorithm in native JavaScript:

    function debounce(fn, duration) {
      var timer;
      return function() {
        clearTimeout(timer);
        timer = setTimeout(fn, duration)
      }
    }
    

    And here's an example of how to use it with an onkeyup event:

    function debounce(fn, duration) {
      var timer;
      return function(){
        clearTimeout(timer);
        timer = setTimeout(fn, duration);
      }
    }
    
    const txt = document.querySelector('#txt')
    const out = document.querySelector('#out')
    const status = document.querySelector('#status')
    
    const onReady = () => {
      txt.addEventListener('keydown', () => {
        out.classList.remove('idle')
        out.classList.add('typing')
        status.textContent = 'typing...'
      })
      
      txt.addEventListener('keyup', debounce(() => {
        out.classList.remove('typing')
        out.classList.add('idle')
        status.textContent = 'idle...'
      }, 800))
    }
    
    document.addEventListener('DOMContentLoaded', onReady)
    #wrapper{
      width: 300px;
    }
    
    input{
      padding: 8px;
      font-size: 16px;
      width: 100%;
      box-sizing: border-box;
    }
    
    #out{
      margin: 10px 0;
      padding: 8px;
      width: 100%;
      box-sizing: border-box;
    }
    
    .typing{
      background: #A00;
      color: #FFF;
    }
    
    .idle{
      background: #0A0;
      color: #FFF;
    }
    <div id="wrapper">
      <input id="txt" placeholder="Type here" />
      <div id="out">Status: <span id="status">waiting...</span></div>
    </div>

    0 讨论(0)
  • 2020-11-29 04:01

    If you are using lodash.js (or underscore.js) you can use the debounce function.

    Example (jQuery used for keyup):

    $('#myTextArea').keyup(_.debounce(function() {
      alert('hello');
    }, 500));
    
    0 讨论(0)
  • 2020-11-29 04:05

    Another alternative is to use a small jQuery plugin called bindWithDelay. It uses the same setTimeout technique that the accepted answer has, but handles the timeouts transparently so your code is a little easier to read. The source code can be seen on github.

    $("#myTextArea").bindWithDelay("keypress", doAjaxStuff, 1000)
    
    0 讨论(0)
  • 2020-11-29 04:06

    You could combine a keypress event handler with setTimeout so that you send an Ajax request a set amount of time after a keypress, cancelling and restarting the timer if another keypress occurs before the timer finishes. Assuming you have a textarea with id 'myTextArea' and an Ajax callback function called doAjaxStuff:

    function addTextAreaCallback(textArea, callback, delay) {
        var timer = null;
        textArea.onkeypress = function() {
            if (timer) {
                window.clearTimeout(timer);
            }
            timer = window.setTimeout( function() {
                timer = null;
                callback();
            }, delay );
        };
        textArea = null;
    }
    
    addTextAreaCallback( document.getElementById("myTextArea"), doAjaxStuff, 1000 );
    
    0 讨论(0)
  • 2020-11-29 04:12

    I would personally use a setInterval that would monitor the textarea for changes and only perform AJAX callbacks when it detects a change is made. every second should be fast and slow enough.

    0 讨论(0)
提交回复
热议问题