Jquery Syntax error, unrecognized expression:

Why do I get this error and how can I test for it so it wont break, I tried checking for null but obviously that wont work, thanks.

Please don't advice to not write the ID like this as I know its wrong but it is a possibility.

var jsonTest = [
  {
    "myId": "''''''\"\"\"\"'''''''''''''\"#####$'''''",
  }
];

alert(jsonTest[0].myId); 
// Works - alerts the myId

$('#' + jsonTest[0].myId ).length; 
// Error: Syntax error, unrecognized expression:
// #''''''""""'''''''''''''"#####$'''''

Answers:

Answer

jQuery's uses this code to detect an id based selector :

characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+"
...
"ID": new RegExp( "^#(" + characterEncoding + ")" ),

This regex fails for "''''''\"\"\"\"'''''''''''''\"#####$'''''" or more simply for "'".

The query engine is limited, which isn't very surprising for a so concise language and id validity rules so lax. it can't handle any valid id.

If you really need to be able to handle any kind of valid id, use

$(document.getElementById(jsonTest[0].myId))

In fact, you should never use $('#'+id) as it simply adds a useless (and a little dangerous) layer of parsing for the same operation.

Answer

If I understood your question, you have an ID that contains special characters. You basically need to escape them so they're treated as literal characters rather than query selectors:

To use any of the meta-characters ( such as !"#$%&'()*+,./:;<=>[email protected][]^`{|}~ ) 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").

... and in this case you also need an additional escaping level for the string delimiter, ". It's crazy but this works:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript"><!--
jQuery(function($){
    console.log( $("#" + "\\'\\'\\'\\'\\'\\'\\\"\\\"\\\"\\\"\\'\\'\\'\\'\\'\\'\\'\\'\\'\\'\\'\\'\\'\\\"\\#\\#\\#\\#\\#\\$\\'\\'\\'\\'\\'").length );
});
//--></script>
</head>
<body>

<div id="''''''&quot;&quot;&quot;&quot;'''''''''''''&quot;#####$'''''">Foo</div>

</body>
</html>

Edit: Of course, dystroy's answer —omit jQuery selection engine and use getElementByID()— is way more practical. jQuery manual links an interesting blog entry that covers this and other related techniques:

document.getElementById() and similar functions like document.getElementsByClassName() can just use the unescaped attribute value, the way it’s used in the HTML. Of course, you would have to escape any quotes so that you still end up with a valid JavaScript string.

Answer

W3C has defined a new function for this this: CSS.escape(). In your example code, it would look like this:

var jsonTest = [
  {
    "myId": "''''''\"\"\"\"'''''''''''''\"#####$'''''",
  }
];

$('#' + CSS.escape(jsonTest[0].myId)).length; // Works 

Browsers don't yet support it, but there is a polyfill library that you can use in the mean time: https://github.com/mathiasbynens/CSS.escape

I've used it with success in my project.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.