Home > Blockchain >  javascript: 2 toggles not working on the same page because of same classname
javascript: 2 toggles not working on the same page because of same classname

Time:09-21

I am new to JS and i am in an issue, I have added 2 identical sitecore modules on same page which has 2 identical script which toggles the class name.

var accItem = document.getElementsByClassName('accordionItem');
var accHD = document.getElementsByClassName('accordionItemHeading');
for (i = 0; i < accHD.length; i  ) {
    accHD[i].addEventListener('click', toggleItem, false);
}
function toggleItem() {
    var itemClass = this.parentNode.className;
    for (i = 0; i < accItem.length; i  ) {
        accItem[i].className = 'accordionItem close';
    }
    if (itemClass == 'accordionItem close') {
        this.parentNode.className = 'accordionItem open';
    }
}

The problem is that only one module click is working because of the identical className. Now how can i use "this" to solve my problem and both modules should work despite of having same classname?

Edit: HTML Code:

<div >
 <div  style="display: block;">
   CONTENT
 </div>
</div>
<div >
 <div  style="display: block;">
  CONTENT
 </div>
</div>

CodePudding user response:

I wasn't able to get your HTML working but the approach I would try in the toggleItem function is as follows:

var accHD = document.getElementsByClassName('accordionItemHeading');

for (i = 0; i < accHD.length; i  ) {
    accHD[i].addEventListener('click', toggleItem, false);
}

function toggleItem() {
  // get the parent accordion element
  let parentAccordion = this.closest(".accordionContent");
  // get all the accordion items within the parent
  let itemsInParent = parentAccordion.querySelectorAll(".accordionItem");
  // make them all closed
  itemsInParent.forEach(item => item.className = 'accordionItem close');
  // make this one open
  this.parentNode.className = 'accordionItem open';
}

CodePudding user response:

So in your script you're referring to accordion-headings but it wasn't included in your HTML. I assume you want to use those headings to be the ones that activate the toggle mechanism. Because your HTML code wasn't complete I've created a possible example based on what I thought it would need for your code to work.

There really isn't much difference, most of the code you've written was all right. I've just added the event parameter to the function toggle. That one makes it possible to retrace the target that fired the click event (the accordionHeading) and from there we can for example get the parent (the accordion-container) and then from there we can go back to find the actual element accordionItem inside this container.

let accordionHeadings = document.getElementsByClassName('accordionHeading');

for(let i=0; i<accordionHeadings.length; i  ){
   accordionHeadings[i].addEventListener('click', toggle);
}

function toggle(event){
  let accordionItem = event.target.parentElement.lastElementChild;
  if(accordionItem.classList.contains('close')){
    accordionItem.classList.remove('close');
    accordionItem.classList.add('open');
  }else{
    accordionItem.classList.remove('open');
    accordionItem.classList.add('close');
  }
}
.accordionContent{ padding: 2em; margin: 0.5em; background-color: lightgrey; }
.open{ display: block; }
.close{ display: none; }
<div >
  <div >
    Click me to toggle the content
  </div>
  <div >
    CONTENT
   </div>
</div>

<div >
  <div >
    Click me to toggle the content
  </div>
  <div >
    CONTENT
   </div>
</div>

  • Related