Piano Keys: Why pass event into event handler function?

In the Piano Keys project,
I found the instructions a bit confusing and resorted to checking the walkthrough video rather soon.

The instructions are as follows:

After the second comment, create a function named keyPlay that changes the background color of the keys when they are pressed down.

In the video, steps 1 and 2 is implemented like this:

let keyPlay = function(event) {
  event.target.style.backgroundColor = 'blue';
}

let keyReturn = function(event) {
  event.target.style.backgroundColor = '';
}

The function is subsequently called like this:

function eventAssignment(note) {
  note.onmousedown = function() {
    keyPlay(event);
  };
  note.onmouseup = function() {
    keyReturn(event);
  };
}

My interpretation would have been to do this instead:

function keyplay(key) {
  key.style.backgroundColor = 'blue';
}

I would attach it to the keys like this then:

keys.forEach(function(key) {
  key.onmousedown = keyPlay;
})
  1. I fail to understand why in the video, in keyPlay() and keyReturn() the event should get passed into its own handler function here (if that is how usage of event handlers was previously introduced, then it was apparently lost on me). Could someone please explain
    A. Why it is done like that? and
    B . how is it actually passed in then at the function call? When the event handler is run, how does Javascript know which event is meant? I can’t see an event being specified in here:
note.onmouseup = function() {
    keyReturn(event);
  };
  1. In the video, the event handler is nested inside an extra anonymous function declaration:
note.onmousedown = function() {
    keyPlay(event);
  };

What is that good for, rather than just doing it like this:
note.onmousedown = keyPlay(event);
- since keyPlay() is already a function…

Last question first: event does not exist, yet. The function reference is registered with the listener, not the return value of invoking the function.

note.onmousedown = keyPlay;

In the above context, event is the global object that refers to the most recent event. It will take some reading to zero in on how it is implemented internally alongside of the global event listener, onmousedown.

Events have their own object, an instance of the Event class that gives the object attributes which can all be found in MDN docs. One such attribute is, target which is the element node upon which the event was triggered. This is how we know which element to restyle. The event object as described here is transient and only exists until the next event it triggered. There can only ever be one event instance.

We should note that in,

 keyPlay(event)

and,

function (event)

‘event’ is not the same thing. In the first example it IS the global event object; in the latter example it is the parameter, which could be any variable and is usually written as just,

function (e) {
    e.target. ...

Time spent reading up on this subject will be well used. Keep exploring the technical and practical aspects surrounding events.

2 Likes

Thank you. I sure hope some more explanation is afforded to this subject in upcoming lessons. If you have some good reading to suggest, I’ll gladly go through it.
It’s just that ever so often, your typical official documentation is aimed at the pros, people who already know how to code and are familiar with most of the technical terms. If a paragraph of documentation contains half a dozen words whose meaning I can only guess, it will only do so much for my understanding of the topic. Just needed to get that off my chest…

Well how does JS know the difference? Shouldn’t it also read the parameter of function(event) as the global event object?

If my above attemt of implementing the task is not best practice, would it at least work (and maybe pass for somewhat practical)?

No, because it is not. It is THE event object directly bound to our target element. We cannot rename event as it applies to global event listeners (the ones with on in their name).

JS knows how to poll event since it is in the global namespace. As for when it is a parameter, that variable only identifies the event object instance which has attributes we can poll.

In that implementation, keys is a collection of element DOM nodes, which similar to an array has .forEach() in its prototype. This allows us to traverse the collection from end to end without breaks, and register the global listener and its callback on each one. I don’t see any objection to that usage, though it’s not how I would write it.

Sadly, I’ve never really gotten into the meat and potatoes of global event listeners or the global event, preferring to always register event listeners with addEventListener(), where we implement handlers with the (e) parameter mentioned above. Consequently I’m doing a pretty messy job of answering your question. My bad.

1 Like

P.S: Sorry I forgot to include a link to the project page, here it is:
https://www.codecademy.com/paths/web-development/tracks/build-interactive-websites/modules/dom-javascript-events/projects/piano-keys

1 Like

Errata

In the above I mistakenly referred to keys as being a collection. Now I see that it is in fact an array. notes is an array of DOM nodes. That is why we can can register events on them.

1 Like