FAQ: Javascript and the DOM - Interactivity with onclick

For the above to return a boolean as you intended you need parentheses around the remainder operator and its operands: !(x % 2).

1 Like

Yeah, that’s what happens when we write sample code and don’t test it. Good catch!

1 Like

How can a function invoked by onclick be called each time the object is clicked on, rather than just once?

The target element has a registered Event Listener attached to it. That listener is given a callback function (an event handler) that is invoked as a result of the event being triggered. When we register the listener we only supply the name of the function (a reference). It is the listener that invokes it.

Hi,
Here is an example of what I am struggling with - the code below is just for testing the behaviour of event handlers for my understanding. I’ve omitted the HTML and CSS as it’s not necessary for someone to understand my issue - it simply renders a square div in the center of the page.

I have set up two events (not sure if it is 2 event listeners, or counts as 1 if it is the same event).
The fact I used the onclick property for one and addEventListener() for the other is just to demonstrate to myself they are producing the same behaviour.

The alert function is able to be called repeatedly, with every click.
The style move right function only fires once, the first time the element is clicked.
Regardless of which order the code is written in or whether I attach the style move handler or the alert handler to the onclick property or with the addEventListener() method - I get the same result. The alert fires multiple times, the style move only fires once on the first click.

Can you help me to understand what I am failing to please?

let parentWindow = document.querySelector(’#parentWindow’);
parentWindow.onclick = () => {alert(‘Hello World’)};
parentWindow.addEventListener(‘click’, () => {parentWindow.style.right = “10px”});

Thanks

I went through and changed a couple things, going from top to bottom -
You are assigning the innerHTML in the turnButtonRed function to ‘Red Button’ - but in your If condition you are checking if it is equal to ‘Red button’ - the letter ‘B’ is capitalized in one and not the other.

In your if condition check you are using 1 equals sign - which is for assignment, it should be 2, or 3 for strict equality.

As mtf highlighted - I changed the switch - but to an else if, not an else - as in your code, you are performing another comparison. You don’t really need the else if and comparison at all, you could just write else and call the turnButtonBlue function, as the if condition in the first part of the function makes that redundant.

Lastly, in the HTML file - the button element is written across 3 lines, each component being on a separate line. When I checked to see what the innerHTML of the button being compared in the if conditions looked like, it was not exactly ‘Blue button’. I collapsed the HTML into one line of code so it then perfectly matched ‘Blue button’. I was able to do this by using alert(element.innerHTML) - as the JS console cannot be seen in this exercise.

Final code is -

let element = document.querySelector("button");

function turnButtonRed (){
  element.style.backgroundColor ='red';
  element.style.color ='white';
  element.innerHTML = 'Red button';
}

function turnButtonBlue (){
  element.style.backgroundColor ='blue';
  element.style.color ='white';
  element.innerHTML = 'Blue button';
}

function redandblue () {
  if (element.innerHTML === 'Blue button') {
    turnButtonRed();
  } else if (element.innerHTML === 'Red button'){
    turnButtonBlue();
  }
}

element.onclick = redandblue;

I had a brainwave…
Maybe it is firing every time I click - however after is has moved after the first time the event handler fires, the style property is remaining at 10px and has already moved that value compared to it’s parent container, therefore no further movement occurs.

SUCCESS !
let parentWindow = document.querySelector(’#parentWindow’);
let value = 10;
parentWindow.addEventListener(‘click’, () => {parentWindow.style.right = ${value}px; value+= 10;});

1 Like

If you’ve not encountered the term, event bubbling then search for it and read up what it means.

A post was split to a new topic: Event Bubbling

Thought it worth noting: in some books / resources, ‘onclick’ is written in camelcase as ‘onClick’, which is how I originally came across this. However, it seems that only ‘onclick’ works (I believe in current JS as well) - bit of a weird quirk as to me the camel case convention makes a little more sense.

  • onclick => global event

  • ‘click’ => event

  • “onClick” => HTML attribute (if supported by the browser)

The latter is more likely to be supported in JSX (React) or other framework.

Bottom line, keep subjectivity out of it, and follow the norms as given in the specs.

1 Like

Ah thanks - I think onClick might have been used then because they were first teaching how to include JS inline in the HTML (while acknowledging this isn’t the best practice)? Or is this a convention that’s changed over time?

Separation of concerns is a subject of the earlier 2000’s that caught on very easily, given the many benefits. HTML that is nothing but, CSS that separates presentation from content, and JS that coordinates behaviors across the other two is the norm. Put the idea of inline script in the rear view mirror.

1 Like

Yeah it’s odd that they taught that way, possibly to get people used to certain concepts before needing to introduce everything at once.

Noted that separation is the best way forward, that makes sense to me!

1 Like

This has sort of been mentioned in this thread but I wanted to get some more clarity,

How does turnButtonRed() get access to element?

function turnButtonRed(){
  // Add code to turn button red
  element.style.backgroundColor = 'red';
  element.style.color = 'white';
  element.innerHTML = 'Red Button';
}

turnButtonRed does not take any arguments based on that definition.
So even though it is registered as a callback function, how does it get access to element ?

Hey, @dk85 welcome to the forums.

element is a variable previously defined in the program outside of the function.

1 Like

Hi @not-ethan, thanks for your help.

But I was wondering in a more general case, if this function was declared in another file.
How would the onClick function pass element to the callback function?

you can either declare it in that file or (not sure if this will work) use modules.

1 Like

for onclick, you could do:

function turnButtonRed(){
  // code to turn button red
  this.style.backgroundColor = 'red';
  this.style.color = 'white';
  this.innerHTML = 'Red Button';
}

where this refers to the element that’s being clicked on [MDN reference]
or more generally,

function turnButtonRed(event){
  const element = event.target;  
  // code to turn button red
  element.style.backgroundColor = 'red';
  element.style.color = 'white';
  element.innerHTML = 'Red Button';
}

which is covered in a later lesson.

2 Likes

Thanks @janbazant1107978602
That helps clear things up for me