Toggle Button
Tags: javascript, beginners
Published: 2022-08-05 18:42:25

The process of learning javascript contains multitudes. There are peaks and there are valleys. It starts out simple. Then a wrench gets thrown into things and you start asking yourself the same questions again and again,  "Wait what goes where?",  "And that thing does what?",  "How do I make it do this?  Or that?" You learn how to ask better questions, too, largely due to necessity. All in all, there are concepts you just have to struggle with in order to fully grasp them. When you do, it's right as rain, easy as pie. 

Creating a "toggle button" is one of these frustrating tasks.
I'm defining a "toggle button" here as an HTML element with an event listener attached to it, which, when clicked, can change an element AND change it back. For example, imagine Instagram. Now imagine there's a cool post you like. So you double tap the post and BOOM - it's been liked by you. The heart icon fills with color and the number of likes increases. If you double tap again, the same user action, the opposite event occurs, reverting the heart back to empty, and decreases the likes count to what it previously was. 

The first thing we need to do is identify what we want the "target" of our event to be - if you wanted something to happen when a user clicked a button, the button would be this "target". In my first example, the target element has been named "shinyBtn". When clicked, the display image of a Pokemon changes. When clicked again, it changes back. It toggles. But, how?

In the code below, I've created variables, assigned their values to locations on the DOM/HTML. This will allow me to set values on these elements' properties in the next step, i.e. "textContent" for a header/title element or the "src" for an image element. 

!["Grabbing" Elements Off the DOM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r1q4t5bd333el6mhkp38.png)

Next, I constructed a function which accesses an API database of Pokemon, performs a GET request, and sets particular pieces of that data on particular DOM/HTML elements, ultimately creating a display Pokemon with an image, name, height, weight, and type. 

![Display Pokemon Function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58mqsauin9bih3f90ej7.png)

Now that we have a display Pokemon, I will add some functionality to the "shinyBtn" using an event listener. Event listeners take two parameters, an event type (in this case, "click") and a function to be invoked when this event occurs. The function argument here will change the display "default" image to a "shiny" image.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j26x3xqitzc4ghm1ubgw.png)

This is cool. This works. But not as a "toggle". It only works once (per object/pokemon) and in one direction - reassigning the display image source from the "default" image to the "shiny" image. If I click the "shinyBtn" again, it doesn't change back. How do I get it to change back? Can I add another event listener to the "shinyBtn" and have this function perform the reverse and reassign the "shiny" image to the "default"?

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uq5rnapi95a693xpvcp.png)

It doesn't work. This is due to javascript running top-down, left to right. The first event listener takes precedence over the second. This button already does a job every time it's clicked. We need this function's behavior to be conditional. If the image is the "default", it should change to the "shiny" image upon the click event and vice versa. This is simple and can look like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no4x287l5znywm1scuo0.png)

The same logic was used in the same web app to change the image of the Pokemon listed on the left side of the screen. With a "mouseover" event added to each image, whenever the mouse moves over the image, an event will occur. The function argument in the event listener will change the target image source to the "back" image if it's currently the "front" image, and vice versa.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bg8zntpqe9dfskf8tgvu.png)

While this last example isn't a "button", it is still toggle behavior.