Альтернатива jQuery text (), которая включает пробелы между элементами?

у меня есть произвольный текст в контейнере. Я не контролирую его, поэтому не знаю его структуры. Но что-то вроде этого:--3-->

<div id='content-area'>
  <h1>Heading</h1>
  <p>A paragraph or two</p>
  <ul>
    <li>item 1</li>
    <li>item 2</li>
  </ul>
</div>

Это просто простой пример для иллюстрации, на самом деле он может содержать гораздо больше элементов и вложенных вещей, таких как таблицы.

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

$('#content-area').text()
// HeadingA paragraph or twoitem 1item 2

проблема в том, что нет пробелов между каждый помеченный элемент. The документация говорит:

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

и все мои поиски, похоже, подтягивают результаты для удаления пробела. Есть ли способ вытащить весь текст и сохранить пространство между элементами? Должно произойти в браузере, поэтому методы javascript-ish.

5 ответов


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

https://jsfiddle.net/3y2yLexv/1/

$( "*" ).each(function( index ) {
   $( this ).append(' ');
});

var str = $('#content-area').text();
//Of course you have to trim duplicated blank spaces.
str = str.replace(/\s\s+/g, ' ');
$('#new').text(str);

Я думаю, что jQuery использует свойство textContent, которое может форматировать вашу строку таким образом. Вместо этого вы можете пройти по дереву, ища textNodes и добавить его в строку/массив.

например:

function getText(domElement) {
  var root = domElement;
  var text = [];

  function traverseTree(root) {
    Array.prototype.forEach.call(root.childNodes, function(child) {
      if (child.nodeType === 3) {
        var str = child.nodeValue.trim();
        if (str.length > 0) {
          text.push(str);
        }
      } else {
        traverseTree(child);
      }
    });
  }
  traverseTree(root);
  return text.join(' ');
}

var text = getText(document.getElementById('content-area'));
document.getElementById('results').innerHTML = text;
<div id='content-area'>
  <h1>Heading</h1>
  <p>A paragraph or two</p>
  <ul>
    <li>item 1</li>
    <li>item 2</li>
  </ul>
</div>
<pre id="results"></pre>

есть куча текстовых узлов с символами пробелов. То, что я сделал, чтобы отфильтровать их, - это обрезать содержимое текстового узла, а затем просто проверить, есть ли что-нибудь рядом с пробелами. Могли бы быть лучше проверить, какие пробелы появляются и просто отфильтровать их.


вы можете использовать jQuery each метод для сбора элементов и включения интервалов с помощью конкатенации строк.

что-то в этом роде для грубого примера:

$(function(){
    var output = "";
    $( "li" ).each( function( index, element ){
        output += $(this).text() + " ";
    });
    $('#output').html(output);
});

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

http://jsfiddle.net/bq50s8eb/

EDIT:

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

$(function(){
    var output = "";
    $( "#content-area *" ).each( function( index, element ){
        output += $(this).text() + " ";
    });
    $('#output').html(output);
});

http://jsfiddle.net/bq50s8eb/1/


Я не уверен, что это работает в любом случае. Мое решение будет регулярным выражением, которое фильтрует теги, пробелы и новые строки из raw html:

$("#content-area").html().replace(/([\s\n]*<[^>]*>[\s\n]*)+/g," ")

http://jsfiddle.net/limond/mrnctqcv/1/

EDIT: конечно, это работает, только если вы можете избежать любых тегов, содержащих html, которые пользователь не может видеть (например,<script>...</script>)


Я решил это, добавив пробел: pre в css. При добавлении элемента динамически с помощью jquery вы можете сделать это так:

$('<a/>') 
.attr("style", 'white-space:pre;')
.text('    X    ');