jQuery 2.0.3
I want to fire off an AJAX call when data changes in an edit input control. I realise I can do this via the onChange event. However if the user enters: 123 I don't want to fire the AJAX 3 times.
Instead I want to wait for a "setting period" and then fire off the call. The setting period gets reset each time the control changes. So the idea being as I type 123 quickly, some time passes (settling) and I make the AJAX call.
Does anyone have any suggestions on how to implement this with jQuery? Are there any constructs I can use in jQuery to do this?
You'll need to throttle the event with a timeout
$('input').on('keyup', function() {
var self = this;
clearTimeout( $(this).data('timer') );
$(this).data('timer',
setTimeout(function() {
$.ajax({
url : 'someurl.php',
data : self.value
});
}, 500)
)
})
Easy way is with setTimeout / clearTimeout on the change event:
var timeout = null;
$('input').bind('keyup blur', function() {
if (timeout !== null) clearTimeout(timeout);
timeout = setTimeout(function() {
// Make your ajax request here
}, 300);
});
Change the 300 to number of milliseconds you want to have to wait before the ajax request is made.
Related
I have a large form on my website that I want to be able to autosave to a database as the user is filling it out. Almost identical to how google drive works when typing a document.
I am trying not to have a function that runs every X seconds but rather a function that runs when the user has taken a break in typing. So, if the user has not typed in 1 hour but is still on the page, it doesn't keep pushing save requests.
This is all I have so far which is a basic javascript form submit.
$("#page1Form").submit(function(event){
event.preventDefault();
$changesSaved.text("Saving...");
var url = "/backend/forms/page1-POST.php";
$.ajax({
type: "POST",
url: url,
data: $("#page1Form").serialize(),
success: function(data) { $changesSaved.text(data); }
});
return false;
});
Debounce the textarea change.
Demo: jsFiddle
Put your ajax call in the saveToDB() function. These event names('input propertychange change') will trigger on any form element change such as radio buttons, inputs, etc.
var timeoutId;
$('#the-textarea').on('input propertychange change', function() {
console.log('Textarea Change');
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
// Runs 1 second (1000 ms) after the last change
saveToDB();
}, 1000);
});
function saveToDB()
{
console.log('Saving to the db');
}
Here is a full demo showing you how to debounce a full form and use ajax to send the data and then return the status (Saving, Saved, etc).
Demo full form and ajax: jsFiddle
I know that this question is old, but I would like to include a code that I like the most. I found it here:
http://codetunnel.io/how-to-implement-autosave-in-your-web-app/
Here is the code:
var $status = $('#status'),
$commentBox = $('#commentBox'),
timeoutId;
$commentBox.keypress(function () {
$status.attr('class', 'pending').text('changes pending');
// If a timer was already started, clear it.
if (timeoutId) clearTimeout(timeoutId);
// Set timer that will save comment when it fires.
timeoutId = setTimeout(function () {
// Make ajax call to save data.
$status.attr('class', 'saved').text('changes saved');
}, 750);
});
It saves after the user stops writing for more than 750 milliseconds.
It also has a status letting the user know that the changes have been saved or not.
Try Sisyphus.js https://github.com/simsalabim/sisyphus. It persists the form data in the browser's local storage and is robust against tabs closing, browser crashes, etc...
I'm sending an ajax request to the server on user's input to an <input> element, like this:
$('#my-input').bind("input", function(event){
// here's the ajax request
});
What bothers me is that it send unnecessarily many requests on every user's keyup, meaning that if the user types very fast, there are many unnecessary requests. So I get the idea that there should be a certain delay/timeout, which waits a certain time (50 miliseconds?) for the user to stop typing before sending the ajax request. That would be one problem solved.
But what about cases when the first ajax request haven't been completed before sending another request? (Typing 60 ms / char while ajax request taking 300 ms).
What is the best way to solve this problem (both idea- and code-based)?
You can use throttle function in underscore library. As its documentation says:
Creates and returns a new, throttled version of the passed function, that, when invoked repeatedly, will only actually call the original function at most once per every wait milliseconds. Useful for rate-limiting events that occur faster than you can keep up with.
Even if you don't want to introduce a new library, you can still get idea about how this function works from its source code. In fact, a simple version of throttle function could be:
function throttle(func, delay) {
var timeout = null;
return function() {
var that = this, args = arguments;
clearTimeout(timer);
timeout = setTimeout(function() {
func.apply(that, args);
}, delay);
};
}
This jQuery throttle-debounce plugin is also helpful. Especially, the debounce function seems more suitable to your needs than throttle function according to its author:
Debouncing can be especially useful for rate limiting execution of handlers on events that will trigger AJAX requests
You could just use the setTimeout function. Every so often, see if the text hasn't changed, and if it hasn't, then process accordingly.
setTimeout(function() {
// Do something after 1 second
}, 1000);
You can set async: false in your ajax request so it will process second ajax call only after completion of first ajax request.
I'd go with #HuiZeng's answer, but just in case you want a slightly modified version.
Steps
Listen to keydown using a setTimeout that you can clear.
When it fires, check if you have a previous request in queue, if so abort it and fire a new one
Example:
var inputTimer = 0, req;
function onInput(e){
clearTimeout(inputTImer);
inputTimer = setTimeout( function(){
// You have access to e here
// Cancel any previous requests
req && req.abort();
req = $.ajax({/*...Do your magic here :)*/})
}, 100)
}
I have a jQuery Ajax request, that I want to call with text input, and so I nested it inside keyup(function(). This works fine.
$("#text_box").keyup(function() {
//AJAX REQUEST
});
But this behaves buggy sometimes. When I input some text very fast, I am getting results for input word with some last letters of the original input word omitted (may be some fault with browser). I want the ajax request to be sent when there is no input activity for a second, I mean, if I input text very fast and rest for a second (means I made the input). How can I do this?
It sounds as if you get results from a previous ajax call. Use a timer with setTimeout and clearTimeout.
var timer = null;
$("#text_box").keyup(function() {
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(someFunction, someDelay);
});
Where someFunction is a function which does your ajax call and someDelay is the delay you want to wait before doing the call, after the user has typed, in ms.
As you are already using jQuery you could use the debounce plugin from Ben Aleman.
Example from the page
// Bind the not-at-all debounced handler to the keyup event.
$('input.text').keyup( text_1 );
// Bind the debounced handler to the keyup event.
$('input.text').keyup( $.debounce( 250, text_2 ) ); // This is the line you want!
omg. for somebody who will search in 2014...
function sendAjax() {
setTimeout(
function() {
$.ajax({
url: "url.php",
type: "POST",
data: data,
success: function(data) {
$("#result").html(data);
}
});
}, 2000);
}
<input onkeyup="function()">
Is there any way to time how long a jquery ajax request has been going on? sometimes searches take too long and it would be nice to add a jquery abort() button if the search takes over, say, 5 seconds. Any way I can do this!
On the other end of the ajax request is a php file that makes a postgresql request.
Much thanks for any ideas!
Take a look at the timeout option (http://api.jquery.com/jQuery.ajax/). You can set it on a particular call, or globally with $.ajaxSetup().
To have the abort button appear after 5 seconds, add a setTimeout function after your call to send. Once the AJAX command is complete, you can add code to clear the timeout and remove the abort button if it exists.
var timeOutID = 0;
$.ajax({
url: 'ajax/test.html',
success: function(data) {
clearTimeOut(timeOutID);
// Remove the abort button if it exists.
}
});
timeOutID = setTimeout(function() {
// Add the abort button here.
}, 5000);
This way the abort button will never appear if AJAX returns quick enough.
Usually, I'll set a timeout once the request is sent that will trigger after 10 seconds or so and then fallback on something else to make sure it still happens (for example, form submission).
So set a variable to false, var failed = false; and do the request
At the same time that the request starts, set a timeout:
setTimeout(function() {
failed = true;
$("#form").submit();
return false;
}, 10000);
In the return function of the ajax call, check to see if the failed variable has been set to true, and if it has, don't actually do whatever it was originally trying, otherwise it could mess something up, or confuse the user if something else is happening (since these things usually happen on slower internet connections, if the next step appears while a new page is loading, they might try to interact and then the page will change).
$.post("ajaxcall.php", {'etc': "etc"},
function(returned) {
if (failed != true) {
//do whatever with returned variable
}
});
var timer = 0,
XHR = $.ajax({
url: 'ajax/mypage.html',
beforeSend: function() {
timer=setTimeout(showAbort, 5000);
}
});
function showAbort() {
$('<input type="button" value="Abort" id="abort_button"/>').appendTo('#some_parent');
$('#abort_button').on('click', function() {
XHR.abort(); //abort the Ajax call
});
}
XHR.always(function() { //fires on both fail and done
clearTimeout(timer);
if ($('#abort_button').length) {
$('#abort_button').remove(); //remove button if exists
}
});
What is the best way to set timeout that will force my page not to set more than one ajax request per minute
Thanks in advance!
I'd use a simple variable holding the timerId returned from setTimeout. Something like this:
var timerId;
var doRequest = function(){
if(timerId) return;
timerId = setTimeout(doRequest, 60*1000);
// ajax code here
};
This will throttle the request to once per minute. If you need to stop the setTimeout call, then simply add another boolean based off the user event you are watching for.