Send a XHR when user "completes" the input instead of keyup - javascript

The HTML code: <input id="goTOxQuestion">
The js code:
$("#goTOxQuestion").keyup(function(){
// send a XHR
})
If the input is 12345,it will send the XHR five times.In fact, I only want the XHR be executed when I have completed the input. I mean,there is no input( no keydown event )in 500 milliseconds, rather then it loses faocus.
My incomplete solution:
var isOver = false;
$("#goTOxQuestion").keyup(function(){
//...
setTimeout(function(){
if(isOver){
//send a XHR
}
},500);
})
$("#goTOxQuestion").keydown(function(){
isOver = false;
})

You can use a combination of setTimeout and clearTimeout like this:
var hTimeout;
$("#goTOxQuestion").keyup(function () {
if (hTimeout) {
clearTimeout(hTimeout);
}
hTimeout = setTimeout(function () {
// ajax code here
}, 500);
});
Demo here
Note that the order in which AJAX requests complete is not guaranteed and you will end up with "race conditions".
Regarding your comment, here is a solution from the top of my mind:
// initialize global counter
var xhrCount = 0;
// increment counter when you create an XHR
xhrCount++;
// pass the current value of this
// variable to the success function
// http://stackoverflow.com/q/1552941/87015
$.ajax("/url/", (function (myStamp) {
console.log("creating success callback #" + myStamp);
return function () {
if (myStamp === xhrCount) {
console.log("firing success handler");
} else {
console.log("suppressing success handler");
}
}
})(xhrCount));

Use setTimeout then:
$("#goTOxQuestion").keyup(function(){
setTimeout(function(){
// send a XHR
}, 1000);
})

The change event seems like a good fit for your needs :
$("#goTOxQuestion").change(function(){
// send a XHR
})
It will be triggered when the input looses focus and the input value was actually modified.

$(document).on('blur',"#goTOxQuestion",function(){
// send a XHR
});

Related

In jQuery how to wait for specific value on variable

