Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event-bubbling with z-indices

JSFiddle: https://jsfiddle.net/uLap7yeq/19/

Problem

Consider two elements, canvas and div, which are on the same tree depth and have the same parent. They are both placed on the same position using CSS however div has the higher z-index. How can you capture events from the div and pass them along to the lower z-index? Do I have to do .dispatchEvent() on the canvas?

EDIT: To clarify, I'd like the div to receive the event, do whatever it wants and then pass it along to the next z-indexed element.

The JSFiddle pasted inline:

/*
     How can I pass the event along to #canvas?
    */
$('#container').on('click', function(e) {
  console.log('#container click');
});
$('#canvas').on('click', function(e) {
  console.log('#canvas click');
});
$('#other-div').on('click', function(e) {
  console.log('#other-div click');
});
#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
}

#canvas {
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <div id="other-div">
    <p>
      Something
    </p>
  </div>
  <canvas id="canvas" width="200" height="200"></canvas>
</div>
like image 709
Johan Sjolen Avatar asked Mar 01 '18 12:03

Johan Sjolen


2 Answers

You can trigger a custom event when you click on the outer-div and make the canvas listening to this event:

$('#container').on('click', function(e) {
  console.log('#container click');
});
$('#canvas').on('click custom', function(e) {
  console.log('#canvas click');
});
$('#other-div').on('click', function(e) {
  console.log('#other-div click');
  $('#canvas').trigger( "custom");
});
#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
  background:rgba(255,0,0,0.2);
}

#canvas {
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
  background:rgba(255,255,0,0.2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <div id="other-div">
  <p>
   Something
  </p>
  </div>
  <canvas id="canvas" width="200" height="200"></canvas>
</div>
like image 43
Temani Afif Avatar answered Oct 24 '22 14:10

Temani Afif


Adding css property pointer-events: none; to the #other-div will let clicks or other pointer-related events to pass through the div and reach both the canvas and the container

#other-div {
  z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}

See Fiddle 1


If this is not suitable because you need that the other-div too captures the event (as per your comment) then you may trigger programmatically an event on the canvas when the container is clicked

$('#container').on('click', function(e) {
  console.log('#container click');
  $('#canvas').click(); // <------
});
$('#canvas').on('click', function(e) {
  e.stopImmediatePropagation(); // <------
  console.log('#canvas click');
});
$('#other-div').on('click', function(e) {
  console.log('#other-div click');
});

When the cointainer receives a click then it triggers a click on the undelying canvas too: $('#canvas').click();

Note that when the click finally hits the canvas the event must stop propagate, otherwise it will bubble and hit both the #other-div and the #container leading to an infinite loop. This is why you have e.stopImmediatePropagation();

See Fiddle 2

like image 192
Paolo Avatar answered Oct 24 '22 14:10

Paolo