Удалить пробелы и разрывы строк между элементами HTML с помощью jQuery

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

var widgetHTML = '    <div id="widget">        <h2>Widget</h2><p>Hi.</p>        </div>';

Должно быть:

alert(widgetHTML); // <div id="widget"><h2>Widget</h2><p>Hi.</p></div>

Я думаю, что шаблон мне понадобится:

>[\s]*<

Можно ли это сделать без использования регулярных выражений?

8 ответов

Решение

Я попробовал технику, которую выложил user76888, и она работала хорошо. Я упаковал его в плагин jQuery для удобства и подумал, что сообществу это может понравиться, поэтому вот:

jQuery.fn.cleanWhitespace = function() {
    this.contents().filter(
        function() { return (this.nodeType == 3 && !/\S/.test(this.nodeValue)); })
        .remove();
    return this;
}

Чтобы использовать это, просто включите его в тег script, затем выберите тег для очистки с помощью jQuery и вызовите функцию следующим образом:

$('#widget').cleanWhitespace();

Рекурсивная версия:

jQuery.fn.htmlClean = function() {
    this.contents().filter(function() {
        if (this.nodeType != 3) {
            $(this).htmlClean();
            return false;
        }
        else {
            this.textContent = $.trim(this.textContent);
            return !/\S/.test(this.nodeValue);
        }
    }).remove();
    return this;
}

Я думаю, что это сделает это...

cleanWhitespace: function(element) {
 element = $(element);
 for (var i = 0; i < element.childNodes.length; i++) {
   var node = element.childNodes[i];
   if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
     Element.remove(node);
 }
}

Вот что сработало для меня и пошагового открытия:

Выход из хромированной консоли

Сначала найдите родительский узел, содержащий неприятные пробелы

$('.controls label[class="radio"]').parent();

[<div class=​"controls">​
<label class=​"radio">​…​</label>​
" "
"    "
<label class=​"radio">​…​</label>​
" "
"    "
</div>​]

Вы можете видеть, что это заключено в массив из скобок [], jQuery всегда будет возвращать структуру, похожую на массив, даже когда был найден один элемент.

Итак, чтобы добраться до HTMLElement, мы берем первый элемент в массиве с индексом 0

$('.controls label[class="radio"]').parent()[0];

<div class=​"controls">​
<label class=​"radio">​…​</label>​
" "
"    "
<label class=​"radio">​…​</label>​
" "
"    "
</div>​

Обратите внимание, что больше нет [] скобок. Причина, по которой нам нужно это сделать, заключается в том, что jQuery будет игнорировать пробелы в dom, а HTMLElement - нет, посмотрим, что произойдет, когда мы получим доступ к свойству childNodes

$('.controls label[class="radio"]').parent()[0].childNodes;

[<label class=​"radio">​…​</label>​, 
" ", 
"    ", 
<label class=​"radio">​…​</label>​, 
" ", 
"    "]

У нас снова есть массив, да, вы указываете скобки [], но видите ли вы другое отличие, смотрите на все запятые, которые мы не могли получить с помощью jQuery. Спасибо HTMLElement, но теперь мы можем вернуться к jQuery, потому что я хочу использовать каждый вместо цикла for, вы согласны со мной? Итак, давайте обернем массив в jQuery и посмотрим, что произойдет:

$($('.controls label[class="radio"]').parent()[0].childNodes);

[<label class=​"radio">​…​</label>​, 
" ", 
"    ", 
<label class=​"radio">​…​</label>​, 
" ", 
"    "]

Отлично! у нас есть точно такая же структура, но внутри jQuery-объекта нет ничего, поэтому давайте вызовем каждый из них и выведем "this" на консоль, чтобы увидеть, что у нас есть.

$($('.controls label[class="radio"]').parent()[0].childNodes).each(function () { 
   console.log('|'+$(this).html()+'|');
});

|<input id="gender_f" name="gender" type="radio" value="f">Female|
|undefined|
|undefined|
|<input id="gender_m" name="gender" type="radio" value="m" checked="">Male|
|undefined|
|undefined|

Таким образом, мы используем jQuery для получения html каждого элемента, стандартного материала `$(this).html, и поскольку мы не можем видеть пустое пространство, давайте дополним его каналом |, хороший план, но что у нас здесь? Как вы можете видеть, jQuery не может превратить пустое пространство в html, и теперь у нас есть неопределенное значение. Но это даже лучше, потому что место, где пробел может быть правдиво неопределенным, определенно ложно =)

Так что давайте избавимся от лохов с помощью jQuery. Все, что нам нужно это $(this).html() || $(this).remove(); Посмотрим:

$($('.controls label[class="radio"]').parent()[0].childNodes).each(function () { 
   $(this).html() || $(this).remove();
});

[<label class=​"radio">​…​</label>​, 
" ", 
"    ", 
<label class=​"radio">​…​</label>​, 
" ", 
"    "]

О, дорогой... но не бойся! Каждый по-прежнему возвращает предыдущую структуру, а не ту, которую мы изменили, давайте посмотрим, что теперь возвращает наш первоначальный запрос.

$('.controls label[class="radio"]').parent();

[<div class=​"controls">​
<label class=​"radio">​…​</label>​
<label class=​"radio">​…​</label>​
</div>​]

И Уолла! Все сексуально и красиво =)

Итак, у вас есть, как удалить пробелы между элементами / тегами в стиле JQuery.

NJoy!

Вы можете сделать это лучше после установки HTML в DOM-узел. После того как браузер проанализировал все и построил дерево DOM из нашей разметки, вы можете выполнить обход DOM и для каждого найденного текстового узла либо полностью удалить его, если в нем нет непробельных символов, либо обрезать пробелы с самого начала и конец, если это так.

Мне пришлось немного изменить принятый ответ, потому что по какой-то причине chrome не захотел удалить Child() на узлах пробелов. Если это произойдет, вы можете заменить узел пустым текстовым узлом, как в этом примере вспомогательной функции:

 var removeWhiteSpaceNodes = function ( parent ) {
    var nodes = parent.childNodes;
    for( var i =0, l = nodes.length; i < l; i++ ){
      if( nodes[i] && nodes[i].nodeType == 3 && !/\S/.test( nodes[i].nodeValue ) ){
        parent.replaceChild( document.createTextNode(''), nodes[i]  );
      }else if( nodes[i] ){
        removeWhiteSpaceNodes( nodes[i] );
      }
    }
  }

Он берет узел, из которого вы хотите удалить пробелы, и рекурсивно заменяет все дочерние пробелы действительно пустым текстовым узлом.

Использование

$($.parseHTML(widgetHTML, document, true)).filter("*"),

Вы могли бы $.trim(widgetHTML); чтобы прочитать окружающие пробелы.

Другие вопросы по тегам