Search code examples
jqueryescapingsizzle

Selecting an element with Id having colons in Sizzle/jQuery


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.


Solution

  • // 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.