1

I'll start off by saying that as an avid browser (but having never posted), thanks in advance for any insight.

I am making a page for my employers code department, which needs to use dynamic dropdowns, since the amount of dropdowns fluctuates per page.

Context:

Originally we were using standard Bootstrap dropdowns, but some of the web providers our clients deal with aren't loading in bootstrap. My initial thought was to side-load it in, however, we work on templates that must work across the board for all of our clients and all of their web providers. Long story short, there were stability issues with bootstrap CSS files overriding various websites that weren't built with bootstrap in mind.

Onto the problem:

Here is my CodePen for you to view.

dropdown = () => {
const dropdown = document.getElementsByClassName("dropdown");
for (let i = 0; i < dropdown.length; i++) {
  const activeDropdown = dropdown[i].id,
        down = "#downChev-" + activeDropdown,
        up = "#upChev-" + activeDropdown,
        downIcon = document.querySelector(down),
        upIcon = document.querySelector(up),
        dropdownNumID = "#" + activeDropdown,
        dropdownID = "#dropdown-" + activeDropdown;

  if (event.target.matches(dropdownNumID)) {
    if (upIcon.classList.contains("show-icon")) {
      upIcon.classList.remove("show-icon");
      downIcon.classList.add("show-icon");
    } else if (downIcon.classList.contains("show-icon")) {
      downIcon.classList.remove("show-icon");
      upIcon.classList.add("show-icon");
    }
    document.querySelector(dropdownID).classList.toggle("dropdown-show")
  }
 }
}

Currently I've built out a dynamic dropdown system that utilizes ID's specific to each dropdown. The problem is that in the first loop that goes through the dropdowns to create the supporting variables, it doesn't create the activeDropdown variable and instead returns a blank variable when logged.

I've troubleshooted in multiple scenarios and have come up with the following:

  1. On localhost and in the CodePen, the code seems to work fine. Once added to the live sites, it breaks at initializing the activeDropdown variable within the loop, returning a blank variable when logged.
  2. If I remove the if condition right after the variables are set in the loop, and log the activeDropdown variable. It logs fine. This leads me to believe that it may be a synch issue. I then turned the if condition into its own function and added a settimeout, allowing the variables to be initialized prior to running the execution items within the new delayed function. Once that was added, the activeDropdown variable was no longer setting properly. It just returns blank when logged.

I'm not sure if my logic of execution is off, or if I've overcomplicated the entire thing. The only real goal here is to make a dynamic structure that allows my front-end dev team to add or remove model divs at will, with a simple modification to the ID's as the list grows.

It's also possible that other scripts that we don't have access to are creating the issue on the live site. However, I assume you guys will be able to find something wrong with my code lol.

KinPie
  • 13
  • 2
  • and of course, there is no error message in the debugger console, on any browser? – Mister Jojo Jul 18 '19 at 17:09
  • Are you loading your JS inside the head or where, is it is possible that your html hasn't fully loaded yet when your JS runs? – H3llskrieg Jul 18 '19 at 17:28
  • No errors, although I don't have much for error handling in place. I only have access to the body section on the web providers that we deal with. So all code including the JS is placed in the body. The JS script is also set to initiate on button press, so the HTML should be fully loaded prior to a user initiating the button press, I would suspect. – KinPie Jul 18 '19 at 17:40
  • https://developer.mozilla.org/en-US/docs/Tools/Browser_Console, or **F12** – Mister Jojo Jul 18 '19 at 18:05
  • Sorry, I suppose it would have been worthwhile for me to include the console error... I don't know why I overlooked it in your initial ask. "Uncaught DOMException: Failed to execute 'matches' on 'Element': '#' is not a valid selector." This is pertaining to JS line 12 in the CodePen, due to the activeDropdown variable not initializing. – KinPie Jul 18 '19 at 18:20

1 Answers1

1

It's difficult to know what's going on since your production environment is likely very different from the code pen, but I think a couple things could be happening.

1) Could be that the JavaScript is running before the entire page has loaded. Make sure your JavaScript code that is equivalent to the CodePen is loaded last on the page. (i.e. put the <script></script> tag at the very end of the document).

2) Some variables could be conflicting, since you are loading the JavaScript directly in the body of the document in the global scope. I have some general stylistic recommendations that may help you solve your problem:

From looking at your CodePen, you're using two different methods to react to click events: You have setup an event listeners with a callback on window.onclick, as well as 2) a function called dropdown that you are attaching to an onclick attribute in the HTML.

I would recommend staying away from the inline onclick attributes, and instead added an event listener to the container of the dropdown. That way your markup is not coupled to the dropdown JS, and you are listening to clicks within that container and not the whole application. You can use the same event listener for opening the dropdowns and closing dropdowns. See this stackoverflow post for more information about this.

In addition, I recommend adding a wrapping function around your code to prevent you from polluting the global scope. This function can be immediately invoked when the page loads, and will add the event listener on the container. You can read more about IIFE's here.

Here a CodePen demonstrating these two recommendations. While I don't know if this will help you solve your problem, hopefully at least you'll learn something new!

saylerb
  • 71
  • 4
  • Thank you for the recommendations! I'll dive into them and see if it resolves my issue! If nothing else, I can surely add a couple tools to my belt. Also, the window.onclick was set to collapse the dropdowns and reset the chevron symbols if you click outside of the dropdowns. I'm not sure if there is a more effective way to reproduce this action. – KinPie Jul 18 '19 at 18:23
  • Hooray! Your suggestions fixed it AND I learned quite a bit. Thank you! – KinPie Jul 18 '19 at 18:38
  • Ah okay, I didn't realize window.onclick was resetting the chevrons. I could look at updating the code pen. – saylerb Jul 19 '19 at 00:06
  • @KinPie I updated my CodePen with some code to close the menus when clicking outside of the button. Hope that helps – saylerb Jul 19 '19 at 00:28