Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does jQuery's :visible selector work differently when filtered?

I noticed today that jQuery's :visible selector shows an unexpected behaviour when combined with an attribute selector. Its behaviour differs depending on
a) whether it is used inline or within the filter method
b) the type of attribute selector it's combined with

Examples:

Given the following markup

<input required name="name" type="text" />

The following is true for jQuery

$('[required="required"]').filter(':visible').length == 0; //true
$('[required="required"]:visible').length == 0; //false - why does jquery find the input?

The disabled attribute shows similar behaviour. However, data attributes do not show the same behaviour:

Given the following markup

<input data-boolean name="name" type="text" />

The following is true for jQuery

$('[data-boolean="true"]').filter(':visible').length == 0; //true
$('[data-boolean="true"]:visible').length == 0; //true

Here's a link to a fiddle that demonstrates the problem.

I wouldn't expect [required="required"] to match an element with a blank required attribute, and it doesn't when used as a selector on its own, but it does when paired with the :visible selector. Why is this?

like image 366
Andy F Avatar asked Jun 24 '15 13:06

Andy F


1 Answers

The root cause of the difference seems to be that Sizzle (the non-native selector code in jQuery) matches boolean attributes like required when an explicit test is made for the formal default attribute value. The native querySelectorAll() code, however, does not, unless the attribute actually had the value in the original HTML.

Boolean selectors like required or readonly can be expressed in HTML without a value, but that implies that the value is to be taken as the attribute name itself.

When you use a pseudo-class like :visible, then Sizzle realizes that the native code won't work so it takes over. It's not the :visible test itself that causes the problem; you get the same effect with :text or any other extension supported by Sizzle (and which doesn't change the sense of the selector, obviously).

Personally I would consider this a bug, though it may be somewhat difficult to fix because the attribute value really is reported as being required when the DOM node is interrogated via getAttribute().

If HTML code were to be meticulously written with the attributes fully specified:

<input required=required ...>

then there'd be no perceived difference, but that seems a little burdensome.

like image 147
Pointy Avatar answered Oct 06 '22 03:10

Pointy