280

Apparently a disabled <input> is not handled by any event

Is there a way to work around this issue ?

<input type="text" disabled="disabled" name="test" value="test" />
$(':input').click(function () {
    $(this).removeAttr('disabled');
})

Here, I need to click on the input to enable it. But if I don't activate it, the input should not be posted.

rmtheis
  • 5,992
  • 12
  • 61
  • 78
Pierre de LESPINAY
  • 44,700
  • 57
  • 210
  • 307
  • 1
    Here is a good alternative http://blog.pengoworks.com/index.cfm/2010/4/23/Attaching-mouse-events-to-a-disabled-input-element –  Oct 18 '10 at 19:52
  • You can use the CSS-pretend-disable and loop over the inputs in onSubmit handler, disabling the non-activated ones for real. – ptrk Jul 09 '15 at 16:22
  • 2
    Just a side note for readers: if you don't mind the **input beign posted** just use `readonly` instead of `disabled`. I know this is not what the OP asked but someone might be in the same situation as me... – Hache_raw May 07 '21 at 11:00

12 Answers12

304

Disabled elements don't fire mouse events. Most browsers will propagate an event originating from the disabled element up the DOM tree, so event handlers could be placed on container elements. However, Firefox doesn't exhibit this behaviour, it just does nothing at all when you click on a disabled element.

I can't think of a better solution but, for complete cross browser compatibility, you could place an element in front of the disabled input and catch the click on that element. Here's an example of what I mean:

<div style="display:inline-block; position:relative;">
  <input type="text" disabled />
  <div style="position:absolute; left:0; right:0; top:0; bottom:0;"></div>
</div>​

jq:

$("div > div").click(function (evt) {
    $(this).hide().prev("input[disabled]").prop("disabled", false).focus();
});​

Example: http://jsfiddle.net/RXqAm/170/ (updated to use jQuery 1.7 with prop instead of attr).

Andy E
  • 338,112
  • 86
  • 474
  • 445
  • 3
    Small thing: if you're using the `disabled` attribute with no value, that implies HTML rather than XHTML, in which case the closing slash is unnecessary. – Tim Down Jun 23 '10 at 09:56
  • 11
    @Tim: indeed it is unnecessary, but it's still valid HTML. It's just a force of habit really and I feel like it looks better. – Andy E Jun 23 '10 at 10:09
  • 1
    Thx Andy, this is quite smart. Isn't there simpler ? Do you know why do desabled inputs are not handleable ? – Pierre de LESPINAY Jun 23 '10 at 11:54
  • 1
    @Glide: I guess the UA's just followed suit on this one, the W3C DOM spec doesn't specifically mention anything about not firing mouse events on a disabled element (as far as I can tell). I only wish I could think of an easier way, maybe somebody else will. – Andy E Jun 23 '10 at 12:00
  • really cool codes! actually, so long as you add the 2 magic div, it will work as expected even if you just set the onclick event on the parent element of the input (which is the div container). – hetaoblog Nov 07 '12 at 08:55
  • IE 11 won't accept a click event on disabled a element, but Chrome 40 and Firefox 33 will. –  Feb 26 '15 at 01:14
  • 3
    This doesn't make sense: any other html element handles mouse events, why not a disabled element (eg. `mouseenter`, etc.) – Augustin Riedinger Jul 08 '15 at 13:03
  • 18
    You can stop the disabled element from "throwing away" your clicks by putting `input[disabled] {pointer-events:none}` in your CSS. Then the click behaves as if you clicked the parent element. IMHO this is the simplest, cleanest solution, but it unfortunately only works for browsers that support the `pointer-events` CSS property: http://caniuse.com/#search=pointer-events – Doin Aug 17 '15 at 20:30
  • 1
    Instead of adding another div you can achieve the same result using the CSS before selector. For example: ```input::before { bottom: 0; content: ''; left: 0; position: absolute; right: 0; top: 0; }``` – Christophe Geers Jan 05 '17 at 14:59
  • @ChristopheGeers That wouldn't work because you can't bind events to pseudo elements. – tylertrotter Nov 09 '17 at 15:01
  • This is by far the best workaround. As @ChristopheGeers points out, it's easy to use a generated pseudo-element to avoid extra markup, and also works even for a full form – laconbass Jul 31 '20 at 01:30
102

Disabled elements "eat" clicks in some browsers - they neither respond to them, nor allow them to be captured by event handlers anywhere on either the element or any of its containers.

