[SOLVED] How should I handle onBlur event in element component?

I am using element component for the UI.
I need to listen the element’s blur event, something like clicking on the empty space, but I can not find a good way to implement this…:sweat:

You could make the background/panel a huge button so when it is clicked on, it sends a ‘onblur’ event to all the children?

1 Like

Oh, I see. But my scenario is more complex.
My scene has many model entities and icons implemented by element component. All entities and icons can be clicked, like the playcanvas online editor.
But the “clicking” implement by different ways.

  • Clicking the entities is implemented by checking ray intersect aabb
  • Clicking the icons is implemented by elements’ event system.

So using a full screen transparent button to dispatch blur event is not enough. I am looking for something like event bubble/capture mechanism in 2D frontend development, so that I can stop event propagation when needed.

The elements have the function to stop event propagation: https://developer.playcanvas.com/en/user-manual/user-interface/input/

Judging from the documentation, it consumes the pc.app.mouse events so basically you can have the element consume the event, if it isn’t consumed, check the entities AABB, if it doesn’t intersect, then it is clicking on ‘nothing’.

1 Like

Oh, ElementInputEvent.stopPropagation is what I am looking for, thanks. :smile:

One more question, If I have a full screen transparent 3D element, and a normal 3D element, they both listen to mousedown event. When mousedown trigger, which one element’s handler will execute first ? :open_mouth:

I’ve created a project to test this: https://playcanvas.com/editor/scene/561496

In the scene, there are the following things:

  • a model
  • a camera
  • a small element button (the white one)
  • a full screen element button (the black one)
  • event handlers:
    • app.mouse.on(‘mousedown’, onClickCamera) in camera
    • element.on(‘mousedown’, onClickSmallBtn) in small element button
    • element.on(‘mousedown’, onClickFullscreenBtn) in fullscreen element button

When clicking, ElementInputEvent will trigger first, and the event listener will only execute once, on the element which is clicked. Then the MouseEvent will trigger. That means:

  • If you click on the small button, the handlers execute order will be:

    • onClickSmallBtn
    • onClickCamera
  • If you click on the full screen button, the handlers execute order will be:

    • onClickFullscreenBtn
    • onClickCamera
  • If you click on the model, the handlers execute order will be:

    • onClickFullscreenBtn
    • onClickCamera

So, if I need onBlur event, I should do something like:

ElementScript.prototype.onFullscreenClick = function(e) {
  if (this.cameraEntity.script.picker.test(e)) {
    // do something
  } else {
    this.app.fire('app:mouse:blur');
  }
};

This means I don’t need to add event handlers on the picker.
What I need is to add methods on the picker, and call them on the fullscreen button’s event handlers.

This also means in a more complex scenario(lots of dynamic models), the picker should have the ability to get all models, maybe using a global variable to save all models, so that the picker can calculate ray intersects of all models.

1 Like