How to delay ajax call on keypress? - javascript

I have an input box where I'm doing an AJAX GET to check if the email is within my database. I'm simply checking for an email address and if it's within the database, we retrieve true/else false. So depending on the return I display either a tick or cross image.
$.ajax({
url: '/api/user/emailaddress/' + emailAddress,
type: 'GET',
dataType: 'json',
success: function(data) {
if (data===true) {
$(".email-address-validator").removeClass("success");
$(".email-address-validator").addClass("error");
}
}
});
Each time a key is pressed within the input box field, this gets called. The problem that I thought might prop up is if someone looks at this file and see's that I'm doing an AJAX GET request on the field that they might just keep pressing keys on that particular input box.
Q: How can I set a timeout on this, for around 5 seconds so a user doesn't just keep spamming the box?

You could set a flag to handle this scenario. Something like this is much better than a timer.
var waitingForResponse= false;
function isValidEmail () {
if (!waitingForResponse) {
waitingForResponse = true;
$.ajax({
url: '/api/user/emailaddress/' + emailAddress,
type: 'GET',
dataType: 'json',
success: function(data) {
waitingForResponse= false;
if (data===true) {
$(".email-address-validator").removeClass("success");
$(".email-address-validator").addClass("error");
}
}
});
}
}
This design pattern will prevent subsequent requests until the first response is received. If you need a further interval between requests than this suggestion, then you can wrap the waitingForResponse flag in a setTimeout function inside the success callback. Like so:
var waitingForResponse= false;
function isValidEmail () {
if (!waitingForResponse) {
waitingForResponse = true;
$.ajax({
url: '/api/user/emailaddress/' + emailAddress,
type: 'GET',
dataType: 'json',
success: function(data) {
setTimeout(function () {
waitingForResponse= false;
}, 5000);
if (data===true) {
$(".email-address-validator").removeClass("success");
$(".email-address-validator").addClass("error");
}
}
});
}
}

Related

Ajax not working properly

