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

34

620

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!

Chardin answered 18/11, 2010 at 22:13 Comment(5)
I think you'll need to define "finish typing" for us.Kellikellia
While @Surreal Dreams' answer satisfies most of your requirements, if the user starts typing again AFTER the specified timeout, multiple requests will be sent to the server. See my answer below which stores each XHR request in a variable and cancels it before firing off a new one. This is actually what Google does in their Instant search.Churchman
The chosen answer is incorrect for a few reasons: 1. It always fires after 5 seconds even if user is typing. 2. It doesn't wait until user has finished typing as requested. 3. It fires multiple requests as mentioned by @Churchman above. See my corrected answer below.Stumpage
What about blur? I guess the user has definitely finished typing when the input element loses focus.Stupid
A simple google search could've gotten you the simple answer: schier.co/blog/2014/12/08/…Ladyinwaiting
K
823

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
}
Kellikellia answered 18/11, 2010 at 22:18 Comment(24)
Thanks :) I started typing my comment on the question and realized I had a decent idea.Kellikellia
Sorry to be a pain in the @ss, but you've got keyup twice instead of keydown on the 2nd event, and textbox isn't a valid selector since there isn't a textbox element :)Churchman
you have keyup typo instead of keydownCurio
Thanks for the notes on the typo, I fixed it. I also updated the selector to be a little more real-world.Kellikellia
This answer does not work correctly, it will always fire after 5 seconds unless the user types very slowly. See working solution below.Stumpage
If you run into trouble here, because the timer fires immediately, try to add quotes around the function call: setTimeout('functionToBeCalled', doneTypingInterval);Breathless
Doesn't work when you copy/paste data into the field.Throes
@Breathless setTimeout() should not be called with a string as the first parameter. Doing so is equivalent to using eval().Hubie
@Macmee - I went ahead and incorporated your suggested edit - I think it's a valid improvement. Please feel free to add any further comment.Kellikellia
Shouldn't this be typingTimer = setTimeout(function() {doneTyping(); }, doneTypingInterval); Just curious. The above mentioned answer didn't work for me :/Landau
I'm seeing a few comments where the callback function, doneTyping in the example, is running immediately. That's usually a result of accidentally including () after the function name. Note that it should read setTimeout(doneTyping, not setTimeout(doneTyping(),Kalikow
@SurrealDreams Hi dear, i have tested your answer for my question but it is not working. If you have a time can you check my QUESTION for me ?Tuckerbag
@Throes to work with paste you have to add 'paste' event like this: on('keyup paste',Capillary
@Capillary - thanks for the comment, that's really useful.Kellikellia
I scrapped the separate keydown function and just added it to the first function. I also added change in there. So it reads like this twitterUsernameField.on('keyup keydown change', function () { and it appears to work fine...Sportsmanship
can i use this in my production ? :DEldridgeeldritch
@colinrickels - go for it. I hope you find it useful.Kellikellia
Here is the code above jsfiddle.net/matt_doran/g0rrj540/4Invitation
worked for me from copy-paste, i just changed my element on this code var $input = $('#myInput');Petrarch
Is there a way we can pass the keyup event to doneTyping function without triggering it immediately?Skeleton
instead of timing, one should consider the string length in the search bar! user can write only 1 character and wait for 5 seconds so better to check string size.Opportunism
I was trying to build a similar function and was apparently way over complicating it. This helped me hash our what I was doing wrong. Thanks!Horton
very very very very high quality @SurrealDreams thanksConde
@Ye'ThuraAg - You can! setTimeout() accepts additional arguments. Any arguments supplied after the interval are used in the call to the delayed function. For instance, to pop up an alert in 5 seconds, you could do setTimeout(alert, 5000, "It's been 5 seconds")Kellikellia
S
482

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.

Stumpage answered 8/5, 2011 at 10:5 Comment(12)
I believe the problem you are having is that you are typing fast enough that you push the second key before releasing the first.Conventionalism
This isn't a problem he is experiencing, it's a problem any user could duplicate as I've just done. Imagine if at the end of the timeout you postback ajax to the server and do something with a response. The accepted answer would have posted back repeatedy for me. Put an alert and type very fast. It will not only trigger at the end of the timeout, for me, it triggered repeatedly. This is the most complete answer, and it uses less code, kudos.Gillenwater
Well, it might be useful to still call the function even if the input is empty. What if you want to clear some search results (for example) when the input is blank again?Talc
I think we should also consider the condition where the user simply pastes come string inside the field .Steepen
use $('#myInput').on('input', function() { if you want this to work with copy and paste. I don't see the point of the check if input is empty. Supposing he wants to erase what he typed this will fail to make the ajax call.Glazing
Why it's if ($('#myInput').val) instead of if ($('#myInput').val())? Should .val be a function?Rawhide
Why not use $(this).val()?Swarey
@Swarey or just this.value, it is so close that you don't need extra effort.Spiv
for me it calls the function immediately :/ not after the 5 seconds, i've tried increasing the time, but the same thing happensCohesive
@Xsmael, I think passing an argument directly to the setTimeout like this: setTimeout(doneTyping(argument), doneTypingInterval); makes the function run twice.Grantinaid
You can pass the event's argument to the setTimeout function using its 3rd parameter. MDN function doneTyping(evt) {...} myInput.addEventListener('keyup', evt => { clearTimeout(typingTimer); if (myInput.value) { typingTimer = setTimeout(doneTyping, doneTypingInterval, evt); } });Contrabassoon
it works perfect for me however is it normal that after the function is called the first time, it will not be called again? what is the user type again after 5 seconds? thanksGanda
R
88

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

Redundant answered 1/5, 2013 at 19:4 Comment(7)
Seems to be available for jQuery, too: code.google.com/p/jquery-debounce and github.com/diaspora/jquery-debounceJovial
It amazes me how people tout "ONE LINE OF CODE" as being critically important. Great. ONE LINE of code that requires a 1.1k JS file to load. I am not downvoting this because is a solution. But the one line bold thing irks me as well as leading to bloat code.Theroid
@Wolfie, I agree with you about code bloat but Underscore and Lodash are the top two depended-upon utilities at NPM so this may be a one-line solution for many people.Relationship
@Relationship I agree that if you are loading the libraries for other purposes, its fine and actually beneficial to use common code. But to load over a K of code for the purpose of one line isn't efficient. Especially with mobile platforms becoming less and less unlimited data. And many Euro areas also pay for internet by the data. So its good to pay attention to bloat when reasonable to do so.Theroid
why i got : Uncaught ReferenceError: _ is not definedTowne
@Theroid He does give the qualifier that it is one line WITH underscore.Merous
You can just get the debouce() function, npmjs.com/package/debounce if that's all you need. Works pretty well.Ilene
W
81

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))
Womankind answered 2/9, 2019 at 21:57 Comment(6)
This really should be the top answer given the yearClerkly
Edited to further remove unneeded variables - can get around having to encapsulate this by passing in a normal instead of arrow function to setTimeout()Womankind
how would I get the event inside the event handler function?Haydeehayden
Why does this not work outside of an event listener? e.g. if I run debounce(() => {alert("test")}, 1000), and I do not run it again within 1000ms, shouldn't it run the callback and alert test?Sashenka
This solution is not working. Also any other solution I found is not working @WomankindBrassbound
@Brassbound I can’t help you if your description of the problem is “it’s not working”. Consider opening your own SO question and linking back to this thread. Peace.Womankind
C
48

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

Churchman answered 18/11, 2010 at 22:19 Comment(3)
I would not recommend this. The code triggers an API request each time a key is pressed. Then it cancels the request if another key is pressed. Even though this solution prevents the AJAX callback to be triggered while the user types, it will still hammer the server with requests.Goddess
Ixg, no this won't. The clearTimeout function he uses clears the previous Timeout events, therefor invoking the API call.Hugmetight
@JohnSmith, i disagree it's probably better to first clear the timer, then check if xhr is empty or whatever your condition might be and finally run the timer with the ajax callMayworm
T
22
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/

Tetchy answered 14/8, 2012 at 13:11 Comment(1)
This worked for me, though keep in mind that when the user tabs-out of the text box you won't get a keyup event as it has lost focus by that point. Setting it to keydown instead seems to solve the problem.Oza
M
17

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);
});
Mogerly answered 8/2, 2018 at 7:11 Comment(0)
M
14

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
}
Metaphosphate answered 30/8, 2016 at 18:45 Comment(0)
I
13

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);
});    
Infantryman answered 24/1, 2019 at 15:11 Comment(3)
Your solution is fantastic, bro!Imena
@Developer Thanks a lot. I've also added another answer to solve a bit more complex scenario (multiple controls per page).Infantryman
good solution. Im using this but instead of keydown im using the 'input' eventHymnology
H
11

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!

