Skip to content

How do I combine selector and tab functions?

I would like to shorten this code, but can’t figure out how.

The code works in the way that when you press the button in the selector, a map point and a text on the bottom of the map appear. It works in this way it is, but I am sure that there is a way to shorten it. I just have not enough knowledge on how to shorten it.

document.addEventListener('DOMContentLoaded', function() {
  document.querySelectorAll('.select__item').forEach( function(tabBtn) {
    tabBtn.addEventListener('click', function(event) {
      const path = event.currentTarget.dataset.path

      document.querySelectorAll('.sketch__item',).forEach( function(tabContent) {
        tabContent.classList.remove('block-active')
      })
      document.querySelectorAll('.details__item',).forEach( function(tabContent) {
        tabContent.classList.remove('block-active')
      })
        document.querySelectorAll(`[data-target="${path}"]`).forEach( function(tabsTarget) {
          tabsTarget.classList.add('block-active')
    })
    })
  })
  //*** tabs active
  let tabsChange = document.querySelectorAll('.select__item')

  tabsChange.forEach(button => {
    button.addEventListener('click', function () {
      tabsChange.forEach(btn => btn.classList.remove('active__tab'))
      this.classList.add('active__tab')
    })
  })
})

let select = function () {
  let selectHeader = document.querySelectorAll('.select__header');
  let selectItem = document.querySelectorAll('.select__item');

  selectHeader.forEach(item => {
    item.addEventListener('click', selectToggle)
  });

  selectItem.forEach(item => {
    item.addEventListener('click', selectChoose)
  });

  function selectToggle() {
    this.parentElement.classList.toggle('is-active');
  }

  function selectChoose() {
    let text = this.innerText,
        select = this.closest('.partner__select'),
        currentText = select.querySelector('.select__current');
    currentText.innerText = text;
    select.classList.remove('is-active');
  }
};

//*** Tabs

select();

Answer

Delegation shortens the code.

If you delegate, you shorten the code. Never loop eventlisteners in a container. Use the container instead

I lost 20 lines and made code easier to debug

NOTE: I did not have your HTML so I may have created some errors or logic issues you will need to tackle

const selectChoose = e => {
  const tgt = e.target;
  let text = tgt.innerText,
    select = tgt.closest('.partner__select'),
    currentText = select.querySelector('.select__current');
  currentText.innerText = text;
  select.classList.remove('is-active');
};
const selectToggle = e => e.target.parentElement.classList.toggle('is-active');

window.addEventListener('load', function() {
  const container = document.getElementById('container');
  container.addEventListener('click', e => {
    const tgt = e.target.closest('.select');
    if (tgt) {
      const path = tgt.dataset.path;
      document.querySelectorAll('.item', ).forEach(tabContent => tabContent.classList.remove('block-active'))
      document.querySelectorAll(`[data-target="${path}"]`).forEach(tabsTarget => tabsTarget.classList.add('block-active'))
    }
  })
  const tabContainer = document.getElementById('tabContainer');
  //*** tabs active
  tabContainer.addEventListener('click', e => {
    const tgt = e.target.closest('button');
    if (tgt) {
      tabContainer.querySelectorAll('.active__tab').forEach(tab => tabclassList.remove('active__tab'))
      tgt.classList.add('active__tab')
    }
  }) const selContainer = document.getElementById('selectContainer');
  selContainer.addEventListener('click', e => {
    const tgt = e.target;
    if (tgt.classList.contains('select__header')) selectToggle(e);
    else if (tgt.classList.contains('select__item')) selectChoose(e)
  })
})