Getting text within element excluding decendants
I see that jQuery has the .text()
function for getting all text within an element and its descendant elements.
Is there a way to only get the text that is directly within the element?
eg.
<div>
Here is <b>some</b> text.
</div>
From that I would want to get just Here is text.
Solution 1:
var result = $('div').contents().map(function() {
if( this.nodeType === 3 ) {
return this.data;
}
}).get().join('');
Example: http://jsfiddle.net/PeXue/
This uses the contents()
[docs] method to get all children of the div
, including text nodes, then the map()
[docs] method to build a collection of the text contents of only the text nodes (this.nodeType === 3
) using their .data
property.
After that is done, it makes an Array from the collection using the get()
[docs] method, and finally joins the result using .join()
[docs].
Of course your selector should be specific to the <div>
you're targeting.
EDIT: If you want to normalize the spaces between the words a bit, you can trim the leading and trailing white space from the content of each text node using the jQuery.trim()
[docs] method, then give .join()
a single space to join each set.
var result = $('div').contents().map(function() {
if( this.nodeType === 3 ) {
return $.trim( this.data );
}
}).get().join(' ');
alert( result );
Example: http://jsfiddle.net/PeXue/1
We could even shorten it a bit, and ensure that any empty text nodes are excluded at the same time:
var result = $('div').contents().map(function() {
return $.trim( this.data ) || null;
}).get().join(' ');
alert( result );
Example: http://jsfiddle.net/PeXue/2
EDIT 2:
You can get an enormous performance increase by using the jQuery.map()
[docs] method, which is meant for more generic use.
var result = $.map( $('div')[0].childNodes, function(val,i) {
if (val.nodeType === 3) {
return val.data;
}
}).join('');
Here's a performance test showing the difference.
Solution 2:
Working example at jsFiddle
var divClone = $('div').clone(); // WARNING:
divClone.children().remove(); // This code is much slower than the
alert(divClone.text()); // code in the selected answer.
Update
The performance test in @patrick dw's answer clearly shows that his approach is the better alternative. I did not delete this answer, because I think it is helpful to future readers of the question who might not know which way is better.