Need some insight on project Piano Keys

So I’ve got to the project Piano Keys and I’ve been coding and following the code along and testing new things but I’m confused why certain aspects work. If someone could explain why certain parts of this code works it’d be nice :smiley:

// 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 = (event) => {

    event.target.style.backgroundColor = "turquoise";

};

const keyReturn = (event) => {

    event.target.style.backgroundColor = "";

};

// Write a named function with event handler properties

// let keyAssignment = (note) => {

//     note.onmousedown = () => {

//         keyPlay(event);

//     };

//     note.onmouseup = () =>{

//         keyReturn(event);

//     }

// };

let keyAssignment = (note) => {

    note.onmousedown = keyPlay;

    note.onmouseup = keyReturn;

};

// let keyAssignment = (note) => {

//     note.onmousedown = function() {

//         keyPlay(event);

//     };

//     note.onmouseup = function() {

//         keyReturn(event);

//     };

// };

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

notes.forEach(keyAssignment);

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

// This variable stores the '-END' lyric element

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

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

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

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

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

}

My question is why does the code work

let keyAssignment = (note) => {

    note.onmousedown = keyPlay;

    note.onmouseup = keyReturn;

};

because in the walkthrough they use a parameter event for the keyPlay and keyReturn like this:

let keyAssignment = (note) => {
    note.onmousedown = function() {
        keyPlay(event);
    };
    note.onmouseup = function() {
        keyReturn(event);
    };
};

I just want to know what’s the best way to code for this? or maybe if it’s for readability?
Or if I should use my code

let keyAssignment = (note) => {

    note.onmousedown = () => {

        keyPlay(event);

    };

    note.onmouseup = () =>{

        keyReturn(event);

    }

};

Just need some clarification if you could please and thank you!

1 Like

It works because you are passing a reference to a function to call. keyPlay is a reference to the function. keyPlay(arg) is calling the function.

() => { keyPlay(event) } is a function that calls keyPlay and then passes in event. This is wrong it should be event => { keyPlay(event)} because otherwise ask yourself, where is event coming from? Either way it is a function that hasn’t been called, so the assignment is a reference to this function. event => { keyPlay(event) }(arg) would be calling the function straight after creating it. Or the next step would be const callKeyPlay = event => { keyPlay(event) } so callKeyPlay now stores the reference to the function and we call it like so callKeyPlay(arg).

So basically you are passing in a reference to a function that can be called elsewhere, where it will have an event argument passed in. You are not calling the function at assignment time.

1 Like

so it should be this instead?

let keyAssignment = (note) => {

    note.onmousedown = keyPlay(event);

    note.onmouseup = keyReturn(event);

};

No, keyPlay(event) would call keyPlay once and return undefined. You should just leave it as keyPlay, so the function gets passed in and can be called inside onmousedown.

2 Likes

For some reason it doesn’t work like this. In the project walkthrough it is written like this :

let keyAssignment = (note) => {
note.onmousedown = function() {
keyPlay(event);
};
note.onmouseup = function() {
keyReturn(event);
};
};

And I can’t get why do we have to write a function to call a function

1 Like

What is the point on the keys array and notes array in this?

The elements have both IDs and Class. Why do we need to do all of those functions and then loop instead of simply accessing the class name and changing the backgroundColor on mousedown and mouseup ?

e.g

let keyBackground = document.getElementByClassName(‘key’ ‘black-keys’);

function keyPlay() {

keyBackground.style.backgroundColor = ‘red’;

}

function keyReturn() {

keyBackground.style.backgroundColor = ‘white’;

}

keyBackground.addEventListener(‘mousedown’, keyPlay);

keyBackground.addEventListener(‘mouseup’, keyReturn);

