0

I have a web page with two canvases sitting on top of one another:

<style>
canvas {
  position: absolute;
}
</style>
<canvas id="first" width=800 height=600></canvas>
<canvas id="second" width=800 height=600></canvas>

(Full example here.)

If I register mousedown handlers for both canvases:

document.getElementById('first').addEventListener('mousedown', function () {
  console.log('first canvas mousedown');
});

document.getElementById('second').addEventListener('mousedown', function () {
  console.log('second canvas mousedown');
});

and click on them, then I only see second canvas mousedown logged. This makes sense since it's on top.

I'd like the event handler for the second canvas to have a first crack at handling the event but, if it doesn't care about it, let it pass through to the event handler for the first canvas, which is underneath it.

In reality these <canvas>es are parts of independent React components, so it's not trivial to unify the event handlers.

danvk
  • 15,863
  • 5
  • 72
  • 116
  • this might help - https://stackoverflow.com/questions/6157929/how-to-simulate-a-mouse-click-using-javascript – Alnitak May 23 '17 at 19:26
  • This is likely completely wrong, but I thought that I remembered that returning false from the handler passed it through to the next responding object. I'm likely remembering some other context where this is true, however. – David Hoelzer May 23 '17 at 22:07

1 Answers1

1

It's possible (albeit tedious) to recreate a new event object that mirrors the contents of the first, and then dispatch to the other element, e.g.:

var pass = false;  // toggles on each event

first.addEventListener('mousedown', function(e) {
  output.innerHTML = "first";
});

second.addEventListener('mousedown', function(e) {
  pass = !pass;
  if (pass) {
    var fields = ['screenX', 'screenY', 'clientX', 'clientY',
                  'ctrlKey', 'altKey', 'shiftKey', 'metaKey',
                  'button', 'buttons', 'relatedTarget', 'region'];
    var opts = {};
    fields.forEach(function(f) {
        if (f in e) {
           opts[f] = e[f];
        }
    });
    var copy = new MouseEvent(e.type, opts);
    first.dispatchEvent(copy);
  } else {
    output.innerHTML = "second";
  }
});

There are other properties from the MouseEvent's super-interfaces that you might want to copy too.

demo at https://jsfiddle.net/070ckbra/2/

Alnitak
  • 334,560
  • 70
  • 407
  • 495