371

Sometimes I use anchors styled as buttons and sometimes I just use buttons. I want to disable specific clicky-things so that:

  • They look disabled
  • They stop being clicked

How can I do this?

biofractal
  • 18,963
  • 12
  • 70
  • 116
  • see my post at the bottom end but here is the less descriptive $("yourSelector").button("enable"); //enable the button or $("yourSelector").button("disable"); //disable the button if the button widget from jqueryUI is used. – El Bayames Apr 20 '15 at 14:13
  • The BS3 documentation says to use `role="button"` for links, but that does not appear to affect this issue. http://getbootstrap.com/css/#buttons – Jess May 12 '17 at 16:32
  • 2
    Having `a.btn[disabled]` appear disabled yet remain clickable is a bug in Bootstrap IMO. The attribute `[disabled]` should only appear disabled for `button` and `input`. – Jess May 12 '17 at 16:38

16 Answers16

581

Buttons

Buttons are simple to disable as disabled is a button property which is handled by the browser:

<input type="submit" class="btn" value="My Input Submit" disabled/>
<input type="button" class="btn" value="My Input Button" disabled/>
<button class="btn" disabled>My Button</button>

To disable these with a custom jQuery function, you'd simply make use of fn.extend():

// Disable function
jQuery.fn.extend({
    disable: function(state) {
        return this.each(function() {
            this.disabled = state;
        });
    }
});

// Disabled with:
$('input[type="submit"], input[type="button"], button').disable(true);

// Enabled with:
$('input[type="submit"], input[type="button"], button').disable(false);

JSFiddle disabled button and input demo.

Otherwise you'd make use of jQuery's prop() method:

$('button').prop('disabled', true);
$('button').prop('disabled', false);

Anchor Tags

It's worth noting that disabled isn't a valid property for anchor tags. For this reason, Bootstrap uses the following styling on its .btn elements:

.btn.disabled, .btn[disabled] {
    cursor: default;
    background-image: none;
    opacity: 0.65;
    filter: alpha(opacity=65);
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
    color: #333;
    background-color: #E6E6E6;
}

Note how the [disabled] property is targeted as well as a .disabled class. The .disabled class is what is needed to make an anchor tag appear disabled.

<a href="http://example.com" class="btn">My Link</a>

Of course, this will not prevent links from functioning when clicked. The above link will take us to http://example.com. To prevent this, we can add in a simple piece of jQuery code to target anchor tags with the disabled class to call event.preventDefault():

$('body').on('click', 'a.disabled', function(event) {
    event.preventDefault();
});

We can toggle the disabled class by using toggleClass():

jQuery.fn.extend({
    disable: function(state) {
        return this.each(function() {
            var $this = $(this);
            $this.toggleClass('disabled', state);
        });
    }
});

// Disabled with:
$('a').disable(true);

// Enabled with:
$('a').disable(false);

JSFiddle disabled link demo.


Combined

We can then extend the previous disable function made above to check the type of element we're attempting to disable using is(). This way we can toggleClass() if it isn't an input or button element, or toggle the disabled property if it is:

// Extended disable function
jQuery.fn.extend({
    disable: function(state) {
        return this.each(function() {
            var $this = $(this);
            if($this.is('input, button, textarea, select'))
              this.disabled = state;
            else
              $this.toggleClass('disabled', state);
        });
    }
});

// Disabled on all:
$('input, button, a').disable(true);

// Enabled on all:
$('input, button, a').disable(false);

Full combined JSFiddle demo.

It's worth further noting that the above function will also work on all input types.