Bear with me I'm my javascript is a little rusty. So I'm trying to use a call by ajax to a PHP file and give it a plan type then make sense of it check to see if it then return a true or false if some allowed slots are less than some slots used up for the plan. Here is the Form in XHTML.
<form method="post" action="/membership-change-success" id="PaymentForm">
<input type="hidden" name="planChosen" id="planChosen" value="" />
</form>
On the same file. The ( < PLAN CHOICE > ) gets parsed out to the current plan.
<script>
var hash = window.location.hash;
var currentPlan = "( < PLAN CHOICE > )";
$(".planChoice").click(function(event){
var isGood=confirm('Are you sure you want to change your plan?');
var success;
$("#planChosen").val($(this).data("plan"));
$.ajax({
url: '/ajax/planCheck.php',
type: "POST",
dataType: 'json',
data: ({plan: $(this).data("plan")}),
success: function (data) { //This is what is not working I can't get it to return true
success = data;
}
});
if(success) {
if (isGood) {
$("#PaymentForm").submit();
}
window.location = '/membership-change-success';
} else {
alert('Please make sure you deactivate your listings to the appropriate amount before you Downgrade.')
}
});
My PHP for the ajax response looks like this.
<?php
require ('../includes/common.php');
include_once ('../includes/db-common.php');
require ('../includes/config.php');
$membership = new membership($dbobject);
$listing = new listing($dbobject);
$totalAvailableListings = ($membership->get_listingsAmount($_POST['plan']));
if($totalAvailableListings>=$listing->get_active_listings($user->id)){
echo json_encode(true); // I've tried with out jason_encode too
} else {
echo json_encode(false);
}
And that's pretty much it if you have any suggestions please let me know.
So I've tried to do it another way.
$(".planChoice").click(function (event) {
var isGood = confirm('Are you sure you want to change your plan?');
var success;
$("#planChosen").val($(this).data("plan"));
if (false) {
if (isGood) {
$("#PaymentForm").submit();
alert('you did it');
}
} else {
alert(isSuccessful($(this).data("plan")));
//alert('Please make sure you deactivate your listings to the appropriate amount before you downgrade.');
}
});
and I have an ajax function
function isSuccessful(plan) {
return $.ajax({
url: '/ajax/planCheck.php',
type: "POST",
dataType: 'json',
data: {plan: plan}
});
}
The alert tells me this [object XMLHttpRequest]
any suggestions?
$.ajax() returns results asynchronously. Use .then() chained to $.ajax() call to perform task based on response
$.ajax({
url: '/ajax/planCheck.php',
type: "POST",
dataType: 'json',
data: {plan: $(this).data("plan")}
})
.then(function(success) {
if (success) {
$("#PaymentForm").submit();
}
// if `form` is submitted why do we need to set `.location`?
// window.location = '/membership-change-success';
} else {
alert('Please make sure you deactivate your listings to the appropriate amount before you Downgrade.')
}
}, function err(jqxhr, textStatus, errorThrown) {
console.log(errorThrow)
})
You should use the following form for your ajax call
$.ajax({
url: '/ajax/planCheck.php',
type: "POST",
dataType: 'json',
data: ({plan: $(this).data("plan")}),
success: success = data
})
.done(function(response) {
if(success) {
if (isGood) {
$("#PaymentForm").submit();
}
window.location = '/membership-change-success';
}
else {
alert('Please make sure you deactivate your listings to the
appropriate amount before you Downgrade.')
}
});
the .done() clause ensures that you perform that code after the ajax call is finished and the response is obtained.

How to call setinterval function in another function is not working

I want to display Updated records count when Ajax process is going on. When i click on start process button updateRecords()function will execute and it will update records status from open to waiting status one by one in database.So at the same time i want display the waiting records count .For this when user click on strat process button i want to call displayWaitingRecords() using setinterval.
I am calling that function like this from updateRecords()
clear_Process = setInterval(function(){displayWaitingRecords()},200);
But displayWaitingRecords() will not call until updateRecords() process completes.But my requirement is displayWaitingRecords() also will execute simaltaniously with updateRecords().
Function to display updated record count
function displayWaitingRecords()
{
jQuery.ajax({
type: 'GET',
crossDomain:true,
async: false,
url: "/curlRRQCount.php",
success: function(count){
if(count)
{
jQuery("#processed_poids_div").html("Processed Order ids:"+count) ;
}
}
});
}
Function when i click on start process button
var clear_Process = "";
function updateRecords()
{
clear_Process = setInterval(function(){displayWaitingRecords()},200);
var str = jQuery("#rrq_form :input[value!='']").serialize();
jQuery.ajax({
async: false,
type: 'POST',
data : str,
url: "/updaterecord_status.php",
success: function(valid_result)
{
if(jQuery.trim(valid_result) == 'Success')
{
jQuery("#rrq_load_img").hide();
jQuery("#rrq_orders_status").html("some success message");
}
}
});
}
Where i am doing wrong? Any help would be greatly appreciated.
You have set async: false. So the ajax call will process synchronized. Set it to false or leave it out (because true is default):
var clear_Process = "";
function updateRecords()
{
clear_Process = setInterval(function(){displayWaitingRecords()},200);
var str = jQuery("#rrq_form :input[value!='']").serialize();
jQuery.ajax({
async: true,
type: 'POST',
data : str,
url: "/updaterecord_status.php",
success: function(valid_result)
{
if(jQuery.trim(valid_result) == 'Success')
{
jQuery("#rrq_load_img").hide();
jQuery("#rrq_orders_status").html("some success message");
}
}
});
}
If you leave it out you have the same result:
function displayWaitingRecords()
{
jQuery.ajax({
type: 'GET',
crossDomain:true,
url: "/curlRRQCount.php",
success: function(count){
if(count)
{
jQuery("#processed_poids_div").html("Processed Order ids:"+count) ;
}
}
});
}

Cannot write in text box while it's autosaving using tinymce-4 plugin

I am using a plugin to autosave a textbox. However, when the autosave function is called, the text box cannot be typed into. I want users to be able to continue typing while the auto save is posted via AJAX.
tinymce.PluginManager.add('jsave', function(editor) {
// Get the form element into a jQuery object.
var $form = $(editor.formElement);
// Settings for initialization.
var settings = {
// Interval to execute the function. Default is 15000 (ms 1000 = 1 second).
//seconds: editor.getParam('jsave_seconds') || 2000,
seconds: 2000,
// This is our url that we will send data. If you want to have two different links,
// one for ajax and one for manual post this setting is pretty useful!
url: editor.getParam('jsave_url') || $form.attr('action'),
// This is the callback that will be executed after the form is submitted
callback: editor.getParam('jsave_callback')
};
$('.form_header,#attachbox').change(function (){
tinymce.get('mail_body').isNotDirty=0;
$("#save_status").html("Not saved");
});
var interval = setInterval(function() {
// Quit the function if the editor is not dirty.
if (!editor.isDirty()){
return;
}
// Update the original textarea
editor.save();
// Create a data string from form elements.
ds =$form.serialize();
// $form.find(':input').each(function (i, el) {
// $el = $(el);
// if($el.attr('name')!=null)
// ds[$el.attr('name')] = $el.val(); }
// );
$("#save_status").html("Saving");
$.ajax({
url: settings.url,
type: $form.attr('method'),
data: ds,
dataType:"json",
async:false,
success: function(msg) {
if (settings.callback){
//editor.setContent(msg.draft_body);
$("#save_status").html("Saved");
settings.callback(msg);
}
else{
$("#save_status").html("Saving error");
console.log(msg);
}
}
});
}, settings.seconds);
}); //vsk.me/en/28/adding-an-autosave-plugin-to-tinymce-2#sthash.jsOruJSd.dpuf
I have solved this problem:
just change form async:false, to async:true, in ajax calling part.
$.ajax({
url: settings.url,
type: $form.attr('method'),
data: ds,
dataType:"json",
async:true,
success: function(msg) {
if (settings.callback){
//editor.setContent(msg.draft_body);
$("#save_status").html("Saved");
settings.callback(msg);
}
else{
$("#save_status").html("Saving error");
console.log(msg);
}
}
});
Why don't you just disable it while doing the ajax call and enable again on ajax call ends?
You have a reference to enable/disable the field via JavaScript here:
make readonly/disable tinymce textarea
That way you could use the complete attribute on your Ajax call to enable the field again after either succes or error response like this:
var interval = setInterval(function() {
// Quit the function if the editor is not dirty.
if (!editor.isDirty()){
return;
}
// Update the original textarea
editor.save();
// Create a data string from form elements.
ds =$form.serialize();
$("#save_status").html("Saving");
tinyMCE.get('textarea_id').getBody().setAttribute('contenteditable', false);
$ajax({
url: settings.url,
type: $form.attr('method'),
data: ds,
dataType:"json",
async:false,
success: function(msg) {
if (settings.callback){
//editor.setContent(msg.draft_body);
$("#save_status").html("Saved");
settings.callback(msg);
}
else{
$("#save_status").html("Saving error");
console.log(msg);
}
},
error:function(){
//DO ERROR STUFF
},
complete:function(){
tinyMCE.get('textarea_id').getBody().setAttribute('contenteditable', true);
}
});

Javascript function being called again while it is still running

I have a javascript function that is called when the user clicks on a button and performs an AJAX query that adds some data to my database. However, I've been getting complaints that a lot of data hasn't been getting through, and I've isolated the problem to be the time between clicks. When they wait long enough between clicks, the data always gets through, but if they don't wait long enough it's a crapshoot.
So I'm pretty much settled that the problem is that the javascript function is being called again while it is already running, which I shouldn't allow. Is there a way I can lock the user's browser at the beginning of the function and unlock it at the end after the AJAX? I know this may irritate my users, but I can't see any other solution.
It's not totally necessary, but here's what my javascript function looks like:
function addtolist(thisform, sdata)
{
var scntDiv = $('#p_data');
var request = $.ajax({ async: false, url: "php_addtolist.php", type: "POST", data: {data:sdata}, dataType: "html" });
request.done(function(msg) { outdata = parseInt(msg); });
$(outdata).appendTo(scntDiv);
}
You can disable the button when the function is called, then re-enable it with the complete callback:
function addtolist(thisform, sdata)
{
$('#submit_btn').prop('disabled', true);
var scntDiv = $('#p_data');
var request = $.ajax({
async: false,
url: "php_addtolist.php",
type: "POST",
data: {data:sdata}, dataType: "html" },
complete: function() { $('#submit_btn').prop('disabled', false); }
);
request.done(function(msg) { outdata = parseInt(msg); });
$(outdata).appendTo(scntDiv);
}
Basically it seems like the outdata is async. the following should resolve.
function addtolist(thisform, sdata)
{
var scntDiv = $('#p_data');
var request = $.ajax({ async: false, url: "php_addtolist.php", type: "POST", data: {data:sdata}, dataType: "html" });
request.done(function(msg) {
outdata = parseInt(msg);
$(outdata).appendTo(scntDiv);
});
}

Stop an ajax request from posting data until a response is received?

i have written a basic commenting system which is a simple write to database form and it uses ajax as well.
The issue is that if i enter my message, and then spam send / the enter key it seems to stack up and then everything is written to the database multiple times.
My ajax is like so:
$(document).ready(function(){
$(document).on('submit', '.addcomment', function() {
var $targetForm = $(this);
$.ajax({
type: "POST",
url: "process/addcomment.php",
data: $targetForm.serialize(),
dataType: "json",
success: function(response){
if (response.databaseSuccess == true) {
$("#container").load("#container");
$targetForm.find('#addcommentbutton').attr("disabled", true);
}
else {
$ckEditor.after('<div class="error">Something went wrong!</div>');
}
}
});
return false;
});
});
The submit button does become disabled, but the form can still be entered via the enter keyboard button or even still with a mass spam of the submit button (which is supposed to be disabled)
Is there a way to 100% disable this form with jquery, until the success JSON message is received?
Anymore code just let me know!
In this case, i would not use delegation. I would instead bind the event directly to the form using .one since each form should submit only once (if that's the case.) If you instead only have one addComment form, then i question why you are using delegation in the first place.
$(commentForm).appendTo(selector).one("submit",function(e){
e.preventDefault(); // prevent this submit
$(this).submit(false); // prevent future submits
// submit data to server
})
Just keep track of if a request is in progress:
$(document).ready(function(){
var isSubmitting = false;
$(document).on('submit', '.addcomment', function() {
var $targetForm = $(this);
if (!isSubmitting) {
isSubmitting = true;
$.ajax({
...
success: function(response){
...
},
complete: function() { isSubmitting = false; }
});
}
});
There are lots of ways to handle this, but the best involves validating the data on the server end. You want to prevent people from overloading the database inadvertently (the "fat finger" problem) or deliberately (the bored script kiddie who decides to crash your server or fill your database with garbage).
The best solution:
Generate a one-time token when the page is requested (called a "nonce")
Post that nonce when you post the data
Only accept it on the server side if the nonce has never been used
This obviously requires you to keep track of a list of valid nonces, but it prevents any glitches or abuse of the send button.
Also, as others have pointed out, disable the button much earlier and only run the submit action handler once. That will help with the inadvertent double-clicks and so on, but you also need the nonce to prevent compulsive clickers or intentional misuse.
Can you do it like below:
$(document).ready(function(){
var isAjaxInProgress = null;
$(document).on('submit', '.addcomment', function() {
var $targetForm = $(this);
if(isAjaxInProgress === null || !$isAjaxInProgress ){
isAjaxInProgress = true;
$.ajax({
type: "POST",
url: "process/addcomment.php",
data: $targetForm.serialize(),
dataType: "json",
success: function(response){
if (response.databaseSuccess == true) {
$("#container").load("#container");
$targetForm.find('#addcommentbutton').attr("disabled", true);
}
else {
$ckEditor.after('<div class="error">Something went wrong!</div>');
}
isAjaxInProgress = false;
}
});
}
return false;
});
});
// declare a global ajax request variable
var is_request_sent = false;
function send_msg()
{
if(is_request_sent == false)
{
$.ajax({
type: "POST",
url: "process/addcomment.php",
data: $targetForm.serialize(),
dataType: "json",
success: function(result){
//alert(result);
is_request_sent = false;
},
error: function(a,b,c)
{
is_request_sent = false;
},
beforeSend: function(jqXHR, plain_jqXHR){
// set request object
is_request_sent = jqXHR;
// Handle the beforeSend event
},
complete: function(){
// update global request variable
is_request_sent = false;
// Handle the complete event
}
});
}
}

Categories