Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

How do I have this animation play across all my select menu's not just one???

Okay so here's my github file: https://github.com/sid-FBLA/FBLA/tree/master

It may look like a lot at first, but the only three things you need to open to understand this issue are: bookings.html(can be found in HTML folder) bookings.css(can be found in CSS folder, the important part is the bottom, scroll to the styles on the "arrow" class) calc.js(can be found in JS folder, the important part here are lines: 130-151)

Please open my project up on a live server, and click on the book menu(navigation bar).

You will see two select menus, one with the heading "Departure Airport" the other with the heading "Arrival Airport."

Now, if you click on the first select menu, you will see the arrow animates up and down, and moves perfectly. However, if you press on the second select menu, the arrow doesn't do anything. How do I make it so that the arrow works on the specific select menu pressed? Any help would be greatly appreciated.

Steven Parker
Steven Parker
231,154 Points

You wrote "Please open my project up on a live server...", but where have you set that up? (you can do it on github).

My bad thanks Steven Parker for informing me, didn't know you could create a live server on Github, anyways, the link to my live server is: https://sid-fbla.github.io/sid-FBLA-FBLA-help/

Steven Parker
Steven Parker
231,154 Points

When I click on "booK', I get a 404 error (page not found).

1 Answer

Steven Parker
Steven Parker
231,154 Points

In calc.js you define const select = document.querySelector('.selection'); and const arrow = document.querySelector('.arrow');. Remember that "querySelector" only selects the first matching item. So only the first box has a click handler, and the handler code only works with the first arrow.

What you probably want is to create a handler that uses DOM traversal to identify the arrow using the select box, and then attach that handler to both boxes. Or, less elegant would be to just replicate the handler and have the copy attached to the second box, and change the arrow references in it to the second arrow.

Yes that is exactly what I want to do, create a handler that uses DOM traversal to identify the arrow using the select box, and then attach that handler to both boxes, I just don't know how to go about it.

Also try this link, it should work: https://sid-fbla.github.io/FBLA/

Github is being a bit annoying at the moment, so most images are not loading, and not all the CSS is being read, but it's enough for the task at hand. Thanks so much for the help so far!

Steven Parker
Steven Parker
231,154 Points

I think this might be what you want, though I didn't have an easy way to test it.

  const select1 = document.querySelector('#1');
  const select2 = document.querySelector('#2');

  function flipper(e) {
    let arrow = e.target.previousElementSibling;
    if (arrow.classList.contains('arrow-down')) {
      arrow.classList.remove('arrow-down');
      arrow.classList.add('arrow-up');
    } else {
      arrow.classList.remove('arrow-up');
      arrow.classList.add('arrow-down');
    }
  }

  select1.addEventListener('click', flipper);
  select2.addEventListener('click', flipper);

And if you give the arrows the class "arrow-up" to start with, you can simplify the function to this:

  function flipper(e) {
    let arrow = e.target.previousElementSibling;
    arrow.classList.toggle('arrow-up');
    arrow.classList.toggle('arrow-down');
  }

Thanks for all your help so far. I added the code you sent, it worked well, I just made a few minor changes, but it's working fine.

However, I want the arrow to go back up when the user clicks outside the select menu(anywhere else on the body). In order to do this I added these lines of code:

body.addEventListener('click', function(e) {
    if (selectMenus != e.target) {
      console.log(e.target);
      for(let i = 0; i < arrow.length; i += 1) {
        console.log(arrow.length);
        $('.arrow').eq(i).removeClass('arrow-down');
        $('.arrow').eq(i).addClass('arrow-up');
      }
  })

selectMenus is just a variable that query selects all of the select elements in the form element, what my code is saying is: if the select menu is not the event target then loop through all the elements with the arrow class and add the class "arrow up." However, this code is not working, instead, all of the arrows are always being changed to class "up" and never switching to class "down." I assume there is something wrong in the 'if statement,' can you please instruct me on how to fix this?

Steven Parker
Steven Parker
231,154 Points

The event target will always be one single element, so it will never be equal to the entire "selectMenus" collection.

Also, if you are using jQuery you don't need discrete loops. You can do things like "$('.arrow').addClass('arrow-up');" to do them all at once. You also have a much more concise way to set up event handlers.

But we're diverging here. Start a fresh question if you have other issues.

Thanks for the help, I marked your answer as the best answer. However, can you please explain how I could make it so that the arrow element toggles its class to "up" when pressed outside of a select menu?

Steven Parker
Steven Parker
231,154 Points

Checking in the body event could work, you just need an effective check (like testing both inputs individually).

But perhaps a better method would be to add "e.stopPropagation();" in the input handler so the body event is never triggered.

Still another concept would be to eliminate the body handler and use "focus" and "blur" events instead of clicks on the input boxes.

I tried the method you told me in which, I checked each body input individually, however, it did not work. Can you show me how you would do this?

Steven Parker
Steven Parker
231,154 Points

I think the 2nd suggestion is probably easiest. Just add "e.stopPropagation();" in the input handler ("flipper"). Then you shouldn't need any tests in the body handler.

The e.stopPropogation does not work as I want to make it so that the arrow element toggles its class to "up" when pressed outside of the select menu. Also I'm having a lot more issues with the arrow right now, I made a new question, if you have any time to spare please respond.

Here is the link to my new question: https://teamtreehouse.com/community/what-is-wrong-with-this-animation

Steven Parker
Steven Parker
231,154 Points

My second suggestion was to add that to the handier for the selects, to prevent the body handler from also running when a select is clicked and resetting the arrows up. The body handler would still need to be set up to react to clicks made outside of the selects.

The third and more complicated suggestion, which eliminates the body handier, would require handling different events on the selects.