Add Event Listener not working with option selection

I’m working on ordering a list of songs alphabetically or by year. However, when I create an “addEventListener” item, it stops working after I make a selection more than once. This is my first post here so I’m unsure what people usually ask for but here’s a piece of the script:

    alphaArtist = document.getElementById("sortBy") // this ID is for the select/option menu in the html part 


    alphaArtist.addEventListener("change", (sortBy) => {

      // this is what i added to delete the existing list before creating the new one sorted
      for (k in songs) {
        document.getElementsByClassName("tuttiName")[k].style.display = "none"
      }

      // Sort alphabetically by artist Name A-Z
      if (alphaArtist.value == "AZSelected") {

        for (k in songs) {

          songs.sort(function ( a, b ) {
            if (a.artist > b.artist ) {
              return 1
            }
            if (a.artist < b.artist ) {
              return -1
            }
            return 0
          })

          div_song = document.createElement('div')
          document.body.appendChild(div_song)

          fullDisplay.className = "tuttiName"
          fullDisplay = document.createElement('a')
          fullDisplay.target = "_blank"
          fullDisplay.innerHTML = songs[k].artist + " - " + songs[k].title + " (" + songs[k].role + ") " + " [" + songs[k].year + "]"
          document.body.appendChild(fullDisplay)
          fullDisplay.href = songs[k].stream
        }
        }
      // Sort alphabetically by artist Name Z-A
      if (alphaArtist.value == "ZASelected") {

        for (k in songs) {

          songs.sort(function ( a, b ) {
            if (a.artist > b.artist ) {
              return -1
            }
            if (a.artist < b.artist ) {
              return 1
            }
            return 0
          })

          div_song = document.createElement('div')
          document.body.appendChild(div_song)

          fullDisplay.className = "tuttiName"
          fullDisplay = document.createElement('a')
          fullDisplay.target = "_blank"
          fullDisplay.innerHTML = songs[k].artist + " - " + songs[k].title + " (" + songs[k].role + ") " + " [" + songs[k].year + "]"
          document.body.appendChild(fullDisplay)
          fullDisplay.href = songs[k].stream

        }
        }})

hopefully this offers some insight into what i’m doing wrong. thanks everyone!

I think the error is in this part

fullDisplay.className = “tuttiName”
fullDisplay=document.createElement(‘a’)

you are reassigning fullDisplay with a new element so you lose className.
You first need to create the new element then assign the class.

And try to refactor the code. There are many repetitions that you could wrap in a function. I.e to try the change I suggest you have to change the code in two locations. When you find yourself copy/paste some code its a good hint you could need a function.

If you would like to review the code together post a the full code.

Let me know if it works.

Thank you for getting back to me so quickly!

I refactored the code to wrap the repetitions in a function. However, for some reason, the problem persists. Here I’m attaching the full code. The problem lies between lines 210 and 324. This is a work in progress for a school project so don’t expect anything too fancy haha