James Donnelly
  • 126,410
  • 34
  • 208
  • 218
  • Thanks for the comprehensive answer. Please see my *Edit 1* for a coffee script version. I am still struggling to get the links to prevent clicking. Did you mean for me to keep the `return false if $(@).prop('disabled')` in the custom click handlers? Without that line those handlers are run regardless. – biofractal May 28 '13 at 11:12
  • 1
    @biofractal as I mentioned `disabled` isn't a valid anchor tag property, so that shouldn't be used. The click event I've given is based upon the `.disabled` class, but what you can use is `hasClass('disabled')` - if that is true, `preventDefault`. – James Donnelly May 28 '13 at 11:35
  • ah, ok. Thanks. So why shouldn't I create and use the `disabled` property on the anchor. Its a dynamic object so I can just set it and use it, like I was extending the anchor's feature set? I have updated my answer below to show this. What do you think? Is it evil? Also, do you have to `.off()` the `preventDefault` click event when you re-enable a link? – biofractal May 28 '13 at 11:49
  • It goes against the specification and wouldn't pass validation tests. If you want a custom `disabled` property you can make use of [`data-*` attributes](http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes). As Bootstrap already applies the same `disabled` property styles to `class="disabled"` you may as well rely on the class instead. – James Donnelly May 28 '13 at 12:10
  • Got it - I have adapted my answer to reflect your comments. I am still concerned that if I hook up `preventDefault` to all anchor click events then I will need to detach them when the link is re-enabled. Or am I misunderstanding something? – biofractal May 28 '13 at 12:32
  • For the answer I've given, the click event handler is only applied to anchor elements with the `disabled` class. If you remove the `disabled` class, that event handler will not be used on that link. – James Donnelly May 28 '13 at 12:34
  • `If you remove the disabled class, that event handler will not be used on that link` - I tested this and unfortunately it does not work that way for me. Even after removing the `disabled` class from the link the previously attached 'preventDefault' handler still runs and the link click is disabled. – biofractal May 28 '13 at 13:15
  • @John Donnelly - To replicate, check this out: http://jsfiddle.net/EDvVr/7/ - perhaps this is a coffee script generating different JS? – biofractal May 28 '13 at 14:29
  • @biofractal I've changed your current `$('a.disabled')` click handler to: `$('body').on('click', 'a.disabled', -> false)`. Seems to do the trick. http://jsfiddle.net/JamesD/EDvVr/8/ :-) – James Donnelly May 28 '13 at 14:55
  • Splendid. I think our work here is done. Thanks for all your help. I have updated my coffee-script version below to reflect all of our comments. Feel free to bump my rep :-) – biofractal May 28 '13 at 15:13
  • Use `.toggleClass` to conditionally add/remove a class name based on a boolean value. There is an overload that takes a boolean (technically, truthy) as the second parameter. – doug65536 Sep 21 '13 at 10:18
  • @doug65536 thanks, I wasn't aware of that boolean parameter on `toggleClass()`! I've updated the answer. To use `$this.toggleClass('disabled', state);` instead. – James Donnelly Sep 22 '13 at 12:50
  • This solution does not seems to work with twitter Bootstrap 3, since onclick tag is placed on label and not on button. – Ruut Mar 11 '14 at 09:57
  • @Ruut this works fine on Bootstrap 3. You must be calling the `disable()` method on the label. – James Donnelly Mar 11 '14 at 10:05
  • @james-donnelly seems to work. I do an ajax call in between the .disable(true) and .disable(false) calls. Google chrome shows disabled buttons only when I place a breakpoint at the ajax call and when there is no breakpoint buttons are clickable during ajax call. – Ruut Mar 11 '14 at 10:28
  • @Andy `disabled` isn't a valid property on `a` elements. Whilst it may be styled to appear unclickable, the browser will not handle the `disabled` property and some may even strip it from the element as it isn't valid syntax. – James Donnelly Nov 08 '16 at 19:26
49

I can't think a simpler/easier way! ;-)


Using Anchor tags (Links) :

<a href="#delete-modal" class="btn btn-danger" id="delete">Delete</a>

To enable the Anchor tag:

 $('#delete').removeClass('disabled');
 $('#delete').attr("data-toggle", "modal");

enter image description here


To disable the Anchor tag:

 $('#delete').addClass('disabled');
 $('#delete').removeAttr('data-toggle');

enter image description here

oikonomopo
  • 4,025
  • 7
  • 44
  • 73
27

Suppose you have text field and submit button,

<input type="text" id="text-field" />
<input type="submit" class="btn" value="Submit"/>

Disabling:

To disable any button, for example, submit button you just need to add disabled attribute as,

$('input[type="submit"]').attr('disabled','disabled');

After executing above line, your submit button html tag would look like this:

<input type="submit" class="btn" value="Submit" disabled/>

Notice the 'disabled' attribute has added.

Enabling:

