Home > front end >  Make each tab section unique instead of triggering other elements
Make each tab section unique instead of triggering other elements

Time:12-31

I am having a select box that works as tabs, it works fine whenever there is one section. However I want to make it work for multiple of sections, I want it basically to be unique and work at its own. I can't add custom class for a different element in html because it's being added dynamically through html system and all have same classes. Is there way to work around this using javascript?

const selectList = document.querySelectorAll("select");

for (let i = 0; i < selectList.length; i  ) {
  selectList[i].addEventListener("change", toggle);
}

function toggle(e) {
  e.target.closest(".section").querySelectorAll(".ul-data").forEach((el) => {
    el.hidden = el.dataset["name"] !== e.target.value;
  });
}
<select >
   <option value="test">Test</option>
   <option value="test1">Test1</option>
</select>
<div >
   <ul  data-name="test">
      <li>Item</li>
   </ul>
</div>
<select >
   <option value="test">Test</option>
   <option value="test1">Test1</option>
</select>
<div >
   <ul  data-name="test">
      <li>Item</li>
   </ul>
</div>

As you can see in the snippet, when you change the first section value the other section changes too which I do not want to happen.

CodePudding user response:

You could use nextElementSibling to find the element that comes directly after e.target (the select box). However i recommend to edit the html structure so there is a wrapper around the select and the ulelements to prevent your code form breaking when the html changes so that there will be an element in between.

You could write your own function similar to closest but for siblings too.

const selectList = document.querySelectorAll("select");

for (let i = 0; i < selectList.length; i  ) {
  selectList[i].addEventListener("change", toggle);
}

function toggle(e) {
  e.target.nextElementSibling.querySelectorAll(".ul-data").forEach((el) => {
    el.hidden = el.dataset["name"] !== e.target.value;
  });
}
<select >
  <option value="test">Test</option>
  <option value="test1">Test1</option>
</select>
<div >
  <ul  data-name="test">
    <li>Item</li>
  </ul>
</div>
<select >
  <option value="test">Test</option>
  <option value="test1">Test1</option>
</select>
<div >
  <ul  data-name="test">
    <li>Item</li>
  </ul>
</div>

CodePudding user response:

You should target the parents which class starts with ^= "section-".
Than, when selecting your elements make sure they're queried not from document but from their parent section-N Element

const EL = (sel, el) => (el || document).querySelector(sel);
const ELS = (sel, el) => (el || document).querySelectorAll(sel);

const ELS_section = ELS('[class^="section-"], [class*=" section-"]');
// PS: use rather a common ".section" in HTML 

ELS_section.forEach(EL_section => {

  const ELS_select = EL(".dropdown", EL_section); // descendant of EL_section
  const ELS_ul = ELS(".ul-data", EL_section);     // descendants of EL_section

  ELS_select.addEventListener("change", () => {
    const name = ELS_select.value;
    ELS_ul.forEach(EL_ul => {
      EL_ul.hidden = name && EL_ul.dataset.name !== name;
    });
  });
  
});
<div >

  <select >
    <option value="">-- All --</option>
    <option value="test">Test</option>
    <option value="test1">Test1</option>
  </select>

  <ul  data-name="test">
    <li>Test</li>
  </ul>
  <ul  data-name="test1">
    <li>Test1</li>
  </ul>

</div>

<div >

  <select >
    <option value="">-- All --</option>
    <option value="test">Test</option>
    <option value="test1">Test1</option>
  </select>

  <ul  data-name="test">
    <li>Test</li>
  </ul>

  <ul  data-name="test1">
    <li>Test1</li>
  </ul>

</div>

CodePudding user response:

try This:

const selectList = document.querySelectorAll("select");

for (let i = 0; i < selectList.length; i  ) {
  selectList[i].addEventListener("change", toggle);
}

function toggle(e) {
  let parent = e.target.closest("[class^='section-']");
  if(!parent) return;
  let ulList = parent.querySelectorAll(".ul-data");

  for (let i = 0; i < ulList.length; i  ) {
    ulList[i].hidden = ulList[i].dataset["name"] !== e.target.value;
  }
}
<div >

  <select >
    <option value="test">Test</option>
    <option value="test1">Test1</option>

  </select>

  <ul  data-name="test">
    <li>Item</li>
  </ul>

  <ul  data-name="test1">
    <li>Item2</li>
  </ul>

</div>

<div >

  <select >
    <option value="test">Test</option>
    <option value="test1">Test1</option>

  </select>

  <ul  data-name="test">
    <li>Item</li>
  </ul>

  <ul  data-name="test1">
    <li>Item2</li>
  </ul>

</div>

  • Related