0

The jQuery selector :contains(text) selects an element if the matching text appears directly within the selected element, in any of that element's descendants, or a combination thereof.
I want to select an element if and only if the matching text appears directly within the selected element. What should I do?

For example,

<ul>
    <li id="1">
       <a><img src="la.gif"></a>
       happy birthday 
       <ul><li>radom</li></ul>
    </li>
    <li id="2">
       <a><img src="la.gif"></a>
       sad 
       <ul><li>happy</li></ul>
    </li>
</ul>

I want to select the li that contains the word "happy" (don't select a li if only its descendant contains the word "happy"). Then only li#1 should be selected.

The following does NOT do what I want because it will select both li#1 and li#2:

$('li:contains("happy")');
Lix
  • 47,311
  • 12
  • 103
  • 131
user110
  • 315
  • 1
  • 11

2 Answers2

3

Edit: As from your updated code, I think you need to use .contents() and check for nodeType to make sure it is a text node and then compare it to the text as you need.

$('ul li').contents().each( function () {
    if (this.nodeType == Node.TEXT_NODE && this.nodeValue.match(/happy/)) {
        $(this).closest('li').css('border', '1px solid red');
    }
});

or using .filter(),

$('ul li').contents().filter( function () {
    if (this.nodeType == Node.TEXT_NODE && this.nodeValue.match(/happy/)) {
         return true;       
    }
}).closest('li').css('border', '1px solid red');

DEMO

Let me know if this works..


ul should only contain li tags.. like below,

<ul>
    <li id="1">happy</li>
    <li id="2">sad <div>happy</div></li>
</ul>

Assuming your html like that, below is the script to get the first list,

$('ul li').filter (function () {
    if ($(this).text() == 'happy') return true;
});

.filter will return the li that has text 'happy'.

DEMO

Selvakumar Arumugam
  • 79,297
  • 15
  • 120
  • 134
  • @Niko Are you mentioning selecting '
      happy
    '? It can be done, but that is not a valid ul construct.
    – Selvakumar Arumugam Mar 09 '12 at 21:56
  • I gave a bad example. Please check out the updated question. My problem is if li has descendants that contains the specified text but li itself doesn't directly contains it, I do NOT want to select it. – user110 Mar 09 '12 at 21:57
  • Yeah, that's not what I mean, you're right about that. But what if the `
  • ` contains a text like "happy birthday"? `:contains` would select this node, your filter won't.
  • – Niko Mar 09 '12 at 21:59
  • $(this).text() will get the text of all desendents of the selected element. If the selected element has a child element and then the proper text, this would still return that element. – Kevin B Mar 09 '12 at 22:00
  • Hmm, I understand it in a different way: The node's text must *contain* the word, it does not need to be equivalent to it. And furthermore the filter must not select a node like `
  • happy
  • `. But you may be right. – Niko Mar 09 '12 at 22:12
  • @SKS, not exactly. The example I give is much more simplified than the actual code. So you may expect all li's has many descendants. I want to filter those who "directly contain" the specified text. KevinB and Niko's interpretations are right. – user110 Mar 09 '12 at 22:21
  • @user1031868 Just add an elseif to that as else if (this.nodeType == Node.TEXT_NODE) { .... } http://jsfiddle.net/skram/HwB9D/9/. I would just have a parent if as TEXT_NODE and inside that check for happy or not. – Selvakumar Arumugam Mar 13 '12 at 15:29
  • Hey, I know it sounds dumb, but i'm using a system which has a default . I have no way to change it to IE9 standard, and the Node seems to be undefined in any standard lower than IE9. What should I do? – user110 Mar 13 '12 at 19:22
  • nvm. I found the answer in this post: http://stackoverflow.com/questions/1423599/node-text-node-and-ie7 – user110 Mar 13 '12 at 19:29