53

Fiddle: http://jsfiddle.net/ugzux/

As you can see, I have a form with a disabled (via javascript) submit button.

I want to be able to bind a click event to it anyway, so I can do some jazzy indication of what needs to be fixed on the input before I'll allow the form to be submitted (i.e enable the button again).

However, disabling the submit button also apparently disables any click events bound to the button, even if they are bound after the disable - any idea how to get around this?

Practically, one solution is to stop disabling the button and instead have an event that does

$('form').submit(function(event){
    event.preventDefault(); 
});

However I want to know the ins and outs of disabled inputs and javascript events, and if there are workarounds as I've never encountered this behaviour before.

4
  • 2
    This is by design. Most UI frameworks ignore disabled controls when dispatching mouse click events, and the one used by your browser is no exception. Commented Oct 20, 2011 at 9:49
  • @Frederic - (using FF6 on mac) thanks for clarifying - do you know where I can find a spec detailing this behaviour - i.e is it in the ECMA spec? Commented Oct 20, 2011 at 9:53
  • 5
    Well, HTML5 does say A form control that is disabled must prevent any click events that are queued on the user interaction task source from being dispatched on the element, so I guess it can be considered as documented (and browsers using a toolkit that does relay click events to disabled controls should arguably ignore them in order to be compliant). Commented Oct 20, 2011 at 10:01
  • 2
    this makes sense, thanks for your thoughtful comments. For anyone interested in solving the problem mentioned in my question, I just gave the button a disabled class rather than a disabled attribute, and tested against that when clicked, preventing form submission if the button had the disabled class. Commented Oct 20, 2011 at 12:18

11 Answers 11

53

Found this in this question -

Firefox, and perhaps other browsers, disable DOM events on form fields that are disabled. Any event that starts at the disabled form field is completely canceled and does not propagate up the DOM tree. Correct me if I'm wrong, but if you click on the disabled button, the source of the event is the disabled button and the click event is completely wiped out. The browser literally doesn't know the button got clicked, nor does it pass the click event on. It's as if you are clicking on a black hole on the web page.

I'd thought you might be able to 'fake' a click by wrapping the button in a div and firing the logic on the div's click event. But, as indicated above, the events on disabled elements do not seem to be bubbled up the DOM tree.

Sign up to request clarification or add additional context in comments.

5 Comments

this tallies with what I've seen, and the workaround you mentioned also does the job - although not pretty :)
You could use a <button type="submit"> instead and, rather than disabling it, you could switch to type="button" and add a class of .disabled, styling it accordingly. In this instance, it will not do anything when clicked but still be registered by the DOM. Granted, this is not necessarily semantic, but just throwing it in the mix. EDIT: I didn't realise you couldn't change the type of a button once DOM is loaded. This approach can still be used, but you'd need to clone/replace the button rather than just switch the type.
A little hacky, but you could use JavaScript to create a proxy element the same dimensions as the disabled button, and absolutely position it on the disabled button. Then you can register clicks with the proxy element.
The easiest fix is to add input[disabled] {pointer-events:none} to your CSS. Then when the input is disabled, its parent element will catch the click, and you can capture that.
Browser support for pointer-events:none: caniuse.com/#search=pointer-events
14

The best way I've found to do this is to use a "disabled" class to disable the button. You can then catch click events normally in jquery. If $(this).hasClass('disabled'), you do your 'jazzy indication' stuff, along with event.preventDefault(); Once the user has done their thing, you can removeClass('disabled') from the input[type="submit"] 'button'. Easy!

3 Comments

yeah that's what I ended up doing, see comments on the question :)
Oh yeah. Works well eh!
It's not a good approach, IMHO. For instance, one can use "disabled" attribute to prevent elements from posting.
8

You could put a div around the submit button and attach a click function to that for when the submit button is disabled:

<div id="sub-div"><input type="submit"><div>

$('sub-div').click(function(event){
    if (attr('submit-button', 'disabled') == 'true')
    {
        alert('Button Disabled')
    }
});

This is just code from the top of my head, so it might not be exactly right. But you get the point.

1 Comment

This won't work in a lot of browsers, since the click gets completely canceled by the disabled button and doesn't bubble up the DOM tree.
1

Making the button readonly can help, because the click event will be fired. Though be aware of the differences in behaviour.

<input type="submit" value="Submit" readonly="readonly" />

Comments

1
$(document).on('click', '.wrapper-of-disabled-button', function(){
  if ($(this).find('button.disabled').length > 0) {
    // Do your magic on the parent -> $(this)
  }
});

Here you go ;)

Comments

1

I have a slight more complicate but similar use case to you:

  1. There are many submit button on the screen, but by default they are disabled
  2. User need to click on the consent checkbox for button to be enabled
  3. The consent checkbox can be toggled on / off
  4. After click on the checkbox, they can click on all of the submit button

