LearnWebCode
LearnWebCode

Reputation: 1401

jQuery to check LI's content - add specific class based on content - trouble with jQuery's $(this)

I'm a jQuery beginner, but I need to style the front-end of a CMS and altering the HTML is not an option, so jQuery to the rescue! I'll be adding a class to a LI depending on the text inside the LI.

I could use a bit of help using the $(this) object of jQuery. For example the following code works:

if ($('div.nav ul li:nth-child(2):contains("About")').length > 0) {
    $('div.nav ul li:nth-child(2)').addClass("about");
}

But in order to not repeat my code exponentially, I would rather write something like this:

if ($('div.nav ul li:nth-child(2):contains("About")').length > 0) {
    $(this).addClass("about");
}

This however is not working. I'm sure that I'm butchering something terribly obvious, but I've read a few tutorials on the $(this) object and I've been staring at my code long enough to come and ask for a bit of help :)

Also, perhaps I'm missing a much easier solution. Let's say I have the following markup.

<ul id="nav">
<li>About</li>
<li>Contact</li>
<li>News</li>
</ul>

Now let's assume this navigation might change in the future so I can't simply assign a class / icon to each LI using nothing but nth-child. Is there a way I can loop through each LI, and then loop through each condition? I'm not familiar enough with jQuery, but in my mix of English and jQuery it might look something like this:

loop through #nav:each li {
    if (child:contains("About")').length > 0) {
        $(this).addClass("about");
    }
    if (child:contains("Contact")').length > 0) {
        $(this).addClass("contact");
    }
    if (child:contains("News")').length > 0) {
        $(this).addClass("news");
    }
}

Unfortunately that is just made up syntax! Can anyone possibly help me write that in REAL jQuery :) If so, I can possibly help you with any CSS issues you may be having.

Thanks!

Upvotes: 1

Views: 2355

Answers (4)

swatkins
swatkins

Reputation: 13630

The jQuery each() function allows you to iterate through a collection. The $(this) object will reference the current element in the iteration. Assuming your classes will always match the content, this code will work. Otherwise, you could create a switch statement for the classes.

$("ul#nav li").each(function(){
    var txt = $(this).text();
    $(this).addClass(txt.toLowerCase());
});

Upvotes: 1

mccow002
mccow002

Reputation: 6914

$(this) works in functions only. It is a reference to the element that the function is called against. An if statement is not a function, therefore, if does not apply. Instead, you can do variable caching, like so:

var $aboutItem = $('div.nav ul li:nth-child(2):contains("About")');
if($aboutItem.length > 0) {
    $aboutItem.addClass("about");
}

Upvotes: 1

Anurag
Anurag

Reputation: 141879

You don't need to loop over the li elements. Working with the sample markup you posted, here's how you can add a class to the About li element.

$('#nav li:contains(About)').addClass('about')

Rinse and repeat two more times, for the other two items.

$('#nav li:contains(Contact)').addClass('contact')
$('#nav li:contains(News)').addClass('news')

Upvotes: 0

ShankarSangoli
ShankarSangoli

Reputation: 69915

In your first code snippet this is not pointing to the DOM element which you expected but it is mostly the instance which executed that code so it will not work.

You can use $.each loop and look for each and apply the class. In this case you can see the use of $(this).

$('#nav > li').each(function(){

    if ($(this).filter(':contains("About")').length > 0) {
        $(this).addClass("about");
    }
    else if ($(this).filter(':contains("Contact")').length > 0) {
        $(this).addClass("contact");
    }
    else if ($(this).filter(':contains("News")').length > 0) {
        $(this).addClass("news");
    }
});

Upvotes: 1

Related Questions