Piano Keys tasks 4-5

I don’t understand why we can’t simply assign function keyPlay to trigger note.onmousedown like this:

note.onmousedown = keyPlay(event);

Why it doesn’t work?

2 Likes

I can’t understand it too!

The above line invokes the function before assignment. We don’t want the function to run at this point, so assign only a callback reference…

note.onmousedown = keyPlay;
1 Like

omg mtf thanks for confirming that this was correct.

As I was watching the video walkthrough for some help on a later step, when it got to this step, he did it completely differently;

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

Could you explain this method for me please?

In that code the callback is the assigned function expression. There is no callback reference since the function is right there. In both examples, event is the global event object which has a target property.

event.target

is the DOM node that triggered the event, as in the key that is clicked.

Hello, I really appreciate your responses in this thread, but I still have a few doubts.

First, here is my overall code for the first few steps of the exercises (the piano keys themselves). I followed the video tutorial for most of it.

// 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));

})

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

const keyPlay = function(event) {

  event.target.style.backgroundColor = '#2a52be';

}

const keyReturn = function(event) {

  event.target.style.backgroundColor = '';

}

// Write a named function with event handler properties

let eventAssignment = function(note) {

  note.onmousedown = function() {

    keyPlay(event);

  }

  note.onmouseup = function() {

    keyReturn(event);

  }

}

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

notes.forEach(eventAssignment);
  1. I understand that the following code, (as mentioned in previous posts here) would invoke the function before it is assigned (or registered?) to note.onmousedown, but then when and where do we invoke keyPlay? I thought by clicking down, that would invoke the keyPlay function…
let eventAssignment = function(note) {
  note.onmousedown = keyPlay(event);
  note.onmouseup = keyReturn(event);
}
  1. In the code below, ‘event’ is a parameter, but when this keyPlay function is eventually called, where does the argument for ‘event’ come from?
const keyPlay = function(event) {
  event.target.style.backgroundColor = '#2a52be';
}
  1. Any further explanation to distinguish between these two bits of code below would be great, because I still don’t understand why there is an ‘event’ parameter in one, and not the other. Again, where does the argument for the ‘event’ parameter come from in the code? Also, it looks like in the first option, doesn’t the code ‘keyPlay(event)’ call the keyPlay function? Something which we’re trying to avoid in the alternative below?
note.onmousedown = function() {
keyPlay(event);
};
note.onmousedown = keyPlay;

Any help to any of these questions would be a big help.

We let the listener invoke it; so that means assigning only the reference when we register the event.

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

event is the name of the global event object which is created and populated with data pertaining to type of event, the event target (what element received the click), and so on. We’re only interested in the target element.

1 Like

Hey @mtf, I had written code that was different from the one in the video, but it still worked. To clarify, would you say that my code:

// Write named functions that change the color of the keys below
  // Passes event as the input argument for keyPlay
  const keyPlay = function(event) {
    event.target.style.backgroundColor = "red";
  };
  
  const keyReturn = function(event) {
    event.target.style.backgroundColor = '';
  }
  
  // My code: 
  // Write a named function with event handler properties
  const pressKey = function(note) {
  note.onmousedown = keyPlay;
  note.onmouseup = keyReturn;
  };

is the equivalent of this code from the video?

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

They might be equivalent if they had the same name. There is a difference, though. I’m hoping the pressKey function is run only once and not every time a key is clicked. We only want to be registering a listener at run time.

There is a difference, though. I’m hoping the pressKey function is run only once and not every time a key is clicked. We only want to be registering a listener at run time.

So why would we want to run the pressKey function only once and not every time a key is clicked? Since we want to use that function whenever the mouse is clicked or released.

I hope you don’t mind me asking, I’m just trying to understand :slightly_smiling_face:

1 Like

We wouldn’t be registering an event listener more than once. The onclick attribute has been added to the element node, with the callback as its value.

I see, so the eventAssignment variable registers the event listener at run time, and then the onmousedown and onmouseup event handlers run the callback functions when those events occur?

Correct. eventAssignment is a function that is only ever run once per session.

When element nodes have an onclick attribute, JS will find it when a click event happens. It will then execute the method that is assigned to that attribute… The callback.

We’ll need to see your entire code to see if your events are properly registered, and that the callbacks are firing when triggered.

