2

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?

2 Answers 2

8

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).

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! But this doesn't work for me in all cases - see my updated question.
0

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
    }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.