0

I'm trying to loop through some elements with an attribute and based on which element I click, I'd like the is-active class to be added to the specific element.

The top section works, clicking on the specific tab, but the problem is with tabBody.

Right now, it adds the class to ALL elements and I cannot figure out where to put this to reference the correct div.

I just want whichever tab-body is active, to be the same tabs-bg is active, and have all that based on which tab is clicked.

I have this code (I've tried let el = this, says already defined):

const tab = document.querySelectorAll('[data-tabs-tab]');
const tabBody = document.querySelectorAll('[data-tabs-body]');

function changeMe() {
  const activeTab = this.hasAttribute('data-tabs-tab');

  [...tab].forEach(el => {
    if (this !== el) {
      el.classList.remove('is-active');
    }
  });
  this.classList.add('is-active');

  [...tabBody].forEach(el => {
    if (el.hasAttribute('data-tabs-body') == activeTab) {
      if (el.classList.contains('tabs-bg')) {
        el.classList.add('is-active');
      }
    } else {
      el.classList.remove('is-active');
    }
  });
}
tab.forEach(el => el.addEventListener('click', changeMe));
<div class="tabs" data-tabs>
  <nav>
    <ul class="tabs__tabs">
      <li data-tabs-tab="one" class="is-active"></li>
      <li data-tabs-tab="two"></li>
      <li data-tabs-tab="three"></li>
    </ul>
  </nav>
  <div class="tabs__content">
    <div data-tabs-body="one" class="tab-body is-active"></div>
    <div data-tabs-body="two" class="tab-body"></div>
    <div data-tabs-body="three" class="tab-body"></div>
  </div>
</div>
<div class="tabs__bg">
  <div data-tabs-body="one" class="tabs-bg is-active"></div>
  <div data-tabs-body="two" class="tabs-bg"></div>
  <div data-tabs-body="three" class="tabs-bg"></div>
</div>

1
  • Your snippet is not working. Commented Jun 19, 2018 at 14:06

1 Answer 1

3

.hasAttribute() just checks to see if the attribute exists on the element. You should be using .getAttribute() instead to get the value of the attribute.

Also, not sure why the if (el.classList.contains('tabs-bg')) block was in there, but I commented it out to make the demo work.

const tab = document.querySelectorAll('[data-tabs-tab]');
const tabBody = document.querySelectorAll('[data-tabs-body]');

function changeMe() {
  const activeTab = this.getAttribute('data-tabs-tab'); // Change here

  [...tab].forEach(el => {
    if (this !== el) {
      el.classList.remove('is-active');
    }
  });
  this.classList.add('is-active');

  [...tabBody].forEach(el => {
    if (el.getAttribute('data-tabs-body') === activeTab) { // and here
      //if (el.classList.contains('tabs-bg')) {
        el.classList.add('is-active');
      //}
    } else {
      el.classList.remove('is-active');
    }
  });
}
tab.forEach(el => el.addEventListener('click', changeMe));
.is-active {color: red;}
<div class="tabs" data-tabs>
  <nav>
    <ul class="tabs__tabs">
      <li data-tabs-tab="one" class="is-active">Tab 1</li>
      <li data-tabs-tab="two">Tab 2</li>
      <li data-tabs-tab="three">Tab 3</li>
    </ul>
  </nav>
  <div class="tabs__content">
    <div data-tabs-body="one" class="tab-body is-active">Tab Body Content 1</div>
    <div data-tabs-body="two" class="tab-body">Tab Body Content 2</div>
    <div data-tabs-body="three" class="tab-body">Tab Body Content 3</div>
  </div>
</div>
<div class="tabs__bg">
  <div data-tabs-body="one" class="tabs-bg is-active">Tab Body BG 1</div>
  <div data-tabs-body="two" class="tabs-bg">Tab Body BG 2</div>
  <div data-tabs-body="three" class="tabs-bg">Tab Body BG 3</div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much, Joseph! It's working perfectly now :) and thanks for the hasAttribute vs. getAttribute tip!
@fencepencil just a side note: you can use Array.prototype.forEach.call(tab, (el) => {}) and bypass creating a new array on each changeMe() call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.