#javascript #tabs #toggle
#javascript #вкладки #переключить
Вопрос:
Я пытался создать систему вкладок, в которой вкладки закрываются по щелчку. В тот момент, когда я пытаюсь закрыть открытую вкладку, она просто остается открытой.
В основном, когда я нажимаю на вкладку, вкладка открывается, и когда я нажимаю на ту же самую открытую вкладку, вкладка должна закрыться. Это то, чего я пытался достичь.
Пробовал использовать метод toggle() для включения и выключения class .active на целевой вкладке следующим образом:
this.classList.toggle("active");
Однако, похоже, это ничего не дает, поскольку выбранная вкладка всегда остается открытой.
Я считаю, что это очень просто сделать, но я просто не могу в этом разобраться.
Я буду признателен за помощь. Приветствия!
const tabs = document.querySelectorAll(".tab");
const tabContents = document.querySelectorAll(".tab-content");
for (let i = 0; i < tabs.length; i ) {
const tab = tabs[i];
tab.addEventListener("click", switchClass);
}
function switchClass() {
for (let i = 0; i < tabs.length; i ) {
const tab = tabs[i];
tab.classList.remove("active");
}
for (let i = 0; i < tabContents.length; i ) {
const tabContent = tabContents[i];
tabContent.classList.remove("show-content");
}
this.classList.toggle("active");
const tabDataAttribute = this.getAttribute("data-content");
document
.querySelector(`.tab-content[data-content="${tabDataAttribute}"]`)
.classList.add("show-content");
}
ul {
margin: 0;
padding: 0;
}
.tab {
display: inline-block;
border: 1px solid lightgrey;
padding: 10px;
cursor: pointer;
}
.active {
background: lightgrey;
}
.tab-content {
display: none;
padding: 10px;
}
.show-content {
display: block;
background: lightgray;
}
<ul>
<li class="tab" data-content="tab1">Tab 1</li>
<li class="tab" data-content="tab2">Tab 2</li>
<li class="tab" data-content="tab3">Tab 3</li>
</ul>
<div class="tab-content" data-content="tab1">1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
<div class="tab-content" data-content="tab2">2. Vivamus iaculis est in sapien congue, ac condimentum.</div>
<div class="tab-content" data-content="tab3">3. Phasellus aliquam orci neque, non varius quam gravida vel.</div>
Комментарии:
1. Кажется, здесь все работает просто отлично.
2. Когда я нажимаю на открытую вкладку, она не закрывается.
3. Вы пробовали это прямо здесь, в Stack Overflow? Он работает просто отлично.
4. Например, нажмите на вкладку 1. Он станет активным, верно? Теперь нажмите на ту же вкладку, чтобы закрыть ее. Он останется открытым. В этом проблема. Я хочу иметь возможность щелкнуть по открытой вкладке и закрыть ее.
5. Я вижу. Проверьте мой ответ на решение.
Ответ №1:
Вы не можете использовать .toggle()
, потому что первое, что вы делаете при обратном вызове, это удаляете active
класс из всех элементов (что правильно), поэтому переключение просто снова включит его (как в текущем случае).
Вместо этого вы должны отслеживать, совпадает ли текущая выбранная вкладка с последней выбранной вкладкой, и действовать соответствующим образом.
В приведенном ниже коде я также объединил циклы и использую синтаксис .forEach()
цикла вместо цикла подсчета, что .forEach()
проще.
И, если у вас не было какой-либо другой необходимости в этом, вам больше не нужен data-content
атрибут.
const tabs = Array.from(document.querySelectorAll(".tab"));
const tabContents = document.querySelectorAll(".tab-content");
// Use the Array.forEach() syntax for looping as it eliminates
// the need for setting up and managing indexes.
tabs.forEach(function(tab){
tab.addEventListener("click", switchClass);
});
let priorActive = null; // Will keep track of last tab made active
function switchClass() {
// Loop over the tabs
tabs.forEach(function(tab, index){
tab.classList.remove("active"); // Remove active
tabContents[index].classList.add("hidden"); // Hide content with corresponding index
});
// Can't use toggle because prior loop just removed the classes, so toggle
// will always add them back. Instead, you must explicitly turn on or off
// based on current situation.
if(priorActive === this){
this.classList.remove("active");
tabContents[tabs.indexOf(this)].classList.add("hidden");
priorActive = null;
} else {
this.classList.add("active");
tabContents[tabs.indexOf(this)].classList.remove("hidden");
priorActive = this;
}
}
ul {
margin: 0;
padding: 0;
}
.tab {
display: inline-block;
border: 1px solid lightgrey;
padding: 10px;
cursor: pointer;
}
.active {
background: lightgrey;
}
.tab-content {
background: lightgray;
padding: 10px;
}
/* Tab content will have this by default */
.hidden {
display:none;
}
<ul>
<li class="tab">Tab 1</li>
<li class="tab">Tab 2</li>
<li class="tab">Tab 3</li>
</ul>
<div class="tab-content hidden">1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
<div class="tab-content hidden">2. Vivamus iaculis est in sapien congue, ac condimentum.</div>
<div class="tab-content hidden">3. Phasellus aliquam orci neque, non varius quam gravida vel.</div>
Ответ №2:
сокращенный способ :
вы можете писать действия только внутри container
затем разделите номер вашего элемента (со loop
счетчиком) по цели события ( this.target
) каждого клика..
наконец, setAttribute
к кнопке вкладки и их содержимому…
я надеюсь, что это помогло…
let container = document.getElementById("tab-container"); // take container for scoping actions
container.addEventListener("mousedown", (e) => {
this.tab = document.getElementsByClassName("tab"); // current tab button , clicked..!
this.content = document.getElementsByClassName("tab-content"); // content of current tab clicked..
for (let w = 0; w < this.tab.length; w ) {
// e.button == 0 is equal to left click by client mouse...
// e.target take the target and return true
e.button == 0 ? this.target = this.tab[w].contains(e.target) : false
if(this.target){
this.tab[w].setAttribute("data-tab",true); //set Attr..
this.content[w].setAttribute("data-content",true); //set Attr..
}else{
this.tab[w].removeAttribute("data-tab"); //remove Attr..
this.content[w].removeAttribute("data-content"); //remove Attr..
}
}
})
ul#tab-container{
margin: 0;
max-width: 330px;
background-color: #f3f3f3;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 0;
}
.tab{
display: inline-block;
cursor: pointer;
padding: 1rem;
text-align: center;
}
.tab[data-tab="true"]{
background-color: #fff;
text-decoration: underline;
text-underline-offset: 1rem;
}
.tab-content{
display:none;
padding: 2rem;
}
.tab-content[data-content="true"]{
display:inline-block;
}
<ul id="tab-container">
<li class="tab" data-tab="true">Tab 1</li>
<li class="tab">Tab 2</li>
<li class="tab">Tab 3</li>
</ul>
<div class="tab-content" data-content="true">1. Lorem ipsum dolor...</div>
<div class="tab-content">2. Vivamus iaculis est...</div>
<div class="tab-content">3. Phasellus aliquam orci...</div>