For enabling button, such as when you have some text in text field. You will need to remove the disable attribute to enable button as,

 if ($('#text-field').val() != '') {
     $('input[type="submit"]').removeAttr('disabled');
 }

Now the above code will remove the 'disabled' attribute.

Sohail xIN3N
  • 2,951
  • 2
  • 30
  • 29
22

I know I'm late to the party, but to specifically answer the two questions:

"I just want to disable specific clicky-things so that:

  • They stop clicking
  • They look disabled

How hard can this be?"

They stop clicking

1.  For buttons like <button> or <input type="button"> you add the attribute: disabled.

<button type="submit" disabled>Register</button>
<input type="button" value="Register" disabled>

2.  For links, ANY link... actually, any HTML element, you can use CSS3 pointer events.

.selector { pointer-events:none; }

Browser support for pointer events is awesome by today's state of the art (5/12/14). But we usually have to support legacy browsers in the IE realm, so IE10 and below DO NOT support pointer events: http://caniuse.com/pointer-events. So using one of the JavaScript solutions mentioned by others here may be the way to go for legacy browsers.

More info about pointer events:

They look disabled

Obviously this a CSS answer, so:

1.  For buttons like <button> or <input type="button"> use the [attribute] selector:

button[disabled] { ... }

input[type=button][disabled] { ... }

--

Here's a basic demo with the stuff I mentioned here: http://jsfiddle.net/bXm5B/4/

Hope this helps.

Ricardo Zea
  • 10,053
  • 13
  • 76
  • 79
18

If, like me, you just want to disable a button, don't miss the simple answer subtly hidden in this long thread:

 $("#button").prop('disabled', true);
Graham Laight
  • 4,700
  • 3
  • 29
  • 28
7

@James Donnelly has supplied a comprehensive answer that relies on extending jQuery with a new function. That is a great idea, so I am going to adapt his code so it works the way I need it to.

Extending jQuery

$.fn.disable=-> setState $(@), true
$.fn.enable =-> setState $(@), false
$.fn.isDisabled =-> $(@).hasClass 'disabled'

setState=($el, state) ->
    $el.each ->
        $(@).prop('disabled', state) if $(@).is 'button, input'
        if state then $(@).addClass('disabled') else $(@).removeClass('disabled')

    $('body').on('click', 'a.disabled', -> false)

Usage

$('.btn-stateful').disable()
$('#my-anchor').enable()

The code will process a single element or a list of elements.

Buttons and Inputs support the disabled property and, if set to true, they will look disabled (thanks to bootstrap) and will not fire when clicked.

Anchors don't support the disabled property so instead we are going to rely on the .disabled class to make them look disabled (thanks to bootstrap again) and hook up a default click event that prevents the click by returning false (no need for preventDefault see here).

Note: You do not need to unhook this event when re-enabling anchors. Simply removing the .disabled class does the trick.

Of course, this does not help if you have attached a custom click handler to the link, something that is very common when using bootstrap and jQuery. So to deal with this we are going tro use the isDisabled() extension to test for the .disabled class, like this:

$('#my-anchor').click -> 
    return false if $(@).isDisabled()
    # do something useful

I hope that helps simplify things a bit.

biofractal
  • 18,963
  • 12
  • 70
  • 116
7

Note that there's a weird problem if you're using Bootstrap's JS buttons and the 'loading' state. I don't know why this happens, but here's how to fix it.

Say you have a button and you set it to the loading state:

var myButton = $('#myBootstrapButton');
myButton.button('loading');

Now you want to take it out of the loading state, but also disable it (e.g. the button was a Save button, the loading state indicated an ongoing validation and the validation failed). This looks like reasonable Bootstrap JS:

myButton.button('reset').prop('disabled', true); // DOES NOT WORK

Unfortunately, that will reset the button, but not disable it. Apparently, button() performs some delayed task. So you'll also have to postpone your disabling:

myButton.button('reset');
setTimeout(function() { myButton.prop('disabled', true); }, 0);

A bit annoying, but it's a pattern I'm using a lot.

Henrik Heimbuerger
  • 9,924
  • 6
  • 56
  • 69
6

Great answer and contributions from all! I had to extend this function slightly to include disabling of select elements:

