#javascript #html #css
#javascript #HTML #css
Вопрос:
У меня есть список с элементами списка, стилизованными под встроенный блок. При нажатии на каждый элемент списка я хочу:
- изменить отображение:inline-block; на отображение:block; элемента списка,
- изменить отображение: нет; на отображение: блок; дочернего div
- Переместите выбранный элемент в начало списка
- Если щелкнуть более одного элемента, все они делают то же самое и перемещаются вверх по списку вместе.
При повторном нажатии (переключении) я хочу, чтобы список изменил вышеуказанное (изменил отображение и вернулся в исходное положение).
До сих пор мне удалось только изменить отображение элемента списка на block, но я не могу настроить таргетинг на дочерний div с помощью element.children или переместить элемент списка наверх.
function showCombo(ID) {
var x = document.getElementById(ID);
var xshow = getComputedStyle(x, null).display; //
if (xshow == "inline-block") {
x.style.display = "block";
} else {
x.style.display = "inline-block";
}
}
li {
display: inline-block;
border: 1px solid black;
border-radius: 3px;
cursor: pointer;
}
li div {
display: none;
}
<ul>
<li ID="1" onclick="showCombo(1)">
<p>Title 1</p>
<div>Show content</div>
</li>
<li ID="2" onclick="showCombo(2)">
<p>Title 2</p>
<div>Show content</div>
</li>
<li ID="3" onclick="showCombo(3)">
<p>Title 3</p>
<div>Show content</div>
</li>
<li ID="4" onclick="showCombo(4)">
<p>Title 4</p>
<div>Show content</div>
</li>
<li ID="5" onclick="showCombo(5)">
<p>Title 5</p>
<div>Show content</div>
</li>
</ul>
Ответ №1:
Переключите класс со всеми свойствами, и это было бы проще:
function showCombo(x) {
x.classList.toggle('active')
}
li {
border: 1px solid black;
margin:2px;
border-radius: 3px;
cursor: pointer;
}
li div {
display: none;
}
ul {
display:flex;
flex-wrap:wrap;
list-style:none;
}
li.active {
width:100%; /* full width*/
order:-1; /* move to the top */
}
li.active div {
display:block; /* show div */
}
<ul>
<li onclick="showCombo(this)">
<p>Title 1</p>
<div>Show content</div>
</li>
<li onclick="showCombo(this)">
<p>Title 2</p>
<div>Show content</div>
</li>
<li onclick="showCombo(this)">
<p>Title 3</p>
<div>Show content</div>
</li>
<li onclick="showCombo(this)">
<p>Title 4</p>
<div>Show content</div>
</li>
<li onclick="showCombo(this)">
<p>Title 5</p>
<div>Show content</div>
</li>
</ul>
Комментарии:
1. Спасибо! Это впечатляюще просто. Усложнит ли ситуацию, если первый элемент списка откроется в своем собственном месте, не перемещаясь наверх, но если щелкнуть два или более, они оба переместятся наверх?
2. @suverenia да, это сделало бы сценарий немного сложным. Возможно, мне потребуется добавить больше JS для обработки этого
3. Хорошо, я все равно доволен этим! Можно ли легко закрыть и открыть все?
4. @suverenia да, вы можете переместить
active
класс в ul и переключить его там и немного изменить CSS, чтобы настроить его какul.active li
5. Хорошо, спасибо. Однако это вызывает у меня проблемы, поскольку дочерний div содержит ссылки, изображения и поля ввода, которые нельзя использовать.
Ответ №2:
Я создал вашу идею, используя javascript с большим упором на нее, но вы можете использовать order
в css, как в предыдущем ответе, это будет проще, если у вас есть вопрос, задайте мне, и если вы хотите немного отредактировать, скажите мне, я добавлю ссылки на объяснения некоторых событий, функций, которые я использовалих в моем коде javascript на случай, если вы их не знаете
var li = document.getElementsByClassName("li"),
ul = document.getElementById("ul");
for (let i = 0; i < li.length; i = i 1) {
li[i].setAttribute("index", i); // Create attribute named index and its value will be the i, this is to know the index of the li, we need it when clicked on it again
li[i].setAttribute("firstclick", "yes"); // This is to know if we clicked at it firsttime or secondtime toggle
li[i].onclick = function () {
if (this.getAttribute("firstclick") == "yes") {
this.setAttribute("firstclick", "no"); // Change it to no to when clicking it once again read the second case
ul.prepend(this); // Put the clicked li at the top of the li, prepend means to put it the first element
this.classList.add("displayBlock") // add the class displayBlock check it in the css it contains display: block
this.getElementsByClassName("content")[0].classList.add("displayBlock"); // Add the displayBlock to the div inside the clicked li to show
} else {
this.setAttribute("firstclick", "yes"); // Change it to yes to when clicking it once again read the first case
ul.insertBefore(this, li[parseInt(this.getAttribute("index")) 1]) // Insert It to its original position
this.classList.remove("displayBlock"); // Remove the display block class
this.getElementsByClassName("content")[0].classList.remove("displayBlock"); // Remove the display block class
}
}
}
li {
display: inline-block;
border: 1px solid black;
border-radius: 3px;
cursor: pointer;
}
li div {
display: none;
}
.displayBlock {
display: block;
}
<ul id="ul">
<li class="li" >
<p>Title 1</p>
<div class="content">Show content</div>
</li>
<li class="li" >
<p>Title 2</p>
<div class="content">Show content</div>
</li>
<li class="li" >
<p>Title 3</p>
<div class="content">Show content</div>
</li>
<li class="li" >
<p>Title 4</p>
<div class="content">Show content</div>
</li>
<li class="li" >
<p>Title 5</p>
<div class="content">Show content</div>
</li>
</ul>
Комментарии:
1. Привет, Таха. Спасибо. У вашего скрипта есть несколько проблем. 1) если вы развернете все, у вас будет неустойчивое поведение, связанное с полем между элементами, а также с их положением и порядком. 2) В некоторых случаях некоторые элементы списка не перемещаются вверх, а элементы списка застревают сверху и снизу. 3) div не может содержать поле ввода div.
2. Здравствуйте, для пункта 1 вы можете редактировать css, например, добавлять поля, и сейчас это не наша задача, для других пунктов да, вы правы, я могу это решить, но просто используйте порядок в css, как в предыдущем ответе, и это будет лучше и проще, потому что я напишу много новыхстроки в javascript (код будет больше :)). Самое главное, что ваша идея решена, и я пытаюсь ее решить. Хорошего дня :), если у вас есть какие-либо вопросы, просто спросите