daGUY
daGUY

Reputation: 28783

jQuery: check if text exists in another element

Using jQuery, I want to check if the text of a link I'm clicking is present in another element on the page. The text in the other element is added dynamically and isn't present on the page initially.

So far I have this:

$("#results a").live("click", function(event){
    var seed = $(this).text();
    if ($("#seeds:has(" + seed + ")")){
        alert("already have it");
    }
    else {
        // other code
    }
});

But for some reason, I always get the "already have it" alert even if the text of the #results a link isn't present in the #seeds <div>. What am I doing wrong?


UPDATE: using :contains instead of :has, as suggested, works for the most part...except if #seeds contains a string that's a superset of the text in the #results anchor.

For example, if #seeds contains the text Americana and the #results anchor's text is America, I will still get the "already have it" alert. I want the alert to appear only for an exact match. Is this possible?

Upvotes: 2

Views: 10600

Answers (2)

Jasper
Jasper

Reputation: 76003

You can use :contains() instead of :has():

$("#results a").live("click", function(event){
    var seed = $(this).text();
    if ($("#seeds:contains(" + seed + ")").length){
        alert("already have it");
    }
    else {
        // other code
    }
});

This checks if the #seeds element contains the text that the link clicked contains.

If you want to find any elements that are descendants of the #seeds element:

$("#results a").live("click", function(event){
    var seed = $(this).text();
    if ($("#seeds").find(":contains(" + seed + ")").length){
        alert("already have it");
    }
    else {
        // other code
    }
});

Here is a demo: http://jsfiddle.net/5wE3p/

Notice that I am checking the length of the returned set of elements, if there are no elements then zero will be returned and the if statement will resolve to false, if there are any elements then it will resolve truthily.

Also note that :contains() is case-sensitive: http://api.jquery.com/contains-selector/

Side-Note

If you are using jQuery 1.4.2 or greater then you can use .delegate() rather than .live(). The main benefit to .delegate() is that you can select your root element. So if for instance, #results, is always present in the DOM then you can use it as the root element rather than the document element (which is what .live() does):

//it's this easy to change to `.delegate()`
$("#results").delegate("a", "click", function(event){
    var seed = $(this).text();
    if ($("#seeds").find(":contains(" + seed + ")").length){
        alert("already have it");
    }
    else {
        // other code
    }
});

If #results is added to the DOM dynamically then you can find it's parent and use it as the root element (... as long as it persists in the DOM).

Update

If you want to only match the exact text of the link then you can iterate through the descendant elements of the #results element and check the text of each element:

$("#results a").live("click", function(event){
    var seed  = $(this).text(),
        found = false;
    $.each($('#seeds').find('*'), function () {
        if ($(this).text() == seed) {
            found = true;
        }
    });
    if (found){
        alert("already have it");
    }
    else {
        alert('that\'s new');
    }
    return false;
});​

Here is a demo: http://jsfiddle.net/5wE3p/1/

You can also use RegExp to match the value:

$("#results a").live("click", function(event){
    var regexp = new RegExp("^(" + $(this).text() + ")$", "i"),
        found  = false;
    $.each($('#seeds').find('*'), function () {
        if ($(this).text().search(regexp) > -1) {
            found = true;
        }
    });
    if (found){
        alert("already have it");
    }
    else {
        alert('that\'s new');
    }
    return false;
});​

Here is a demo: http://jsfiddle.net/5wE3p/2/

The important part here is the creation of the RegExp: var regexp = new RegExp("^(" + $(this).text() + ")$", "i"). Notice the i flag which sets the RegExp to search case-insensitive. Also the ^ matches the beginning of the string and $ matches the end, so this look to see if the current text being checked is the exact same string as the search term (except that it's case-insensitive).

Upvotes: 8

ShankarSangoli
ShankarSangoli

Reputation: 69915

Use :contains() instead of :has() and check for length property because jQuery always gives an object.

:has(selector) takes selector as input and looks for element which match selector where as :contains(text) takes the text to check for within elements text content and select them.

$("#results a").live("click", function(event){
    var seed = $(this).text();
    if ($("#seeds:contains(" + seed + ")").length){
        alert("already have it");
    }
    else {
        // other code
    }
});

Upvotes: 0

Related Questions