Проверить, не содержит ли элемент содержимого, является ли прозрачный контейнер пустым

#javascript #html #css

#javascript #HTML #css

Вопрос:

Мне нужно проверить, не содержит ли HTML-элемент (подойдет любой элемент) содержимого. Под содержимым я не имею в виду текстовое содержимое или любые другие элементы HTML, потому что это уже задано. Я имею в виду, хочу проверить, является ли это просто пустым элементом. Например: абзац, содержащий ссылку, которая содержит текст, если ссылка скрыта, абзац остается пустым

Если я скрою ссылку, останется только элемент paragraph, который теперь пуст. В нем нет никаких стилей, так что это просто прозрачный контейнер с полями / отступами / чем угодно, но без других визуальных стилей. Есть ли способ обнаружить это в Javascript? Подойдет любая странная особенность браузера. Уродливые решения тоже допустимы.

Комментарии:

1. Это кажется довольно сложной проблемой; у вас может возникнуть любое из множества взаимодействий, например, visibility CSS, делают ли «визуальные» стили при наведении курсора мыши элемент непустым? Возможно, вы захотите рассказать нам, что вы на самом деле пытаетесь здесь сделать или почему вас волнует эта ситуация. Возможно, вам наплевать на эти элементы, возможно, вы захотите, чтобы они были рядом, или, возможно, сможете просто заставить их родителей исчезнуть.

2. …и вы не хотите использовать библиотеку, подобную jQuery?

Ответ №1:

Вы хотите рекурсивно обойти дочерние узлы вашего элемента и проверить их, чтобы увидеть, все ли они пустые. Логика рекурсивного перемещения не сложна. На самом деле все зависит от того, как вы определяете пустой элемент:

Отображение: отсутствует
Или видимость: скрыта
Или все выключено следующие критерии верны:

  • Текст
    • Нет
    • или только пробел
    • или цвет текста прозрачный
    • или цвет текста совпадает с цветом фона родительского элемента
  • Фон
    • Прозрачный
    • Соответствует родительскому
  • Граница
    • Стиль: отсутствует
    • или ширина 0px
    • или цвет прозрачный
    • или цвет соответствует родительскому фону
  • Тег
    • Не <img />
  • Дочерние элементы
    • Нет
    • или все удовлетворяют вышеуказанным критериям

Итак, ваша рекурсивная функция будет выглядеть примерно так:

 if (!window.getComputedStyle)
{
    window.getComputedStyle = function(el)
    {
        return el.currentStyle || {};
    };
}
function isElementBlank(el)
{
    var style = window.getComputedStyle ? getComputedStyle(el, null) : el.currentStyle;
    if (style.display == "none" || style.visibility == "hidden")
    {
        return true;
    }
    if (el.tagName.toLowerCase() == "img")
    {
        return false;
    }
    var parentBG = "transparent";
    for (var parent = el.parentNode; parent; parent = parent.parentNode)
    {
        var parStyle = getComputedStyle(parent, null);
        if (parStyle.backgroundColor != "transparent")
        {
            parentBG = parStyle.backgroundColor;
            break;
        }
    }
    if (style.backgroundColor != "transparent" amp;amp; style.backgroundColor != parentBG)
    {
        return false;
    }
    if (style.borderColor != "transparent" amp;amp; 
        style.borderColor != parentBG amp;amp; 
        parseInt(style.borderWidth) > 0 amp;amp; 
        style.borderStyle != "none")
    {
        return false;
    }
    for (var i = 0; i < el.childNodes.length; i  )
    {
        var child = el.childNodes[i];
        if (child.nodeType == 3)
        {
            if (/S/.test(child.nodeValue) amp;amp; 
                style.color != parentBG amp;amp; 
                style.color != "transparent")
            {
                return false;
            }
        }
        else if (!isElementBlank(child))
        {
            return false;
        }
    }
    return true;
}
  

Я не тестировал это, но, по крайней мере, это начало.

Ответ №2:

Вы могли бы использовать метод, при котором вы удаляете весь HTML, а затем обрезаете результат.

Если результатом является пустая строка, то видимого текста нет.

Это не приведет к обнаружению div с высотой и цветом фона, хотя, если вам нужно такое обнаружение, вам также нужно будет просмотреть поддерево while в поисках элементов с любым видимым css, что потребует очень подробного кода.

Ответ №3:

Чтобы обнаружить теги с пустым содержимым, вы можете перебирать все дочерние узлы каждого узла и искать непустые текстовые узлы. Если найден непустой текстовый узел, тест пройден, в противном случае узел является пустым от содержимого. Я выполнил тест, который, похоже, отлично работает в Firefox:

 <div id="container">
<div>Text <span>buzz</span>
</div>
<p><a href="#">Hello</a>
</p>
</div>

<script>
var all = document.getElementsByTagName('body')[0].getElementsByTagName('*');


allNodes: for (var i = 0, l = all.length; i < l; i  ) {

  // for each childNode of every node...
  for (var ii = 0, sub = all[i].childNodes, ll = sub.length; ii < ll; ii  ) {

    // is it a text node?
    if (sub[ii].nodeType == 3) {
      // Is the text node NOT empty?
      if (/[^s] /.test(sub[ii].nodeValue)) {
        continue allNodes;
      }

    }

  }

  console.log(all[i], ' fails');

}
</script>
  

Результат теста:

 <div id="container"> fails
<p> fails
  

Комментарии:

1. Просто любопытно, почему вы используете document.getElementsByTagName('body')[0] вместо document.body ?

2. вероятно, потому что Javascript не является моим основным языком: P