dans.blog


The miscellaneous ramblings and thoughts of Dan G. Switzer, II

Attaching mouse events to a disabled input element

I was doing some UI work this morning and ran into a bit of a problem. We have some HTML input elements that need to be disabled so the user can not interact with them. The problem is, we wanted to display a message to the user if they tried to interact with the element. While some browsers respond to a mousedown event, Firefox and Opera ignore all mouse-related events on a disabled form field. Since they seem to completely ignore mouse interaction, that means not even event delegation works.

After thinking about various ways to work around the behavior, I thought the most elegant solution might be to add an overlay over the disabled element which I'd use as the hotspot for mouse interaction. The overlay lays on top of the element and intercepts all mouse interaction.

Let's look at some sample HTML:

<label for="normal">
  <input type="checkbox" disabled="disabled" />
  Disabled Option
</label>

With a little jQuery magic, we can find the disabled element, get the parent <label /> element and then place a <div /> element over where the label element resides. The code looks like this:

// on DOM ready
$(document).ready(function (){
  // attach a click behavior to all checkboxes
  $(":checkbox").click(function (){
    alert("Clicked!");
  });

  // find the disabled elements
  var $disabled = $("#overlay-example input:disabled");

  // loop through each of the disable elements and create an overlay
  $disabled.each(function (){
    // get the disabled element
    var $self = $(this)
      // get it's parent label element
      , $parent = $self.closest("label")
      // create an overlay
      , $overlay = $("<div />");

    // style the overlay
    $overlay.css({
      // position the overlay in the same real estate as the original parent element 
        position: "absolute"
      , top: $parent.position().top
      , left: $parent.position().left
      , width: $parent.outerWidth()
      , height: $parent.outerHeight()
      , zIndex: 10000
      // IE needs a color in order for the layer to respond to mouse events
      , backgroundColor: "#fff"
      // set the opacity to 0, so the element is transparent
      , opacity: 0
    })
    // attach the click behavior
    .click(function (){
      // trigger the original event handler
      return $self.trigger("click");
    });

    // add the overlay to the page  
    $parent.append($overlay);
  });
});

You can see a live example here.