Exploring z-indices in event bubbling

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

Issue

Let's examine a scenario where there are two elements, canvas and div, positioned in the same location using CSS. The div has a higher z-index compared to the canvas, but how can we make sure events triggered on the div get passed down to the lower z-indexed element? Is it necessary to use .dispatchEvent() on the canvas?

UPDATE: Just to clarify, I want the div to handle the event first, perform its actions, and then pass the event along to the next element with a lower z-index.

The JSFiddle code provided below:

/*
     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>

Answer №1

By adding the CSS property pointer-events: none; to the #other-div, you can allow clicks and other pointer-related events to pass through the div, reaching both the canvas and the container.

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

For a demonstration, check out Fiddle 1.


If the above solution is not suitable because you require the other-div to also capture the event, as per your comment, then you can programmatically trigger 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 container receives a click, it will automatically trigger a click on the underlying canvas: $('#canvas').click();

It's important to note that when the click reaches the canvas, the event must be stopped from propagating to prevent an infinite loop that would hit both the #other-div and the #container. This is why we have e.stopImmediatePropagation();

For a visual representation, see Fiddle 2.

Answer №2

If you want to create a custom event triggered by clicking on the outer-div, you can have the canvas listen for 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>

Answer №3

One way to implement a dynamic solution is by modifying the Element prototype:

if (!document.elementsFromPoint) {
    document.elementsFromPoint = elementsFromPoint;
}

function elementsFromPoint(x, y) {
    var parents = [];
    var parent = void 0;
    do {
        if (parent !== document.elementFromPoint(x, y)) {
            parent = document.elementFromPoint(x, y);
            parents.push(parent);
            parent.style.pointerEvents = 'none';
        } else {
            parent = false;
        }
    } while (parent);
    parents.forEach(function (parent) {
        parent.style.pointerEvents = 'initial';
    });
    return parents;
}

Element.prototype.makeEventGoThrough = function(eventName) {
  $(this).on(eventName, (e) => {
    var elements = document.elementsFromPoint(e.clientX, e.clientY);
    var children = [].slice.call(this.children);
    elements = elements.filter(element => element !== this && !children.find(el => el === element));
    elements.forEach(element => $(element).trigger(eventName));
  });
}


/*
 How can I pass the event along to #canvas?
*/
document.getElementById('other-div').makeEventGoThrough('click');
$('#other-div').on('click', () => console.log('other-div clicked'));
$('#canvas').on('click', () => console.log('canvas clicked'));
#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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can someone help me figure out this lengthy React error coming from Material UI?

