3

I have an HTML which has some elements having ids with colons. For example,

<div id="i:have:colons">Get my selector!!</div>
<my:another:test> This time with tag names </my:another:test>

I want to select these elements using jQuery. Here are my few attempts and Jsbin Demo

function escape(id) {
  return id.replace( /(:|\.|\[|\])/g, '\\$1');
}

var id = "i:have:colons";

// Does not work
console.log($('#' + id).length);

// Works
console.log($("#i\\:have\\:colons").length);

var escapedId = escape(id);

// Q1. Why answer shows only 1 backslash while I used 2 in regex
console.log(escapedId); //'i\:have\:colons'

// Works
console.log($('#' + escapedId).length);

// Q2. Does not work while escapedId === 'i\:have\:colons'. How and why ?
console.log($('#' + 'i\:have\:colons').length);

Edit After T.J Answer

var tag = 'my:another:test';

console.log('Testing tag name now----');

console.log($(tag).length);

var tag2 = tag.replace(/[:]/g, '\\\\:');

// Does not work with tagnames but this works with Id
console.log($(tag2).length);

var tag3 = tag.replace(/[:]/g, '\\:');

// Q3. Why does this work with tagnames but not with ids ?
console.log($(tag3).length);

My Question is in the comments in JS code.

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
Sachin Jain
  • 21,353
  • 33
  • 103
  • 168

1 Answers1

4

// Q1. Why answer shows only 1 backslash while I used 2 in regex

Because the string you used as a substitute only had one backslash in it, because backslashes are special in string literals. To get an actual backslash into the selector, you need \\ in the string literal. But your escape function is correct, because you only want one in the actual regex.

// Q2. Does not work while escapedId === 'i\:have\:colons'. How and why ?

console.log($('#' + 'i\:have\:colons').length);

Much the same reason, there are no backslashes in the selector. \: in a string literal is just :. You need to escape the backslashes:

console.log($('#' + 'i\\:have\\:colons').length);

Options for selecting these elements:

  1. Escape the id value correctly, using your escape function.

  2. Use getElementById:

     $(document.getElementById("i:have:colons"))
    
  3. Use an attribute selector:

     $('[id="i:have:colons"]')
    

    But that will be slower (although the odds of it mattering are low), as jQuery won't optimize it into a getElementById call.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I am happy to accept the answer but just wondering why the same logic is not working with tag names. Checkout http://jsbin.com/lejili/2/edit?html,js,console – Sachin Jain Aug 25 '14 at 11:27
  • @blunderboy: Actually, part of my answer was wrong (now fixed), your `escape` function was fine; my answer to your actual Q1 was correct, but then I went off on a tangent that was incorrect. So the answer to your Q3 is: It *does* work with both IDs and tag names: http://jsbin.com/cukib/1/edit?html,js,console (Although note that HTML tag names are not supposed to have colons in them: http://www.w3.org/TR/html5/syntax.html#syntax-tag-name) – T.J. Crowder Aug 25 '14 at 11:39