Using jQuery, I have done it with Overlapping the button with a div, and wrapping the div instead another div

See the below demo

var toggleNeedConsent = function() {
  var isEnableCheckbox = $('#consent-confirm-checkbox').prop('checked');
  $('.needConsentButton').prop('disabled', !isEnableCheckbox);
  if (!isEnableCheckbox) {
    if (!$(".needConsentButtonOutterDiv").length) {
      $('.needConsentButton').wrap("<div class='needConsentButtonOutterDiv' style='display: inline-block; position:relative'></div>");
    }
    $('.needConsentButton').after('<div class="needConsentButtonDiv" style="position:absolute; top:0; left:0; width: 100%; height:100%; ;"></div></div>');

    $('.needConsentButtonDiv').click(function(e) {
      alert('Please accept the consent first');
    })
  } else {
    $(".needConsentButtonDiv").remove();
  }
}

$(function() {
  toggleNeedConsent();
  $('#consent-confirm-checkbox').click(function() {
    toggleNeedConsent();
  });

  $("#approveButton").click(function() {
    alert('You are a wizard, Harry!');
  })

  $("#approve2Button").click(function() {
    alert('Harry, you are a wizard!');
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click consent checkbox before approve! <input type="checkbox" id="consent-confirm-checkbox">
<br/>
<br/>

<button class="needConsentButton" id="approveButton">Approve Form1!</button>

<br/>
<br/>
<button class="needConsentButton" id="approve2Button">Approve Form2!</button>

Good things about this approach:

  • Only need to add a class for the button to be disabled, the other HTML remain the same
  • Can consent multiple button at once
  • The button is actually disabled instead of using fancy customized method, that make external library understand and make CSS accordingly

Comments

0

An other workaround with combination of a required checkbox could be:

<input type="checkbox" class="einwilligung" name="einwilligung" value="ja"/>
<div class="einwilligung_hinweis">U need to check this box</div>
<div class="button_outer">
        <input type="submit" name="submit" value="Senden" id="submitButton" disabled="disabled" class="nope btn" />
        <span class="button_overlay"></span>
 </div>

CSS-Magic

#submitButton{
display:inline-block;
color:#D00019;
width:160px;
z-index:30;
position:absolute;
display:block;
top:0;
left:0;
height:30px;
outline:none;
}

#submitButton.nope{
z-index:10;
color:#333;
}

.button_outer {
width:162px;
height:32px;
z-index:50;
position:relative;
}

span.button_overlay{
display:block;
height:30px;
width:162px;
position:absolute;
top:0;
left:0;
background:#fff;
opacity:0.3;
filter: alpha(opacity=30);
z-index:20;
}

.einweilligung_hinweis_error{
color:red;
}

JQuery-Stuff

(document).ready(function() {

  $('.einwilligung').click(function() {
    var buttonsChecked = $('.einwilligung:checked');
    if (buttonsChecked.length) {
      $('#submitButton').removeAttr('disabled');
      $('#submitButton').removeClass('nope');
      $('.einwilligung_hinweis').removeClass('einweilligung_hinweis_error');
    }
    else {
      $('#submitButton').attr('disabled', 'disabled');
      $('#submitButton').addClass('nope');
    }
  });

  $('.button_outer').click(function(){
     if($('#submitButton').hasClass('nope')){
          $('.einwilligung_hinweis').addClass('einweilligung_hinweis_error');
      }else{
          $('.einwilligung_hinweis').removeClass('einweilligung_hinweis_error');
      }
  });

});

Maybe not state of the art, but it works pretty well!

  • the checkbox needs to be checked for giving the submit button a higher z-index
  • if not, there is the button_overlay above, with a click event on it, for highlighting the message

Comments

0

You should use .disabled class to style element to look disabled and then handle it as you wish using .hasClass('.disabled') in your JS code. It sould work as long as you didn't put "pointer-events: none;" declaration in your css code for .disabled class

Comments

0

I accomplished this by using jQuery and two buttons. Have one showing and one hidden, then use the .show() and .hide() functions to alternate between them.

<script src="https://code.jquery.com/jquery-3.5.0.js">

$('#one').click(function () {
  $('#one').hide();
  $('#two').show();
});
$('#two').click(function () {
  $('#two').hide();
  $('#one').show();
});
<button id="one">one</button>
<button id="two" hidden>two</button>

Comments

-1

Just don't disable the button, but prevent submit of the form. Looks like you're trying to validate the form; when you let JS take over the submit action, and return false, the form won't be submit

1 Comment

please read the question again, what I want to know is why disabled submit buttons also disable bound javascript events and if there are workarounds - this problem is merely the context of how I encountered the issue
-2

css

[disabled]{
pointer-events:none;
}

html

<span class="button"><input type="submit" disabled /></span>

You can try this for button click

$('.button').click(function(){
// do your code here.
});

1 Comment

Didn't work at all. pointer-events:none; will not allow registering any click event

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.