Использование jQuery для сбора всех текстовых узлов из упакованного набора, разделенных пробелами - PullRequest
9 голосов
/ 14 мая 2010

Я ищу способ собрать весь текст в упакованный набор jQuery, но мне нужно создать пробелы между узлами-братьями, у которых нет текстовых узлов между ними.

Например, рассмотрим этот HTML-код:

<div>
  <ul>
    <li>List item #1.</li><li>List item #2.</li><li>List item #3.</li>
  </ul>
</div>

Если я просто использую метод jQuery text() для сбора текстового содержимого <div>, например:

var $div = $('div'), text = $div.text().trim();

alert(text);

, который производит следующий текст:

Элемент списка № 1. Элемент списка № 2. Элемент списка № 3.

потому что между каждым элементом <li> нет пробелов. На самом деле я ищу вот что (обратите внимание на один пробел между каждым предложением):

Элемент списка № 1. Элемент списка № 3. Элемент списка № 3.

Это подсказывает мне, что мне нужно пройти через узлы DOM в обернутом наборе, добавив текст для каждого в строку, а затем пробел. Я попробовал следующий код:

var $div = $('div'), text = '';

$div.find('*').each(function() {
  text += $(this).text().trim() + ' ';
});

alert(text);

но это привело к следующему тексту:

Это элемент списка № 1. Это элемент списка № 2. Это элемент списка № 3. Это элемент списка № 1. Это элемент списка № 2. Это пункт списка № 3.

Я предполагаю, что это потому, что я перебираю каждого потомка <div> и добавляю текст, поэтому я получаю текстовые узлы как в <ul>, так и в каждом из его <li> дочерних элементов, что приводит к дублированию текста .

Думаю, я мог бы найти / написать простую функцию JavaScript для рекурсивного обхода DOM обернутого набора, сбора и добавления текстовых узлов - но есть ли более простой способ сделать это с помощью jQuery? Кросс-браузерная согласованность очень важна.

Спасибо за любую помощь!

Ответы [ 3 ]

7 голосов
/ 14 мая 2010

jQuery имеет дело главным образом с элементами, его возможности текстовых узлов относительно слабы. Вы можете получить список всех детей с contents(), но вам все равно придется пройти его, проверяя типы, так что это на самом деле ничем не отличается от простого использования простого DOM childNodes. Нет способа рекурсивно получить текстовые узлы, поэтому вам придется написать что-то самостоятельно, например. что-то вроде:

function collectTextNodes(element, texts) {
    for (var child= element.firstChild; child!==null; child= child.nextSibling) {
        if (child.nodeType===3)
            texts.push(child);
        else if (child.nodeType===1)
            collectTextNodes(child, texts);
    }
}
function getTextWithSpaces(element) {
    var texts= [];
    collectTextNodes(element, texts);
    for (var i= texts.length; i-->0;)
        texts[i]= texts[i].data;
    return texts.join(' ');
}
2 голосов
/ 19 октября 2011

Это самое простое решение, которое я мог придумать:

$("body").find("*").contents().filter(function(){return this.nodeType!==1;});
0 голосов
/ 14 мая 2010

Вы можете использовать метод jQuery contents () , чтобы получить все узлы (включая текстовые узлы), а затем отфильтровать ваш набор только до текстовых узлов.

$("body").find("*").contents().filter(function(){return this.nodeType!==1;});

Оттуда вы можете создать любую необходимую вам структуру.

...