#javascript #html #css #accordion
Вопрос:
Я пытаюсь сделать вложенные аккордеоны (вы расширяете один, затем внутри вы можете развернуть другой), но по какой-то причине внутренний аккордеон не работает.
Это основано на коде аккордеона школы w3, но я заменил кнопки изображением. Моя логика заключалась в том, что если я скопирую первый аккордеон и переименую его в «аккордеон 1», я могу просто позже назвать аккордеон1, и произойдет то же самое, что и с оригинальным аккордеоном.
Но когда я нажимаю на внутреннюю кнопку аккордеона, ничего не происходит. Я не совсем понимаю, почему это так, поскольку, похоже, это прямая копипаста. Я не уверен, что здесь нужно что-то делать по-другому
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i ) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight "px";
}
});
}
var acc1 = document.getElementsByClassName("accordion1");
var i;
for (i = 0; i < acc1.length; i ) {
acc1[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight "px";
}
});
}
.accordion {
background-image: url(https://i.imgur.com/Jqsaukf.png);
background-repeat: no-repeat;
background-position: 50% 50%;
/* put the height and width of your image here */
height: 50px;
width: 200px;
border: none;
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.accordion:after {
content: '02B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "2212";
}
.accordion1 {
background-image: url(https://i.imgur.com/VXlZ0Ja.png);
background-repeat: no-repeat;
background-position: 50% 50%;
/* put the height and width of your image here */
height: 500px;
width: 200px;
border: none;
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active1,
.accordion1:hover {
background-color: #ccc;
}
.accordion1:after {
content: '02B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active1:after {
content: "2212";
}
.panel {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
<h2>Accordion with symbols</h2>
<p>In this example we have added a "plus" sign to each button. When the user clicks on the button, the "plus" sign is replaced with a "minus" sign.</p>
<button class="accordion"></button>
<div class="panel">
<button class="accordion1"></button>
<div class="panel1">
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<br>
<button class="accordion"></button>
<div class="panel">
<p><img src="https://i.imgur.com/Jqsaukf.png" alt="Italian Trulli"></p>
</div>
<button class="accordion"></button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
РЕДАКТИРОВАТЬ: Я изменил имена переменных, которые я перепутал; т. Е. панель и панель 1, активный и активный 1, и это работает, но я все равно хотел бы знать, есть ли более краткий/эффективный способ сделать это.
Я собираюсь захотеть иметь более 10 аккордеонов с разными изображениями в качестве кнопок, так что этот модуль будет безумно длинным, если не будет какого-то способа его сконденсировать. Может быть, цикл for, который заменяет каждое изображение в массиве аккордеонов? Не уверен, имеет ли это смысл или даже возможно с помощью html/javascript/css.
Ответ №1:
Я привел этот пример того, как вы могли бы это сделать. Главное-концепция зацикливания и то, как вы можете упростить HTML для добавления/удаления нескольких элементов аккордеона. Вы можете гнездиться сколько угодно.
Примечания: Элемент .аккордеон имеет больше смысла, если его назвать .аккордеон-вкладка. Я не делал много стилей CSS, просто для примера. В Javascript я показал, как вы можете извлечь атрибут изображения и использовать его так, как вам заблагорассудится. Вероятно, вы могли бы закодировать многое из этого лучше и эффективнее, но я постарался сделать это быстро и читабельно для людей.
Дайте мне знать, если вам понадобится какая-либо помощь. Благослови тебя Господь!
const acc = document.querySelectorAll(".accordion"); // Get all accordion tab elements
let i;
for (i = 0; i < acc.length; i ) {
const accordion = acc[i];
accordion.setAttribute('data-index', i);
// Add content
const content = accordion.getAttribute('data-content'); // Getting the accordion tab content
const accordionContent = document.createElement("div"); // Create content element
accordionContent.classList.add("accordion-content"); //Add content class
accordionContent.innerHTML = content; // Add HTML
accordion.prepend(accordionContent) // Add to DOM, if you want the nested accordions before the content, you can use append instead of prepend
// Accordion button
const imageData = accordion.getAttribute('data-image') ? accordion.getAttribute('data-image').split('|') : false; // Get image and alt text then split it by the | character in the attribute
const button = document.createElement("button"); // Create a button
button.classList.add("accordion-button"); // Add button class
button.style.backgroundImage = "url('" imageData[0] "')"; // Add background image, you could instead create an image element and add the imageData[0] to the src, but you'd probably need to create your images at the perfect size or add and extract the dimensions in the data-image attribute. Ex: data-image="image1.png|Alt text for image|100px,100px"
button.setAttribute('aria-label', imageData[1]); // Add image alt text
accordion.prepend(button); // Add to DOM
button.onclick = function() {
togglePanel(accordion); // Add button click function, function is below in the code
}
}
function togglePanel(accordion) {
const button = accordion.querySelector('.accordion-button')
const accordionContent = accordion.querySelector('.accordion-content')
// Handle toggling here. I suggest set CSS styles, but you could use javascript to slide it
accordion.classList.toggle('active');
};
/* I used display none and block just for the example. You can do the height transition with CSS or Javascript */
.accordion .accordion,
.accordion .accordion-content {
display: none;
}
.accordion.active>.accordion,
.accordion.active>.accordion-content {
display: block;
}
/* Just for example styling*/
button {
cursor: pointer;
height: 50px;
width: 100%;
}
button:after {
content: ' '
}
.accordion.active > button:after {
content: '-'
}
.accordion-content {
padding: 20px;
width: 100%;
}
.accordion .accordion {
margin-left: 20px;
}
.accordion.active > button {
background: #4169e1;
}
.accordion .accordion.active > button {
background: #a1caf1;
}
.accordion .accordion .accordion.active > button {
background: #a4dded;
}
<!-- Main accordion -->
<div class="accordion"
data-image="image1.png|Alt text for image"
data-content="Accordion 1 text"
>
<!-- Nested accordion -->
<div class="accordion"
data-image="image2.png|Alt text for image"
data-content="Nested accordion 1 content. Image should show below: <img src=amp;quot;https://media.swncdn.com/via/11580-mount-zion-bst.jpgamp;quot; width=amp;quot;300amp;quot;>"
></div>
</div>
<div class="accordion"
data-image="image2.png|Alt text for image"
data-content="Accordion 2 text"
>
<!-- Nested accordion -->
<div class="accordion"
data-image="image2.png|Alt text for image"
data-content="Nested accordion 2 text"
></div>
</div>
<div class="accordion"
data-image="image3.png|Alt text for image"
data-content="Accordion 3 has no nested accordion"
>
</div>
<div class="accordion"
data-image="image2.png|Alt text for image"
data-content="Accordion 2 text"
>
<!-- Nested accordion -->
<div class="accordion"
data-image="image2a.png|Alt text for image"
data-content="Nested accordion 2 text"
>
</div>
<!-- Another nested accordion -->
<div class="accordion"
data-image="image2a.png|Alt text for image"
data-content="Another nested accordion 2 text"
>
<!-- Double nested accordion -->
<div class="accordion"
data-image="image2b.png|Alt text for image"
data-content="Double nested accordion 2 text"
></div>
</div>
</div>
Комментарии:
1. Большое вам спасибо! Этот ответ-именно то, что мне было нужно. Мне любопытно, как вы можете настроить содержимое внутри аккордеона на изображение, а не на текст. У вас есть данные-содержимое=»Вложенный текст аккордеона 1″, так как же вы измените это на изображение?
2. Вы можете поместить что угодно в атрибут содержимого данных, но для изображений вам просто нужно будет использовать «вместо» символа, так как он находится внутри » «. Я отредактировал вырезку, чтобы показать ее.