193

If my html looked like this:

<td class="controlCell">
    <input class="inputText" id="SearchBag.CompanyName" name="SearchBag.CompanyName" type="text" value="" />
</td>

How could I select #SearchBag.CompanyName with JQuery? I can't get it to work and I fear it's the dot that's breaking it all. The annoying thing is that renaming all my id's would be a lot of work, not to mention the loss in readability.

Note:
Please let's not start talking about how tables are not made for lay-outing. I'm very aware of the value and shortcomings of CSS and try hard to use it as much as possible.

Boris Callens
  • 90,659
  • 85
  • 207
  • 305
  • 1
    Is a period in an ID even valid HTML? – cletus Mar 03 '09 at 09:23
  • 7
    Yes. IDs may contain ‘-’, ‘_’, ‘.’ and ‘:’. http://www.w3.org/TR/html4/types.html#type-name – bobince Mar 03 '09 at 10:01
  • Jeps, my pages all validate except for the double tag the asp.net mvc framework generates.. – Boris Callens Mar 03 '09 at 10:02
  • 2
    possible duplicate of [How do I get jQuery to select elements with a . (period) in their ID?](http://stackoverflow.com/questions/350292/how-do-i-get-jquery-to-select-elements-with-a-period-in-their-id) – 2rs2ts Dec 03 '13 at 17:07

8 Answers8

234

@Tomalak in comments:

since ID selectors must be preceded by a hash #, there should be no ambiguity here

“#id.class” is a valid selector that requires both an id and a separate class to match; it's valid and not always totally redundant.

The correct way to select a literal ‘.’ in CSS is to escape it: “#id\.moreid”. This used to cause trouble in some older browsers (in particular IE5.x), but all modern desktop browsers support it.

The same method does seem to work in jQuery 1.3.2, though I haven't tested it thoroughly; quickExpr doesn't pick it up, but the more involved selector parser seems to get it right:

$('#SearchBag\\.CompanyName');
bobince
  • 528,062
  • 107
  • 651
  • 834
  • 1
    "#id.class is a valid selector that requires both an id and a separate class to match": As per the HTML spec, IDs must be unique throughout the document. What would "#id.class" be good for? I mean, you can't be any more specific than "#id", can you? – Tomalak Mar 03 '09 at 10:19
  • 2
    @Tom: “#id.class” might be good for multiple documents using the same stylesheet, or setting states with client-side-scripting. For example “#navhome.navselected”. – bobince Mar 03 '09 at 10:43
  • @bobince: Yeah, cletus came up with the same example, and I quess it's valid. Still it feels strange to me, and I can't see the genuine advantage of being able to do that. Especially in the light of HTML allowing dots in the ID and the fact that you can always use ".navselected" to achieve the same. – Tomalak Mar 03 '09 at 10:49
  • 1
    You might, for example, want a selected #navhome to light up in a different colour to a selected #navabout, but other .navselected properties to be shared. I wouldn't say this situation comes up all the time, but I've certainly needed it occasionally. – bobince Mar 03 '09 at 11:17
  • It's an edge case, but I can follow the logic (you've got my +1 already). The drawback that remains is that since this isn't caught by quickExpr, the getElementById() shortcut in jQuery is probably not used, and thus it will perform worse even though it is an ID. Same goes for my solution. – Tomalak Mar 03 '09 at 12:35
  • Yeah, I would go for ‘_’ rather than ‘.’ if possible; in addition to jQuery performance, the CSS backslash escape is just ugly! – bobince Mar 03 '09 at 13:29
  • 5
    I think answer of @Tomalak is more elegant, like: ```$('[id="profile.birthdate"]')``` – dr.dimitru Oct 10 '14 at 17:06
135

One variant would be this:

