If I have html like this:
This is some text
First span text
Not sure how flexible or how many cases you need it to cover, but for your example, if the text always comes before the first HTML tags – why not just split the inner html at the first tag and take the former:
$('#listItem').html().split('<span')[0];
and if you need it wider maybe just
$('#listItem').html().split('<')[0];
and if you need the text between two markers, like after one thing but before another, you can do something like (untested) and use if statements to make it flexible enough to have a start or end marker or both, while avoiding null ref errors:
var startMarker = '';// put any starting marker here
var endMarker = '<';// put the end marker here
var myText = String( $('#listItem').html() );
// if the start marker is found, take the string after it
myText = myText.split(startMarker)[1];
// if the end marker is found, take the string before it
myText = myText.split(endMarker)[0];
console.log(myText); // output text between the first occurrence of the markers, assuming both markers exist. If they don't this will throw an error, so some if statements to check params is probably in order...
I generally make utility functions for useful things like this, make them error free, and then rely on them frequently once solid, rather than always rewriting this type of string manipulation and risking null references etc. That way, you can re-use the function in lots of projects and never have to waste time on it again debugging why a string reference has an undefined reference error. Might not be the shortest 1 line code ever, but after you have the utility function, it is one line from then on. Note most of the code is just handling parameters being there or not to avoid errors :)
For example:
/**
* Get the text between two string markers.
**/
function textBetween(__string,__startMark,__endMark){
var hasText = typeof __string !== 'undefined' && __string.length > 0;
if(!hasText) return __string;
var myText = String( __string );
var hasStartMarker = typeof __startMark !== 'undefined' && __startMark.length > 0 && __string.indexOf(__startMark)>=0;
var hasEndMarker = typeof __endMark !== 'undefined' && __endMark.length > 0 && __string.indexOf(__endMark) > 0;
if( hasStartMarker ) myText = myText.split(__startMark)[1];
if( hasEndMarker ) myText = myText.split(__endMark)[0];
return myText;
}
// now with 1 line from now on, and no jquery needed really, but to use your example:
var textWithNoHTML = textBetween( $('#listItem').html(), '', '<'); // should return text before first child HTML tag if the text is on page (use document ready etc)
It'll need to be something tailored to the needs, which are dependent on the structure you're presented with. For the example you've provided, this works:
$(document).ready(function(){
var $tmp = $('#listItem').children().remove();
$('#listItem').text('').append($tmp);
});
Demo: http://jquery.nodnod.net/cases/2385/run
But it's fairly dependent on the markup being similar to what you posted.
I came up with a specific solution that should be much more efficient than the cloning and modifying of the clone. This solution only works with the following two reservations, but should be more efficient than the currently accepted solution:
With that said, here is the code:
// '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);
}
This untested, but I think you may be able to try something like this:
$('#listItem').not('span').text();
http://api.jquery.com/not/
Just like the question, I was trying to extract text in order to do some regex substitution of the text but was getting problems where my inner elements (ie: <i>
, <div>
, <span>
, etc.) were getting also removed.
The following code seems to work well and solved all my problems.
It uses some of the answers provided here but in particular, will only substitute the text when the element is of nodeType === 3
.
$(el).contents().each(function() {
console.log(" > Content: %s [%s]", this, (this.nodeType === 3));
if (this.nodeType === 3) {
var text = this.textContent;
console.log(" > Old : '%s'", text);
regex = new RegExp("\\[\\[" + rule + "\\.val\\]\\]", "g");
text = text.replace(regex, value);
regex = new RegExp("\\[\\[" + rule + "\\.act\\]\\]", "g");
text = text.replace(regex, actual);
console.log(" > New : '%s'", text);
this.textContent = text;
}
});
What the above does is loop through all the elements of the given el
(which was simply obtained with $("div.my-class[name='some-name']");
. For each inner element, it basically ignores them. For each portion of text (as determined by if (this.nodeType === 3)
) it will apply the regex substitution only to those elements.
The this.textContent = text
portion simply replaces the substituted text, which in my case, I was looking for tokens like [[min.val]]
, [[max.val]]
, etc.
This short code excerpt will help anyone trying to do what the question was asking ... and a bit more.
just put it in a <p>
or <font>
and grab that $('#listItem font').text()
First thing that came to mind
<li id="listItem">
<font>This is some text</font>
<span id="firstSpan">First span text</span>
<span id="secondSpan">Second span text</span>
</li>