Hyperbole answered 15/1, 2014 at 11:7 Comment(0)
T
9

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>
Teferi answered 9/3, 2022 at 23:13 Comment(1)
Perfect! Nice job which works as expectedClothes
S
6

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

Sybilla answered 5/10, 2011 at 19:44 Comment(0)
H
4

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)

Homeopathist answered 18/11, 2010 at 22:16 Comment(0)
W
4

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.

Wobbly answered 28/8, 2013 at 10:3 Comment(0)
M
4

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);
});
Mcmahan answered 15/3, 2017 at 9:39 Comment(0)
M
3

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
}
Maghutte answered 26/4, 2016 at 13:35 Comment(0)
C
3

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);
};
Chaldea answered 13/1, 2018 at 16:18 Comment(1)
the question is already answered... and it is pretty similar to thisOpsonize
H
2

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>
Hobgoblin answered 22/2, 2015 at 1:45 Comment(0)
S
2

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.

Stepsister answered 28/8, 2017 at 23:47 Comment(2)
onfocusout had poor support when the question was asked (nearly 7 years ago now), and also the effect with onfocusout would be somewhat different. You would have to wait for the user to leave focus on the element whereas with the timeout/debounce solution it "fires" as soon as the user stops typing and the user is not required to switch focus. A use case example would be one of those registration forms where when the user stops entering a potential username a checkmark or "X" appears to the right of the form field indicating that the name is available.Chardin
if the search bar is on focus, no one needs to come outside, after some time result will be directly shown as no open is typing any moreAnalgesia
I
2

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);
Infantryman answered 26/4, 2019 at 6:16 Comment(0)
L
2

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);
}
Lepus answered 1/2, 2022 at 13:32 Comment(0)
L
1

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.

