使用.text()仅检索不嵌套在子标记中的文本

如果我有这样的HTML:

<li id="listItem"> This is some text <span id="firstSpan">First span text</span> <span id="secondSpan">Second span text</span> </li> 

我试图用.text()来检索string“这是一些文本”,但如果我说$('#list-item').text() ,我得到“这是一些textFirst跨度textSecond span text“。

有没有办法通过像.text("")的标签中的自由文本(而不是其子标签内的文本)来获取(也可能删除,通过.text("") )?

HTML不是由我写的,所以这是我必须要处理的。 我知道在编写html文件时将文本包装在标签中会很简单,但是再次预先写好html。

我喜欢这个基于在这里find的clone()方法的可重用实现,只获得父元素内的文本。

代码仅供参考:

 $("#foo") .clone() //clone the element .children() //select all the children .remove() //remove all the children .end() //again go back to selected element .text(); 

简单的回答:

 $("#listItem").contents().filter(function(){ return this.nodeType == 3; })[0].nodeValue = "The text you want to replace with" 

这似乎是过度使用jquery的一个例子。 以下将抓取文本忽略其他节点:

 document.getElementById("listItem").childNodes[0]; 

你将需要修剪,但它可以得到你想要的,在一个简单的线。

编辑

以上将获得文本节点 。 要获得实际的文本,使用这个:

 document.getElementById("listItem").childNodes[0].nodeValue; 

更简单快捷:

 $("#listItem").contents().get(0).nodeValue 

类似于接受的答案,但没有克隆:

 $("#foo").contents().not($("#foo").children()).text(); 

这是一个jQuery插件为此目的:

 $.fn.immediateText = function() { return this.contents().not(this.children()).text(); }; 

这里是如何使用这个插件:

 $("#foo").immediateText(); // get the text without children 

不是代码:

 var text = $('#listItem').clone().children().remove().end().text(); 

只是成为jQuery的jQuery的缘故? 当简单的操作涉及到许多链接命令和那么多(不必要的)处理时,也许是时候写一个jQuery扩展:

 (function ($) { function elementText(el, separator) { var textContents = []; for(var chld = el.firstChild; chld; chld = chld.nextSibling) { if (chld.nodeType == 3) { textContents.push(chld.nodeValue); } } return textContents.join(separator); } $.fn.textNotChild = function(elementSeparator, nodeSeparator) { if (arguments.length<2){nodeSeparator="";} if (arguments.length<1){elementSeparator="";} return $.map(this, function(el){ return elementText(el,nodeSeparator); }).join(elementSeparator); } } (jQuery)); 

致电:

 var text = $('#listItem').textNotChild(); 

参数是在遇到不同的情况下,例如

 <li>some text<a>more text</a>again more</li> <li>second text<a>more text</a>again more</li> var text = $("li").textNotChild(".....","<break>"); 

文字将有价值:

 some text<break>again more.....second text<break>again more 

它需要根据需求量身定制,这取决于你所呈现的结构。 对于你提供的例子,这个工作:

 $(document).ready(function(){ var $tmp = $('#listItem').children().remove(); $('#listItem').text('').append($tmp); }); 

演示: http : //jquery.nodnod.net/cases/2385/run

但是它相当依赖于你所发布的标记。

尝试这个:

 $('#listItem').not($('#listItem').children()).text() 
 $($('#listItem').contents()[0]).text() 

Stuart答案的简短变体。

或者用get()

 $($('#listItem').contents().get(0)).text() 

这是一个古老的问题,但最重要的答案是非常低效的。 这是一个更好的解决scheme:

 $.fn.myText = function() { var str = ''; this.contents().each(function() { if (this.nodeType == 3) { str += this.textContent || this.innerText || ''; } }); return str; }; 

只要做到这一点:

 $("#foo").myText(); 
 jQuery.fn.ownText = function () { return $(this).contents().filter(function () { return this.nodeType === Node.TEXT_NODE; }).text(); }; 

把它放在<p><font>并抓住$('#listItem font')。text()

首先想到的东西

 <li id="listItem"> <font>This is some text</font> <span id="firstSpan">First span text</span> <span id="secondSpan">Second span text</span> </li> 

我提出了一个特定的解决scheme,该解决scheme应该比克隆的克隆和修改更有效率。 这个解决scheme只适用于以下两个保留,但应该比目前接受的解决scheme更有效率:

  1. 你只得到文本
  2. 您要提取的文本位于子元素之前

这就是说,这里是代码:

 // 'element' is a jQuery element function getText(element) { var text = element.text(); var childLength = element.children().text().length; return text.slice(0, text.length - childLength); } 

我build议使用createTreeWalker来查找所有不附加到html元素的文本元素(这个函数可以用来扩展jQuery):

 function textNodesOnlyUnder(el) { var resultSet = []; var n = null; var treeWalker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, function (node) { if (node.parentNode.id == el.id && node.textContent.trim().length != 0) { return NodeFilter.FILTER_ACCEPT; } return NodeFilter.FILTER_SKIP; }, false); while (n = treeWalker.nextNode()) { resultSet.push(n); } return resultSet; } window.onload = function() { var ele = document.getElementById('listItem'); var textNodesOnly = textNodesOnlyUnder(ele); var resultingText = textNodesOnly.map(function(val, index, arr) { return 'Text element N. ' + index + ' --> ' + val.textContent.trim(); }).join('\n'); document.getElementById('txtArea').value = resultingText; } 
 <li id="listItem"> This is some text <span id="firstSpan">First span text</span> <span id="secondSpan">Second span text</span> </li> <textarea id="txtArea" style="width: 400px;height: 200px;"></textarea> 

我认为这也是一个很好的解决scheme – 如果你想获得所有文本节点的内容是所选元素的直接子节点。

 $(selector).contents().filter(function(){ return this.nodeType == 3; }).text(); 

注意:jQuery文档使用类似的代码来解释内容函数: https : //api.jquery.com/contents/

PS还有一个更丑陋的方法来做到这一点,但这更深入地展示了事情的工作原理,并允许在文本节点之间自定义分隔符(也许你想在那里换行)

 $(selector).contents().filter(function(){ return this.nodeType == 3; }).map(function() { return this.nodeValue; }).toArray().join(""); 

这对我来说是一个好方法

  var text = $('#listItem').clone().children().remove().end().text(); 

你可以试试这个

 alert(document.getElementById('listItem').firstChild.data) 

为了能够修剪结果,使用DotNetWala就像这样:

 $("#foo") .clone() //clone the element .children() //select all the children .remove() //remove all the children .end() //again go back to selected element .text() .trim(); 

我发现使用像document.getElementById("listItem").childNodes[0]这样的短版本不适用于jQuery的trim()。

使用额外的条件来检查innerHTML和innerText是否相同。 只有在这些情况下,才能更换文字。

 $(function() { $('body *').each(function () { console.log($(this).html()); console.log($(this).text()); if($(this).text() === "Search" && $(this).html()===$(this).text()) { $(this).html("Find"); } }) }) 

http://jsfiddle.net/7RSGh/

这未经testing,但我认为你可以尝试这样的事情:

  $('#listItem').not('span').text(); 

http://api.jquery.com/not/

我不是一个jQuery的专家,但如何,

 $('#listItem').children().first().text()