Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 207
Mere Development Avatar asked Jun 05 '15 10:06

Mere Development


4 Answers

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>
like image 133
adeneo Avatar answered Sep 18 '22 06:09

adeneo


You can use flags (read @Banana's answer). Also, you can (un)handle events using jQuery:

// idea
$('#selector').on('event.name', function(){
    // do something
    // then remove event
    $(this).off('.name');
});

// example
$('#selector').on('click.eventsGroup1', function(){
    // do something
    // then remove event
    $(this).off('.eventsGroup1');
});

You have all the information you need at jQuery Docs.

like image 43
kosmos Avatar answered Sep 19 '22 06:09

kosmos


with css you can specify if an element can receive mouse events:

https://developer.mozilla.org/en/docs/Web/CSS/pointer-events

to turn mouse events off:

$(".container a").css({ "pointer-events": "none" });

turning them on again:

$(".container a").css({ "pointer-events": "auto" });
like image 32
Olaf Now Avatar answered Sep 18 '22 06:09

Olaf Now


As many posters have noted you can use the pointer-events property to prevent clicks. Since inline styles are an evil thing I will post a CSS solution: Add a class: "disable-click" to the element and add the CSS code :

.disable-click {
    pointer-events: none;
    position: relative;
}
.disable-click * {
    pointer-events: none;
}
.disable-click:before {
    content: "";
    pointer-events: none;
    position: absolute;
    top: 0;
    bottom:0;
    left:0;
    right:0;
    background: transparent;
}

This should prevent users from being able to interact with the container and it's children using click and touch events. This works best on modern browsers but I also added the pseudo element "mask" which will provide similar functionality on older bowsers as well.

Please note: this will not always prevent users from being able to tab into a "disabled" element using the keyboard. This is especially true for older browsers.

like image 21
Kenneth Moore Avatar answered Sep 20 '22 06:09

Kenneth Moore