Leveridge answered 18/11, 2010 at 22:17 Comment(0)
S
1

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.

Soil answered 19/12, 2019 at 10:51 Comment(0)
R
1

for alpine.js users <input @input.debounce.500ms="fn()">

Relationship answered 16/11, 2022 at 4:41 Comment(0)
C
0

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.

Charleycharlie answered 18/11, 2010 at 22:16 Comment(0)
D
0

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.
    }
  });
Dylan answered 9/7, 2012 at 12:42 Comment(1)
Not a bad idea to do limited validation prior to sending the ajax request.Beetner
M
0

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)

Materialize answered 25/10, 2012 at 16:33 Comment(0)
E
0

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);
            }
        });  
    });
});    
Ebracteate answered 23/1, 2016 at 22:32 Comment(0)
L
0

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;
});
Limpet answered 7/10, 2019 at 2:38 Comment(0)
B
0

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}`);
}
Batsman answered 20/10, 2019 at 10:16 Comment(0)
F
0

Not a direct answer bu if someone looking for an AngularJS solution. I wrote a directive according to the popular solutions here.

 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();
        });
    };
}]);
Forgave answered 15/10, 2020 at 15:36 Comment(1)
You should also add an example of how to use the directive in template.Romulus
I
0

You guys have heard of closures in javascript ?!

it's very simple and straightforward just compare you current input value with the old value that the setTimeOut function closes over, and voila, you're done.

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);
})
Ingather answered 14/12, 2020 at 11:43 Comment(0)
N
0

I needed mine to run for a specific control and this worked for me :

function debounce(func, timeout) {
            let timer;
            return (...args) => {
                clearTimeout(timer);
                timer = setTimeout(() => { func.apply(this, args); }, timeout);
            };
        }

$('#txtFilterClientCode').keyup(debounce(function () {
            console.log("Test");
        }, 1000));
Nag answered 17/11, 2021 at 8:30 Comment(0)
H
-2

Wow, even 3 comments are pretty correct!

  1. Empty input is not a reason to skip function call, e.g. I remove waste parameter from url before redirect

  2. .on ('input', function() { ... }); should be used to trigger keyup, paste and change events

  3. definitely .val() or .value must be used

  4. You can use $(this) inside event function instead of #id to work with multiple inputs

  5. (my decision) I use anonymous function instead of doneTyping in setTimeout to easily access $(this) from n.4, but you need to save it first like var $currentInput = $(this);

EDIT I see that some people don't understand directions without the possibility to copy-paste ready code. Here you're

var typingTimer;
//                  2
$("#myinput").on('input', function () {
    //             4     3
    var input = $(this).val();
    clearTimeout(typingTimer);
    //                           5
    typingTimer = setTimeout(function() {
        // do something with input
        alert(input);
    }, 5000);      
});
Hapte answered 14/8, 2015 at 13:32 Comment(3)
How this answers the question?Busybody
@ThomasOrlita this answer supplements 3 most rated answers. Take a look at accepted one: 1. it doesn't support paste, it doesn't use this, etc. (I think it's important but I don't want to get lost in tons of comments)Hapte
This does not answer the question. If you would like to comment about another answer, there is a commenting system (I'm using it right now!)Womankind

© 2022 - 2024 — McMap. All rights reserved.