I'm stuck in a problem that seems to be very simple to solve, but I doesn't figured out. I have 3 radio each one have their data attribute for the selected payment method, but the problem is, in jQuery code I need to submit an AJAX request, based on the selected radio switch. But If I click in the first radio, give and go to 3rd radio, I get 2 POST requests. For the first radio and 3rd, when should be 1. o.O
$("#payment-form input[name=payment_option]").change(function() {
var payment_method = $("input[name=payment_option]:checked").data('payment-method');
$("#checkout-button").prop('disabled', false);
console.log(payment_method);
switch (payment_method) {
// First radio
case 'pagseguro':
$("#paypal-button").css('display', 'none');
$("#checkout-button").css('display', 'block');
$("#checkout-button").prop('disabled', false);
$checkout_button.click(function() {
$.ajax({
url: 'http://usercp.dev/doacao/fazer-doacao/pagamento/pagseguro',
type: 'GET',
dataType: 'json',
success: function(response) {
if (response.success) {
var code = response.transaction_code
PagSeguroLightbox({
code: code
}, {
success: function(transactionCode) {
$.post("http://usercp.dev/doacao/fazer-doacao/pagamento/received", {
payment_token: response.payment_token,
payment_method: response.payment_method,
transaction_code: transactionCode,
transaction_done: response.success,
csrf_token: $('meta[name="csrf-token"]').attr('content')
})
.done(function(response) {
if (!response.success) {
toastr.error("Oops!", response.error)
}
window.location.replace(response.redirect);
}, 'json');
},
abort: function() {
toastr.options.positionClass = 'toast-top-center';
toastr.info("Você cancelou a operação de pagamento.");
$(".loader").addClass('hidden');
}
});
} else {
toastr.options.positionClass = 'toast-top-center';
toastr.error(response.error);
if (response.redirect !== "") {
window.location.replace(response.redirect);
}
}
}
});
$(".loader").removeClass('hidden');
$("#checkout-button").prop('disabled', true);
$("#checkout-button").html('<i class="fa fa-circle-o-notch fa-spin fa-fw"></i>');
});
break;
// PayPal have their one button, so work without errors.
case 'paypal':
$("#paypal-button").css('display', 'block');
$("#checkout-button").css('display', 'none');
break;
// PicPay I try to use the same button as PagSeguro (first radio)
// but as I mentioned above,
// If selected PagSeguro first and jump to PicPay I'll see to post requests (one for PagSeguro and another for PicPay). I want to fix this.
case 'picpay':
$("#paypal-button").css('display', 'none');
$("#checkout-button").css('display', 'block');
$("#checkout-button").prop('disabled', false);
$checkout_button.click(function() {
$.ajax({
url: 'http://usercp.dev/doacao/fazer-doacao/pagamento/picpay',
type: 'GET',
dataType: 'json',
success: function(response) {
if (!response.success) {
toastr.error("Oops!", response.error)
}
window.location.replace(response.redirect);
}
});
$(".loader").removeClass('hidden');
$("#checkout-button").prop('disabled', true);
$("#checkout-button").html('<i class="fa fa-circle-o-notch fa-spin fa-fw"></i>');
});
break;
}
});
HTML is simple.
<input type="radio" class="radio" name="payment_option" id="payment_option" data-payment-method="pagseguro">
<input type="radio" class="radio" name="payment_option" id="payment_option" data-payment-method="paypal">
<input type="radio" class="radio" name="payment_option" id="payment_option" data-payment-method="picpay">
So you have 2 buttons that trigger a different ajax request each, and you want to be able to trigger ajax A, then trigger ajax B and cancel ajax A.
First you must understand that Ajax is async. That means that when the ajax starts, it triggers a thread of actions separate from your main thread where all your javascript exists.
If you want to cancel A when B is triggered, or cancel B when A is triggered, you need to keep track of your ajax requests.
The simplest way I can imagine is to put your ajax inside a variable
var currentAjax = $.ajax(/* Ajax A */)
Then when you trigger a new ajax you can do something like this to get rid of the previous one
if (currentAjax) { currentAjax.abort() }
currentAjax = $.ajax(/* the new ajax you selected */)
to sum it up better
we have a variable (it could be global for simplicity's sake) that contains the last activated ajax
var currentPayAjax;
$checkout_button.click(function() {
// an inefficient but doable way to try and cancel any potential previous get
try { currentPayAjax.abort() } catch(err){}
switch (payment_method) {
case 'pagseguro':
currentPayAjax = $.ajax({/* stuff A */})
break;
case 'picpay':
currentPayAjax = $.ajax({/* stuff B */})
break;
}
)}
Related
I'm pretty new to using javascript, and ajax. So I have a button that's supposed to delete the item when clicked.
<button type="submit" class="delete-button" data-id="{{ d_id }}">Delete</button>
I used ajax to send the delete POST request. While this is happening (the item takes a while to delete) how can I go about having a loading circle in the HTML. I would like to show a processing bar or something similar while the request is processing and when it's done, refresh the to show the change. Currently after a successful delete, the user can't see the change until they manually refresh the page.
$(document).ready(function() {
$(".delete-button").click(function () {
var d_id = $(this).attr('d_id');
$.ajax({
type: "POST",
url: "/delete/" + d_id
}).done(function (data) {
if (data === 'Deleted') {
console.log("Deleted")
} else {
console.log("Failed")
}
})
});
});
I have a HTTP handler (ASHX) which I am calling from UI side using an AJAX function. The following is what needs to happen in this call:
When the section loads, it will display the status of the short code on the server in the shortcodestatus span. It will either say on or off:
<a class="btn btn-default" id="toggleshortcode">Short Code <span id="shortcodestatus"></span></a>
This is the function for getting the status of the short code and this works properly. I can manually change the status of the short code and the changes reflect properly on the div when I reload the page:
function ShortCodeStatus() {
$.ajax({
type: "GET",
url: "Handler.ashx?action=shortcodestatus",
success: function (output) {
console.log("getShortCodeStatus: " + output);
$("#shortcodestatus").empty();
if (output == "true") {
$("#shortcodestatus").text("ON");
$("#shortcodestatus").addClass("btn btn-success");
}
else {
$("#shortcodestatus").text("OFF");
$("#shortcodestatus").addClass("btn btn-danger");
}
}
});
};
This is the short code status code from the handler:
case "shortcodestatus":
{
output = ShortCodeStatus() ? "true" : "false";
}
break;
I want to be able to click on the toggleshortcode div to fire off this event through the handler. The functions for disabling and enabling the short code are working properly:
case "toggleshortcode":
{
if (ShortCodeStatus() == true)
{
DisableShortCode();
output = "false";
}
else
{
EnableShortCode();
output = "true";
}
}
break;
Here is the ajax call for the short code toggle:
$('#toggleshortcode').click(function () {
$.ajax({
type: "POST",
url: "Handler.ashx?action=toggleshortcode",
success: function (output) {
console.log("toggleshortcode: " + output);
ShortCodeStatus();
}
});
});
I'm hitting the URLs correctly and I'm getting the correct responses from each function. However the change to the short code does not seem to be happening.
For example, if the short code is off, the ShortCodeStatus function will return false and thus render the OFF button. When I click on the toggleshortcode button, the output is true (I want to turn on short code) which is correct but when the ShortCodeStatus function fires again in the success, it will still say false. The ajax functions seem correct but I can't figure out why the toggleshortcode on the handler is not firing properly.
Thank you so much for your time!
I'm seeing 2 cases that you can check.
First, in the ajax call for 'toggleshortcode', you are calling the function 'getShortCodeStatus()', and base on your example the correct name of the function is 'ShortCodeStatus()'.
Second, in the call to 'Handler.ashx?action=toggleshortcode', you are already returning the status (true or false), I suggest you make a javascript function named SetShortCodeStatus(status) , and use this inside of the success of both ajax request 'Handler.ashx?action=shortcodestatus' and 'Handler.ashx?action=toggleshortcode'.
function SetShortCodeStatus(status) {
$("#shortcodestatus").empty();
if (status == "true") {
$("#shortcodestatus").text("ON");
$("#shortcodestatus").addClass("btn btn-success");
}
else {
$("#shortcodestatus").text("OFF");
$("#shortcodestatus").addClass("btn btn-danger");
}
}
function ShortCodeStatus() {
$.ajax({
type: "GET",
url: "Handler.ashx?action=shortcodestatus",
success: function (output) {
console.log("getShortCodeStatus: " + output);
SetShortCodeStatus(output);
}
});
};
$('#toggleshortcode').click(function () {
$.ajax({
type: "POST",
url: "Handler.ashx?action=toggleshortcode",
success: function (output) {
console.log("toggleshortcode: " + output);
SetShortCodeStatus(output);
}
});
});
I have a delete link for every row in my grid. It looks like this:
<font color="#CC0000">Delete</font>
My objective is to check if a record has been printed or not by making an Ajax call to an ASP.net Web Method two times. Once before the user confirms delete, and once again after they click confirm.
I easily took care of this by creating a synchronous AJAX call, but I read everywhere that synchronous AJAX calls are horrible and depricated.
After looking here I decided to use JQuery deferred objects to grab the response values
What I did was this:
After clicking "Delete" OnDeleteRecordClick(recordID) gets called.
First, I make my Ajax Call, then return false (notice the end of the method)
Then, after I get the first response, depending on if the record is not printed or not, I show a javascript confirmation, and make my ajax call again, Then return false again.
After the second response, if the record is unprinted, I return true, to delete the record.
Here's my OnDeleteRecord:
function OnDeleteRecordClick(recordID) {
// This action takes place asynchronously
BeforeRecordDelete (recordID)
.done(function (r) {
if (r.d == 1) {
// Check isPrinted before clicking "Confirm"
alert("You can't delete this record printed.");
return false;
} else {
if (ConfirmDelete('record')) {
// Check isPrinted again after clicking "Confirm"
BeforeRecordDelete (recordID)
.done(function (r) {
if (r.d == 1) {
alert("You can't delete this record because it has been printed.");
return false;
} else {
// Proceed to delete
return true;
}
})
.fail(function (x) {
Alert("server failed");
return false
});
// Return false until we get a response from the server
return false;
} else {
// User clicks "Cancel"
return true;
}
}
})
.fail(function (x) {
// Tell the user something bad happened
Alert("server failed");
return false;
});
// Return false until we get a response from the server
return false;
}
Here's my async AJAX call:
BeforeRecordDelete = function (recordID) {
return $.ajax({
type: "POST",
url: "RecordList.aspx/IsRecordPrinted",
contentType: "application/json; charset=utf-8",
data: '{RecordID: "' + RecordID + '"}',
dataType: "json"
});
}
Here's my problem: When I return false two times, then return true, the hyperlink wouldn't work.
My questions are:
Can I even do this to a hyperlink? (Returning multiple values to OnClick)
Is there a better way to do this? I really want to do this asynchronously, but my brain hurts.
I'll start with an apology - I'm a .NET coder with little (no) front-end experience.
When the user clicks on Submit, the form needs to call a REST service, if the service returns true then the user is presented with a warning that a duplicate exists and are asked whether they want to continue. Appreciate any help.
I have the Submit button ONCLICK wired up to Approve()
When the checkForDuplicateInvoice() gets called, it passes the control back to the calling function right away before the ajax call has a chance to get the result. The effect is that the Validate() function finishes without taking into account whether or not a duplicate invoice exists.
I need help in modifying the form so that when the user clicks on the submit button, the form validates (including the ajax call to the db) before finally submitting.
I've modified the code based on Jasen's feedback.
I'm including https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js in my header.
The error I get now is "Object doesn't support property or method 'button'"
What I have now for my form submission/validation is:
$(document).ready(function () {
$("#process").button().click( function () {
if (ValidateFields()) { // internal validation
var companyCode = document.getElementById("_1_1_21_1").value;
var invoiceNo = document.getElementById("_1_1_25_1").value;
var vendorNo = document.getElementById("_1_1_24_1").value;
if (vendorNo == "undefined" || invoiceNo == "undefined" || companyCode == "undefined") {
return false;
}
$.ajax({ // external validation
type: "GET",
contentType: "application/json;charset=utf-8",
//context: $form,
async: false,
dataType: "jsonp",
crossDomain: true,
cache: true,
url: "http://cdmstage.domain.com/services/rest/restservice.svc/CheckDuplicateInvoice?InvoiceNumber=" + invoiceNo + "&VendorNumber=" + vendorNo + "&CompanyCode=" + companyCode,
success: function (data) {
var result = data;
var exists = result.CheckForInvoiceDuplicateResult.InvoiceExists;
var valid = false;
if (exists) {
if (confirm('Duplicate Invoice Found! Click OK to override or Cancel to return to the form.')) {
valid = true;
}
}
else {
valid = true; // no duplicate found - form is valid
}
if (valid) {
document.getElementById("_1_1_20_1").value = "Approve";
doFormSubmit(document.myForm);
}
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
});
});
First review How do I return the response from an asynchronous call? Understand why you can't return a value from the ajax callback functions.
Next, disassociate the submit button from the form to prevent it from performing default submission. Test it to see it does nothing.
<form>
...
<button type="button" id="process" />
</form>
Then wire it up to make your validation request
$("#process").on("click", function() {
if (valid()) {
$(this).prop("disabled", true); // disable the button to prevent extra user clicks
// make ajax server-side validation request
}
});
Then you can make your AJAX request truly asynchronous.
$.ajax({
async: true,
...,
success: function(result) {
if (exists) {
// return true; // returning a value is futile
// make ajax AddInvoice call
}
}
});
Pseudo-code for this process
if (client-side is valid) {
server-side validation: {
on response: if (server-side is valid) {
AddInvoice: {
on response: if (successful) {
form.submit()
}
}
}
}
}
In the callback for the server-side validation you make the AddInvoice request.
In the callback for AddInvoice you call your form.submit().
In this way you nest ajax calls and wait for each response. If any fail, make the appropriate UI prompt and re-enable the button. Otherwise, you don't automatically submit the form until both ajax calls succeed and you call submit() programmatically.
I have two buttons on the form I'm getting, this first piece of coce allow me to know which was the button clicked by getting the id of it.
var button;
var form = $('.register_ajax');
$('#vote_up, #vote_down').on("click",function(e) {
e.preventDefault();
button = $(this).attr("id");
});
and this other send the form data through AJAX using the info already obtained from the button using the script above.
form.bind('submit',function () {
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
cache: false,
dataType: 'json',
data: form.serialize() + '&' + encodeURI(button.attr('name')) + '=' + encodeURI(button.attr('value')) ,
beforeSend: function() {
//$("#validation-errors").hide().empty();
},
success: function(data) {
if(data.message == 0){
$("#fave").attr('src','interactions/favorite.png');
$("#favorite").attr('value',1);
console.log(data.errors);
}
if(data.message == 1)
{
$("#fave").attr('src','interactions/favorite_active.png');
$("#favorite").attr('value',0);
}
if(data.message == "plus")
{
$("#vote_up").attr('class','options options-hover');
$("#vote_down").attr('class','options');
console.log(data.message);
}
if(data.message == "sub")
{
$("#vote_down").attr('class','options options-hover');
$("#vote_up").attr('class','options');
console.log("sub");
}
},
error: function(xhr, textStatus, thrownError) {
console.log(data.message);
}
});
return false;
});
The problem is that the data is not being passed to the ajax function, the button info is being saved on the button var, but it's not being obtained at time on the ajax call to work with it (or at least that is what I think). I'd like to know what can I do to make this work, any help appreciated.
1st edit: If I get the button data directly like button = $('#vote_up'); it doesn't work either, it only works if I get the button directly like this but without using the function.
2nd edit: I found the solution, I posted below.
var button is in the scope of the .on('event', function(){})
You need to declare the variable in the shared scope, then you can modify the value inside the event callback, i.e.
var button,
form = $('.register_ajax');
$('#vote_up, #vote_down').on("click",function(e) {
e.preventDefault();
button = $(this).attr("id");
});
You are being victim of a clousure. Just as adam_bear said you need to declare the variable outside of the function where you are setting it, but you are going to keep hitting these kind of walls constantly unless you dedicate some hours to learn the Good Parts :D, javascript is full of these type of things, here is a good book for you and you can also learn more from the author at http://www.crockford.com/.
I Found the solution, I just changed a little bit the click function like this:
var button;
var form = $('.register_ajax');
var data = form.serializeArray();
$('#vote_up, #vote_down').on("click",function(e) {
e.preventDefault();
button = $(this).attr("id");
data.push({name: encodeURI($(this).attr('name')), value: encodeURI($(this).attr('value'))});
form.submit();
});
using e.preventDefault(); and form.submit(); to send the form. also I changed the data.serialize to serializeArray(); because it's more effective to push data into the serializeArray(). in the second script I just changed the data.serialize() and used the data variable that I already filled with the serializeArray() and the data.push():
form.bind('submit',function () {
alert(button);
$.ajax({
url: form.attr('action'),
type: form.attr('method'),
cache: false,
dataType: 'json',
data: data,
//here goes the rest of the code
//...
});
return false;
});
it worked for me, it solved the problem between the click and submit event that wasn't allowing me to send the function through ajax.