2

I'm new to JQuery and struggling to set an attribute of an element inside a list. I have the following html

<ul class="collections">
<li><a href="#" id="2">LINEN </a></li>
<li><a href="#" id="3">ANIMAL PRINTS</a></li>
<li><a href="#" id="4">BASKET WEAVE</a></li>
<li><a href="#" id="5">FAUX LEATHER</a></li>
<li><a href="#" id="6">FAUX SUEDE</a></li>
<li><a href="#" id="7">HALLMARK</a></li>
<li><a href="#" id="8">JUMBO CORD</a></li>
<li><a href="#" id="9">PHYTHON</a></li>
<li><a href="#" id="10">CHENILLE CARLTON</a></li>

I want to add the attribute class = "current" to the item in the list where the id is 2.

I can set all items using $('.collections a').attr('class','current');

I can detect the item with the id of 2 using:

if($('.collections a').attr('id') == 2){
        console.log('WE HAVE A MATCH');

    }

But here I am unsure how to get a reference to the actual element.

I've managed set the class using the equals method:

        $(".collections a:eq(0)").attr('class','current');

But would prefer to be able to set it using the id of the element in case the ordering of the list should change.

Any help would be greatly appreciated.

Thanks in advance.

Regards

Bear
  • 1,541
  • 3
  • 20
  • 32

3 Answers3

3

As the id attribute should be unique, this will do it

$(".collections a#2").addClass("current")

But I strongly advise you NOT to start your id-s with numbers

Zoltan Toth
  • 46,981
  • 12
  • 120
  • 134
  • 1
    Why not? As of HTML5, IDs can legally start with numerals. Backwards compatibility is not an issue either, since this has always worked, even though it was against the spec. – Joseph Silber Jul 17 '12 at 00:42
  • I cant use the above nor can I use document.getElementById('2').setAttribute('class','current'); as I have an id of another element in a separate div which is 2. This is the case as I am pulling the id's straight from a database. Is it possible to search for an for the required element with the id 2 just in the collections class? – Bear Jul 17 '12 at 00:44
  • @JosephSiber Just for backward compatibility and to avoid some unexpected behavior, that might cause some hard to find bugs – Zoltan Toth Jul 17 '12 at 00:44
  • @Bear updated with the collection selector, but that's *absolutely* invalid markup to have 2 elements with the same id – Zoltan Toth Jul 17 '12 at 00:46
  • 1
    @ZoltanToth - That wouldn't really work either. [If you have 2 elements with matching IDs (which you shouldn't), you should use an attribute selector](http://stackoverflow.com/questions/7262195/several-elements-with-the-same-id-responding-to-one-css-id-selector/7262229#7262229). – Joseph Silber Jul 17 '12 at 00:48
  • I know, I need to modify my code to remove the duplicates. Through trial and error I found the following to work $(".collections a:#2").attr('class','current'); but this isn't ideal as it may lead to bugs. Originally I didn't have duplicates but through adding extra functionality duplicates are present on 2 occasions. – Bear Jul 17 '12 at 00:49
  • @JosephSiber You're right - it will work. But that doesn't mean we should follow bad practices, even if they currently work. I think we can agree that we have to try to write robust code avoiding ambiguous solutions that might suffice now, but fail in the future. – Zoltan Toth Jul 17 '12 at 00:55
  • 1
    @ZoltanToth - Compare [this](http://jsfiddle.net/69va4/) to [this](http://jsfiddle.net/69va4/1/). – Joseph Silber Jul 17 '12 at 01:00
  • @JosephSiber - Exactly. We have to do it [right](http://jsfiddle.net/69va4/2/) to make it work and not "hack" it. My point - we should not rely on browsers' ways and ability to handle our faulty code, but try to do things correctly. If the OP suddenly duplicates not just the `id`-s but the `class`-es - http://jsfiddle.net/69va4/3/ And in case of `classes` it's not even duplication because that's absolutely legit to use the same class multiple times – Zoltan Toth Jul 17 '12 at 14:49
1

This should be fine:

var id = 2;
$('.collections li a').removeClass('current'); // reset current class
$('#' + id).addClass('current'); // set current case given an ID
Martin
  • 6,632
  • 4
  • 25
  • 28
1

There are at least a few question here that need to be answered.

  1. to retrieve and set attributes, use $.prop() (link)
  2. to retrieve an element by its id property use the hash selector ($('#id_of_element') or $('li#id_of_li_element')) (full list of selectors here)
  3. to check a retrieved collections, look at $('selector').length. It's 0 if it didn't find anything so you can use if($('li#id_of_li').length){ ... };
  4. don't use numeric ids because some browsers don't see them. Always start an id with an alphabetic letter example <li id="li_1"> instead of <li id="1">.
  5. to set, retrieve and remove classes, use the dedicated methods $.addClass('classname'), $.hasClass('classname') and $.removeClass('classname')
  6. to check whether an element matches a particular selector, you can use $('elements').is('selector') (link here)

I really hope this clears out some of the problems

Silviu-Marian
  • 10,565
  • 6
  • 50
  • 72
  • Thanks for your detailed answer, really helped. The following seemed to work in chrome at least $(".collections a:#2").addClass('current'); but I doubt its correctness / cross browser compatibility. I plan to remove the duplicate id's and refrain from using leading numbers. – Bear Jul 17 '12 at 00:56
  • 1
    It's `$('.collections a#2').addClass('current'); ` (without `:` between `a` and `#`). If you start your id with a letter instead of number the whole rig will be completely cross-browser. – Silviu-Marian Jul 17 '12 at 01:19