Табы на чистом JS

133
10 февраля 2022, 08:50

Знаю, что в сети полно примеров, но, простого варианта без излишеств я не увидел, и, изначально это был простой вариант вкл/выкл через onclick. Потом решил добавить класс к текущему элементу. А теперь - чтоб при открывании одного блока, закрывались все остальные. Сейчас это выглядит так:

.block { 
  display: none; 
} 
 
.block.active { 
  display: block; 
} 
 
a.active { 
  color: red; 
}
<a href="javascript:void(0)" class="toggle-1" onclick="event.preventDefault(); document.getElementsByClassName('block b1')[0].classList.toggle('active');  document.getElementsByClassName('toggle-1')[0].classList.toggle('active');">One</a> 
<a href="javascript:void(0)" class="toggle-2" onclick="event.preventDefault(); document.getElementsByClassName('block b2')[0].classList.toggle('active');  document.getElementsByClassName('toggle-2')[0].classList.toggle('active');">Two</a> 
<a href="javascript:void(0)" class="toggle-3" onclick="event.preventDefault(); document.getElementsByClassName('block b3')[0].classList.toggle('active');  document.getElementsByClassName('toggle-3')[0].classList.toggle('active');">Three</a> 
 
<div class="block b1">123</div> 
<div class="block b2">456</div> 
<div class="block b3">789</div>

Помогите это дело записать проще. Чтоб при нажатии на ссылку она получала класс .active и такой же класс получал элемент на странице, например .block.b1, а при открывании 2й ссылки, очищались предыдущие классы у других элементов. По аналогии с табами.

Можно отдельным скриптом, если в inline будет слишком муторно.

Спасибо!

Answer 1

Вариант с привязкой к порядку элементов: У каждой кнопки - своя пара, другой блок.

tabs("link", "block"); 
setJsVoid(document.querySelectorAll(".link")); 
 
function tabs(btnClass, blockClass) { 
  var link = document.querySelectorAll("." + btnClass); 
  var tabs = document.querySelectorAll("." + blockClass); 
 
  for (var i = 0; i < link.length; i++) { 
    setClick(i); 
  } 
 
  function setClick(i) { 
    link[i].addEventListener('click', function() { 
      removeClass(link, 'active'); 
      removeClass(tabs, 'active'); 
      // При клике - убрать активный класс со всех кнопок и блоков, 
       
      addClass(link[i], 'active'); 
      addClass(tabs[i], 'active'); 
      // Добавить на нужные элементы. 
    }); 
  } 
} 
 
/**************************/ 
 
function addClass(elems, className) { 
  if (elems instanceof HTMLElement) { 
    elems.classList.add(className); 
    return; 
  } 
 
  for (var i = 0; i < elems.length; i++) { 
    elems[i].classList.add(className); 
  } 
} 
 
function removeClass(elems, className) { 
  if (elems instanceof HTMLElement) { 
    elems.classList.remove(className); 
    return; 
  } 
 
  for (var i = 0; i < elems.length; i++) { 
    elems[i].classList.remove(className); 
  } 
} 
 
function setJsVoid(elems) { 
  for (var i = 0; i < elems.length; i++) { 
    elems[i].setAttribute('href', "javascript:void(0);"); 
  } 
}
.block { display: none; } 
 
.block.active { display: block; } 
.link.active { color: red; }
<a class="link">One</a> 
<a class="link">Two</a> 
<a class="link">Three</a> 
 
<div class="block">111</div> 
<div class="block">222</div> 
<div class="block">333</div>

И с привязкой к конкретным классам:

tabs("link", "block"); 
setJsVoid(document.querySelectorAll(".link")); 
 
