53

Given this HTML:

<a href="#" class="artist">Soulive<span class="create-play">Play</span></a>

I want to get the text content of the a (which is this in the context of my function) without the text content of the span, so I'm left with:

Soulive

If I do:

$(this).text();

I get:

SoulivePlay

How do I exclude the text content of the span?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
daGUY
  • 27,055
  • 29
  • 75
  • 119

4 Answers4

74

A micro-plugin:

$.fn.ignore = function(sel) {
  return this.clone().find(sel || ">*").remove().end();
};

...having this HTML:

<div id="test"><b>Hello</b><span> World</span>!!!</div>

will result in:

var text = $('#test').ignore("span").text(); // "Hello!!!"
var html = $('#test').ignore("span").html(); // "<b>Hello</b>!!!"

if you want it faster and you need only to exclude the immediate children... use .children( instead of .find(

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • 1
    Perfect! I had something similar with `:not` but I was missing `.contents()`, which is the key. Thanks! – daGUY Jul 05 '12 at 21:30
  • `contents` doesn't not accept any arguments with newer jQuery: http://api.jquery.com/contents/. The fiddle fails with jQuery 1.10.1 – Mrchief Aug 04 '14 at 04:38
  • 1
    @Mrchief *I had a small phone-talk with John Resig, he apologized for the terrible mistake and promised it will be fixed in the next version of* ;) kidding, **edited my answer!** (and thanks for notifying!) – Roko C. Buljan Aug 04 '14 at 06:51
  • 1
    Wonderful innovative idea, Big thanks to solve bigger looking issue within a minute. – Mihir Bhatt Feb 07 '18 at 09:29
  • It’s 2020 now and JQuery still hasn’t added the `ignore()`? – Jens Apr 03 '20 at 11:31
  • @Jens seems like they didn't https://api.jquery.com/ – Roko C. Buljan Apr 03 '20 at 11:35
23

http://jsfiddle.net/r8kNL/

$(this).contents().filter(function() {
  return this.nodeType == 3;
}).text()
Roman
  • 5,888
  • 26
  • 47
18
$(this).clone().find('span').remove().end().text();

otherwise, with a different approach, if you're sure that your span elements always contain the word "play" at the end, just use a replace() or a substring() function, e.g.

var text = $(this).text();
text = text.substring(0, text.length-4);

the latter example is a too-localized and not bulletproof method for sure, but I mentioned just to propose a solution from a different point of view

Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
  • You could use `"*"` so that it wouldn't be dependent on this specific structure I think – Esailija Jul 05 '12 at 15:45
  • 1
    Alternatively, you could replace `find('span')` with `children()`. – Richard Jul 05 '12 at 15:47
  • No @Roko, `children()` would be more efficient than `find()` as `children()` only traverses 1-level down, and as we're removing the children anyway, this will subsequently remove all lower-levels. – Richard Jul 05 '12 at 22:11
  • $('li.yourclass').find('span').remove().end().text(); work fine for me. Tks – Florida Sep 06 '15 at 16:10
2
$( this.childNodes ).map( function(){
    return this.nodeType === 3 && this.nodeValue || "";
}).get().join("");
Esailija
  • 138,174
  • 23
  • 272
  • 326