What's the best way to prevent a double-click on a link with jQuery?
I have a link that triggers an ajax call and when that ajax call returns it shows a message.
The problem is if I double-click, or click it twice before the ajax call returns, I wind up with two messages on the page when I really want just one.
I need like a disabled attribute on a button. But that doesn't work on links.
$('a').on('click', function(e){
e.preventDefault();
//do ajax call
});
You can use data- attributes, something like this:
$('a').on('click', function () {
var $this = $(this);
var alreadyClicked = $this.data('clicked');
if (alreadyClicked) {
return false;
}
$this.data('clicked', true);
$.ajax({
//some options
success: function (data) { //or complete
//stuff
$this.data('clicked', false);
}
})
});
I came with next simple jquery plugin:
(function($) {
$.fn.oneclick = function() {
$(this).one('click', function() {
$(this).click(function() { return false; });
});
};
// auto discover one-click elements
$(function() { $('[data-oneclick]').oneclick(); });
}(jQuery || Zepto));
// Then apply to selected elements
$('a.oneclick').oneclick();
Or just add custom data atribute in html:
<a data-oneclick href="/">One click</a>
You need async:false
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false.
$.ajax({
async: false,
success: function (data) {
//your message here
}
})
you can use a dummy class for this.
$('a#anchorID').bind('click',function(){
if($(this).hasClass('alreadyClicked')){
return false;
}else{
$(this).addClass('alreadyClicked);
$/ajax({
success: function(){$('a#anchorID').removeClass('alreadyClicked');},
error: function(){$('a#anchorID').removeClass('alreadyClicked');}
});
}});
Check this example. You can disable the button via CSS attribute after the first click (and remove this attribute after an ajax request or with a setTimeout) or use the jQuery.one() function to remove the trigger after the first click (without disabling the button)
var normal_button = $('#normal'),
one_button = $('#one'),
disabled_button = $('#disabled'),
result = $('#result');
normal_button.on('click', function () {
result.removeClass('hide').append(normal_button.html()+'<br/>');
});
one_button.one('click', function () {
result.removeClass('hide').append(one_button.html()+'<br/>');
});
disabled_button.on('click', function () {
disabled_button.attr('disabled', true);
setTimeout(function () {
result.removeClass('hide').append(disabled_button.html()+'<br/>');
}, 2000);
});
Although there are some good solutions offered, the method I ended up using was to just use a <button class="link"> that I can set the disabled attribute on.
Sometimes simplest solution is best.
You can disable click event on that link second time by using Jquery
$(this).unbind('click');
See this jsfiddle for reference
Demo
You can disable your links (for instance, href="#" ), and use a click event instead, binded to the link using the jQuery one() function.
Bind all the links with class "button" and try this:
$("a.button").click(function() { $(this).attr("disabled", "disabled"); });
$(document).click(function(evt) {
if ($(evt.target).is("a[disabled]"))
return false;
});
Related
I have a group of buttons with different values but same name (says "save"). When one of this button is clicked, a jquery event is triggered and sends the value of that exact button with an ajax call to the server. When the server responds with a success, I would like the value of that same clicked button to change into "saved". I have written a little function that does that, but the problem is that when you click on one of those buttons that say "save" and it's a success, all the values of the other buttons change into "saved". How can I change only the value of the clicked button and instead of all the buttons with the same name?
Here's my html:
<button class="homemade" name="saveArticle" value="v1">Save</button>
<button class="homemade" name="saveArticle" value="v2">Save</button>
Here's my Jquery function:
$(function() {
$('[name="saveArticle"]').bind('click', function() {
$.getJSON('/articles/save', {
article_id: this.value,
}, function(data) {
$("[name='saveArticle']").text(data.message);
});
return false;
});
});
use arrow functions then you can just use this to refer to the clicked button.
$(function() {
$('[name="saveArticle"]').bind('click', function() {
$.getJSON('/articles/save', {
article_id: this.value,
}, (data)=>{
$(this).text(data.message);
});
return false;
});
});
alternatively you could use the event target.
$(function() {
$('[name="saveArticle"]').bind('click', function(event) {
$.getJSON('/articles/save', {
article_id: this.value,
}, function(data) {
$(event.target).text(data.message);
});
return false;
});
});
Shouldn’t that do the trick to give you access to the element that was clicked?
$(function() {
$('[name="saveArticle"]').bind('click', function() {
// here `this` points to element on which event fired
$(this) // <-- creates jQuery object of it
});
});
I'm trying to figure out how to change behaviour of a button using AJAX.
When the button is clicked, it means that user confirmed order recently created. AJAX calls /confirm-order/<id> and if the order has been confirmed, I want to change the button to redirect to /my-orders/ after next click on it. The problem is that it calls again the same JQuery function. I've tried already to remove class="confirm-button" attribute to avoid JQuery again but it does not work. What should I do?
It would be enough, if the button has been removed and replaced by text "Confirmed", but this.html() changes only inner html which is a text of the button.
$(document).ready(function () {
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
var id = this.value;
var url = '/confirm-order/'+id;
$.ajax({
type: 'get',
url: url,
success: function (data) {
$this.empty();
$this.attr('href','/my-orders/');
$this.parent().attr("action", "/my-orders/");
$this.html('Confirmed');
}
})
});
});
The event handler will be still attached to the button, so this will run again:
b.preventDefault();
which will prevent the default, which is opening the href. You need to remove the event handler on success. You use the jQuery #off() method:
$(".confirm-button").off('click');
or more shortly:
$this.off('click');
You can add to your success function something like: $this.data('isConfirmed', true);
And then in your click handler start by checking for it. If it's true, redirect the user to the next page.
$(".confirm-button").click(function (b) {
b.preventDefault();
var $this = $(this);
if ($this.data('isConfirmed')) {
... redirect code ...
}
else {
... your regular code ...
}
}
You need to use .on() rather than .click() to catch events after the document is ready, because the "new" button appears later.
See http://api.jquery.com/on/
$(document).ready(function() {
$('.js-confirm').click(function(){
alert('Confirmed!');
$(this).off('click').removeClass('js-confirm').addClass('js-redirect').html('Redirect');
});
$(document).on('click', '.js-redirect', function(){
alert('Redirecting');
});
});
<button class="js-confirm">Confirm</button>
To use jquery on method instead of deprecated live method in this simple case
$("#myForm").live('submit', function() {
alert("submit");
});
would be
$(document).on('submit', '#myForm', function() {
alert("submit");
});
Now, how to do the same with "pure" on, without extra things(like e.g. assign id to form and then use that id as a selector or smth like that) in this case
$("#myInput").parents("form").live('submit', function() {
alert("submit");
});
thanks
Run the event handler on all form submissions, then test to see if the form contains the input you care about inside it.
jQuery(document).on('submit', 'form', function (evt) {
if (jQuery(evt.target).find('#myInput').length === 0) {
return;
}
// Otherwise run the rest of the function normally
});
I have a form with a submit input and I need that when the button gets clicked, my script do some Ajax actions. Also I need to disable that button during the Ajax request. So I need a jQuery command to avoid real form submit when input is clicked. I tried to use this:
$('input.searchplease').click(function () {
$(this).attr('disabled', 'disabled');
alert('Yep');
//Do Ajax
});
This didn't worked. I mean, the alert shown correctly but form is submitted. So what is your suggestion?
Try this:
$('input.searchplease').click(function (e) {
$(this).attr('disabled', 'disabled');
alert('Yep');
//Do Ajax
e.preventDefault();
});
$('input.searchplease').click(function () {
alert('yep');
return false;
});
This should work
You can do this:
$('form').submit(function(){
... ajax things
return false;
});
I would rather not disable the button (and then enable it), unless I have to.
try this way :
$("#id-of-your-form").submit(function() {
$("#id-of-your-submit-input").attr("disabled", true);
// do-ajax
// you can use jquery's ajax complete handler to enable the submit button again
return false;
});
I think this will do the trick:
$('form').submit(function(event) {
event.preventDefault();
$('#submit-button-ID').attr('disabled', 'disabled');
$.ajax({
...,
success: function() {
$('#submit-button-ID').removeAttr('disabled');
}
});
});
I tried to use focus for first input field on the form. but
it doesn't work. When I call attr("id") for that input it worked. When I call focus for the same input, I didn't see any
result. I also tried to use native Javascript. Does anyone know how to
fix that?
You are all misunderstanding the question. When Colorbox opens you can't focus an input field?
...unless you add your focus to the Colobox onComplete key e.g.
$('#mydiv a').colorbox({ onComplete:function(){ $('form input:first').focus(); }});
You could also bind the focus to an event hook:
$('#mydiv a').bind('cbox_complete', function(){
$('form input:first').focus();
});
That should be enough to get started.
use
$(document).ready(function() {
// focus on the first text input field in the first field on the page
$("input[type='text']:first", document.forms[0]).focus();
});
It may be happening that when your colorbox is opened its focus goes onto the highest element i.e. body of page. use document.activeElement to find that focus went to which element. Then find iframe or id of your colorbox and then set focus on it
Try the first selector,
$("form input:first").focus();
http://jsfiddle.net/erick/mMuFc/
I've just stumbled on this problem.
I think it's best to have a single $.colorbox opener like this:
function showActionForColorBox(
_url,
_forFocus
) {
$.colorbox(
{
scrolling: false,
href: _url,
onComplete: function () {
idColorboxAjaxIndect1.appendTo($('#cboxOverlay'));
idColorboxAjaxIndect2.appendTo($('#cboxOverlay'));
idColorboxAjaxIndect3.appendTo($('#cboxOverlay'));
idColorboxAjaxIndect4.appendTo($('#cboxOverlay'));
// --> Possible element's ID for focus
if (_forFocus) {
$('#' + _forFocus).focus();
}
return;
},
onCleanup: function () {
// TODO: ?
return;
},
onClosed: function () {
if (shouldReloadPageAfterColorBoxAction) {
// --> Should we reload whole page?
shouldReloadPageAfterColorBoxAction = false; // NOTE: To be sure: Reset.
window.location.reload(false);
}
else if (cbEBillsActionReloadPopup) {
// --> Should we reload colorbox
cbEBillsActionReloadPopup = false;
showActionForColorBox(_url);
}
else if (cbShouldLoadAnotherContentAfterClosed) {
// --> Should we reload colorbox with custom content?
cbShouldLoadAnotherContentAfterClosed = false;
$.colorbox({ html: setupContentForcbShouldLoadAnotherContentAfterClosed });
setupContentForcbShouldLoadAnotherContentAfterClosed = '';
}
return;
}
}
);
return;
}
You can also use
$.colorbox({
...,
trapFocus: false
});
to disable focus inside colorbox