Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What chars needs escaping in querySelector?

Tags:

javascript

css

According to the document here: https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector#Notes

It says some characters need to be escaped when doing querySelector:

To match ID or selectors that do not follow the CSS syntax (by using a colon or space inappropriately for example), you must escape the character with a back slash. As the backslash is an escape character in JavaScript, if you are entering a literal string, you must escape it twice (once for the JavaScript string, and another time for querySelector):

I was hoping to write a function that does the escaping on a string but needed to know which chars needed escaping first.

Thanks

like image 775
Noitidart Avatar asked Apr 03 '14 07:04

Noitidart


2 Answers

Updated answer:

In a comment below you said:

The thing is Im making a firefox addon Im doing is identifying items by the attribute in label (cuz class is same for all items). and so querySelector('[label="blah blah blah"]') and the user can edit the label, so thats where the problem comes in, users can make it anything.

Ah, that changes everything. A completely different set of rules applies for the operand in an attribute selector. As you're using " to surround the operand, I think you just have to escape the " with a backslash (and of course, escape any backslashes with a backslash), e.g. the selector (not the string for querySelector, we'll come back to that) for a label with the text testing "one" two three would be [label="testing \"one\" two three"]. So starting with a variable containing the target label, we'd replace all " characters with \" and all \ characters with \\:

var div = document.querySelector('[label="' + theLabel.replace(/["\\]/g, '\\$&') + '"]');

Full example: Live Copy

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Escaping attributes</title>
</head>
<body>
  <div label='testing "one" \two three'>This should turn green</div>
  <script>
    (function() {
      var label = 'testing "one" \\two three';
      var div = document.querySelector('[label="' + label.replace(/["\\]/g, '\\$&') + '"]');
      div.style.color = "green";
    })();
  </script>
</body>
</html>

Original answer:

Full details in the CSS specification; for instance, the details for what characters in ID and class selectors need escaping is here:

In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item). For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".

Now, the thing about querySelector / querySelectorAll is that since they take a string, and backslashes are special in string literals, you have to use two backslashes in a string literal to have one backslash in your CSS selector. So for the last example in the quote, suppose you wanted to use that as a class selector. You'd have to do this:

var list = document.querySelectorAll(".B\\26 W\\3F");

...which passes the selector .B\26 W\3F into the selector engine. Live Example | Live Source

like image 99
T.J. Crowder Avatar answered Oct 15 '22 13:10

T.J. Crowder


If it is possible, you can use this solution, albeit not cross-browser (all modern browsers except IE) - https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape

CSS.escape(".foo#bar") ->"\.foo\#bar"
like image 29
mlosev Avatar answered Oct 15 '22 13:10

mlosev