Javascript. Submit form after user stop typing - javascript

How i can submit form after user complete typing input?
Example: The user started typing. After the introduction of several characters stopped. The form was submited.

Here is a example for you.
var timer;
var doneTypingInterval = 3000; // wait 3 seconds
var $input = $('input');
$input.on('keyup', function () {
clearTimeout(timer);
timer = setTimeout(doneTyping, doneTypingInterval);
});
$input.on('keydown', function () {
clearTimeout(timer);
});
function doneTyping () {
alert('done')
}
Html
<input type="text">
But i don't recommend this. It can be annoying for your user's.

i hope this sample helps :
HTML
<form>
<input name="query" id="query">
<p id="message" > </p>
</form>
JS
function submitForm(){
//do some stuff
}
jQuery(document).ready(function(){
window.timeout=null;
jQuery('#query').on('keyup', function(event){
clearTimeout(window.timeout);
window.timeout = setTimeout(submitForm, 1000); // waits 1 second for user to press a new key
});
});

Related

How to set if condition on keyup() in Jquery

<label id="statusLabel">Online</label>
<input type="text" id="txtInput">
<script>
if($('txtInput').keyup()) {
$('#statusLabel').text('typing...');
}
else {
$('#statusLabel').text('online');
}
</script>
I want set statusLabel.text to 'typing' when I'm typing on the keyboard.And statusLabel.text to 'online' when I'm not typing on the keyboard.I have tried this code and It's not working.Is it possible to do so?.Really appreciate if your'll can help.Thanks
This can be done using a timer that gets reset every time a user presses a key in the input field.
The time is used to show the text online after waiting for a certain amount of time when user haven't typed anything, 1 sec in this example.
So after X amount of millisecond the status is set back to online since system waited for X millisecond before shiting label from typing... to online.
var timer = null;
$('#txtInput').keydown(() => {
$('#statusLabel').text('Typing...');
clearTimeout(timer);
timer = setTimeout(() => $('#statusLabel').text('Online'), 1000)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label id="statusLabel">Online</label>
<input type="text" id="txtInput">
this might help you when user start typing then it will show 'typing...' by default after certain time it will show 'online' :
$('txtInput').keyup(function(){
$('#statusLabel').text('typing...');
function timer(){
$('#statusLabel').text('online');
}
//setTimeout(myFunc,5000);
setTimeout(timer,3000);
});
I would do something like this:
var typing;
var interval = 500;
//on keyup, start the countdown
$('#txtInput').keyup(function() {
$('#statusLabel').text('typing...');
clearTimeout(typing);
if ($('#txtInput').val()) {
typing = setTimeout(doneTyping, interval);
}
});
function doneTyping() {
$('#statusLabel').text('online')
}
Here I use setTimeout and clearTimeout so the text dont flash between typing... and online.
Basic, what it does is that when you start typing, it changes the text, and clears the timer. If you press another key within 0,5 seconds then it will clear the timer once more.
Once you haven't typed anything for 0,5 sec then it will change the text of statusLabel
Demo
var typing;
var interval = 500;
//on keyup, start the countdown
$('#txtInput').keyup(function() {
$('#statusLabel').text('typing...');
clearTimeout(typing);
if ($('#txtInput').val()) {
typing = setTimeout(doneTyping, interval);
}
});
function doneTyping() {
$('#statusLabel').text('online')
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label id="statusLabel">Online</label>
<input type="text" id="txtInput">
var timerID;
$('#txt').keyup(function(){
$('#status').text('Typing...');
timerID = setTimeout(clearThis, 1300);
});
function clearThis(){
$('#status').text('online');
clearInterval(timerID);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label id="status">Online</label>
<br>
<input type="text" id="txt">

Method runs multiple times [duplicate]

I want to trigger an ajax request when the user has finished typing in a text box. I don't want it to run the function on every time the user types a letter because that would result in A LOT of ajax requests, however I don't want them to have to hit the enter button either.
Is there a way so I can detect when the user has finished typing and then do the ajax request?
Using jQuery here!
So, I'm going to guess finish typing means you just stop for a while, say 5 seconds. So with that in mind, let's start a timer when the user releases a key and clear it when they press one. I decided the input in question will be #myInput.
Making a few assumptions...
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 seconds 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
}
The chosen answer above does not work.
Because typingTimer is occassionaly set multiple times (keyup pressed twice before keydown is triggered for fast typers etc.) then it doesn't clear properly.
The solution below solves this problem and will call X seconds after finished as the OP requested. It also no longer requires the redundant keydown function. I have also added a check so that your function call won't happen if your input is empty.
//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
}
And the same code in vanilla JavaScript solution:
//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
}
This solution does use ES6 but it's not necessary here. Just replace let with var and the arrow function with a regular function.
It's just one line with underscore.js debounce function:
$('#my-input-box').keyup(_.debounce(doSomething , 500));
This basically says doSomething 500 milliseconds after I stop typing.
For more info: http://underscorejs.org/#debounce
Late answer but I'm adding it because it's 2019 and this is entirely achievable using pretty ES6, no third party libraries, and I find most of the highly rated answers are bulky and weighed down with too many variables.
Elegant solution taken from this excellent blog post.
function debounce(callback, wait) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(function () { callback.apply(this, 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))
Yes, you can set a timeout of say 2 seconds on each and every key up event which will fire an ajax request. You can also store the XHR method and abort it on subsequent key press events so that you save bandwith even more. Here's something I've written for an autocomplete script of mine.
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
});
Hope this helps,
Marko
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);
}
});
full example here: http://jsfiddle.net/ZYXp4/8/
Both top 2 answers doesn't work for me. So, here is my solution:
var timeout = null;
$('#myInput').keyup(function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
//do stuff here
}, 500);
});
Declare the following delay function:
var delay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})()
and then use it:
let $filter = $('#item-filter');
$filter.on('keydown', function () {
delay(function () {
console.log('this will hit, once user has not typed for 1 second');
}, 1000);
});
Modifying the accepted answer to handle additional cases such as paste:
//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
}
I like Surreal Dream's answer but I found that my "doneTyping" function would fire for every keypress, i.e. if you type "Hello" really quickly; instead of firing just once when you stop typing, the function would fire 5 times.
The problem was that the javascript setTimeout function doesn't appear to overwrite or kill the any old timeouts that have been set, but if you do it yourself it works! So I just added a clearTimeout call just before the setTimeout if the typingTimer is set. See below:
//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. I would have liked to have just added this as a comment to Surreal Dream's answer but I'm a new user and don't have enough reputation. Sorry!
I don't think keyDown event is necessary in this case (please tell me why if I'm wrong). In my (non-jquery) script similar solution looks like that:
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)
}
}
It's my first reply on Stack Overflow, so I hope this helps someone, someday:)
const inText = document.getElementById('inText')
const outText = document.getElementById('outText')
const delay = 1000
let timer
inText.addEventListener('input', code => {
clearTimeout(timer);
timer = setTimeout(x => {
outText.innerHTML = inText.value
}, delay, code)
})
<textarea id='inText'>edit this and...</textarea>
<pre id='outText'>see the results after you stop typing for one second</pre>
Well, strictly speaking no, as the computer cannot guess when the user has finished typing. You could of course fire a timer on key up, and reset it on every subsequent key up. If the timer expires, the user hasn't typed for the timer duration - you could call that "finished typing".
If you expect users to make pauses while typing, there's no way to know when they are done.
(Unless of course you can tell from the data when they are done)
agree with the #going 's answer. Another similar solution that worked for me is the one below. The only difference is that I am using .on("input"...) instead of keyup. This only captures changes in the input. other keys like Ctrl, Shift etc. are ignored
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);
});
I was implementing the search at my listing and needed it to be ajax based. That means that on every key change, searched results should be updated and displayed. This results in so many ajax calls sent to server, which is not a good thing.
After some working, I made an approach to ping the server when the user stops typing.
This solution worked for me:
$(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
You will notice that there is no need to use any timer while implementing this.
I feel like the solution is somewhat a bit simpler with the input event:
var typingTimer;
var doneTypingInterval = 500;
$("#myInput").on("input", function () {
window.clearTimeout(typingTimer);
typingTimer = window.setTimeout(doneTyping, doneTypingInterval);
});
function doneTyping () {
// code here
}
I just figured out a simple code to wait for user to finish typing:
step 1.set time out to null then clear the current timeout when the user is typing.
step 2.trigger clear timeout to the variable define before keyup event is triggered.
step 3.define timeout to the variable declared above;
<input type="text" id="input" placeholder="please type" style="padding-left:20px;"/>
<div class="data"></div>
javascript code
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);
};
This is the a simple JS code I wrote:
<!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>
Why not just use onfocusout?
https://www.w3schools.com/jsreF/event_onfocusout.asp
If it's a form, they will always leave focus of every input field in order to click the submit button so you know no input will miss out on getting its onfocusout event handler called.
Multiple timers per page
All the other answers only work for one control (my other answer included).
If you have multiple controls per page (e.g. in a shopping cart) only the last control where the user typed something will get called. In my case this is certainly not the wished behaviour - each control should have its own timer.
To solve this, you simply have to pass an ID to the function and maintain a timeoutHandles dictionary as in the following code:
Function Declaration:
var delayUserInput = (function () {
var timeoutHandles = {};
return function (id, callback, ms) {
if (timeoutHandles[id]) {
clearTimeout(timeoutHandles[id]);
}
timeoutHandles[id] = setTimeout(callback, ms);
};
})();
Function Usage:
delayUserInput('yourID', function () {
//do some stuff
}, 1000);
Here is a solution that fires after 1 second of not typing, but also fires instantly when the input is blank. This is useful when clearing search results after the user deletes the input query. This solution also supports copying and pasting into the search box. The $(() => { ... }); wrapping the top portion of code simply means "do this when the page is loaded" in simple Jquery terms.
var searchTimer;
var searchInterval = 1000;
$(() => {
$('#search-box').on('input', (event) => {
clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
searchContacts(event.target.value);
}, (event.target.value.length > 0) ? searchInterval : 0);
});
});
function searchContacts(val) {
console.log('searching: ' + val);
}
You can use the onblur event to detect when the textbox loses focus:
https://developer.mozilla.org/en/DOM/element.onblur
That's not the same as "stops typing", if you care about the case where the user types a bunch of stuff and then sits there with the textbox still focused.
For that I would suggest tying a setTimeout to the onclick event, and assuming that after x amount of time with no keystrokes, the user has stopped typing.
If there is necessity for the user to move away from the field, we can use "onBlur" instead of Onchange in Javascript
<TextField id="outlined-basic" variant="outlined" defaultValue={CardValue} onBlur={cardTitleFn} />
If that is not necessary setting timer would be the good option.
for alpine.js users <input #input.debounce.500ms="fn()">
Once you detect focus on the text box, on key up do a timeout check, and reset it each time it's triggered.
When the timeout completes, do your ajax request.
If you are looking for a specific length (such as a zipcode field):
$("input").live("keyup", function( event ){
if(this.value.length == this.getAttribute('maxlength')) {
//make ajax request here after.
}
});
Not sure if my needs are just kind of weird, but I needed something similar to this and this is what I ended up using:
$('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');
});
Which allows me to have elements like this in my application:
<input type="text" data-url="/controller/action/" class="update">
Which get updated when the user is "done typing" (no action for 2 seconds) or goes to another field (blurs out of the element)
If you need wait until user is finished with typing use simple this:
$(document).on('change','#PageSize', function () {
//Do something after new value in #PageSize
});
Complete Example with ajax call - this working for my pager - count of item per list:
$(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);
}
});
});
});
Simple and easy to understand.
var mySearchTimeout;
$('#ctl00_mainContent_CaseSearch').keyup(function () {
clearTimeout(mySearchTimeout);
var filter = $(this).val();
mySearchTimeout = setTimeout(function () { myAjaxCall(filter); }, 700);
return true;
});
For passing parameters to your function along with ES6 syntax.
$(document).ready(() => {
let timer = null;
$('.classSelector').keydown(() => {
clearTimeout(timer);
timer = setTimeout(() => foo('params'), 500);
});
});
const foo = (params) => {
console.log(`In foo ${params}`);
}