<html>
  <head>
    <title>Final Assignment HV</title>

    <style>

    #theHeader {
      font-family: arial;
      color: pink;
      font-size: 38px;
      text-align: center;
    }

    .column {
      float: left;
      width: 25%;
    }

    h2 {
      font-family: arial;
    }

    label {
      font-family: arial;
    }

    a {
      font-family: arial;
    }

    </style>

  </head>

  <body>

    <h1 id="theHeader">Hendrick Valera Discography</h1>

    <div class="column">

    <h2 class="FilterHeader">Role</h2>
    <input type="checkbox" id="check_1" value="1">
    <label for="check_1">Producer</label> <br>

    <input type="checkbox" id="check_2" value="2">
    <label for="check_2">Mix Engineer</label> <br>

    <input type="checkbox" id="check_3" value="3">
    <label for="check_3">Mastering</label> <br>

    <input type="checkbox" id="check_4" value="4">
    <label for="check_4">Mix Assistant</label> <br>

    <input type="checkbox" id="check_5" value="5">
    <label for="check_5">Artist</label> <br>

    <input type="checkbox" id="check_6" value="6">
    <label for="check_6">Sax/Flute</label> <br>
    <br>

    </div>

    <div class="column">

    <h2 class="FilterHeader">Genre</h2>
    <input type="checkbox" id="Gcheck_1" value="1">
    <label for="Gcheck_1">Hip-Hop</label> <br>

    <input type="checkbox" id="Gcheck_2" value="2">
    <label for="Gcheck_2">R&B/Jazz</label> <br>

    <input type="checkbox" id="Gcheck_3" value="3">
    <label for="Gcheck_3">House</label> <br>

    <input type="checkbox" id="Gcheck_4" value="4">
    <label for="Gccheck_4">Reggaeton</label> <br>

    <input type="checkbox" id="Gcheck_5" value="5">
    <label for="Gcheck_5">Pop</label> <br>

    <input type="checkbox" id="Gcheck_6" value="6">
    <label for="Gcheck_6">Rock</label> <br>

    <input type="checkbox" id="Gcheck_7" value="7">
    <label for="Gcheck_7">Indie</label> <br>
    <br>

    </div>

    <div class="column">

    <h2 class="FilterHeader">Release Year</h2>
      <select id="selectYear">
        <option></option>
        <option>2022</option>
        <option>2021</option>
        <option>2020</option>
        <option>2019</option>
        <option>2018</option>
        <option>2017</option>
      </select>
      <br><br>

    </div>

    <div class="column">

    <h2 class="FilterHeader">Search by Artist</h2>
    <input type="text" id="ArtistSearch" value="Artist Name">
    <br><br>
    <button id="ClickSearch">Search</button>

    <br><br><br><br><br><br>

    </div>
    <button>Reset Filters</button>
    <br><br><hr><br>

      <select id="sortBy">
        <option value="defaultSelected">Sort By</option>
        <option value="NewSelected">Date (Newest)</option>
        <option value="OldSelected">Date (Oldest)</option>
        <option value="AZSelected">Artist (A-Z)</option>
        <option value="ZASelected">Artist (Z-A)</option>
      </select>

      <br><br><br>

    <script>

    let songs = [
    /*
    {
      title: "",
      artist: "",
      role: "",
      year: ,
      genre: "",
      stream: ""
    },
    */
    {
      title: "What Are Friends For EP",
      artist: "Chynna Lewis",
      role: "Mix Assistant",
      year: 2022,
      genre: "R&B",
      stream: "https://open.spotify.com/album/1PoY1vH332I6lOAyLZtZ20?si=toZMed-4Q2GazwwEFWW_7A"
    },
    {
      title: "Stars",
      artist: "Rishi Love",
      role: "Mixing & Mastering",
      year: 2022,
      genre: "House",
      stream: "https://open.spotify.com/track/5WGm3B206qsJzdwNztQVPM?si=cdd8dda610cc44be"
    },
    /*
    {
      title: "",
      artist: "",
      role: "",
      year: ,
      genre: "",
      stream: ""
    },
    */
    {
      title: "Airegin",
      artist: "Braxton Cook",
      role: "Mixing & Mastering",
      year: 2021,
      genre: "Jazz",
      stream: "https://youtu.be/EX5WlDs0gNU"
    },
    /*
    {
      title: "",
      artist: "",
      role: "",
      year: ,
      genre: "",
      stream: ""
    },
    */
    /*
    {
      title: "",
      artist: "",
      role: "",
      year: ,
      genre: "",
      stream: ""
    },
    */
    /*
    {
      title: "",
      artist: "",
      role: "",
      year: ,
      genre: "",
      stream: ""
    },
    */
    ]

    // Create full list of songs

    function listSongs(arr) {

      for (k in arr) {
        div_song = document.createElement('div')
        document.body.appendChild(div_song)

        fullDisplay = document.createElement('a')
        fullDisplay.className = "tuttiName"
        fullDisplay.target = "_blank"
        fullDisplay.innerHTML = arr[k].artist + " - " + arr[k].title + " (" + arr[k].role + ") " + " [" + arr[k].year + "]"
        document.body.appendChild(fullDisplay)
        fullDisplay.href = arr[k].stream
      }
    }

    // default view of list

    listSongs(songs)

    // sorting section of the program

    alphaArtist = document.getElementById("sortBy")

    alphaArtist.addEventListener("change", (sortingBy) => {

      for (k in songs) {
        document.getElementsByClassName("tuttiName")[k].style.display = "none"
      }

      // Sort alphabetically by artist Name A-Z [default]
      if (alphaArtist.value == "defaultSelected") {

        for (k in songs) {

          songs.sort(function ( a, b ) {
            if (a.artist > b.artist ) {
              return 1
            }
            if (a.artist < b.artist ) {
              return -1
            }
            return 0
          })
        }
        listSongs(songs)
        }
      // Sort alphabetically by artist Name A-Z
      if (alphaArtist.value == "AZSelected") {

        for (k in songs) {
          songs.sort(function ( a, b ) {
            if (a.artist > b.artist ) {
              return 1
            }
            if (a.artist < b.artist ) {
              return -1
            }
            return 0
          })
        }
        listSongs(songs)
        }
      // Sort alphabetically by artist Name Z-A
      if (alphaArtist.value == "ZASelected") {

        for (k in songs) {

          songs.sort(function ( a, b ) {
            if (a.artist > b.artist ) {
              return -1
            }
            if (a.artist < b.artist ) {
              return 1
            }
            return 0
          })
        }
        listSongs(songs)
        }
      // Sort by newest
      if (alphaArtist.value == "NewSelected") {

        for (k in songs) {

          songs.sort(function ( a, b ) {
            if (a.year > b.year ) {
              return -1
            }
            if (a.year < b.year ) {
              return 1
            }
            return 0
          })
        }
        listSongs(songs)
        }
      // Sort by oldest
      if (alphaArtist.value == "OldSelected") {

        for (k in songs) {

          songs.sort(function ( a, b ) {
            if (a.year < b.year ) {
              return -1
            }
            if (a.year > b.year ) {
              return 1
            }
            return 0
          })
        }
        listSongs(songs)
        }

    })

    // Hide text in search bar
    emptyArtist = document.getElementById("ArtistSearch")

    function hideText() {
      emptyArtist.value = ""
    }

    emptyArtist.addEventListener("click", hideText)

    /*
    */

    </script>

  </body>