$("input[id='SearchBag.CompanyName']")
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 1
    Indeed. Could you tell me why your solution works and $("#SearchBag.CompanyName") doesn't? – Boris Callens Mar 03 '09 at 09:17
  • 10
    Because .CompanyName is treated as a class selector. – cletus Mar 03 '09 at 09:22
  • 2
    Quickly looking at the source code, it is either a deliberate design decision or a bug. The regex used to identify id selectors (named quickExpr) does not include the dot as a valid character. The HTML spec however allows it. – Tomalak Mar 03 '09 at 09:29
  • Then howcome your selector does include the dot and mine doesn't? – Boris Callens Mar 03 '09 at 09:32
  • @cletus: But since ID selectors must be preceded by a hash #, there should be no ambiguity here. HTML allows a dot in the ID attribute, so should CSS/jQuery. Can you point out a situation where allowing this could cause trouble? (I can't, but I'm not sure.) – Tomalak Mar 03 '09 at 09:33
  • 6
    Having a class selector on an ID is possibly useful. Imagine you have a #menu element on every page but want to make it different on one of your pages. #menu.hideme for example? Marginal I know but it's valid. – cletus Mar 03 '09 at 10:40
  • 2
    This clearly is the superior answer. Works also with variables like this: $("tr[id='" + private_var + "']").css("background-color", "#EEEEEE"); – Stephan Kristyn Aug 13 '12 at 10:32
  • @Tomalak Please note, dot notation with backslashes is much quicker: http://jsperf.com/jquery-selectors-perf-test – dr.dimitru Nov 25 '14 at 15:29
  • 1
    @Tomalak I was having the same issue as Boris, so I used backslashes where I was directly referencing the id itself. But problem came when I was getting list of ids with and without dot in them from page, there i could not used backslashes. This have helped me in achieving what I needed. thanks – emphywork Sep 08 '16 at 08:58
37

You don't need to escape anything if you use document.getElementById:

$(document.getElementById('strange.id[]'))

getElementById assumes the input is just an id attribute, so the dot won't be interpreted as a class selector.

Blender
  • 289,723
  • 53
  • 439
  • 496
20

Short Answer: If you have an element with id="foo.bar", you can use the selector $("#foo\\.bar")

Longer Answer: This is part of the jquery documentation - section selectors which you can find here: http://api.jquery.com/category/selectors/

Your question is answered right at the beginning of the documentation:

If you wish to use any of the meta-characters ( such as 
!"#$%&'()*+,./:;?@[\]^`{|}~ ) 
as a literal part of a name, you must escape the character with 
two backslashes: \\. For example, if you have an element with id="foo.bar", 
you can use the selector $("#foo\\.bar"). The W3C CSS specification contains 
the complete set of rules regarding valid CSS selectors. Also useful is the 
blog entry by Mathias Bynens on CSS character escape sequences for identifiers.
oneiros
  • 3,527
  • 12
  • 44
  • 71
  • 4
    You do realize that this question is more than three years old and the documentation may not have been the same then, right? – Reimius Sep 21 '12 at 17:38
12

attr selection seems to be appropriate when your ID is in a variable:

var id_you_want='foo.bar';
$('[id="' + id_you_want + '"]');
bishop
  • 37,830
  • 11
  • 104
  • 139
4

This is documented in the jQuery selectors API:

To use any of the meta-characters (such as !"#$%&'()*+,./:;<=>?@[\]^`{|}~) as a literal part of a name, it must be escaped with with two backslashes: \\. For example, an element with id="foo.bar", can use the selector $("#foo\\.bar").

In short, prefix the . with \\.

$('#SearchBag\\.CompanyName')

The problem is that . will match a class, so $('#SearchBag.CompanyName') would match <div id="SearchBag" class="CompanyName">. The escaped with \\. will be treated as a normal . with no special significance, matching the ID you desire.

This applies to all the characters !"#$%&'()*+,./:;<=>?@[\]^`{|}~ which would otherwise have special significance as a selector in jQuery.

Jon Surrell
  • 9,444
  • 8
  • 48
  • 54
2

Guys who's looking for more generic solution, I found one solution which inserts one backward slashes before any special characters, this resolves issues related to retrieving name & ID from a div which contains special characters.

"Str1.str2%str3".replace(/[^\w\s]/gi, '\\$&')

returns "Str1\\.str2\\%str3"

Hope this is useful !

Community
  • 1
  • 1
Abhishek
  • 1,558
  • 16
  • 28
1

You can use an attribute selector:

$("[id='SearchBag.CompanyName']");

Or you can specify element type:

$("input[id='SearchBag.CompanyName']");
ntroccoli
  • 44
  • 2