скрыть все элементы до определенного элемента
с jQuery и имея контейнер-обертку вокруг содержимого в пределах каждого h1, я мог бы скрыть их.
но без контейнера-контейнера, как это сделать?
какой лучший способ сделать что-то, что просто скрывает все до следующего h1?
Я не использую jQuery, потому что это часть приложения React.
h1 {
border-bottom: solid 1px #000;
}
span {
float: right;
}
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>
<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>
Ответы
Ответ 1
Я могу сделать это с помощью этого css. Просто добавьте класс "start" в h1, из которого вы хотите начать свертывание элементов и класса "вверх" до h1, до которого вы хотите, чтобы элементы разрушались.
CSS
.start ~ *:not(h1) {
display: none;
}
.upto ~ * {
display: block !important;
}
HTML
<h1 class='start'>h1 <span>x</span></h1>
...
<h1 class ='upto'>h1-1 <span>x</span></h1>
Здесь все элементы между началом и вверх будут скрыты. Вы можете получить эффект коллапса, добавив соответственно классы "старт" и "вверх"
Добавление класса к следующему h1 может быть также выполнено с помощью Javascript. Итак, у меня может быть простая js-функция, которая устанавливает "start" и "upto".
function collapse(startHeaderNumber, uptoHeaderNumber) {
var allHeaders = document.getElementsByTagName("h1");
var totalNoOfHeaders = allHeaders.length;
if (startHeaderNumber > totalNoOfHeaders) {
return;
}
var startHeader = allHeaders[startHeaderNumber - 1];
startHeader.classList.add('start');
if (uptoHeaderNumber <= totalNoOfHeaders) {
var uptoHeader = allHeaders[uptoHeaderNumber - 1];
uptoHeader.classList.add('upto');
}
}
И вы можете просто называть это как
collapse(1 ,2)
И это разрушит все элементы между заголовками 1 и 2. Или вы можете называть это так,
collapse(1)
который скроет все элементы из первого заголовка до последнего.
Для полной демонстрации, пожалуйста, см. Эту скрипку
Ответ 2
похоже, что вы хотите что-то подобное функции jQuery nextUntil()
. Вот хорошее руководство для этого в vanilla js. Код выглядит следующим образом:
var nextUntil = function (elem, selector, filter) {
// Setup siblings array
var siblings = [];
// Get the next sibling element
elem = elem.nextElementSibling;
// As long as a sibling exists
while (elem) {
// If we've reached our match, bail
if (elem.matches(selector)) break;
// If filtering by a selector, check if the sibling matches
if (filter && !elem.matches(filter)) {
elem = elem.nextElementSibling;
continue;
}
// Otherwise, push it to the siblings array
siblings.push(elem);
// Get the next sibling element
elem = elem.nextElementSibling;
}
return siblings;
};
Я, очевидно, не знаю контекста, стоящего за тем, что вы делаете, но я считаю, что это лучше, изменяя HTML. Это потенциально может позволить вам сделать некоторые из них с помощью только селекторов css nth child
Ответ 3
Вы можете использовать previousElementSibling рекурсивно, чтобы получить всех братьев и сестер ваших элементов h1
. Вот рабочий пример с использованием previousElementSibling
:
const elems = document.getElementsByTagName('h1');
for (let i = 0; i < elems.length; i++) hidePrev(elems[i]);
function hidePrev(elem)
{
var pre = elem.previousElementSibling;
if (!pre) return;
pre.style.display = 'none';
hidePrev(pre);
}
h1 {
border-bottom: solid 1px #000;
}
span {
float: right;
}
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>
<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>
Ответ 4
Я прокомментировал код. И я надеюсь, вы понимаете, что здесь происходит, но если нет, просто напишите ниже.
function hideUntilNextSiblingWithSameName(elementName) {
/*
* @Param {elementName: String}
* Hide all elements until the next one with the same name
*/
var trackH1 = 0,
element = document.getElementsByTagName(elementName)[0],
node = element.parentNode.firstChild;
do {
// Keep truck of element with the same name.
if (node.tagName === element.tagName) trackH1 += 1;
// Stop if catch element with same name
if (trackH1 == 2) break;
// Do not hide link, script, style and text node
if (node.nodeType === 3 || node.tagName === "LINK" || node.tagName === "SCRIPT" || node.tagName === "STYLE") continue;
// Hide element
else {
node.style.visibility = "hidden";
}
} while (node = node.nextSibling)
}
hideUntilNextSiblingWithSameName("h1")
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>
<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>
<link rel="stylesheet" href="">
<script></script>
<style></style>
Ответ 5
Вы можете сделать это проще, например, следующим образом. Идея состоит в том, чтобы найти непосредственного родителя узлов, body
в этом случае и найти всех его непосредственных потомков.
Затем начните удаление элементов, пока мы не найдем нужный элемент. В этом примере я попытался скрыть элементы, но вы можете просто изменить код, чтобы удалить их.
Ниже приведена рабочая демонстрация:
const elems = document.querySelectorAll('body > *');
const elemBefore = document.querySelectorAll('h1')[1];
for (let i = 0; i < elems.length; i++) {
let elem = elems[i];
if (elem === elemBefore) {
break;
}
elem.style.display = 'none';
}
h1 {
border-bottom: solid 1px #000;
}
span {
float: right;
}
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>
<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>
Ответ 6
Возможно, вы можете использовать трюк и скрыть
за h1 и h2 через css:
const selector = document.querySelectorAll('h1, h2');
const clickH = function (event) {
const h = event.target;
const attr = h.getAttribute('class');
if (attr === '') {
h.setAttribute('class', 'closed')
return undefined;
}
h.setAttribute('class', '')
}
selector.forEach((h) => {
h.setAttribute('class', 'closed')
h.addEventListener('click', clickH);
})
h1, h2 {
position: relative;
border-bottom: solid 1px #000;
background-color: #fff;
height: 50px;
border-bottom: solid 1px #000;
display: block;
z-index: 2;
margin-bottom: 0;
}
.closed {
margin-bottom: -50px;
}
p {
height: 30px;
}
span {
float: right;
}
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>
<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>