jQuery.fn.extend({
disable: function (state) {
    return this.each(function () {
        var $this = jQuery(this);
        if ($this.is('input, button'))
            this.disabled = state;
        else if ($this.is('select') && state)
            $this.attr('disabled', 'disabled');
        else if ($this.is('select') && !state)
            $this.removeAttr('disabled');
        else
            $this.toggleClass('disabled', state);
    });
}});

Seems to be working for me. Thanks all!

Brandon Johnson
  • 329
  • 5
  • 11
5

For that kind of behavior I always use the jQueryUI button widget, I use it for links and buttons.

Define the tag within HTML:

<button id="sampleButton">Sample Button</button>
<a id="linkButton" href="yourHttpReferenceHere">Link Button</a>

Use jQuery to initialize the buttons:

$("#sampleButton").button();
$("#linkButton").button();

Use the button widget methods to disable/enable them:

$("#sampleButton").button("enable"); //enable the button
$("#linkButton").button("disable"); //disable the button

That will take care of the button and cursor behavior, but if you need to get deeper and change the button style when disabled then overwrite the following CSS classes within your page CSS style file.

.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
      background-color:aqua;
      color:black;
 }

But remember: those CSS classes (if changed) will change the style for other widgets too.

Noumenon
  • 5,099
  • 4
  • 53
  • 73
El Bayames
  • 545
  • 7
  • 14
  • 1
    Pretty sure this answer is for *[jQuery UI buttons](https://jqueryui.com/button/)* and **not** for [Bootstrap buttons](http://getbootstrap.com/components/#glyphicons-examples) used with plain vanilla jQuery, the latter being what the OP is using. Btw, putting an answer in a comment on the question is not the preferred method of dissemination. ;^) – ruffin Aug 19 '15 at 19:32
5

The following has worked for me very well:

$("#button").attr('disabled', 'disabled');
Ahsan
  • 3,845
  • 2
  • 36
  • 36
3

I know my answer is late, but IMO this is the easiest way to toggle a Button 'enable' and button 'disable'

function toggleButtonState(button){

  //If button is enabled, -> Disable
  if (button.disabled === false) {
    button.disabled = true;

  //If button is disabled, -> Enable
  } else if (button.disabled === true) {
    button.disabled = false;
  }
}
jward01
  • 750
  • 4
  • 11
  • 26
2

This is a rather late answer, however I stumbled upon this question while searching for a way to disable boostrap buttons after clicking them and maybe add a nice effect (f.e a spinner). I've found a great library that does exactly that:

http://msurguy.github.io/ladda-bootstrap/

You just include the required css and js, add some properties to your buttons and enable lada with javascript... Presto ! Your buttons have a new life (please check the demo to see how beautiful it is) !

Serafeim
  • 14,962
  • 14
  • 91
  • 133
2

This above does not work because sometimes

$(this).attr('checked') == undefined

adjust your code with

if(!$(this).attr('checked') || $(this).attr('checked') == false){
Kiko Seijo
  • 701
  • 8
  • 11
2

Suppose you have these buttons on page like :

<input type="submit" class="byBtn" disabled="disabled" value="Change"/>
<input type="submit" class="byBtn" disabled="disabled" value="Change"/>
<input type="submit" class="byBtn" disabled="disabled" value="Change"/>
<input type="submit" class="byBtn" disabled="disabled" value="Change"/>
<input type="submit" class="byBtn" disabled="disabled" value="Change"/>
<input type="submit"value="Enable All" onclick="change()"/>

The js code:

function change(){
   var toenable = document.querySelectorAll(".byBtn");        
    for (var k in toenable){
         toenable[k].removeAttribute("disabled");
    }
}
Guillaume Fache
  • 813
  • 10
  • 21
Samit
  • 74
  • 6
2

Say you have that looks like this that is currently enable.

<button id="btnSave" class="btn btn-info">Save</button>

Just add this:

$("#btnSave").prop('disabled', true);

and you will get this which will disable button

<button id="btnSave" class="btn btn-primary" disabled>Save</button>
Apollo
  • 1,990
  • 12
  • 44
  • 65
  • 2
    The question asked about buttons _and_ anchors. The `disabled` property is not a valid property for anchor tags. – biofractal May 04 '17 at 07:15
0

If you want to disable the clickable, you can also add inline this in html

style="cursor: not-allowed;"
Ken Xu
  • 11
  • 2