Показать/скрыть по одному элементу за раз

Я использую этот скрипт для отображения/скрытия контента. Однако как я могу закрыть открытые элементы при их открытии? Я пробовал что-то вроде этого, но это работает неправильно:

// Get siblings
var contentSiblings = document.querySelectorAll('.content');

// close them before opening new one
if (contentSiblings) {
        contentSiblings.forEach((elem) => {
                if (elem.classList.contains('is-visible')) {
                        hide(elem);
                }
        });
}

// Show/hide filter content
var show = function (elem) {
    elem.classList.add('is-visible');
};

// Hide an element
var hide = function (elem) {
    elem.classList.remove('is-visible');
};

// Toggle element visibility
var toggle = function (elem) {

    // If the element is visible, hide it
    if (elem.classList.contains('is-visible')) {
        hide(elem);
        return;
    }

    // Otherwise, show it
    show(elem);
};

// Listen for click events
document.addEventListener('click', function (event) {

    // Make sure clicked element is our toggle
    if (!event.target.classList.contains('btn')) return;

    // Prevent default link behavior
    event.preventDefault();

    // Get the selected content
    var content = document.querySelector(event.target.hash);
    if (!content) return;

    // Toggle the content
    toggle(content);

}, false);
.content {
    display: none;
    opacity: 0;
    transition: opacity .15s linear;
}

.content.is-visible {
    display: block;
    opacity: 1;
}
<a class = "btn" id = "btn-one" href = "#one">Button one</a>
<a class = "btn" id = "btn-two" href = "#two">Button two</a>
<div class = "content" id = "one">Content one</div>
<div class = "content" id = "two">Content two</div>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
55
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вероятно, простым подходом было бы всегда скрывать все элементы «контента» перед их отображением. Например, функция show может сначала скрыть все элементы, а затем показать указанный элемент:

// Show/hide filter content
var show = function (elem) {
    // Hide all others first
    document.querySelectorAll('.content').forEach(hide);

    elem.classList.add('is-visible');
};

// Hide an element
var hide = function (elem) {
    elem.classList.remove('is-visible');
};

// Toggle element visibility
var toggle = function (elem) {

    // If the element is visible, hide it
    if (elem.classList.contains('is-visible')) {
        hide(elem);
        return;
    }

    // Otherwise, show it
    show(elem);
};

// Listen for click events
document.addEventListener('click', function (event) {

    // Make sure clicked element is our toggle
    if (!event.target.classList.contains('btn')) return;

    // Prevent default link behavior
    event.preventDefault();

    // Get the selected content
    var content = document.querySelector(event.target.hash);
    if (!content) return;

    // Toggle the content
    toggle(content);

}, false);
.content {
    display: none;
    opacity: 0;
    transition: opacity .15s linear;
}

.content.is-visible {
    display: block;
    opacity: 1;
}
<a class = "btn" id = "btn-one" href = "#one">Button one</a>
<a class = "btn" id = "btn-two" href = "#two">Button two</a>
<div class = "content" id = "one">Content one</div>
<div class = "content" id = "two">Content two</div>
Ответ принят как подходящий

Вы можете добавить функцию hideAllElements, чтобы скрыть все видимые элементы перед отображением содержимого:

// Show/hide filter content
function show(elem) {
    hideAllElements()
    
    elem.classList.add('is-visible');
};

// Hide an element
function hide (elem) {
    elem.classList.remove('is-visible');
};

// Hide all elements
function hideAllElements (elem) {
    const visibleElements = document.querySelectorAll('.is-visible');
    for (const element of visibleElements) {
        element.classList.remove('is-visible');
    }
};

// Toggle element visibility
function toggle (elem) {

    // If the element is visible, hide it
    if (elem.classList.contains('is-visible')) {
        hide(elem);
        return;
    }

    // Otherwise, show it
    show(elem);
};

// Listen for click events
document.addEventListener('click', function (event) {
    
    // Make sure clicked element is our toggle
    if (!event.target.classList.contains('btn')) return;

    // Prevent default link behavior
    event.preventDefault();

    // Get the selected content
    const content = document.querySelector(event.target.hash);
    if (!content) return;

    // Toggle the content
    toggle(content);

}, false);
.content {
    display: none;
    opacity: 0;
    transition: opacity .15s linear;
}

.content.is-visible {
    display: block;
    opacity: 1;
}
<a class = "btn" id = "btn-one" href = "#one">Button one</a>
<a class = "btn" id = "btn-two" href = "#two">Button two</a>
<div class = "content" id = "one">Content one</div>
<div class = "content" id = "two">Content two</div>

Кстати, если вы даете своим функциям описательные имена, комментарии больше не нужны.

Спасибо за замечание, я исправил.

André 16.08.2024 14:03

Именно, большое спасибо.

Meek 16.08.2024 14:08

вы также можете сделать:

document.body.addEventListener('click', e =>
  {
  if (!e.target.matches('.btn')) return;
  
  if ( document.body.className === e.target.id )
    document.body.className = '';
  else  
    document.body.className = e.target.id;
  })
.content {
  display: none;
  opacity: 0;
  transition: opacity .15s linear;
}

body.btn-one #one.content ,
body.btn-two #two.content { 
  display: block;
  opacity: 1;
  }
<a class = "btn" id = "btn-one" href = "#">Button one</a>
<a class = "btn" id = "btn-two" href = "#">Button two</a>
<div class = "content" id = "one">Content one</div>
<div class = "content" id = "two">Content two</div>

С небольшим количеством CSS; гибкий макет , комбинатор следующего уровня и :has(), вы можете показывать и скрывать элементы с помощью переключателей.

section {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

section label {
  order: 1;
  display: inline-block;
  align-self: start;
}

section label:has(input:checked) {
  background: PowderBlue;
}

section label:has(input:checked)+div {
  display: block;
}

section input {
  display: none;
}

section div {
  order: 2;
  display: none;
  width: 100%;
  border: solid black thin;
  min-height: 5em;
}
<section>
  <label><input type = "radio" name = "tab" checked>Button one</label>
  <div class = "content">Content one</div>
  <label><input type = "radio" name = "tab">Button two</label>
  <div class = "content">Content two</div>
</section>

Другие вопросы по теме

Невозможно выровнять нижнюю границу ввода и текстовую область внутри таблицы div
Отображение таблицы с текстом <p>
Как я могу зафиксировать объект HTML при прокрутке вправо, но позволить ему исчезнуть из поля зрения при прокрутке вниз?
Чтение переменной из файла через javascript в html-файле (на стороне клиента)
Наверняка есть более простой способ сделать это? HTML, CSS, JS
Нужна помощь в анализе HTML-разметки с помощью CSVHelper через мой .NET API
Есть ли только способ CSS выбрать последний вложенный элемент по имени класса?
Проблемы доступности тегов span/mark, вложенных в абзацы
Кнопка воспроизведения звука запускает фантомный второй щелчок, когда currentTime изменяется программно, предотвращая воспроизведение
CSS и JavaScript не применяются правильно после переноса содержимого HTML в компонент приложения Angular из-за проблем с инкапсуляцией просмотра и порядком загрузки скриптов