问题 替代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方法。


7612
2017-09-17 16:30


起源

这不是一个简单的任务,特别是如果嵌套很深......用例是什么? - charlietfl
我即将发布类似的问题......感谢Rothrock。如果有人想看它,这是一个小提琴手。 jsfiddle.net/99x50s2s/112 - Vimalan Jaya Ganesh
@charlietfl,在我的项目中,用例是,我想从用户那里捕获重复的条目。 (例如:具有多个空格的相同单词。)Jquery比较无法捕捉到这种差异。 - Vimalan Jaya Ganesh
@VimalanJayaGanesh仍然不清楚将会有什么比较。在本文的任何地方都有任何重复的单词?或者来自其他来源的文字作为比较?如果有其他来源问题可能会简单得多 - charlietfl
@charlietfl,看看这个: jsfiddle.net/99x50s2s/113。罗斯洛克,如果我转移你的问题,我很抱歉。 - Vimalan Jaya Ganesh


答案:


如果嵌套结构未知,您可以为每个元素添加空格

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);

7
2017-09-17 16:46



简单的想法...不确定我会想到这个+1 - charlietfl
爱它。这有一个额外的好处,一段时间后删除双倍空间 - 是的2015年和我合作的一些人仍然这样做!谢谢。 - Rothrock
我发现的一件事是尝试将空格附加到表元素会产生错误。所以要小心。 - Rothrock
我认为这会改变html文档本身。我怎样才能在JavaScript中实现相同的目标? - Gnoliz


我认为jQuery使用textContent属性,它可以像这样格式化你的字符串。你可以做的是遍历树,查找textNodes并将其附加到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>

有一堆带有空格字符的文本节点。我做了什么来过滤它们是修剪文本节点的内容,然后检查空白旁边是否有任何东西。可能最好检查出现哪个空格字符,然后将其过滤掉。


2
2017-09-17 17:18



主席先生,你是一位真正的英雄。谢谢! - maryisdead


你可以使用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/


1
2017-09-17 16:40



OP已经声明结构是未知的,所有这一切都是一个非常简单的列表案例 - charlietfl
很公平。我会扩大。 - Nicholas Hazel
一旦你开始嵌套,这将失败...父文本也将包含子文本 - charlietfl
我使用了OP提供的确切示例...... - Nicholas Hazel
这并不意味着它将在未知的结构中工作......放一个 <p> 在每个里面 <li> 例如......将有文本重复 jsfiddle.net/bq50s8eb/2 - charlietfl


我不确定这是否适用于任何情况。我的解决方案是一个正则表达式,用于过滤原始html中的标签,空格和新行:

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

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

编辑:当然,这只有在你可以避免任何包含用户看不到的html的标签时才有效(例如: <script>...</script>


1
2017-09-17 17:00





我通过添加white-space:pre来解决这个问题。 使用jquery动态添加元素时,您可以这样做:

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

0
2018-02-04 20:42