Reputation: 15695
For some reason, $('#p-foo').siblings('.bar')
works, but $('#g-foo').siblings('.bar')
does not. Can anyone point out to me why this is the case?
<div>
<p id="p-foo"></p>
<p class="bar"></p>
</div>
<svg>
<g id="g-foo"></g>
<g class="bar"></g>
</svg>
I wrote a quick test script to demonstrate the problem:
var selector = '.bar',
attribute = '[class=bar]';
var check = function (foo, d) {
console.log(d + ' matches ' + foo.siblings(d).length);
};
var p_foo = $('#p-foo');
console.log('DIV');
check(p_foo, selector);
check(p_foo, attribute);
var g_foo = $('#g-foo');
console.log('SVG');
check(g_foo, selector);
check(g_foo, attribute);
And the output is:
DIV
.bar matches 1
[class=bar] matches 1
SVG
.bar matches 0
[class=bar] matches 1
Upvotes: 1
Views: 804
Reputation: 55688
I thought this was an interesting problem, so I did a little source code research.
.siblings()
calls
$.filter
, which delegates to Sizzle and eventually uses the filters here.
If you use the [class=bar]
selector, Sizzle uses the ATTR
filter, which simply retrieves the attribute and does an equality check against its value. This works for both p
and g
.
If you use the .bar
selector, Sizzle uses the CLASS
filter, which uses a regex against elem.className
. In SVG elements, however, className
is not a string, but an instance of SVGAnimatedString
(which, to be perfectly honest, I've never fully wrapped my head around, but it seems to have both an animValue
and a baseValue
). The regex fails, and the element isn't matched.
I believe Sizzle has additional handling that might make this work if the entire document is SVG or XML, but because this SVG is embedded in an HTML doc, that doesn't kick in.
Upvotes: 3