Why does JQuery $.post submit twice?

Why does this call my Action twice? For background, using .change only works when a user clicks somewhere else on the form. Also .change will not fire when the browser is closed. Hence the timer combined with the data-dirty property check. Thanks in advance.
var timeoutId;
$(function() {
var formElements = $('#myformid').find('input, select, textarea').add('[form=myformid]').not(':disabled').each(function() {
$(this).attr('data-dirty', false).on('input propertychange change', function() {
var changedText = $(this).val();
var commentID = $(this).attr('id');
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
// Runs 1 second (1000 ms) after the last change
// Saving to DB Here
$.post('#Url.Action("UpdateComment", "CommentJournal")', {
"ChangedText": changedText,
"commentID": commentID
});
$(this).attr('data-dirty', true);
}, 1000);
});
});
});
//Controller
[HttpPost]
[AllowAnonymous]
public ActionResult UpdateComment(string changedText, string commentID) {
return null;
}
Probably because both input and change events are being fired, with the change firing more than 1000ms after input fired, since change only fires when focus leaves the control. Example:
var timerId = 0;
$("#field1").on("input change", function(event) {
var type = event.type;
clearTimeout(timerId);
timerId = setTimeout(function() {
console.log("timeout fired for '" + type + "'");
}, 1000);
});
<p>Type something in the first field, wait at least a second, then tab out of the field:</p>
<div>
<label>
First field:
<input type="text" id="field1">
</label>
</div>
<div>
<label>
second field:
<input type="text" id="field2">
</label>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
If you hook input, there's no need to hook change.

