如何触发一个延迟的onkeyup事件,直到用户暂停键入?

时间:2009-10-25 10:47:22

标签: javascript jquery ajax

我有一个textarea,人们输入一些文本(自然),我想这样做,以便偶尔发出一个AJAX请求,以获得有关textarea的内容的一些建议(如堆栈溢出的相关问题,但对于textarea,而不是文本输入)。问题是我无法在每个按键时执行AJAX请求(它没用,而且非常耗费资源),我不确定最有效的方法是什么(每X个字一次?每隔X秒?或其他什么?)。

这样做最好的方法是什么?

提前谢谢。

7 个答案:

答案 0 :(得分:64)

您可以将keypress事件处理程序与setTimeout结合使用,以便在按键后发送Ajax请求一定时间,如果在计时器完成之前发生另一次按键,则取消并重新启动计时器。假设你有一个id为'myTextArea'的textarea和一个名为doAjaxStuff的Ajax回调函数:

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

答案 1 :(得分:12)

您正在寻找的内容称为debouncing。以下是本机JavaScript中的通用算法:

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

以下是如何将其与onkeyup事件一起使用的示例:



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>
&#13;
&#13;
&#13;

答案 2 :(得分:9)

另一种选择是使用名为bindWithDelay的小型jQuery插件。它使用与接受的答案相同的setTimeout技术,但透明地处理超时,因此您的代码更容易阅读。 source code可以在github上看到。

$("#myTextArea").bindWithDelay("keypress", doAjaxStuff, 1000)

答案 3 :(得分:3)

如果您使用的是lodash.js(或underscore.js),则可以使用debounce function

示例(用于keyup的jQuery):

$('#myTextArea').keyup(_.debounce(function() {
  alert('hello');
}, 500));

答案 4 :(得分:1)

我个人会使用setInterval监视textarea的更改,并在检测到更改时仅执行AJAX回调。每一秒都应该快速而缓慢。

答案 5 :(得分:0)

如果您对jQuery解决方案感兴趣,jQuery Suggest是一个很好的实现。

每次都没有意义重新发明轮子。

答案 6 :(得分:0)

如果您在网站周围使用此功能并且不想跟踪所有setTimeout引用等,那么我将其打包到可用的插件here中。

该插件为普通的$ .ajax方法添加了一些选项,用于缓冲和取消之前的ajax调用。