Použití jQuery ke shromáždění všech textových uzlů ze zabalené sady oddělených mezerami

Hledám způsob, jak shromáždit veškerý text v zabalené sadě jQuery, ale potřebuji vytvořit mezery mezi sourozeneckými uzly, které mezi sebou nemají žádné textové uzly.

Zvažte například toto HTML:

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

Pokud jednoduše použiji text() jQuery metoda pro shromáždění textového obsahu <div> , jako například:

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

alert(text);

čímž vznikne následující text:

Položka seznamu #1.Položka seznamu #2.Položka seznamu #3.

protože mezi každým <li> nejsou žádné mezery živel. Ve skutečnosti hledám toto (všimněte si jediné mezery mezi každou větou):

Položka seznamu #1. Položka seznamu č. 3. Položka seznamu #3.

To mi naznačuje, že musím procházet uzly DOM v zabalené sadě a připojit text pro každý z nich k řetězci, za kterým následuje mezera. Zkoušel jsem následující kód:

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

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

alert(text);

ale výsledkem byl následující text:

Toto je položka seznamu č. 1. Toto je položka seznamu č. 2. Toto je položka seznamu č. 3. Toto je položka seznamu #1. Toto je položka seznamu #2. Toto je položka seznamu #3.

Předpokládám, že je to proto, že procházím každým potomkem <div> a připojení textu, takže dostávám textové uzly v obou <ul> a každý z jeho <li> děti, což vede k duplicitnímu textu.

Myslím, že bych pravděpodobně mohl najít/zapsat obyčejnou JavaScriptovou funkci, která by rekurzivně procházela DOM zabalené sady, shromažďovala a připojovala textové uzly – ale existuje jednodušší způsob, jak to udělat pomocí jQuery? Konzistence napříč prohlížeči je velmi důležitá.

Děkujeme za jakoukoli pomoc!

Odpověď

jQuery se zabývá převážně prvky, jeho schopnosti textových uzlů jsou relativně slabé. Můžete získat seznam všech dětí s contents() , ale stále byste museli projít kontrolou typů, takže se to ve skutečnosti neliší od pouhého použití prostého DOM childNodes . Neexistuje žádná metoda, jak rekurzivně získat textové uzly, takže byste museli něco napsat sami, např. něco jako:

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(' ');
}