Ticket #6448 (closed bug: fixed)
Problem with selector having "]" and context
| Reported by: | maizy | Owned by: | |
|---|---|---|---|
| Priority: | high | Milestone: | 1.5 |
| Component: | selector | Version: | 1.5b1 |
| Keywords: | scope ] | Cc: | |
| Blocking: | Blocked by: | #6093 |
Description
I have html structure like that:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<body>
<div id="wrap">
<!-- ... -->
<button name="belongs[ok]">Ok</button>
<!-- ... -->
</div>
</body>
</html>
This selectors work fine:
$('button[name$="ok\\]"]').length === 1; //true
$('button[name*="ok"]').length === 1; //true
$('div#wrap button[name$="ok\\]"]').length === 1; //true
$('button[name*="ok\\]"]', $('#wrap')).length === 1; //true
$('div#wrap').length === 1; //true
but that doesn't:
var res = $('button[name$="ok\\]"]', $('#wrap')).length;
res === 1; //false
res === 0; //true
jQuery 1.4.2. Checked on Google Chrome 5.0.342.9 beta (Linux), FF 3.5.9 (Linux).
Change History
comment:2 Changed 3 years ago by rsinton
Something else that works: $('button[name$="ok\\]"]', $('#wrap') matches against <button name="belongs[ok\]">Ok</button>.
This looks like the double-backslash is causing a match on a literal backslash, instead of escaping the following special character, but this is only happening when a context parameter is supplied, and that context parameter is a jQuery object (not a raw DOM element). Very curious.
comment:3 Changed 3 years ago by rsinton
Sorry, was confusing get[0] with get(0).
$('button[name$="ok\\]"]', $('#wrap').get(0) )
and
$('button[name$="ok\\]"]', $('#wrap') )
both fail.
So the apparent behaviour is as simple as: double backslashes are required for matching special chars when no context parameter is given, but single backslashes work when there is a context parameter supplied.
comment:4 Changed 3 years ago by rsinton
Some work with a debugger makes me think that the issue lies in .filter(), which gets called internally when there is a context parameter.
As expected from that theory, this fails:
$('#wrap button').filter('[name$="ok\\]"]' )
but this works:
$('#wrap button').filter('[name$="ok\]"]' )
comment:5 Changed 3 years ago by rsinton
I doubt that it's really the correct place to do it, but confirmed that replacing
Sizzle.filter = function(expr, set, inplace, not){
with
Sizzle.filter = function(expr, set, inplace, not){
expr = expr.replace(/\\/g, "");
makes the problem go away, by removing the single backslash that has already been unescaped down from the double one in the original selector.
Please follow the bug reporting guidlines and use jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

Some extra observations: