Cannot disable Twitter bootstrap button with jQuery? - javascript

I am doing some AJAX when a button is clicked
$btn.button('loading');
$.ajax({
type: 'PUT',
url: 'event/',
data: put_data,
dataType: 'json',
success: function(data){
if (data.redirect) {
window.location = data.redirect;
}
else {
$btn.button('reset');
if ($btn.is('#my-btn')) {
console.log('disabling button');
$btn.prop('disabled', true);
}
}
}
});
disabling button shows up in the console, but the button does not get disabled. Loading and resetting the button works just fine. I tried .addClass('disabled') and .attr('disabled','disabled'), but those also don't work.
See here: http://codepen.io/anon/pen/Wvbeeg

The problem is that button('reset') is asynchronous. You can watch the changes live in the html an see they aren't immediate
A short delay after reset resolves the problem, but personallly i would just code this whole process myself instead of using the bootstrap API
$(document).ready(function() {
$('#mybutton').click(function() {
var $btn = $(this);
$btn.button('loading');
setTimeout(function() {/// mimic ajax delay
$btn.button('reset');
setTimeout(function() {// short delay after reset
$btn.prop('disabled', true);
}, 200);
}, 1000);
});
});
DEMO

Remove:
$btn.button('reset');
For some reason, this doesn't evaluate until after you disable it. (It's asynchronous)
Rather than resetting the button using the 'reset' code, it might be better to just remove the disabled property if it exists. That will effectively enable the button if it should be active.
Modified code:
$btn.button('loading');
$.ajax({
type: 'PUT',
url: 'event/',
data: put_data,
dataType: 'json',
success: function(data){
if (data.redirect) {
window.location = data.redirect;
}
else {
if ($btn.is('#my-btn')) {
console.log('disabling button');
$btn.prop('disabled', true);
} else {
$btn.prop('disabled', false);
}
}
}
});
Bonus tip: Don't use .removeProp() to re-enable the button. That will completely remove the property and you won't be able to use it again. More about prop() here: https://api.jquery.com/prop/

It's because you are using jQuery to bind a click event to the button. So the disable property won't be able to stop it. In your code you will need to add this:
$('#mybutton').off('click');
That will unbind the event from the button.

Related

In jQuery, using e.preventDefault() does not show checkbox status as checked

I have been trying to stop form submission on event click of a checkbox. But unable to show checked state in the UI. I have also tried to use a separate event loop as mentioned in this answer.
First the checkbox will be loaded by ajax, and append as HTML so I had been using on an event
discountElement.rentalCompanyWithDiscountDiv
.on('click', discountElement.rentalCompanyCheckBox, this.loadCamperFromCountryAndRentalCompany);
Here is code for adding checked attribute to the HTML and calling another request via ajax
loadTakeOverAndReturnableStation: function (e) {
if (e.target.checked) {
e.target.setAttribute('checked', 'checked');
discountElement.camperIds.push(e.target.value);
} else {
e.target.removeAttribute('checked');
discountElement.camperIds.splice(discountElement.camperIds.indexOf(e.target.value), 1);
}
if (discountElement.camperIds.length>0 && discountElement.rentalCompanyIds.length>0){
var country_id = discountElement.country.val();
var _token = discountElement._token.val();
$.ajax({
url: discountElement.fetchStations.val(),
method: "POST",
headers: {
'X-CSRF-TOKEN': _token
},
data: {
country_id: country_id,
_method: 'POST',
'discount_id': discountElement.discountId.val(),
'rental_company_id': discountElement.rentalCompanyIds,
'camper_id': discountElement.camperIds
},
success: discountModule.fillDiv
});
}else{
discountElement.takeOverStationsDiv.empty();
discountElement.returnableStationsDiv.empty();
}
}
This is my initial state of code which will resubmit form on every click. When I add e.preventDefault(); It will not show checked state in UI but worked as if it is checked.
When I tried to implement checked state on setTimeout as suggested on the above answer like this
e.preventDefault();
setTimeout(function () {
if (e.target.checked) {
e.target.setAttribute('checked', 'checked');
discountElement.camperIds.push(e.target.value);
} else {
e.target.removeAttribute('checked');
discountElement.camperIds.splice(discountElement.camperIds.indexOf(e.target.value), 1);
}
},1);
It does not work, either showing checked in the UI or on background,

avoid multiple clicks on a div