IMHO the simplest, cleanest way to "fix" this (if you do in fact need to capture clicks on disabled elements like the OP does) is just to add the following CSS to your page:

input[disabled] {pointer-events:none}

This will make any clicks on a disabled input fall through to the parent element, where you can capture them normally. (If you have several disabled inputs, you might want to put each into an individual container of its own, if they aren't already laid out that way - an extra <span> or a <div>, say - just to make it easy to distinguish which disabled input was clicked).


The downside is that this trick unfortunately won't works for older browsers that don't support the pointer-events CSS property. (It should work from IE 11, FF v3.6, Chrome v4): caniuse.com/#search=pointer-events

If you need to support older browsers, you'll need to use one of the other answers!

Doin
  • 7,545
  • 4
  • 35
  • 37
  • I wasn’t sure if `input[disabled]` would also match elements disabled by JavaScript (`element.disabled = true;`) but it seems it does. Anyway, I find `input:disabled` cleaner. – Martin Apr 27 '16 at 10:18
  • This seems like a good solution, doesn't work for me in IE11 though! Also you say FF 38+ and Chrome 31+ but your caniuse link says FF 3.6+ and Chrome 4+? – user764754 Feb 03 '17 at 09:23
  • @user764754 ...my mistake, I didn't realize I needed to click "Show All" on the caniuse page to get earlier browser versions! Have fixed that. As for IE11, I just tested it, and it works fine (see https://jsfiddle.net/7kkszq1c/1/ for the code, though for some reason the jsFiddle site didn't work for me in IE11, I had to paste it into a .htm file instead) – Doin Feb 04 '17 at 21:11
  • Thanks for the update! In the meantime I also observed that it works on a website in IE11 but not with jsfiddle. Maybe because of the jsfiddle iframe... – user764754 Feb 05 '17 at 11:22
  • @Martin: `input:disabled` is a Jquery selector and won't work in CSS, whereas `input[disabled]` will. – Protector one Jul 12 '17 at 11:31
  • 3
    @Protectorone :disabled is a pseudo-class since CSS 3: https://www.w3.org/TR/css3-selectors/#UIstates – Martin Jul 12 '17 at 11:41
  • Now I think this is the cleanest answer personally – Chanwoo Park May 30 '19 at 05:52
83

Maybe you could make the field readonly and on submit disable all readonly fields

$(".myform").submit(function(e) {
  $("input[readonly]").prop("disabled", true);
});

and the input (+ script) should be

<input type="text" readonly="readonly" name="test" value="test" />
$('input[readonly]').click(function () {
  $(this).removeAttr('readonly');
});

A live example:

$(".myform").submit(function(e) {
  $("input[readonly]").prop("disabled", true);
  e.preventDefault();
});


$('.reset').click(function () {
  $("input[readonly]").prop("disabled", false);
})