1 Like

Thank you, that really helps to clear things up. Like I said, my code worked, in that the keys changed color when pressed. But I was unsure if I was going about assigning the event listeners and handlers the right way, as the code in the video was different.

This is my full code:

// 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));
})

// Write named functions that change the color of the keys below
const keyPlay = function(event) {
  event.target.style.backgroundColor = "red";
};

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

// Write a named function with event handler properties
const pressKey = function(note) {
note.onmousedown = keyPlay;
note.onmouseup = keyReturn;
};

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

notes.forEach(pressKey);

// These variables store the buttons that progress the user through the lyrics
let nextOne = document.getElementById('first-next-line');
let nextTwo = document.getElementById('second-next-line');
let nextThree = document.getElementById('third-next-line');
let startOver = document.getElementById('fourth-next-line');


let wordFive = document.getElementById('word-five');
let wordSix = document.getElementById('word-six');

let lastLyric = document.getElementById('column-optional');

let letterNoteThree = document.getElementById('letter-note-three');
let letterNoteFour = document.getElementById('letter-note-four');



// These statements are "hiding" all the progress buttons, but the first one
nextTwo.hidden = true;
nextThree.hidden = true;
startOver.hidden= true;

// Write anonymous event handler property and function for the first progress button

nextOne.onclick = function() {
nextTwo.hidden = false;
nextOne.hidden = true;
document.getElementById('letter-note-five').innerHTML = "D";
document.getElementById('letter-note-six').innerHTML = "C";
};


// Write anonymous event handler property and function for the second progress button

nextTwo.onclick = function() {
nextThree.hidden = false;
nextTwo.hidden = true;
wordFive.innerHTML = "DEAR";
wordSix.innerHTML = "FRI-";
lastLyric.style.display = "inline-block";
letterNoteThree.innerHTML = "G";
letterNoteFour.innerHTML = "E";
letterNoteFive.innerHTML = "C";
letterNoteSix.innerHTML = "B";
};


// Write anonymous event handler property and function for the third progress button

let wordOne = document.getElementById('word-one');
let wordTwo = document.getElementById('word-two');
let wordThree = document.getElementById('word-three');
let wordFour = document.getElementById('word-four');

let letterNoteOne = document.getElementById('letter-note-one');
let letterNoteTwo = document.getElementById('letter-note-two');


nextThree.onclick = function() {
lastLyric.style.display = 'none';
startOver.hidden = false;
nextThree.hidden = true;
wordOne.innerHTML = "HAP-";
wordTwo.innerHTML = "PY";
wordThree.innerHTML = "BIRTH";
wordFour.innerHTML = "DAY";
wordFive.innerHTML = "TO";
wordSix.innerHTML = "YOU!";
letterNoteOne.innerHTML = "F";
letterNoteTwo.innerHTML = "F";
letterNoteThree.innerHTML = "E";
letterNoteFour.innerHTML = "C";
letterNoteFive.innerHTML = "D";
letterNoteSix.innerHTML = "C";
};





// This is the event handler property and function for the startOver button
startOver.onclick = function() {
  nextOne.hidden = false;
  startOver.hidden = true;
   document.getElementById('word-one').innerHTML = 'HAP-';
  document.getElementById('letter-note-one').innerHTML = 'G';
  document.getElementById('word-two').innerHTML = 'PY';
  document.getElementById('letter-note-two').innerHTML = 'G';
  document.getElementById('word-three').innerHTML = 'BIRTH-';
  document.getElementById('letter-note-three').innerHTML = 'A';
  document.getElementById('word-four').innerHTML = 'DAY';
  document.getElementById('letter-note-four').innerHTML = 'G';
  document.getElementById('word-five').innerHTML = 'TO';
  document.getElementById('letter-note-five').innerHTML = 'C';
  document.getElementById('word-six').innerHTML = 'YOU!';
  document.getElementById('letter-note-six').innerHTML = 'B';
}

This name is misleading. The purpose of this function is to assign event listeners. We can see that it is only run at the start of the session.


On a side note, when assigning nodes that are going to be session length, we should use const, not let since it tells the reader, “These are fixed for the duration.”

1 Like

Thanks for the feedback, that really helps clear things up :slightly_smiling_face:

1 Like