Piano keys - How do the first functions link together?

I’ve just completed the first 7 steps of the Piano Keys assignment (with the help of the youtube video)

Piano keys assignment

But i’m confused as to how all the functions link together to know that the event it’s listening for is specific to the piano keys. In the lessons we just did on events there was a clear indicator of what event was happening on what element through the syntax of the functions and listeners.
But in this one I can’t follow the link between them. Could someone please help. I will try to be more specific below.

Here is the code separated out:

This first bit I get that it creates an array called ‘notes’ with the elements in. All good so far.

// The keys and notes variables store the piano keys

const keys = ['c-key', 'd-key', 'e-key', 'f-key', 'g-key', 'a-key', 'b-key', 'high-c-key', 'c-sharp-key', 'd-sharp-key', 'f-sharp-key', 'g-sharp-key', 'a-sharp-key'];

const notes = [];

keys.forEach(function(key){

notes.push(document.getElementById(key));

})

Next are two functions that change the colour of the target element. Kind of ok at this point with the syntax of the functions but lost on how it knows what the target element is…

// Write named functions that change the color of the keys below

const keyPlay = function(event) {

event.target.style.backgroundColor = 'green';

};

const keyReturn = function(event) {

event.target.style.backgroundColor = '';

};

The final few lines of code. No idea how the system knows that ‘note’ (not ‘notes’) is a key that can be pressed. I would assume ‘onmousedown’ is the first event being triggered by the mouse being pushed down, but can’t see how that gets translated into being a key and then passed up to the function that changes the color. I can’t see the connections…Please help!

// Write a named function with event handler properties

const eventHandler = function(note) {
  note.onmousedown = keyPlay;
  note.onmouseup = keyReturn;
};

// Write a loop that runs the array elements through the function

notes.forEach(eventHandler);

No idea how the system knows that ‘note’ (not ‘notes’) is a key that can be pressed.

const eventHandler = function(note)

The above line basically declares the argument name note for the function eventHandler(). It only lives inside the scope of this function and is required when invoking it (eg: eventHandler(“C-sharp”)… or whatever format they’re using for notes)

In this eventHandler() block, you have two functions that are possibly triggered on some events: keyPlay() and keyReturn(). Both of these are functions that affect color (eg: event.target.style.backgroundColor = 'green';)

We can follow the bread crumbs…

  • eventHandler(csharp);
  • csharp.onmousedown = keyPlay;
  • “in csharp’s scope” keyPlay(onmousedown)
  • onmousedown.csharp.style.backgroundColor = ‘green’

or something like that. I forgot what the whole code looks like but this may give you a good idea. If you really want to see the trail yourself it’s good to put console.log statements and open up the console and see how things “filter through” as you click on them.

1 Like

Thank you.
The ‘bread crumbs’ section at the end helps a lot.

I’m still not clear though how the system knows that ‘note’ in const eventHandler = function(note) refers to the pressing of one of the piano keys specifically. It seems to be a generic argument for the function.
In the Codecademy exercises to learn event handlers prior to this they were a lot more specific as to what was expected to be clicked in the ‘event’. Syntax such as:

let eventHandlerFunction = function() {
//code block
}
eventTarget.onclick = eventHandlerFunction

‘eventTarget’ was clearly defined as what was ‘expecting’ to be clicked on. In the Piano Keys exercise though I don’t see how we have coded it so that the system is listening for a click on the piano keys. It seems it’s waiting for a generic click anywhere with ‘note’ as the place holder (I tried clicking elsewhere and nothing turned color! lol). I would expect to see (based on the lessons) something more like pianoKeys.onclick = eventHandlerFunction with this setting off the chain reaction of events.

You’re right, it is generic.

I think when notes.forEach(eventHandler); is run it gives the event handler to every note. Or something like that.

1 Like

What toastedpitabread said is really the big thing. You seem to be tracking with the logic up until the line where you put notes.forEach(eventHandler);

All of the code leading up to that point is meant to be dynamic and can be used on multiple pieces of code. This makes it so you can have any argument passed into it:

  1. keyPlay will feed into an eventHandler function (Dynamic)
  2. keyReturn will feed into an eventHandler function (Dynamic)
  3. eventHandler takes in any note (Dynamic: Will be the notes from your notes array) and uses that as the event target for the keyPlay and keyReturn functions made before. Because you made keyPlay and keyReturn dynamic, you can do something like this.
  4. The final step is to iterate through the notes array and call the eventHandler function on each of them:
notes.forEach(note => {
  eventHandler(note);
});

This notes array is already targeting a specific element in your HTML and when you call the eventHandler function on each of these notes, then it sets them up to be targets for the keyPlay and keyReturn functions.

Basically, what you created by stringing these functions together is a system that you could input any array of HTML elements into the eventHandler function and it would apply keyPlay and keyReturn. The last bit of code is applying these things specifically to the notes array, which is targeting the piano keys.

Hopefully this is helpful, it ended up being a bit wordier than I had anticipated!

2 Likes

Nice summary!

eventHandler(note)

Makes more sense if we name the function for what it does…

assignKey()

as in,

notes.forEach(assignKey)
3 Likes

Thank you.
I can see how the last line of code completes the event handling process now for specifically the piano keys.