I have an variable
var IsAjaxing;
I set it to true everytime a ajax is fired on the page. And then set it to false when ajax is finished;
I am building a SafeAjaxing event so work would only be done when the page is not ajaxing:
// safe-ajaxing: Triggers when no ajax is running
$($fieldRenderPageDOM).on("safe-ajaxing", '.field-render', function(e, work) {
$.when({ IsAjaxing: false }).done(work);
});
This doesn't seem to wait, work is always called immediately.
It would be called like this:
$fieldDOM.trigger("safe-ajaxing", function () {
$fieldDOM.trigger("do-work");
$fieldDOM.trigger("do-some-more-work);
});
You should use promises for this purpose:
var IsAjaxing = function(){
var defer = $.Deferred().resolve();
return {
On: function(){
defer = $.Deferred();
},
Off: function(){
defer.resolve();
},
Promise: function() {
return defer.promise();
},
IsOn: function() {
return defer.state() == "pending";
},
IsOff: function() {
return defer.state() != "pending";
}
};
}();
And then your event will be:
// safe-ajaxing: Triggers when no ajax is running
$($fieldRenderPageDOM).on("safe-ajaxing", '.field-render', function(e, work) {
$.when(IsAjaxing.Promise()).done(work);
});
Each time when you start ajax request run:
IsAjaxing.On();
Each time when you finish ajax run:
IsAjaxing.Off();
To check the current state of IsAjaxing, call the IsOn and IsOff function.
This might not be the best way, but it works.
You really should optimize the code i've written, but this is to get you started.
var isAjaxing = false;
var check = function(){
if(isAjaxing){
// do something
alert();
// freeze the checking
// manual restart is required
clearInterval(interval);
}
}
var interval = setInterval(check, 10);
// to demonstrate the variable change
setInterval(function(){
isAjaxing = true;
}, 3000);
This scripts checks if the variable is changed every 10 miliseconds.
Note: The clearInterval() function is used to stop checking.
I am building a SafeAjaxing event so work would only be done when the page is not ajaxing.
Don't build this yourself. Just use the builtin ajax events of jQuery, namely
ajaxStart "This event is triggered if an Ajax request is started and no other Ajax requests are currently running."
ajaxStop "This global event is triggered if there are no more Ajax requests being processed."

Javascript- How to check if operation has been completed on this event

Is there any way to check if the event is completed and element is free to perform another action?
Like I want to do
$('#button-cancel').on('click', function() {
// send ajax call
});
/****************************************
extra code
*******************************************/
$('#button-cancel').on('click', function() {
if(ajax call is completed) {
//do some thing
}
});
I don't want to send ajax call in second onclick as it is already been sent, just want to check if it is done with ajax then do this
You can introduce a helper variable:
// introduce variable
var wasAjaxRun = false;
$('#button-cancel').on('click', function() {
// in ajax complete event you change the value of variable:
$.ajax({
url: "yoururl"
// other parameters
}).done(function() {
// your other handling logic
wasAjaxRun = true;
});
});
$('#button-cancel').on('click', function() {
if(wasAjaxRun === true) {
//do some thing
}
});
EDIT: I just noticed that you have event handlers attached to the same button. In that case my initial answer would not work, because first event hander would be executed every time you click the button.
It is not very clear from the description what you want to do with your first event hander. I assume you want to use some data, and if you already have this data, then you use it immediately (like in second handler), if you don't have it - you make the AJAX call to get the data (like in first handler).
For such scenario you could use single event handler with some conditions:
var isAjaxRunning = false; // true only if AJAX call is in progress
var dataYouNeed; // stores the data that you need
$('#button-cancel').on('click', function() {
if(isAjaxRunning){
return; // if AJAX is in progress there is nothing we can do
}
// check if you already have the data, this assumes you data cannot be falsey
if(dataYouNeed){
// You already have the data
// perform the logic you had in your second event handler
}
else { // no data, you need to get it using AJAX
isAjaxRunning = true; // set the flag to prevent multiple AJAX calls
$.ajax({
url: "yoururl"
}).done(function(result) {
dataYouNeed = result;
}).always(function(){
isAjaxRunning = false;
});
}
});
You should be able to provide handlers for AJAX return codes. e.g
$.ajax({
type: "post", url: "/SomeController/SomeAction",
success: function (data, text) {
//...
},
error: function (request, status, error) {
alert(request.responseText);
}
});
you can disable the button as soon as it enters in to the event and enable it back in ajax success or error method
$('#button-cancel').on('click', function() {
// Disable button
if(ajax call is completed) {
//do some thing
//enable it back
}
});
This is edited, more complete version of dotnetums's answer, which looks like will only work once..
// introduce variable
var ajaxIsRunning = false;
$('#button').on('click', function() {
// check state of variable, if running quit.
if(ajaxIsRunning) return al("please wait, ajax is running..");
// Else mark it to true
ajaxIsRunning = true;
// in ajax complete event you change the value of variable:
$.ajax({
url: "yoururl"
}).done(function() {
// Set it back to false so the button can be used again
ajaxIsRunning = false;
});
});
You just need to set a flag that indicates ajax call is underway, then clear it when ajax call returns.
var ajaxProcessing = false;
$('#button-cancel').on('click', function(){
processAjaxCall();
});
function processAjaxCall() {
if(ajaxProcessing) return;
ajaxProcessing = true; //set the flag
$.ajax({
url: 'http://stackoverflow.com/questions/36506931/javascript-how-to-check-if-operation-has-been-completed-on-this-event'
})
.done(function(resp){
//do something
alert('success');
})
.fail(function(){
//handle error
alert('error');
})
.always(function(){
ajaxprocessing = false; //clear the flag
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button-cancel">Cancel</button>
What you can do is call a function at the end of an if statement like
if(ajax call is completed) {
checkDone();
}
function checkDone() {
alert("Done");
}

Universal button handler in javascript

I have a lot of buttons on my web app that request and post data to PHP to retrieve and update a database. I am struggling to create a universal way to prevent multiple button clicks when submitting forms, because I am using AJAX and Jquery.
This is my current implementation but I can't even tell if it works. It seems to work 99% of the time.
In my common functions.js file I have this function which is in the global scope
var canClick = true;
function buttonWithPromise(promise){
if(!canClick) return;
canClick = false;
promise.done(function(){
canClick = true;
});
}
Then any time I attach a .click to a dom element I do it like this:
$('body').on('click', '.table > .row', function(){
var nbr = $(this).attr('nbr');
buttonWithPromise(get_count(nbr));
});
And some function that might be called will have a deferred object.
function get_count(){
var defer = $.Deferred();
var options = "getCount"
Query.init(options)
.fetchData(function(data){ //Ajax data request
if(data){
}
defer.resolve();
});
return defer.promise();
}
Since this only sometimes works, I can tell it's wrong. Any advice for improvements?
Everything in Javascript is an object, yes? So why not:
$('body').on('click', '.button', function()
{
// Set default value of property
if(typeof this.isClicked === 'undefined')
this.isClicked = false;
// Check if button is working
if(this.isClicked)
{
// Send error to console if button is busy
console.log('Cannot click as a network action is occuring!');
}else
{
// Begin new network action if button is not busy
var self = this;
console.log('Begin network for: ' + $(this).text());
this.isClicked = true;
setTimeout(function()
{
// Reset button state once network action is done
console.log('End network for: ' + $(self).text());
self.isClicked = false;
//Call any callbacks/promises here
}, 5000);
}
});
Fiddle:
http://jsfiddle.net/mdLfug1t/
NOTE: I'm using setTimeout to simulate an ajax request
EDIT: Let me put this more into context:
function buttonWithPromise(promise)
{
if(typeof promise.canClick === 'undefined')
promise.canClick = true;
if(!promise.canClick) return;
promise.canClick = false;
promise.done(function()
{
promise.canClick = true;
});
}
The problem that you're running into is that "canClick" is global and so gets modified by every promise. You need to make it a property of a promise so that you can create infinite promises, each with their own instance of canClick.

Multiple ajax Allow only latest call

I have an input box on which there is an ajax request on every key press. so if i enter word "name" there will be 4 successful request. So i actually want only the latest request of executed. so if i enter word "name" there will be only one request which will be the last one.
and i also have a solution for this (this is a simple example with click method)
JS script
var callid = 1;
function ajaxCall (checkval ){
if(checkval == callid){
$.ajax({
type: 'post',
url: baseurl + "test/call_ajax",
data: {
val: "1"
},
success: function(data) {
console.log(data)
}
});
}
}
function call(){
var send = callid+=1;
setTimeout( function(){ ajaxCall(send) } , 500);
}
html script
<a href="#" onclick="call()" > Call ajax </a>
This is working perfectly. But i was think if there is way to refine it a little bit more.
Any ideas :)
I am sure you are looking some better intent technique for event dispatching.
var eventDispatcher = null;
$('.textbox').keyup(function(){
if(eventDispatcher) clearTimeout(eventDispatcher);
eventDispatcher = setTimeout(function(){
$.ajax({ ... });
}, 300);
});
You could do your ajax inside of a setTimeout. So you don't need to declare and check an additional variable or write another function like call()
$(document).ready(function () {
var timer;
$('#fillMe').keypress(function () {
clearTimeout(timer);
timer = setTimeout(function () {
//replace this with your ajax call
var content = $('#fillMe').val();
$('#result').text('You will only see this if the user stopped typing: ' + content);
}, 1000); // waits 1s before getting executed
});
});
<input type="text" id="fillMe">
<div id="result"></div>
On every keypress event this clears the timeout and immediately creates a new timeout. This means the content of the setTimeout function only gets executed if the user stopped typing for at least 1 second.
Of course 1 second is just the value for the example purpose. You can change it to whatever you want or think is a good time (like 500ms)
See my jsfiddle
setTimeout returns an id that you can store and use to clear the previously set timer:
var timerId;
function call() {
if (timerId !== undefined) {
clearTimeout(timerId);
}
timerId = setTimeout( function() { ajaxCall(send) }, 500);
}
The result of this should be that the ajaxCall method will be called 500ms after the last letter is entered.

Jquery ajax live validation / timeout question

I'm still kindof new to jQuery, so there probably is an easy solution, but I can't find anything.
I've made this registration form, that checks if the username or email is taken as the user is typing in the username. Basically it just makes a json request that returns true or false depending on if the username / email is already taken.
The problem is, that now it makes a request on basically every keypress that the user makes while focused on the field if the input text is more than 3 characters long. For now, that works, but that's a lot of server requests. I'd like it to make a request only when the user has not typed for, say, a half second.
Any ideas on how I might be able to do that ?
$(document).ready(function() {
$("#user_username").keyup(function () {
var ln = $(this).val().length;
if (ln > 3) {
$.getJSON("/validate/username/",
{value:$(this).val()},
function(data){
if (data.reg == true) {
$("#status-for-username").html("Username already in use");
} else {
$("#status-for-username").html("Username available");
}
});
}
});
$("#user_email").keyup(function () {
var ln = $(this).val().length;
if (ln > 3) {
$.getJSON("/validate/email/",
{value:$(this).val()},
function(data){
if (data.reg == true) {
$("#status-for-email").html("E-mail already in use");
} else {
$("#status-for-email").html("");
}
});
}
});
});
For waiting an amount of time since the last keystroke, you could do something like the jQuery.typeWatch plugin does.
Here I post you a light implementation of the concept:
Usage:
$("#user_username").keyup(function () {
typewatch(function () {
// executed only 500 ms after the last keyup event.
}, 500);
Implementation:
var typewatch = function(){
var timer = 0; // store the timer id
return function(callback, ms){
clearTimeout (timer); // if the function is called before the timeout
timer = setTimeout(callback, ms); // clear the timer and start it over
}
}();
StackOverflow uses the plugin I mention, for syntax coloring the code on edition.
You can use window.setTimeout and window.clearTimeout. Basically trigger a function to invoke in x milliseconds and if another keypress event is fired beforehand then you clear that handler and start a new one.
//timeout var
var timer;
$('#username').keyUp( function(){
//clear any existing timer
window.clearTimeout( timer );
//invoke check password function in 0.5 seconds
timer = window.setTimeout( checkPasswordFunc, 500 );
});
function checkPasswordFunc(){
//ajax call goes here
}

Categories