$('input[readonly]').click(function () {
  $(this).removeAttr('readonly');
})
input[readonly] {
  color: gray;
  border-color: currentColor;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="myform">
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  <input readonly="readonly" value="test" />
  
  <button>Submit</button>
  <button class="reset" type="button">Reset</button>
</form>
Tokimon
  • 4,072
  • 1
  • 20
  • 26
  • 6
    +1, this is a decent alternative suggestion. The only downside is that the input box will not take on the disabled styling, which varies between browsers so it would be hard to make it look consistent with the user's expectations of a disabled input. – Andy E Jun 24 '10 at 09:57
  • true. Perhaps this could be worked around with CSS? But yes it would not have the same look as normal diabled input fields – Tokimon Jun 29 '10 at 21:26
  • Excellent alternative solution. I like this one better because you can do any necessary styling with CSS (i.e. make it LOOK disabled) yet still have events available. – Joshua Feb 01 '11 at 04:43
  • this is exactly what i needed! – Lorenzo Oct 10 '20 at 17:00
16

I would suggest an alternative - use CSS:

input.disabled {
    user-select : none;
    -moz-user-select : none;
    -webkit-user-select : none;
    color: gray;
    cursor: pointer;
}

instead of the disabled attribute. Then, you can add your own CSS attributes to simulate a disabled input, but with more control.

Ron Reiter
  • 3,852
  • 3
  • 30
  • 34
7

$(function() {

  $("input:disabled").closest("div").click(function() {
    $(this).find("input:disabled").attr("disabled", false).focus();
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<div>
  <input type="text" disabled />
</div>
Rejeesh Prarath
  • 497
  • 5
  • 8
7

Instead of disabled, you could consider using readonly. With some extra CSS you can style the input so it looks like an disabled field.

There is actually another problem. The event change only triggers when the element looses focus, which is not logic considering an disabled field. Probably you are pushing data into this field from another call. To make this work you can use the event 'bind'.

$('form').bind('change', 'input', function () {
    console.log('Do your thing.');
});
mnille
  • 1,328
  • 4
  • 16
  • 20
Nykac
  • 129
  • 2
  • 7
4

OR do this with jQuery and CSS!

$('input.disabled').attr('ignore','true').css({
    'pointer-events':'none',
     'color': 'gray'
});

This way you make the element look disabled and no pointer events will fire, yet it allows propagation and if submitted you can use the attribute 'ignore' to ignore it.

sidonaldson
  • 24,431
  • 10
  • 56
  • 61
  • @Precastic, that's true, but it works for almost all other browsers at this point and you can use a [polyfill for ie < 11](https://github.com/kmewhort/pointer_events_polyfill). sidonaldson, why not use straight CSS to apply styles? – KyleMit Oct 26 '14 at 23:30
  • @KyleMit you could add a class rather than setting the styles, but that's not what this thread is about! I was only suggesting pointer events which is still a good and correct answer depending on browser matrix you are building for. And thanks for everyone who has marked this answer down that kinda sucks as nothing here is incorrect :/ – sidonaldson Oct 28 '14 at 16:42
  • 1
    @sidonaldson, It's a good answer so I also wish it was ranked higher as well. I'm [not sure what the ignore attribute does](https://www.google.com/#q=html+attribute+ignore). But my point about CSS was that I don't think we need jQuery to be the vehicle for applying CSS. You could just setup a CSS rule that targeted the same selector and also disabled pointer events. [In this fiddle](http://jsfiddle.net/KyleMit/pxx8pk6v/), the jQuery and CSS should be doing the same thing, but the CSS will be far more performant. – KyleMit Oct 28 '14 at 17:11
  • @KyleMit ah, well assuming the form is submitted you will have to somehow tell the backend to ignore that field if it contained a value (since we're spoofing disabled). – sidonaldson Oct 28 '14 at 17:28
  • I agree CSS could be more powerful as you can use a selector based on an attribute! Check this demo where I've matched chromes own disabled field: http://jsfiddle.net/KyleMit/pxx8pk6v/ – sidonaldson Oct 28 '14 at 17:29
1

There is no reason you can't simulate the disabled attribute using a combination of CSS and readonly:

Faux-Disabled: <input type="text" value="1" readonly="1" style="background-color:#F6F6F6;"><br>

Real-Disabled: <input type="text" disabled="true" value="1"></input>

Note: This will not have the regular behavior of disabled in the <form>, which prevents the server from seeing the field. This is just in case you want to disable a field that doesn't matter server-side.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
0

We had today a problem like this, but we didn't wanted to change the HTML. So we used mouseenter event to achieve that

var doThingsOnClick = function() {
    // your click function here
};

$(document).on({
    'mouseenter': function () {
        $(this).removeAttr('disabled').bind('click', doThingsOnClick);
    },
    'mouseleave': function () {
        $(this).unbind('click', doThingsOnClick).attr('disabled', 'disabled');
    },
}, 'input.disabled');
Raul Sanchez
  • 270
  • 2
  • 17
0

I did something very similar the Andy E; except I used a surrounding tag. However, I needed the 'name' so I changed it to an tag without the 'href'.

Glyn
  • 1,933
  • 5
  • 37
  • 60
-1

I find another solution:

<input type="text" class="disabled" name="test" value="test" />

Class "disabled" immitate disabled element by opacity:

<style type="text/css">
    input.disabled {
        opacity: 0.5;
    }
</style>

And then cancel the event if element is disabled and remove class:

$(document).on('click','input.disabled',function(event) {
    event.preventDefault();
    $(this).removeClass('disabled');
});
npth
  • 9
  • 1
  • 1
    The JavaScript part does not work for me. Apart from that, it does not answer the question, as it is about enabling a disabled input. In this example however it is not disabled at the start, and thus gets sent on submit. – Raimund Krämer Nov 16 '15 at 14:08
-2

suggestion here looks like a good candidate for this question as well

Performing click event on a disabled element? Javascript jQuery

jQuery('input#submit').click(function(e) {
    if ( something ) {        
        return false;
    } 
});
Community
  • 1
  • 1
katzmopolitan
  • 1,371
  • 13
  • 23