我想在用户输入文本框时触发ajax请求。我不希望它在每次用户输入字母时都运行该函数,因为这会导致大量的ajax请求,但是我不希望他们也必须点击输入按钮。
有没有办法可以检测用户何时完成输入然后执行ajax请求?
在这里使用jQuery! 戴夫
答案 0 :(得分:593)
所以,我猜猜完成打字就意味着你停了一会儿,说5秒钟。因此,考虑到这一点,让我们在用户释放密钥时启动计时器,并在按下密钥时清除它。我决定有问题的输入是#myInput。
做出一些假设......
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
var $input = $('#myInput');
//on keyup, start the countdown
$input.on('keyup', function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$input.on('keydown', function () {
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
答案 1 :(得分:346)
上面选择的答案不起作用。
因为typingTimer被多次设置(在快速打字机等触发keydown之前按两次键盘)然后它没有正确清除。
下面的解决方案解决了这个问题,并在OP请求完成后调用X秒。它也不再需要冗余的keydown功能。我还添加了一个检查,以便在输入为空时不会发生函数调用。
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms (5 seconds)
//on keyup, start the countdown
$('#myInput').keyup(function(){
clearTimeout(typingTimer);
if ($('#myInput').val()) {
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
和vanilla JavaScript解决方案中的相同代码:
//setup before functions
let typingTimer; //timer identifier
let doneTypingInterval = 5000; //time in ms (5 seconds)
let myInput = document.getElementById('myInput');
//on keyup, start the countdown
myInput.addEventListener('keyup', () => {
clearTimeout(typingTimer);
if (myInput.value) {
typingTimer = setTimeout(doneTyping, doneTypingInterval);
}
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
此解决方案确实使用ES6,但这里没有必要。只需将let
替换为var
,将箭头函数替换为常规函数。
答案 2 :(得分:70)
只有一行 underscore.js 去抖功能:
$('#my-input-box').keyup(_.debounce(doSomething , 500));
在我停止输入后,这基本上说是 doSomething 500毫秒。
答案 3 :(得分:40)
是的,您可以在每个启动事件上设置2秒的超时时间,该事件将触发ajax请求。您还可以存储XHR方法并在随后的按键事件中将其中止,以便您节省带宽甚至更多。这是我为自己的自动完成脚本编写的内容。
var timer;
var x;
$(".some-input").keyup(function () {
if (x) { x.abort() } // If there is an existing XHR, abort it.
clearTimeout(timer); // Clear the timer so we don't end up with dupes.
timer = setTimeout(function() { // assign timer a new timeout
x = $.getJSON(...); // run ajax request and store in x variable (so we can cancel)
}, 2000); // 2000ms delay, tweak for faster/slower
});
希望这有帮助,
马尔科
答案 4 :(得分:17)
var timer;
var timeout = 1000;
$('#in').keyup(function(){
clearTimeout(timer);
if ($('#in').val) {
timer = setTimeout(function(){
//do stuff here e.g ajax call etc....
var v = $("#in").val();
$("#out").html(v);
}, timeout);
}
});
此处的完整示例:http://jsfiddle.net/ZYXp4/8/
答案 5 :(得分:10)
我喜欢Surreal Dream的答案,但我发现我的“doneTyping”功能会触发每个按键,即如果你真的很快输入“Hello”;当你停止输入时,该功能只会发射一次,而不是只发射一次。
问题是javascript setTimeout函数似乎没有覆盖或终止已经设置的任何旧超时,但是如果你自己这样做就可以了!所以我只是在setTimeout之前添加了一个clearTimeout调用,如果设置了typingTimer。见下文:
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
//on keyup, start the countdown
$('#myInput').on("keyup", function(){
if (typingTimer) clearTimeout(typingTimer); // Clear if already set
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('#myInput').on("keydown", function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
N.B。我本来希望将此作为对Surreal Dream答案的评论添加,但我是新用户并且没有足够的声誉。遗憾!
答案 6 :(得分:8)
修改已接受的答案以处理其他案例,例如粘贴:
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 2000; //time in ms, 2 second for example
var $input = $('#myInput');
// updated events
$input.on('input propertychange paste', function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
答案 7 :(得分:6)
前两个答案对我都不起作用。所以,这是我的解决方案:
var timeout = null;
$('#myInput').keyup(function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
//do stuff here
}, 500);
});
答案 8 :(得分:4)
在这种情况下我不认为keyDown事件是必要的(如果我错了,请告诉我为什么)。在我的(非jquery)脚本中,类似的解决方案看起来像这样:
var _timer, _timeOut = 2000;
function _onKeyUp(e) {
clearTimeout(_timer);
if (e.keyCode == 13) { // close on ENTER key
_onCloseClick();
} else { // send xhr requests
_timer = window.setTimeout(function() {
_onInputChange();
}, _timeOut)
}
}
这是我对Stack Overflow的第一个回复,所以我希望有一天能帮助别人:)
答案 9 :(得分:4)
嗯,严格来说不是,因为计算机无法猜到用户何时完成输入。当然,您可以在按键上启动计时器,并在每个后续按键上重置它。如果计时器到期,用户没有输入计时器持续时间 - 你可以称之为“完成输入”。
如果您希望用户在打字时暂停,则无法知道他们何时完成。
(当然,除非数据完成后你可以告诉他们)
答案 10 :(得分:2)
最新答案,但是我要添加它,因为它是在2019年,并且完全可以使用漂亮的ES6,没有第三方库来实现,而且我发现大多数获得高度评价的答案都是庞大的,并且变量太多。 >
的优雅解决方案function debounce(callback, wait) {
let timeout;
return (...args) => {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => callback.apply(context, args), wait);
};
}
window.addEventListener('keyup', debounce( () => {
// code you would like to run 1000ms after the keyup event has stopped firing
// further keyup events reset the timer, as expected
}, 1000))
答案 11 :(得分:2)
同意@going的回答。另一个对我有用的类似解决方案是下面的解决方案。唯一的区别是我使用.on("输入" ...)而不是keyup。这仅捕获输入中的更改。忽略其他键,如Ctrl,Shift等
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms (5 seconds)
//on input change, start the countdown
$('#myInput').on("input", function() {
clearTimeout(typingTimer);
typingTimer = setTimeout(function(){
// doSomething...
}, doneTypingInterval);
});
答案 12 :(得分:2)
对于input
事件,我觉得解决方案有点简单:
var typingTimer;
var doneTypingInterval = 500;
$("#myInput").on("input", function () {
window.clearTimeout(typingTimer);
typingTimer = window.setTimeout(doneTyping, doneTypingInterval);
});
function doneTyping () {
// code here
}
答案 13 :(得分:2)
我正在我的列表中实现搜索,并且需要它是基于ajax的。这意味着在每次关键更改时,都应更新并显示搜索结果。这导致发送到服务器的这么多ajax调用,这不是一件好事。
经过一些工作,我在用户停止输入时设法ping服务器。
这个解决方案对我有用:
$(document).ready(function() {
$('#yourtextfield').keyup(function() {
s = $('#yourtextfield').val();
setTimeout(function() {
if($('#yourtextfield').val() == s){ // Check the value searched is the latest one or not. This will help in making the ajax call work when client stops writing.
$.ajax({
type: "POST",
url: "yoururl",
data: 'search=' + s,
cache: false,
beforeSend: function() {
// loading image
},
success: function(data) {
// Your response will come here
}
})
}
}, 1000); // 1 sec delay to check.
}); // End of keyup function
}); // End of document.ready
您会注意到在执行此操作时无需使用任何计时器。
答案 14 :(得分:1)
这是我写的一个简单的JS代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
var date = new Date();
initial_time = date.getTime();
if (typeof setInverval_Variable == 'undefined') {
setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
}
}
function DelayedSubmission_Check() {
var date = new Date();
check_time = date.getTime();
var limit_ms=check_time-initial_time;
if (limit_ms > 800) { //Change value in milliseconds
alert("insert your function"); //Insert your function
clearInterval(setInverval_Variable);
delete setInverval_Variable;
}
}
</script>
</head>
<body>
<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />
</body>
</html>
答案 15 :(得分:1)
您可以使用onblur事件来检测文本框何时失去焦点: https://developer.mozilla.org/en/DOM/element.onblur
这与“停止输入”不一样,如果你关心用户输入一堆东西然后坐在那里文本框仍然聚焦的情况。
为此,我建议将setTimeout绑定到onclick事件,并假设在没有击键的x时间后,用户已停止输入。
答案 16 :(得分:1)
我只是想出了一个等待用户完成输入的简单代码:
步骤1.将超时设置为null,然后在用户键入时清除当前超时。
步骤2.触发keyup事件之前触发清除超时定义变量。
步骤3.对上面声明的变量定义超时;
<input type="text" id="input" placeholder="please type" style="padding-left:20px;"/>
<div class="data"></div>
javascript代码
var textInput = document.getElementById('input');
var textdata = document.querySelector('.data');
// Init a timeout variable to be used below
var timefired = null;
// Listen for keystroke events
// Init a timeout variable to be used below
var timefired = null;// Listen for keystroke events
textInput.onkeyup = function (event) {
clearTimeout(timefired);
timefired = setTimeout(function () {
textdata.innerHTML = 'Input Value:'+ textInput.value;
}, 600);
};
答案 17 :(得分:1)
声明以下delay
函数:
var delay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})()
然后使用它:
let $filter = $('#item-filter');
$filter.on('keydown', function () {
delay(function () {
console.log('this will hit, once user has not typed for 1 second');
}, 1000);
});
答案 18 :(得分:0)
用于将参数与ES6语法一起传递给函数。
$(document).ready(() => {
let timer = null;
$('.classSelector').keydown(() => {
clearTimeout(timer);
timer = setTimeout(() => foo('params'), 500);
});
});
const foo = (params) => {
console.log(`In foo ${params}`);
}
答案 19 :(得分:0)
如果用户有必要离开该领域,我们可以在Javascript中使用“ onBlur”代替Onchange
<TextField id="outlined-basic" variant="outlined" defaultValue={CardValue} onBlur={cardTitleFn} />
如果那不是必须的,那么设置计时器将是个不错的选择。
答案 20 :(得分:0)
如果有人正在寻找AngularJS解决方案,则不是直接答案。我根据这里流行的解决方案写了一条指令。
app.directive("ngTypeEnds", ["$timeout", function ($timeout) {
return function (scope, element, attrs) {
var typingTimer;
element.bind("keyup", function (event) {
if (typingTimer)
$timeout.cancel(typingTimer);
if (angular.element(element)[0].value) {
typingTimer = $timeout(function () {
scope.$apply(function () {
scope.$eval(attrs.ngTypeEnds);
});
}, 500);
}
event.preventDefault();
});
};
}]);
答案 21 :(得分:0)
简单易懂。
var mySearchTimeout;
$('#ctl00_mainContent_CaseSearch').keyup(function () {
clearTimeout(mySearchTimeout);
var filter = $(this).val();
mySearchTimeout = setTimeout(function () { myAjaxCall(filter); }, 700);
return true;
});
答案 22 :(得分:0)
你们听说过javascript中的闭包吗?!
这非常简单明了,只需将当前输入值与setTimeOut函数关闭的旧值进行比较,就可以了。
let timer;
$('#myInput').on('keyup', function() {
window.clearTimeout(timer);
// here is the closures javascript magic happens.
const value = $(this).val();
timer = setTimeout(() => {
if(value === $(this).val() && $(this).val()!== ''){
alert($(this).val());
}
}, 500);
})
答案 23 :(得分:0)
如果您需要等到用户完成输入,请使用简单的:
$(document).on('change','#PageSize', function () {
//Do something after new value in #PageSize
});
使用ajax调用完成示例 - 这适用于我的寻呼机 - 每个列表的项目数:
$(document).ready(function () {
$(document).on('change','#PageSize', function (e) {
e.preventDefault();
var page = 1;
var pagesize = $("#PageSize").val();
var q = $("#q").val();
$.ajax({
url: '@Url.Action("IndexAjax", "Materials", new { Area = "TenantManage" })',
data: { q: q, pagesize: pagesize, page: page },
type: 'post',
datatype: "json",
success: function (data) {
$('#tablecontainer').html(data);
// toastr.success('Pager has been changed', "Success!");
},
error: function (jqXHR, exception) {
ShowErrorMessage(jqXHR, exception);
}
});
});
});
答案 24 :(得分:0)
所有其他答案仅适用于一个控件(包括my other answer)。 如果您每页有多个控件(例如,在购物车中),则只会调用用户在其中键入内容的最后一个控件。就我而言,这当然不是所希望的行为-每个控件都应具有自己的计时器。
要解决此问题,只需要将ID传递给函数并维护timeoutHandles字典,如以下代码所示:
功能声明:
var delayUserInput = (function () {
var timeoutHandles = {};
return function (id, callback, ms) {
if (timeoutHandles[id]) {
clearTimeout(timeoutHandles[id]);
}
timeoutHandles[id] = setTimeout(callback, ms);
};
})();
功能用法:
delayUserInput('yourID', function () {
//do some stuff
}, 1000);
答案 25 :(得分:0)
为什么不使用onfocusout?
https://www.w3schools.com/jsreF/event_onfocusout.asp
如果它是一个表单,它们将始终保留每个输入字段的焦点,以便单击提交按钮,因此您知道在调用其onfocusout事件处理程序时不会错过任何输入。
答案 26 :(得分:0)
不确定我的需求是否有点奇怪,但我需要类似于此的东西,这就是我最终使用的内容:
$('input.update').bind('sync', function() {
clearTimeout($(this).data('timer'));
$.post($(this).attr('data-url'), {value: $(this).val()}, function(x) {
if(x.success != true) {
triggerError(x.message);
}
}, 'json');
}).keyup(function() {
clearTimeout($(this).data('timer'));
var val = $.trim($(this).val());
if(val) {
var $this = $(this);
var timer = setTimeout(function() {
$this.trigger('sync');
}, 2000);
$(this).data('timer', timer);
}
}).blur(function() {
clearTimeout($(this).data('timer'));
$(this).trigger('sync');
});
这允许我在我的应用程序中包含这样的元素:
<input type="text" data-url="/controller/action/" class="update">
当用户“完成输入”(2秒内没有动作)或进入另一个字段(模糊了元素)时会更新
答案 27 :(得分:0)
如果您要查找特定长度(例如邮政编码字段):
$("input").live("keyup", function( event ){
if(this.value.length == this.getAttribute('maxlength')) {
//make ajax request here after.
}
});
答案 28 :(得分:0)
在文本框中检测到焦点后,在按键上执行超时检查,并在每次触发时重置它。
超时完成后,请执行ajax请求。
答案 29 :(得分:-1)
空输入不是跳过函数调用的原因,例如我在重定向
await
应该用于触发Compare
,.on ('input', function() { ... });
和keyup
事件
必须使用paste
或change
您可以使用.val()
内部事件功能代替.value
来处理多个输入
(我的决定)我在$(this)
中使用匿名函数代替#id
,以便从n.4轻松访问doneTyping
,但您需要先将其保存为{{{} 1}}