[type or paste code here](https://www.codecademy.com/paths/web-development/tracks/build-interactive-websites/modules/dom-javascript-events/projects/piano-keys)
1 Like
let keyBackground = document.getElementsByClassName('key', 'black-keys');

Here, keyBackground is a collection of elements, not one HTML element.
And a collection has no .style (no style property or any such getter/setter).
(Although I guess you could use JQuery or something similar, or you could create such a getter/setter.)

So something like
keyBackground.style.backgroundColor = 'red';
would not work here [and would cause an error because keyBackground.style is undefined ]

Guys have you noticed if you click over the Note name it doesnt change color but only around the letters?

with this you get that fixed:

.keynote{
width: 100%;
height: 100%;
text-align: center;
display: flex;
flex-direction: column;
justify-content: end;
margin: 0 auto;
bottom: 0;
color: #141c3a;
}

.black-keynote{
width: 100%;
height: 100%;
text-align: center;
display: flex;
flex-direction: column;
justify-content: end;
/margin-top: 75px;/
}

The step-by-step solution is overengineered on purpose, just to give students more brainfuckery. Hate such assignments.
“Take out the trash. MAKE SURE YOU ONLY USE AN EXCAVATOR FOR THIS ASSIGNMENT”

The instructions for this one suck. The walk through sucks.
I’m shopping around

I have to honest, as the video works and the code also does, I find myself for the second time stoped here.
I refuse to go on without understanding, even, with the "later I will understand’.
Up until now everything in the program has a direction of sense,
but this code, at least to me, is written in a different style, the video also shows us a different way of writing which through the program has been discarded.
This code needs to be explained. And if there is another way of coding the solution it also needs to be presented, at least one on the same style of the program.

I want to think of course I need to understand better, practice more until I get here?
well, it feels to me part of a different program. It’s so alien.
I have to admit it has question me to follow along.

The absence of comment on the video itself 3 also haunts me.

2 Likes

Hi there, I have completed this project but can someone explain to me for section 6 :

At the beginning of the code, we have variable name assignments for the keys array and the empty notes array. There is also a function looping through the keys array and pushing the keys elements to the notes array to be assigned a variable name.

Now, you must create a .forEach loop that will pass the elements in the notes array through your event assignment function.

code -

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

function keyPlay(e) {

e.target.style.backgroundColor = ‘lime’

}

function keyReturn(e) {

e.target.style.backgroundColor = ‘’

}

// Write a named function with event handler properties

function play(note){

note.addEventListener(‘mousedown’, keyPlay);

note.addEventListener(‘mouseup’, keyReturn)

}

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

notes.forEach(play)

Can someone explain how it is accessing the DOM without using querySelector or getElementById.
I understand I am accessing the note array and passing in the play function but how does this target an element in DOM without using querySelector or getElementById.

Earlier in the code, document.getElementById is to get the relevant elements.
keys is a list of ids.
and you use a .forEach to put the element that has each id into notes
so notes is an array of elements.

oh yes thanks for clearly it up for me. I knew I was missing something. Thanks again

The whole piano project is extremely poorly defined and terribly messy.

// 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 = () => {
  notes.forEach((key) => {
    key.addEventListener('mousedown' , () => {
      key.style.backgroundColor = 'grey' ;
    })
  })
} ;

const keyReturn = () => {
  notes.forEach((note) => {
    note.addEventListener('mouseup' , () => {
      note.style.backgroundColor = '' ;
    })
  })
} ; 

// Write a named function with event handler properties
// ------- task 5 --------
namedFunction = note => {
  note.addEventListener('mousedown' , keyPlay) ;
  note.addEventListener('mouseup' , keyReturn) ;
} ;

// Write a loop that runs the array elements through the function
// ------- task 6 --------
notes.forEach((key) => {
  namedFunction(key) ;
}) ;

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

// This variable stores the '-END' lyric element
let lastLyric = document.getElementById('column-optional');

// 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.addEventListener('click' , () => {
  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.addEventListener('click' , () => {
  nextThree.hidden = false ;
  nextTwo .hidden = true ;
  document.getElementById('word-five').innerHTML = 'DEAR' ;
  document.getElementById('word-six').innerHTML = 'FRI-' ;
  lastLyric.style.display = 'inline-block' ;
  document.getElementById('letter-note-three').innerHTML = 'G' ;
  document.getElementById('letter-note-four').innerHTML = 'E' ;
  document.getElementById('letter-note-four').innerHTML = 'C' ;
  document.getElementById('letter-note-six').innerHTML = 'B' ;
}) ;

// Write anonymous event handler property and function for the third progress button
nextThree.addEventListener('click' , () => {
  startOver.hidden = false ;
  nextThree.hidden = true ;
  document.getElementById('word-one').innerHTML = 'HAP-' ;
  document.getElementById('word-two').innerHTML = 'PY' ;
  document.getElementById('word-three').innerHTML = 'BIRTH' ;
  document.getElementById('word-four').innerHTML = 'DAY' ;
  document.getElementById('word-five').innerHTML = 'TO' ;
  document.getElementById('word-six').innerHTML = 'YOU!' ;
  // -------------------- task 19 ---------------------
  document.getElementById('letter-note-one').innerHTML = 'F' ;
  document.getElementById('letter-note-two').innerHTML = 'F' ;
  document.getElementById('letter-note-three').innerHTML = 'E' ;
  document.getElementById('letter-note-four').innerHTML = 'C' ;
  document.getElementById('letter-note-five').innerHTML = 'D' ;
  document.getElementById('letter-note-six').innerHTML = 'C!' ;
  // -------------------- task 20 ---------------------
  lastLyric.style.display = 'none' ;
}) ;

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

I don’t understand why my code isn’t working for step 10.

nextOne.onclick = function() {
nextTwo.hidden = false;
nextOne.hidden = true;

document.getElementByID(“letter-note-five”).innerHTML = “D”
document.getElementById(“letter-note-six”).innerHTML = “C”
};

by all accounts it should work, I checked with the code in the walkthrough video, but I’m not understanding by my keys aren’t changing letters to ‘D’ and ‘C’. Can someone please help me?

You wrote    getElementByID          instead of          getElementById.

THANK YOU!!! Omg, I feel so silly!

Can someone explain to me the solution to the video in step 4 which is this:

let eventAsign = function (note) { note.onmousedown = function () { keyPlay(event)

How does keyPlay have the right object tied to the parameter event? in my mind it should be this in order to work?

let eventAsign = function (note) { note.onmousedown = function (event) { keyPlay(event)

But you don’t have to have a paramater in the anonymous function in order for keyPlay event to fire correctly on the right key. Why is that? How is keyPlay getting the right event? My guess is that .onmousedown fires an event object into the global scope and somehow keyPlay is capturing it?