Вот современное нативное решение JavaScript; который на самом деле очень похож на jQuery от 2010 года. Я адаптировал его из этого ответа для проекта, над которым я работаю, и подумал, что поделюсь им здесь.
document.querySelectorAll("*:empty").forEach((x)=>{x.remove()});
document.querySelectorAll
возвращает NodeList
; по сути, это массив всех узлов DOM, которые соответствуют селектору CSS, указанному в качестве аргумента.
*:empty
- это селектор, который выбирает все элементы (*
означает «любой элемент»), который является пустым (что означает :empty
).
Это выберет любой пустой элемент внутри всего документа , если вы хотите удалить только пустые элементы из определенной части страницы (т.е. только те, которые находятся внутри какого-то элемента div
); Вы можете добавить идентификатор к этому элементу и затем использовать селектор #id *:empty
, что означает любой пустой элемент в элементе с идентификатором id
.
Это почти наверняка то, что вы хотите. Технически некоторые важные теги (например, теги <meta>
, теги <br>
, теги <img>
и т. Д.) Являются "пустыми"; поэтому, не указав область действия, вы в конечном итоге удалите некоторые теги, которые вам, вероятно, небезразличны.
forEach
перебирает каждый элемент в результирующем NodeList
и запускает на нем анонимную функцию (x)=>{x.remove()}
. x
является текущим элементом в списке, и вызов .remove()
для него удаляет этот элемент из DOM.
Надеюсь, это кому-нибудь поможет. Удивительно видеть, как далеко зашёл JavaScript за 8 лет; от почти всегда нуждающейся в библиотеке, чтобы написать что-то сложное в сжатой форме, до возможности делать это изначально.
Редактировать
Итак, метод, описанный выше, будет работать нормально в большинстве случаев, но у него есть две проблемы:
- Такие элементы, как
<div> </div>
, не обрабатываются как :empty
(без пробела между ними). Селекторы уровня 4 CSS исправили это с введением селектора :blank
(который похож на пустой, если не учитывать пробелы), но в настоящее время его поддерживает только Firefox (в форме с префиксом поставщика).
- Самозакрывающиеся теги перехватываются
:empty
- и с :blank
это так же будет.
Я написал чуть большую функцию, которая работает с этими двумя вариантами использования:
document.querySelectorAll("*").forEach((x)=>{
let tagName = "</" + x.tagName + ">";
if (x.outerHTML.slice(tagName.length).toUpperCase() == tagName
&& /[^\s]/.test(x.innerHTML)) {
x.remove();
}
});
Мы перебираем все элементы на странице. Мы берем имя тега этого элемента (например, если элемент является div, это будет DIV
, и используем его для создания закрывающего тега - например, </DIV>
.
Этот тег имеет длину 6 символов. Мы проверяем, соответствуют ли последние 6 символов в верхнем регистре элементов HTML. Если это так, мы продолжим. Если это не так, элемент не имеет закрывающего тега и поэтому должен быть самозакрывающимся. Это предпочтительнее, чем список, потому что это означает, что вам не нужно ничего обновлять, если в спецификацию добавляется новый самозакрывающийся тег.
Затем мы проверяем, содержит ли содержимое элемента какие-либо пробелы. /[^\s]/
является рег. []
является набором в RegEx и будет соответствовать любому символу, который появляется внутри него. Если ^
является первым элементом, набор становится отрицательным - он будет соответствовать любому элементу, который НЕ находится в наборе. \s
означает пробел - табуляции, пробелы, переносы строк. Так что [^\s]
говорит: "любой символ, который не является пробелом".
Сопоставление с этим, если тег не является самозакрывающимся, и его содержимое содержит символ без пробелов, то мы удаляем его.
Конечно, это немного больше и менее элегантно, чем предыдущая строчка. Но это должно работать практически для каждого случая.