function tabs(btnClass, blockClass) { 
  var link = document.querySelectorAll("." + btnClass); 
  var tabs = document.querySelectorAll("." + blockClass); 
 
  for (var i = 0; i < link.length; i++) { 
    setClick(i); 
  } 
 
  function setClick(i) { 
    link[i].addEventListener('click', function() { 
      removeClass(link, 'active'); 
      removeClass(tabs, 'active'); 
       
      var className = this.dataset.open; 
      var blocks = document.querySelectorAll("." + className); 
      // Добавил data-атрибуты в HTML и эти 2 строчки в скрипте. 
       
      addClass(link[i], 'active'); 
      addClass(blocks , 'active'); 
    }); 
  } 
} 
 
/**************************/ 
 
function addClass(elems, className) { 
  if (elems instanceof HTMLElement) { 
    elems.classList.add(className); 
    return; 
  } 
 
  for (var i = 0; i < elems.length; i++) { 
    elems[i].classList.add(className); 
  } 
} 
 
function removeClass(elems, className) { 
  if (elems instanceof HTMLElement) { 
    elems.classList.remove(className); 
    return; 
  } 
 
  for (var i = 0; i < elems.length; i++) { 
    elems[i].classList.remove(className); 
  } 
} 
 
function setJsVoid(elems) { 
  for (var i = 0; i < elems.length; i++) { 
    elems[i].setAttribute('href', "javascript:void(0);"); 
  } 
}
.block { display: none; } 
 
.block.active { display: block; } 
.link.active { color: red; }
<a class="link" data-open="block-1">One</a> 
<a class="link" data-open="block-2">Two</a> 
<a class="link" data-open="block-3">Three</a> 
 
<div class="block block-1">111</div> 
 
<div class="block block-2">222</div> 
<div class="block block-2">222</div> 
 
<div class="block block-3">333</div> 
<div class="block block-3">333</div> 
<div class="block block-3">333</div>

Answer 2

Как-то так...

Тут добавлены стили для навигации со скроллингом, но сам скрипт занимает 5 строчек

<!DOCTYPE html>
<html>
<head>
  <title>Drag and drop</title>
  <style>
    ::-webkit-scrollbar {
        width: 0;
        height: 0;
        background: transparent;
    }
    html {
        -ms-overflow-style: none;
        scrollbar-width: none;
    }
    nav {
      border: 1px solid black;
      overflow-x: scroll !important;
      user-select: none;
    }
    nav>ul {
      display: flex;
      flex-direction: row;
      flex-wrap: nowrap;
      padding-inline-start: 0;
      margin-block-start: 0;
      margin-block-end: 0;
    }
    nav>ul>li {
      list-style-type: none;
      padding: 5px;
      margin: 5px;
    }
    nav>ul>li:not(:first-child) {
      margin-left: -1px;
      border-left: 1px solid black;
    }
    .block {
      padding: 10px;
      background-color: whitesmoke;
      border: 1px solid black;
    }
    .block:nth-child(1)::before { content: "First"; }
    .block:nth-child(2)::before { content: "Second"; }
    .block:nth-child(3)::before { content: "Third"; }
    .block.focus { background-color: cyan; }
  </style>
</head>
<body>
  <nav>
    <ul>
      <li>Link</li>
      <li>Link</li>
      <li>Link</li>
    </ul>
  </nav>
  <main>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </main>
  <script>
    document.querySelectorAll('nav>ul>li').forEach((item, index) => {
      const element = document.querySelector(`main>div:nth-child(${index + 1})`);
      item.addEventListener('mousemove', () => element.classList.add('focus'));
      item.addEventListener('mouseout', () => element.classList.remove('focus'));
    });
  </script>
</body>
</html>
READ ALSO
Div блок вылазит за границы страницы

Div блок вылазит за границы страницы

Доброго времени суток всемИмеется код, в нем по нажатию на кнопку копируется скрытый текст

68
callback функция с циклом for внутри

callback функция с циклом for внутри

Есть следующий код, функция для перебора массива и функция для работы с элементом массива -handler4Которая должна взять строку из массива и сделать...

67
Как проигнорировать знак - в input number

Как проигнорировать знак - в input number

Есть поле input type="number" и кнопка при нажатию на которую данные с инпута, которые обрабатывает php, уходят в бднужно сделать следующее: чтобы при...

65