</html>

Thanks Paolo!

Just got the idea.
First thing first: use strict mode and declare you’re variables with let, var or const keyword just to avoid some strange behaviours.

Now to the point. What’s happen is that when you sort the first time it works fine.
When you try to sort the list the second time what you’re trying to do is:

  1. hide the previous list
  2. show the new list sorted with the selected option

What happen instead is that point 2 is working fine but point 1 is what failing.
The new list is appended just behind the old list but the old list is not hiding.

So it’s a great time to learn to debug.

Look for the lines of code where you’re trying to hide the old list and add some console.log to see what’s happening.

Hint: you’re using for … in statement to loop over arrays when it’s safer to use a for … of loop for arrays.

If you can’t resolve the problem I will be happy to show you the a possible implementation.

But if you can figure it out yourself you’ll benefit of a deep understanding of what’s happening and surely you will not repeat the same mistake in the future.

And if you’re interested I could suggest you some more refactoring you could do :smile:

Let me know how you doing

Paolo,

Thank you so much for all your help!

First, I tried changing the for-in loops for for-of and I would get an error every time, even with the classic for loop ( k = 0 ; k = arr.length ; k++ ). I switched the code to js and the error I got was that they couldn’t recognize the objects in the array: arr[k].artist, etc… I even tried putting the function first, then the array of objects and then call the function and the problem persisted. Do you know why this might be?

Second, back in html I added an alert to trigger every time I switched the options, like this:

  alert(document.getElementsByClassName("tuttiName")[0])

and weirdly every time I changed the options the alert shown was the link for the first item in the default order. So for example, if I change the option from oldest to A-Z, the alert shown was the link for what would be the 3rd item in the order by oldest, does that make sense? maybe this is a clue of what the issue is? I just don’t know how to tackle it.

Lastly, I followed your tip of using let, var, const to assign variables. But I’m still stuck, if you could steer me in the right direction that would be amazing!

Thanks again!

The error is because the way for of loop works that differs from for in loop.

For in loop is used to loop through the properties of object thus for (k in array) k = “0” , “1”, … And you could get the value (the song object in your case) with arr[k]

For of loop instead loop through the values of an array directly.
So you should do
for (song of arr)

Read through the mdn doc for a better explanation. Seem you dont know how loops works so try to understand it first reading the docs. Moving functions calls up and down youre code and crossing fingers for the program to work is very common when youre working on the same issue for a long time and cant figure out a solution (I do it too much still) but you must resist that urge (just like i told you about copypasting) take a break and try to understand where the problem come from.

Moving piece of code around rarely works and, even when it do, you cant realize why it works.

Unless you only want to complete the assignement in which case come back to for in loop which worked just fine :slight_smile:

For the second question yes it totally make sense :slight_smile:
The problem here are more than one.

But focus on one problem at a time.
Try to fix the logic first then we could work on the html part.

Hope this help you.
I leave you the links to the mdn docs.
Read them and try to implement both versions to find out the differnces.

Let me know how youre going

Thank you so much Paolo!! I was able to get it done!! this is what I wrote (I changed the clear list action to make it a function):

function deleteAll(arr) {
  let currentList = document.querySelectorAll("a.tuttiName")
  for ( j of currentList ) {
    j.style.display = "none"
  }      
}

You’ve been of so much help I really appreciate your time. Might end up creating a new post with my next section of the code as soon as I encounter the next wall haha.

Glad to help. Will watch out for your next post :wink:

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.