How to setInterval on ready, stop on textarea focus, then start on textarea focusout?

I have a social stream that I want to update with setInterval. SetInterval needs to be stopped when someone is leaving a comment or a reply otherwise it clears the content of the textarea because it is nested inside the content being updated.
I'm attempting to use this code, modified, from another answer, but it is failing in that it won't stop the timer after the first cycle of the setInterval timer.
HTML...
<div id="social_stream_content">
<textarea id="comments" rows="4" cols="50" placeholder="Set focus to stop timer"></textarea>
</div>
JS...
function auto_load(){
data = '<textarea id="comments" rows="4" cols="50" placeholder="Set focus to stop timer..."></textarea>';
$("#social_stream_content").html(data);
alert("auto_load invoked");
}
var myInterval;
var interval_delay = 10000;
var is_interval_running = false; //Optional
$(document).ready(function(){
auto_load(); //Call auto_load() function when document is Ready
//Refresh auto_load() function after 10000 milliseconds
myInterval = setInterval(interval_function, interval_delay);
$('textarea').focus(function () {
console.log('focus');
clearInterval(myInterval); // Clearing interval on window blur
is_interval_running = false; //Optional
}).focusout(function () {
console.log('focusout');
clearInterval(myInterval); // Clearing interval if for some reason it has not been cleared yet
if (!is_interval_running) //Optional
myInterval = setInterval(interval_function, interval_delay);
});
});
interval_function = function () {
is_interval_running = true; //Optional
// Code running while textarea is NOT in focus
auto_load();
}
Edit: I've updated the code to include everything as tested on JSfiddle. The timer will stop if you immediately set focus to the comment textarea after closing the alert at document ready.
After removing focus, and the first cycle of the interval timer completes, the timer will not stop again. The focus event seems to stop firing.
Is this because the comment textarea is nested inside the content area that is updating? I'm pulling my hair out. If I remove the nesting, it works as expected.
My caveat is that the comment textareas are always going to be nested inside of the social stream's content div, for obvious reasons.
So, to update the question further: Is there a way to get the interval timer to stop on textarea focus using jquery, while the focused element is nested inside the updating element? Why does the focus event stop firing after the first interval completes?
Edit: The complete JS code, working coreectly, with Jeremy Klukan's solution incorporated, for anyone doing the same type of project.
WORKING JS:
function auto_load(){
data = '<textarea id="comments" rows="4" cols="50" placeholder="Set focus to stop timer..."></textarea>';
$("#social_stream_content").html(data);
alert("auto_load invoked");
}
var myInterval;
var interval_delay = 10000;
var is_interval_running = false; //Optional
$(document).ready(function(){
auto_load(); //Call auto_load() function when document is Ready
//Refresh auto_load() function after 10000 milliseconds
myInterval = setInterval(interval_function, interval_delay);
$('body').on('focus', '#social_stream_content textarea', function (event) {
console.log('focus');
clearInterval(myInterval); // Clearing interval on window blur
is_interval_running = false; //Optional
}).on('focusout', '#social_stream_content textarea', function(event) {
console.log('focusout');
clearInterval(myInterval); // Clearing interval if for some reason it has not been cleared yet
if (!is_interval_running) //Optional
myInterval = setInterval(interval_function, interval_delay);
});
});
interval_function = function () {
is_interval_running = true; //Optional
// Code running while textarea is NOT in focus
auto_load();
}
You can detect focus and blur for a textarea using addEventListener (events: focus and blur).
You can end a setInterval() using clearInterval() passing anintervalID.
Below a simple working example showing the principal (in vanilla JavaScript).
Basically:
When page load timer starts.
When user focus textarea timer stops.
When user blur textarea timer starts again.
Documentation:
WindowTimers.clearInterval()
WindowTimers.setInterval()
You may also find of interest Document.activeElement.
window.app = {
timerRef: null,
timerStart: function() {
this.timerRef = setInterval(function() {
//alert("Hello");
console.log('refresh stream');
}, 2000);
},
timerStop:function(){
clearInterval(this.timerRef);
},
txtAreaListenFocus: function() {
var txtArea = document.getElementById('txtArea');
txtArea.addEventListener('focus', function(event) {
this.timerStop();
console.log('focus');
}.bind(this));
},
txtAreaListenBlur: function() {
var txtArea = document.getElementById('txtArea');
txtArea.addEventListener('blur', function(event) {
this.timerStart();
console.log('blur');
}.bind(this));
},
start: function() {
this.timerStart();
this.txtAreaListenFocus();
this.txtAreaListenBlur();
}
};
window.app.start();
<textarea id="txtArea" rows="4" cols="50">
Some content here
</textarea>
Jquery version below. You can use .focusout() and .focusin():
$(document).ready(function(){
window.app = {
timerRef: null,
timerStart: function() {
this.timerRef = setInterval(function() {
//alert("Hello");
console.log('refresh stream');
}, 2000);
},
timerStop:function(){
clearInterval(this.timerRef);
},
txtAreaListenFocus: function() {
$('#txtArea').focusin(function(event) {
this.timerStop();
console.log('focus');
}.bind(this));
},
txtAreaListenBlur: function() {
$('#txtArea').focusout(function(event) {
this.timerStart();
console.log('blur');
}.bind(this));
},
start: function() {
this.timerStart();
this.txtAreaListenFocus();
this.txtAreaListenBlur();
}
};
window.app.start();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="txtArea" rows="4" cols="50">
Some content here
</textarea>
Regarding specifically your code in question, I have fix it in the working example below.
$(document).ready(function() {
var myInterval;
var interval_delay = 1000;
var is_interval_running = false; //Optional
var interval_function = function() {
is_interval_running = true; //Optional
console.log('refresh stream');
// Code running while comment textarea is not in focus
//auto_load();
};
//auto_load(); //Call auto_load() function when DOM is Ready
//Refresh auto_load() function after 1000 milliseconds
myInterval = setInterval(interval_function, interval_delay);
$('#textarea').focus(function() {
clearInterval(myInterval); // Clearing interval on window blur
is_interval_running = false; //Optional
}).focusout(function() {
clearInterval(myInterval); // Clearing interval if for some reason it has not been cleared yet
if (!is_interval_running) //Optional
myInterval = setInterval(interval_function, interval_delay);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="textarea" rows="4" cols="50">
Some content here
</textarea>
The focus event stops working, because when your interval function fires, it is replacing the contents of the DIV that contains it, so that TEXTAREA no longer exists.
Do this instead:
$('body').on('focus', '#social_stream_content textarea', function (event) {
// Focus handler
}).on('focusout', '#social_stream_content textarea', function(event) {
// Focusout handler
});
This will capture all focus and focusout events that match the selector "#social_stream_content textarea" without directly attaching to either object.
My fix :D
HTML:
<div id="social_stream_content"></div>
jQuery:
var myInterval;
var interval_delay = 1000;
var is_interval_running = false; //Optional
$(document).ready(function(){
data = '<textarea id="comments" rows="4" cols="50" placeholder="Set focus to stop timer..."></textarea>';
$(data).appendTo("#social_stream_content");
//Refresh auto_load() function after 10000 milliseconds
var myInterval = setInterval(interval_function, interval_delay);
$('#comments').focus(function () {
console.log('focus');
clearInterval(myInterval); // Clearing interval on window blur
is_interval_running = false; //Optional
}).focusout(function () {
console.log('focusout');
clearInterval(myInterval); // Clearing interval if for some reason it has not been cleared yet
if (!is_interval_running) //Optional
myInterval = setInterval(interval_function, interval_delay);
});
});
interval_function = function () {
is_interval_running = true; //Optional
// Code running while textarea is NOT in focus
$("#comments").val("");
console.log("loop");
}
Hope it helps.

Run javascript function when user finishes typing instead of on key up?

I want to trigger an ajax request when the user has finished typing in a text box. I don't want it to run the function on every time the user types a letter because that would result in A LOT of ajax requests, however I don't want them to have to hit the enter button either.
Is there a way so I can detect when the user has finished typing and then do the ajax request?
Using jQuery here!
So, I'm going to guess finish typing means you just stop for a while, say 5 seconds. So with that in mind, let's start a timer when the user releases a key and clear it when they press one. I decided the input in question will be #myInput.
Making a few assumptions...
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 seconds 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
}
The chosen answer above does not work.
Because typingTimer is occassionaly set multiple times (keyup pressed twice before keydown is triggered for fast typers etc.) then it doesn't clear properly.
The solution below solves this problem and will call X seconds after finished as the OP requested. It also no longer requires the redundant keydown function. I have also added a check so that your function call won't happen if your input is empty.
//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
}
And the same code in vanilla JavaScript solution:
//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
}
This solution does use ES6 but it's not necessary here. Just replace let with var and the arrow function with a regular function.
It's just one line with underscore.js debounce function:
$('#my-input-box').keyup(_.debounce(doSomething , 500));
This basically says doSomething 500 milliseconds after I stop typing.
For more info: http://underscorejs.org/#debounce
Late answer but I'm adding it because it's 2019 and this is entirely achievable using pretty ES6, no third party libraries, and I find most of the highly rated answers are bulky and weighed down with too many variables.
Elegant solution taken from this excellent blog post.
function debounce(callback, wait) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(function () { callback.apply(this, 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))
Yes, you can set a timeout of say 2 seconds on each and every key up event which will fire an ajax request. You can also store the XHR method and abort it on subsequent key press events so that you save bandwith even more. Here's something I've written for an autocomplete script of mine.
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
});
Hope this helps,
Marko
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);
}
});
full example here: http://jsfiddle.net/ZYXp4/8/
Both top 2 answers doesn't work for me. So, here is my solution:
var timeout = null;
$('#myInput').keyup(function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
//do stuff here
}, 500);
});
Declare the following delay function:
var delay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})()
and then use it:
let $filter = $('#item-filter');
$filter.on('keydown', function () {
delay(function () {
console.log('this will hit, once user has not typed for 1 second');
}, 1000);
});
Modifying the accepted answer to handle additional cases such as paste:
//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
}
I like Surreal Dream's answer but I found that my "doneTyping" function would fire for every keypress, i.e. if you type "Hello" really quickly; instead of firing just once when you stop typing, the function would fire 5 times.
The problem was that the javascript setTimeout function doesn't appear to overwrite or kill the any old timeouts that have been set, but if you do it yourself it works! So I just added a clearTimeout call just before the setTimeout if the typingTimer is set. See below:
//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. I would have liked to have just added this as a comment to Surreal Dream's answer but I'm a new user and don't have enough reputation. Sorry!
I don't think keyDown event is necessary in this case (please tell me why if I'm wrong). In my (non-jquery) script similar solution looks like that:
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)
}
}
It's my first reply on Stack Overflow, so I hope this helps someone, someday:)
const inText = document.getElementById('inText')
const outText = document.getElementById('outText')
const delay = 1000
let timer
inText.addEventListener('input', code => {
clearTimeout(timer);
timer = setTimeout(x => {
outText.innerHTML = inText.value
}, delay, code)
})
<textarea id='inText'>edit this and...</textarea>
<pre id='outText'>see the results after you stop typing for one second</pre>
Well, strictly speaking no, as the computer cannot guess when the user has finished typing. You could of course fire a timer on key up, and reset it on every subsequent key up. If the timer expires, the user hasn't typed for the timer duration - you could call that "finished typing".
If you expect users to make pauses while typing, there's no way to know when they are done.
(Unless of course you can tell from the data when they are done)
agree with the #going 's answer. Another similar solution that worked for me is the one below. The only difference is that I am using .on("input"...) instead of keyup. This only captures changes in the input. other keys like Ctrl, Shift etc. are ignored
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);
});
I was implementing the search at my listing and needed it to be ajax based. That means that on every key change, searched results should be updated and displayed. This results in so many ajax calls sent to server, which is not a good thing.
After some working, I made an approach to ping the server when the user stops typing.
This solution worked for me:
$(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
You will notice that there is no need to use any timer while implementing this.
I feel like the solution is somewhat a bit simpler with the input event:
var typingTimer;
var doneTypingInterval = 500;
$("#myInput").on("input", function () {
window.clearTimeout(typingTimer);
typingTimer = window.setTimeout(doneTyping, doneTypingInterval);
});
function doneTyping () {
// code here
}
I just figured out a simple code to wait for user to finish typing:
step 1.set time out to null then clear the current timeout when the user is typing.
step 2.trigger clear timeout to the variable define before keyup event is triggered.
step 3.define timeout to the variable declared above;
<input type="text" id="input" placeholder="please type" style="padding-left:20px;"/>
<div class="data"></div>
javascript code
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);
};
This is the a simple JS code I wrote:
<!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>
Why not just use onfocusout?
https://www.w3schools.com/jsreF/event_onfocusout.asp
If it's a form, they will always leave focus of every input field in order to click the submit button so you know no input will miss out on getting its onfocusout event handler called.
Multiple timers per page
All the other answers only work for one control (my other answer included).
If you have multiple controls per page (e.g. in a shopping cart) only the last control where the user typed something will get called. In my case this is certainly not the wished behaviour - each control should have its own timer.
To solve this, you simply have to pass an ID to the function and maintain a timeoutHandles dictionary as in the following code:
Function Declaration:
var delayUserInput = (function () {
var timeoutHandles = {};
return function (id, callback, ms) {
if (timeoutHandles[id]) {
clearTimeout(timeoutHandles[id]);
}
timeoutHandles[id] = setTimeout(callback, ms);
};
})();
Function Usage:
delayUserInput('yourID', function () {
//do some stuff
}, 1000);
Here is a solution that fires after 1 second of not typing, but also fires instantly when the input is blank. This is useful when clearing search results after the user deletes the input query. This solution also supports copying and pasting into the search box. The $(() => { ... }); wrapping the top portion of code simply means "do this when the page is loaded" in simple Jquery terms.
var searchTimer;
var searchInterval = 1000;
$(() => {
$('#search-box').on('input', (event) => {
clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
searchContacts(event.target.value);
}, (event.target.value.length > 0) ? searchInterval : 0);
});
});
function searchContacts(val) {
console.log('searching: ' + val);
}
You can use the onblur event to detect when the textbox loses focus:
https://developer.mozilla.org/en/DOM/element.onblur
That's not the same as "stops typing", if you care about the case where the user types a bunch of stuff and then sits there with the textbox still focused.
For that I would suggest tying a setTimeout to the onclick event, and assuming that after x amount of time with no keystrokes, the user has stopped typing.
If there is necessity for the user to move away from the field, we can use "onBlur" instead of Onchange in Javascript
<TextField id="outlined-basic" variant="outlined" defaultValue={CardValue} onBlur={cardTitleFn} />
If that is not necessary setting timer would be the good option.
for alpine.js users <input #input.debounce.500ms="fn()">
Once you detect focus on the text box, on key up do a timeout check, and reset it each time it's triggered.
When the timeout completes, do your ajax request.
If you are looking for a specific length (such as a zipcode field):
$("input").live("keyup", function( event ){
if(this.value.length == this.getAttribute('maxlength')) {
//make ajax request here after.
}
});
Not sure if my needs are just kind of weird, but I needed something similar to this and this is what I ended up using:
$('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');
});
Which allows me to have elements like this in my application:
<input type="text" data-url="/controller/action/" class="update">
Which get updated when the user is "done typing" (no action for 2 seconds) or goes to another field (blurs out of the element)
If you need wait until user is finished with typing use simple this:
$(document).on('change','#PageSize', function () {
//Do something after new value in #PageSize
});
Complete Example with ajax call - this working for my pager - count of item per list:
$(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);
}
});
});
});
Simple and easy to understand.
var mySearchTimeout;
$('#ctl00_mainContent_CaseSearch').keyup(function () {
clearTimeout(mySearchTimeout);
var filter = $(this).val();
mySearchTimeout = setTimeout(function () { myAjaxCall(filter); }, 700);
return true;
});
For passing parameters to your function along with ES6 syntax.
$(document).ready(() => {
let timer = null;
$('.classSelector').keydown(() => {
clearTimeout(timer);
timer = setTimeout(() => foo('params'), 500);
});
});
const foo = (params) => {
console.log(`In foo ${params}`);
}

Categories