jQuery detect click on disabled submit button
Asked Answered
D

11

50

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.

Defensive answered 20/10, 2011 at 9:31 Comment(4)
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.Metamathematics
@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?Defensive
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).Metamathematics
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.Defensive
D
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.

Defence answered 20/10, 2011 at 10:4 Comment(5)
this tallies with what I've seen, and the workaround you mentioned also does the job - although not pretty :)Defensive
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.Thorma
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.Nikolos
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.Venessavenetia
Browser support for pointer-events:none: caniuse.com/#search=pointer-eventsVenessavenetia
G
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!

Gallery answered 21/8, 2013 at 5:48 Comment(3)
yeah that's what I ended up doing, see comments on the question :)Defensive
Oh yeah. Works well eh!Gallery
It's not a good approach, IMHO. For instance, one can use "disabled" attribute to prevent elements from posting.Outroar
M
6

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.

Martsen answered 20/10, 2011 at 10:5 Comment(1)
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.Venessavenetia
O
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" />
Orestes answered 12/11, 2013 at 9:59 Comment(0)
O
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 ;)

Observable answered 15/8, 2014 at 9:47 Comment(0)
C
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
Cavesson answered 17/5, 2019 at 4:5 Comment(0)
M
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
Milk answered 5/12, 2012 at 10:31 Comment(0)
L
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

Lohr answered 11/3, 2016 at 3:10 Comment(0)
R
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>
Redbreast answered 3/1, 2023 at 10:2 Comment(0)
O
-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

Olfactory answered 20/10, 2011 at 9:37 Comment(1)
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 issueDefensive
B
-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.
});
Boche answered 1/8, 2019 at 10:52 Comment(1)
Didn't work at all. pointer-events:none; will not allow registering any click eventPidgin

© 2022 - 2024 — McMap. All rights reserved.