как я могу перебирать элементы div внутри одного div, и если все они имеют одинаковое значение display («none»), отображать сообщение? Я только учусь и мне нужно использовать это на сто процентов jQuery
<div class = "test1">
<div class = "test2" style = "display:none">
</div>
<div class = "test2" style = "display:none">
</div>
<div class = "test2" style = "display:none">
</div>
<div class = "test2" style = "display:none">
</div>
</div>
Я попробовал это, используя jQuery.each
jQuery('.test1 > .test2').each(function(){
if (jQuery(this).css('display') == 'none'){
jQuery('.test_message').text('nothing');
}
})
Если вы поддерживаете jQuery, вы также поддерживаете обычный JS. В обычном JS это будет if ([...document.querySelectorAll( 'div > div' )].filter(v => v.style.display !== 'none').length === 0) document.querySelector( '.test-message' ).textContent = "Nothing is displayed";
или что-то в этом роде.
Кроме того, если вы только начинаете, я бы посоветовал вам переосмыслить свою цель использования «стопроцентного jQuery». jQuery была фантастической библиотекой, но есть и другие библиотеки и подходы, более подходящие для современной разработки. Лучше потратить время на изучение сначала простого JS, а затем фреймворка, такого как React, Angular и т. д.
кстати, на самом деле это самый короткий путь: [...document.querySelectorAll('.test1 > .test2')].every(el => el.style.display === 'none');
узнать, соответствуют ли все эти элементы div этому условию или нет (истина/ложь). Начиная с ES6, javascript стал чем-то гораздо более мощным, чем может предложить jquery... поэтому вам следует оставить его позади (а это было почти 10 лет назад!)
Ваш селектор jQuery('.test_message')
не найдет ни одного элемента на основе HTML, которым вы поделились.
Проблема с вашей текущей логикой заключается в том, что вы тестируете каждый .test2
div индивидуально, а затем выводите сообщение на основе этого единственного элемента. Вместо этого вам нужно сначала проверить все элементы, а затем при необходимости вывести сообщение.
Для этого вы можете сохранить флаг, определяющий состояние элементов div, а затем изменить этот флаг, если какой-либо из них не соответствует этому состоянию. Вот рабочий пример:
jQuery($ => {
let allHidden = true;
$('.test1 > .test2').each(function() {
if ($(this).css('display') !== 'none') {
allHidden = false;
return;
}
})
if (allHidden) {
$('.test_message').text('nothing');
}
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class = "test1">
<div class = "test2" style = "display: none"></div>
<div class = "test2" style = "display: none"></div>
<div class = "test2" style = "display: none"></div>
<div class = "test2" style = "display: none"></div>
</div>
<div class = "test_message"></div>
Это также можно было бы сделать без явного цикла, используя селектор :visible
:
jQuery($ => {
if (!$('.test1 > .test2:visible').length) {
$('.test_message').text('nothing');
}
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class = "test1">
<div class = "test2" style = "display: none"></div>
<div class = "test2" style = "display: none"></div>
<div class = "test2" style = "display: none"></div>
<div class = "test2" style = "display: none"></div>
</div>
<div class = "test_message"></div>
Наконец, обратите внимание, что в приведенных выше примерах я использовал сокращенный обработчик document.ready
, который является псевдонимом переменной $
. Это означает, что вы можете безопасно использовать префикс $
вместо подробного ключевого слова jQuery
, не затрагивая при этом другие скрипты, которые также могут использовать $
.
Самый простой способ — изменить свою логику. Вы можете выбрать все элементы, у которых нет атрибута style = "display:none"
, и проверить длину списка узлов с помощью !NodeList.length
. Если это утверждение истинно, то все элементы будут иметь этот атрибут, поскольку ничего не возвращается:
const visibleChildElements = document.querySelectorAll('.test1 > .test2:not([style* = "display:none"])');
if (!visibleChildElements.length) {
console.info('all child elements are hidden');
} else {
console.clear();
}
<div class = "test1">
<div class = "test2" style = "display:none"></div>
<div class = "test2" style = "display:none"></div>
<div class = "test2" style = "display:none"></div>
<div class = "test2" style = "display:none"></div>
</div>
В качестве примечания: как уже говорилось, вам не следует сосредотачиваться на 100% jQuery в 2024 году. Даже Bootstrap-5 избавился от jQuery 2 года назад, поскольку это больше не имеет смысла. Он «устарел», поскольку простой Javascript догнал функциональность.
Если вы хотите выбрать все дочерние элементы в JS, вы также можете использовать querySelector('element').children
Просто заметьте: это будет работать, только если вы установите style = "display:none"
непосредственно в своем HTML. Если вы поместите CSS во внешнюю таблицу стилей или добавите какие-либо другие свойства CSS в HTML, это будет нарушено, но это, безусловно, самый простой подход в простом JS.
Некоторые другие решения потерпят неудачу, если значение отображения установлено во внешнем CSS.
Вместо этого используйте checkVisibility
Также обратите внимание, что я использую более читаемый Array.from вместо оператора распространения [...collection], чтобы получить методы массива, доступные в коллекции.
const allHidden = Array.from(document.querySelectorAll('.test1 > .test2'))
.every(el => !el.checkVisibility());
document.getElementById('testMessage').textContent = allHidden ? 'all child elements are hidden' : 'some child elements are visible';
.text3 { display: none; }
<div class = "test1">
<div class = "test2" style = "display:none"></div>
<div class = "test2" style = "display:none"></div>
<div class = "test2 text3"></div>
<div class = "test2" style = "display:none"></div>
</div>
<span id = "testMessage"></span>
Если вы ДОЛЖНЫ использовать jQuery, попробуйте
const $test2Elements = $('.test1 > .test2')
const allHidden = $test2Elements
.map(function() { return $(this).is(":visible") }) // jQuery map
.get() // get the array
.every(e => !e); // look at each and return if true was found or run through all false
$("#testMessage").text(allHidden ? 'all child elements are hidden' : 'some child elements are visible');
.text3 { display: none; }
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class = "test1">
<div class = "test2" style = "display:none"></div>
<div class = "test2" style = "display:none"></div>
<div class = "test2 text3"></div>
<div class = "test2" style = "display:none"></div>
</div>
<span id = "testMessage"></span>
jQuery.each()
должно работать. Пожалуйста, покажите, что вы пробовали, чтобы мы могли помочь вам отладить это.