7

In JavaScript, the addEventListener() method is used like this:

object.addEventListener("click", myScript);

In Scala.js: I have a canvas, and I want to listen to clicks only on the canvas, not the entire document. In the Scala.js.dom library, addEventListener is defined as:

 def addEventListener(`type`: String, listener: js.Function1[Event, _], useCapture: Boolean = ???): Unit = ???

I'm not sure what "useCapture" refers to. But I tried:

dom.document.getElementById("canvas").addEventListener("click", {
(e:dom.MouseEvent) => { /*do something*/ }
}, false)

And the error message I got:

found   : org.scalajs.dom.MouseEvent => Unit
required: scala.scalajs.js.Function1[org.scalajs.dom.Event, _]

Can someone explain what "useCapture" refers to, and how to correctly use addEventListener in Scala.js?

user3025403
  • 1,070
  • 3
  • 21
  • 33
  • Regarding `useCapture`, the following snippet is from the [Mozilla docs](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters): "indicates that events of this type will be dispatched to the registered listener, before being dispatched to any EventTarget beneath it in the DOM tree." – Matthias Braun May 03 '17 at 14:36

2 Answers2

10

The error message you get is a perfectly normal type error: addEventListener expects a js.Function1[dom.Event, _], but you're giving it a js.Function1[dom.MouseEvent, _]. Since the first argument is in contravariant position, this does not typecheck.

There are two solutions: either you make your function take a dom.Event, that you then cast to dom.MouseEvent, like this:

canvas.addEventListener("click", { (e0: dom.Event) =>
  val e = e0.asInstanceOf[dom.MouseEvent]
  ...
}, false)

or you use onclick which is more precisely typed:

canvas.onclick = { (e: dom.MouseEvent) =>
  ...
}
sjrd
  • 21,805
  • 2
  • 61
  • 91
  • is there a `+=` operator (or similar), such as `canvas.onclick += { (e: dom.MouseEvent) => ... }` – David Portabella Jul 02 '19 at 19:02
  • 1
    @David Portarella: No, at least not in the default scalajs-dom facade. Maybe there exists a library out there that provides something like that. – sjrd Jul 03 '19 at 04:16
1

Event capture is the process by which an EventListener registered on an ancestor of the event's target can intercept events of a given type before they are received by the event's target. Capture operates from the top of the tree, generally the Document, downward, making it the symmetrical opposite of bubbling which is described below. The chain of EventTargets from the top of the tree to the event's target is determined before the initial dispatch of the event. If modifications occur to the tree during event processing, event flow will proceed based on the initial state of the tree..

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-basic

window.addEventListener("click", function(){console.log('something1')}, false);
window.addEventListener("click", function(){console.log('something2')}, true);

The order will be

something 2 (defined first, using capture=true)

something 1 (defined second using capture=true)

Ref 2

Note on the second ref: The order is not guaranteed!

capture phase

The process by which an event can be handled by one of the target ancestors before being handled by the target node.

REF 3

Community
  • 1
  • 1
Pogrindis
  • 7,755
  • 5
  • 31
  • 44