Альтернатива jQuery 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>
Это простой пример для иллюстрации, на самом деле он может содержать гораздо больше элементов и вложенных элементов, таких как таблицы.
Я хочу вытащить весь текст и сделать некоторую обработку на словах. Я использую следующий jQuery для получения текста.
$('#content-area').text()
// HeadingA paragraph or twoitem 1item 2
Проблема в том, что между каждым помеченным элементом нет пробелов. В документации говорится:
Из-за различий в парсерах HTML в разных браузерах возвращаемый текст может меняться в новых и других пробелах.
И все мои поиски, похоже, подтягивают результаты для удаления пробелов. Есть ли способ вытащить весь текст и сохранить пространство между элементами? Нужно происходить в браузере, поэтому методы javascript-ish.
Ответы
Ответ 1
В случае неизвестной вложенной структуры вы можете добавлять пробелы к каждому элементу
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);
Ответ 2
Я думаю, что jQuery использует свойство textContent, которое может форматировать вашу строку. Вместо этого вы можете пересечь дерево, которое ищет текстовые_Nodes и добавляет его в String/Array.
Например:
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>
Ответ 3
Вы можете использовать jQuery для each
метода для сбора элементов и включать интервал с использованием конкатенации строк.
Что-то в этом роде для грубого примера:
$(function(){
var output = "";
$( "li" ).each( function( index, element ){
output += $(this).text() + " ";
});
$('#output').html(output);
});
Не стесняйтесь видеть вывод, отображаемый путем кэширования того, что вы хотите, в переменную, которая заставит его записывать только DOM один раз.
http://jsfiddle.net/bq50s8eb/
РЕДАКТИРОВАТЬ:
Если вы не знаете, что такое структура, но вы уверены, что все они будут в пределах одного div, вы можете использовать универсальный селектор jQuery.
$(function(){
var output = "";
$( "#content-area *" ).each( function( index, element ){
output += $(this).text() + " ";
});
$('#output').html(output);
});
http://jsfiddle.net/bq50s8eb/1/
Ответ 4
Я не уверен, что это работает в любом случае. Мое решение будет регулярным выражением, которое фильтрует теги, пробелы и новые строки из raw html:
$("#content-area").html().replace(/([\s\n]*<[^>]*>[\s\n]*)+/g," ")
http://jsfiddle.net/limond/mrnctqcv/1/
EDIT: Конечно, это работает только в том случае, если вы можете избежать любых тегов, содержащих html, которые пользователь не может видеть (например, <script>...</script>
)
Ответ 5
Я решил это, добавив пробел: до css. При динамическом добавлении элемента с помощью jquery вы можете сделать это так:
$('<a/>')
.attr("style", 'white-space:pre;')
.text(' X ');