It's probably sthg simple, but I still didn't find a solution, I would like to avoid multiple clicks on a button, before finishing an ajax call.
Here is what I tried :
<button id="btn_pay"></button>
$("#btn_pay").click( function() {
$('#btn_pay').prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
alert("success");
},complete:function(){
//we re-enable the button
$('#btn_pay').prop('disabled', false);
}
});
Problem :
If I click several times on the button, many alerts appear, it's like the button is still active, and many ajax call are done instead of jsut 1 at a time..
Any idea ?
You can control it with a simple variable:
<button id="btn_pay"></button>
var disabled = false; // global var to control button state
$("#btn_pay").click( function() {
if (disabled) {
return;
}
Stripe.card.createToken(form, stripeResponseHandler);
disabled = true; // button is now blocked
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
disabled = false; // release button lock
alert("success");
},complete:function(){
disabled = false; // release button lock
},fail: function(){
disabled = false; // when fail, you need to release the lock too
}
});
}
Other solutions with event handlers may work for you too, but this is a simpler way to implement this feature.
Try e.preventdefault();
The event.preventDefault() method stops the default action of an
element from happening. For example: Prevent a submit button from
submitting a form. Prevent a link from following the URL.
I have Also facine this type of problem , i have prevent it by using this .. May be it will help you
<button id="btn_pay"></button>
$("#btn_pay").click( function(e) {
e.preventdefault();
$('#btn_pay').prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
alert("success");
},complete:function(){
//we re-enable the button
$('#btn_pay').prop('disabled', false);
}
});
Modify your code:
.unbind() Remove a previously-attached event handler from the elements.
.bind Attach a handler to an event for the elements.
<button id="btn_pay"></button>
<script>
$("#btn_pay").click( function(e) {
$("#btn_pay").unbind("click");
$('#btn_pay').prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
var stripeResponseHandler = function(status, response) {
$.ajax({
type: "POST",
success: function(data){
alert("success");
},complete:function(){
//we re-enable the button
$("#btn_pay").bind("click");
}
});
</script>
Checkout the tutorials :
http://api.jquery.com/bind/
http://api.jquery.com/unbind/
You can also avoid multiple clicks on button by adding loading image untill your ajax call is completed in beforeSend: event.
for example:
$.ajax
({
url: 'your-url',
data: "",
type: 'post',
beforeSend: function() {
$("#loading-image").show();
},
success: function(result)
{
//alert(result);
$("#loading-image").hide();
}
});
You have to keep image in div id 'loading-image' and by default display:none(CSS Setup).
<div id="loader_div_all" style="position: absolute ! important;opacity: 0.60;display: none;">
<img src="ajaxSpinner.gif" style="width: 200px; height: 200px; margin-left: 500px; margin-top: 1060px;'">
$("#buttonid").click(function(){
$.ajax({
url: 'PATH_TO_AJAX_REQUEST_URL',
type: 'POST',
data: {/*Data set here*/},
beforeSend: function () {
$("#loader_div_all").css('display','block');
},
success: function(resp) {
$("#loader_div_all").css('display','none');
/*Perform Ajax Success Action Here*/
}
});
});
Link the disabled state of the button to the response function firing. This way the visual cue and the button behaviour should match.
$("#btn_pay").click( function(event) {
event.preventDefault();
if ($(this).prop('disabled')) {
return;
}
$(this).prop('disabled', true);
Stripe.card.createToken(form, stripeResponseHandler);
});
(It would be better to pass a callback re-enabling the button to stripeResponseHandler, so that that function is not tied to a specific button calling it).

jQuery toggle two clicks required in firefox

This works fine on all other browsers but in firefox, I need to click my 'show more reviews' link twice for my on click event to fire. any ideas?
$moreReviewsWrapper.toggle(function() {
$(this).on('click', function(e) {
e.preventDefault();
var moreReviewEndpoint = $(this).data().more;
if(moreReviewEndpoint) {
$.ajax({
type: 'GET',
dataType: 'html',
contentType: 'text/html; charset=utf-8',
url: moreReviewEndpoint,
beforeSend: function() {
$moreReviewsLink.text('Loading more reviews ...');
},
success: success,
error: function(){
$moreReviewsLink.prop('hidden', false);
$moreReviewsLink.text(originalText);
$commonError.show();
}
});
}
});
}, function() { $(this).off(); });
The structure of your jQuery looks kind of weird to me. toggle() is a show/hide function, and the first argument is a duration argument. You're passing it a function that creates an event handler. My guess is jQuery ends up running that function to evaluate it for a number (to use as the duration), which then sets your event handler.
I'm not sure what toggle() is supposed to be doing here, but moving your event listener outside of toggle() will fix your issue.

make sure ajax request doesn't get fired multiple time

I was working on a simple form page and I was wondering what happens if someone clicks the submit button many many times (incase my shared hosting somehow seems to be slow at that time).
Also, incase anyone wants to look at my code
$.ajax({
url: "submit.php",
type: 'POST',
data: form,
success: function (msg) {
$(".ressult").html("Thank You!");
},
error: function () {
$(".result").html("Error");
}
});
Is there a way to make it so after the user clicks it once, it won't run it again until the first click is done?
Thank you
You can use jQuery's .one() function:
(function handleSubmit() {
$('#submitBtn').one('click', function() {
var $result = $('.result');
$.ajax({
url: 'submit.php',
type: 'POST',
data: form,
success: function (msg) {
$result.html('Thank You!');
handleSubmit(); // re-bind once.
},
error: function () {
$result.html('Error');
}
}); // End ajax()
}); // End one(click)
}()); // End self-invoked handleSubmit()
*Edit: * Added recursion for multiple submissions.
Use a boolean flag
if (window.isRunning) return;
window.isRunning = true;
$.ajax({
url:"submit.php",
type: 'POST',
data: form,
success: function (msg){
$(".ressult").html("Thank You!");
},
error: function (){
$(".result").html("Error");
},
complete : function () {
window.isRunning = false;
}
});
var $button = $(this);
$button.prop('disabled', true); // disable the button
$.ajax({
url:"submit.php",
type: 'POST',
data: form,
success: function (msg){
$(".ressult").html("Thank You!");
},
error: function (){
$(".result").html("Error");
},
complete: function() {
$button.prop('disabled', false); // enable it again
}
});
Have you considered replacing your submit button with a loader image while the query executes, then re-adding it once the query is complete?
EDIT: Using the loader image is a sort of universal "I'm doing something" indicator, but disabling the button would work too!
You could disable the submit button, before the ajax call is made. And then, if required, enable it on success.

Why does this if/else not work in jquery for me?

I have the following that fires off when a checkbox is changed.
$(document).ready(function() {
$("#reviewed").change(function(){
if ($('#reviewed:checked').val() !== null) {
$.ajax({
url: "cabinet_reviewed.php?reviewed=yes",
cache: false,
success: function(html){
$("#reviewDate").replaceWith(html);
}
});
} else {
$.ajax({
url: "cabinet_reviewed.php?reviewed=no",
cache: false,
success: function(html){
$("#reviewDate").replaceWith(html);
}
});
}
});
})
This only works once. I'm looking to see when the check box is changed and what the value of it is once changed.
UPDATE:
I've change the code around to the following (based on everyone's comments)
$(document).ready(function() {
$("#reviewed").click(
function() {
var rURL = 'cabinet_reviewed.php?reviewed=';
if ($("#reviewed").is(":checked"))
rURL = rURL + "yes";
else
rURL = rURL + "no";
alert (rURL);
$.ajax({
url: rURL,
cache: false,
success: function(html){
$("#reviewDate").replaceWith(html);
}
});
});
})
The file cabinet_reviewed.php simply echos the value of $_GET['reviewed']
With this updated code the alert shows the correct URL but the second click does not run the .ajax.
Do I need to do something so the .ajax is run again?
Try with != instead of !==
And also this as an alternative:
$('#reviewed').is(':checked')
The below code works consistently in FF 3.5 and IE8:
$("#reviewed").click(
function() {
if ($("#reviewed").is(":checked"))
alert('checked');
else
alert('not checked');
}
);
After your update:
This code...
success: function(html){
$("#reviewDate").replaceWith(html);
}
... is replacing the element with ID=reviewDate in the DOM with the HTML that is returned from the Ajax call, so it is no longer present the second time the Ajax call is made.
Will something simpler like this work for you?
success: function(html){
$("#reviewDate").html(html);
}
There are apparently some bugs with the change() event for checkboxes in IE. Try using the click() event instead and see if it works better.
You normally want to use click event to track changes in checkboxes/radiobuttons. The change event is only fired if the new value differs from the old value. In checkboxes/radiobuttons there's no means of an initial value, only the checked attribute which is often not predefinied, hence the need to click twice before the change event is fired.
In checkboxes/radiobuttons you also don't want to check the value by val(), it's always the same. You rather want to check the checked state using this.checked.
Thus, the following should work:
$(document).ready(function() {
$("#reviewed").click(function() {
if (this.checked) {
// ...
} else {
// ...
}
});
});

Categories

Resources