tags:

views:

24536

answers:

7

Say a web page has a string such as "I am a simple string" that I want to find. How would I go about this using JQuery?

+4  A: 

Take a look at highlight (jQuery plugin).

Chris Doggett
+21  A: 

jQuery has the contains method. Here's a snippet for you:

<script type="text/javascript">
$(function() {
    var foundin = $('*:contains("I am a simple string")');
});
</script>

The selector above selects any element that contains the targe string. The foundin will be a jQuery object that contains any matched element. See the API information at: http://docs.jquery.com/Selectors/contains#text

One thing to note with the '*' wildcard is that you'll get all elements, including your html an body elements, which you probably don't want. That's why most of the examples at jQuery and other places use $('div:contains("I am a simple string")')

Tony Miller
many thanks Tony.
Keith Donegan
@Tony, how would I go about manipulating just the matching text and not just the whole parapgraph, div etc etc?
Keith Donegan
Should point out that this is case-sensitive. A user named "me" wrote this on the jQuery docs page:$.expr[':'].icontains = function(obj, index, meta, stack){return (obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0;};Example:$("div:icontains('John')").css("text-decoration", "underline");
Brandon Bloom
does this work for json? What if I want to filter some text in a json value?
egfx
+10  A: 

Normally jQuery selectors do not search within the "text nodes" in the DOM. However if you use the .contents() function, text nodes will be included, then you can use the nodeType property to filter only the text nodes, and the nodeValue property to search the text string.

    $('*', 'body')
        .andSelf()
        .contents()
        .filter(function(){
            return this.nodeType === 3;
        })
        .filter(function(){
            // Only match when contains 'simple string' anywhere in the text
            return this.nodeValue.indexOf('simple string') != -1;
        })
        .each(function(){
            // Do something with this.nodeValue
        });
BarelyFitz
To clarify, as Tony mentioned you can use the ":contains()" selector to search within the text nodes, but jQuery will not return the individual text nodes in the results (just a list of elements). But when you use .contents(), then jQuery returns both elements and text nodes. For more info: http://docs.jquery.com/Traversing/contents
BarelyFitz
BarelyFitz, nice one!
Keith Donegan
+2  A: 

This will select just the leaf elements that contain "I am a simple string".

$('*:contains("I am a simple string")').each(function(){
     if($(this).children().length < 1) 
          $(this).css("border","solid 2px red") });

Paste the following into the address bar to test it.

javascript: $('*:contains("I am a simple string")').each(function(){ if($(this).children().length < 1) $(this).css("border","solid 2px red") }); return false;

If you want to grab just "I am a simple string". First wrap the text in an element like so.

$('*:contains("I am a simple string")').each(function(){
     if($(this).children().length < 1) 
          $(this).html( 
               $(this).text().replace(
                    /"I am a simple string"/
                    ,'<span containsStringImLookingFor="true">"I am a simple string"</span>' 
               )  
           ) 
});

and then do this.

$('*[containsStringImLookingFor]').css("border","solid 2px red");
Slim
the .filter() function would be more useful than .each() here. In fact, you could actually put it in one selector: "*:contains('blah'):empty"
nickf
#nickf - :empty wont select a text node that contains text. So if the text node contains "I am a simple string" it is excluded.http://docs.jquery.com/Selectors/empty
Slim
+2  A: 

If you just want the node closest to the text you're searching for, you could use this:

$('*:contains("my text"):last');

This will even work if your HTML looks like this:

<p> blah blah <strong>my <em>text</em></strong></p>

Using the above selector will find the <strong> tag, since that's the last tag which contains that entire string.

nickf
This doesn't seem to work. On this page, for example, *:contains("the"):last returns only 1 element.
bzlm
@bzlm: well it didn't necessarily specify that he wanted to find multiple occurrences.
nickf
@nickf Aha. Is there a way to make it work for multiple occurrences? I think it's a more elegant solution than the ones involving recursive node type checking etc.
bzlm
the only way i could think to get the all the nodes, but not all the ancestors up the line would be to loop through the result, removing all parents, though you could have problems, eg: `<p>my text <b>my text</b></p>` -- removing the ancestors of the `<b>` tag would lose the other match
nickf
A: 

Very nice stuff. it helped me a lot thanks

ooty