Issues encountered:X ERROR in ./src/Pages/Crypto_transactions.js 184:35-43 The export 'default' (imported as 'DataGrid') could not be found in '@material-ui/data-grid' (potential exports include: DATA_GRID_PROPTYPES, DEFAULT ...

Creating an interactive checkbox input field utilizing a JSON-driven database

Can someone assist me with creating dynamic checkboxes? I have JSON data structured as follows: [ { "categoryName": "Category 1", "items": [ { "value": "value1", "label": "label1" }, { "value": "value2" ...

Utilizing Font Awesome icons dynamically presents challenges when integrating with SVG & JavaScript

Recently, I started using the new JS&SVG implementation of font-awesome's v5 icons. It seems to be working perfectly for icons (such as <i class='fas fa-home'></i>) that are already present in the DOM at page load. The <i& ...

What is the best way for a background-image to determine its height in CSS?

I am currently working on a website project and I would like to include my title using a background-image because it uses a unique font. In my design class, we were taught that this is the best approach. However, I am struggling with setting the correct di ...

Generating a dataframe with cells that have a combination of regular and italicized text using the sjPlot package functions

I've been trying to set up a basic data table where the genus name in the "Coral_taxon" column is italicized, but the "spp." part following it remains lowercase. I thought of using the expression() function for each row in "Coral_taxon," but so far, I ...

utilizing array.map() to nest multiple layers of arrays

I am facing a challenge with a JavaScript array structure that contains three top-level objects. Each of these objects has an "teamLineup" array, which in turn holds two more objects named "team". These "team" objects have another array called "starters", ...

JavaScript code encounters a math calculator script error

Am I overlooking something in my script? Everything seems to work fine when I click the minus (-) button, but when I press the plus (+) button, the calculator malfunctions. It displays 1, 11, 21, and so on, all ending with 1... Here is my code: functi ...

Is there a way to deactivate the onClick event when the dropdown placeholder is chosen?

I have experimented with different methods to prevent the onClick event when selecting either placeholder, but I have not been successful. Here is my current code: <div class="choosesign"> <div class="zodiacs"> < ...

Unable to identify the pdf file using multer in node.js

const multer=require('multer'); var fileStorage = multer.diskStorage({ destination:(req,file,cb)=>{ if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/jpg' || file.mimetype==='image/png') { ...

Using the tensorflow library with vite

Greetings and apologies for any inconvenience caused by my relatively trivial inquiries. I am currently navigating the introductory stages of delving into front-end development. Presently, I have initiated a hello-world vite app, which came to life throug ...

Image that adjusts its size according to the device screen width while

My goal is to create responsive images with a fixed height. Below is the HTML code I am using: <div class="col-md-6"> <div class="img"> <img src="http://image.noelshack.com/fichiers/2016/16/1461065658-b-v-s.jpg"> </div&g ...

What is the best way to create a form that includes both dynamic objects and dynamic arrays using a JSON schema?

I have observed how a JSON schema can be utilized to construct dynamic arrays. My goal is to develop a JSON web form using a JSON schema that allows for objects (dictionaries) to be expandable similar to arrays. For example, you can visit the demonstrati ...

Flask fails to recognize JSON data when transmitted from Nodejs

I am encountering an issue when trying to send JSON data from Node to Flask. I am having trouble reading the data in Flask as expected. Despite attempting to print request.data in Flask, no output is being displayed. Additionally, when I tried printing req ...

Adaptable design tailored for smartphones

When it comes to developing mobile websites for various platforms such as iPhone 3 and 4, Android, Blackberry Torch, etc., I usually find myself needing to slice images based on the specific platform. The challenge arises from constantly having to slice im ...

Finding elements based on their class can be accomplished by using XPath

Can you show me how to effectively utilize the :not selector to choose elements in a scenario like this: <div class="parent"> <div class="a b c"/> <div class="a"/> </div> I am trying to select the div with only the class & ...

Navigating within a React application - rendering JSX components based on URL parameters

As I work on developing a web-app with a chapter/lesson structure, I have been exploring ways to handle the organization of lessons without storing HTML or React code in my database. One idea I had was to save each lesson as a .jsx file within a folder str ...

The GET request on the Express route is malfunctioning, causing the Postman request to time out after getting stuck for some

My Express app seems to be experiencing some issues with the GET route. When making a request using Postman, the response gets stuck for a while before fetching. The GET route is properly set up with all necessary request parsers and the app initialized an ...

Equal spacing title in horizontal menu with Bootstrap design

Is there a way to evenly distribute menu links with varying text lengths in equal width bootstrap columns? Adjusting the column class between col-md-1 and col-md-3 doesn't seem to give accurate spacing. If you want to see, I've set up a fiddle h ...

The comparison between local variables and data can result in a significant drop in performance

My current project involves VueJS and Cesium, but I'm facing a performance issue with a significant drop in frame rate. While I have identified the problem area, I am unsure of why this is happening and how to resolve it. export default { name: ...

Transforming into an input field from a dropdown with Bootstrap select when using AJAX in js.erb

I'm encountering a small issue while updating the view results via AJAX in Ruby on Rails (js.erb). Specifically, when I update/render the form using AJAX, the selectpicker transforms into a simple input and disappears from the view. Any suggestions on ...