Javascript – How to disable / re-enable all click/touch/mouse events on an html element and children

csshtmljavascriptjquery

I have a parent HTML element with various links, SVGs, text within it at various levels. When a certain link in the parent element is clicked, I'm trying to fade it 50% and disable any further interaction with it from touch / mouse events until it's re-enabled.

My code is complex and spaghetti-like so here is a very simple example:

$(function() {

  $('.container a').on({
    // I'm just showing click below for simplicity, I'll be adding some handling for mouse/touch events.
    click: function(e) {
      $('.container').fadeTo("slow", 0.5);
      $('.info').fadeTo("slow", 1);
    }
  });

  $('.info a').on({
    click: function(e) {
      $('.info').fadeOut();
      $('.container').fadeTo("slow", 1);
    }
  });

});
.container {
  background-color: #123435;
  padding: 1em;
}
.info {
  display: none;
  background-color: #435123;
  padding: 1em;
}
.container a,
.info,
.info a {
  color: #bbc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <a href="#">Show Info (click me)</a>
  <br>
  <a href="thingy1.htm">Other Link 1</a>
</div>
<div class="info">
  Some info (div.container and all it's contents now need to be totally disabled)
  <br>
  <a href="#">Hide Info</a>
  <br>
</div>

What I've tried

When container is faded I've attempted to set disabled attributes on all children, which works for any form inputs, but not for links.

I've also tried adding a 'faded' class and then checking for it like so:

$('.container:not(.faded) a').on({
  click: function(e) {
    $('.container').addClass("faded").fadeTo("slow", 0.5);
    $('.info').fadeTo("slow", 1);
  }
});

..but it seems that the 'on' action doesn't take into account the new class for the selector.. or something!

Help please. I'm very happy to consider a completely different way to tackle this. Thanks.

Best Solution

If you want to really disable everything, not just the event handlers added with javascript, you have to make sure even all the default actions are prevented.

The easy way to make sure all interaction with an element is disabled, is to put an other element on top of it, or by using CSS to disable all pointer-events

In modern browsers (from IE 11 and up) you can use pointer-events

$(function() {
  $('.container a').on('click', function(e) {
      $('.container').fadeTo("slow", 0.5).css('pointer-events', 'none');
      $('.info').fadeTo("slow", 1);
  });

  $('.info a').on('click', function(e) {
      $('.info').fadeOut();
      $('.container').fadeTo("slow", 1).css('pointer-events', 'auto');
  });
});
.container {
  background-color: #123435;
  padding: 1em;
}

.info {
  display: none;
  background-color: #435123;
  padding: 1em;
}

.container a, .info, .info a {
  color: #bbc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container"> <a href="#">Show Info (click me)</a>
  <br> <a href="thingy1.htm">Other Link 1</a>
</div>
<div class="info">Some info (div.container and all it's contents now need to be totally disabled)
  <br> <a href="#">Hide Info</a>
  <br>
</div>

In older browsers (IE 10 and down), you'll probably have to use an overlay that covers all the other elements

$('.container a').on('click', function(e) {
  $('.info').fadeTo("slow", 1);

  var container = $('.container').fadeTo("slow", 0.5);
  var overlay   = container.clone(false);

  overlay.empty().prop('id', 'overlay').css({
    cssText    : container.css('cssText'),
    top        : container.position().left,
    left       : container.position().top,
    position   : 'absolute',
    background : 'transparent'
  }).appendTo(container.parent());
});

$('.info a').on('click', function(e) {
  $('.info').fadeOut();
  $('.container').fadeTo("slow", 1);
  $('#overlay').remove();
});
.container {
  background-color: #123435;
  padding: 1em;
}

.info {
  display: none;
  background-color: #435123;
  padding: 1em;
}

.container a, .info, .info a {
  color: #bbc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container"> <a href="#">Show Info (click me)</a>
  <br> <a href="thingy1.htm">Other Link 1</a>
</div>
<div class="info">Some info (div.container and all it's contents now need to be totally disabled)
  <br> <a href="#">Hide Info</a>
  <br>
</div>