Let say I have this piece of HTML :
<div id="container">
<ul>
<li><a href="#" data-some-info="foo">Bar</a>
<!-- repeating a few like the one --> -->
<!-- above for a while ... -->
</uL>
</div>
And I want to apply something to all the anchor elements with the data some-info
when it is defined.
I just want to understand why this behaviour (is it a bug?)
$("#container").find("a:data(some-info)").size(); // -> 0
$("#container").find("a").data("some-info"); // -> "foo"
$("#container").find("a:data(some-info)").size(); // -> 1 (actual expected val)
Any ideas?
More Info : I'm using jQuery 1.9.0, and jQuery UI 1.9.2
** Edit **
I know about $("#container").find("a[data-some-info]")
. This is not what I question here. If there is a data selector, why does it behave this way?
This is how the selector is implemented:
$.extend( $.expr[ ":" ], {
data: $.expr.createPseudo ?
$.expr.createPseudo(function( dataName ) {
return function( elem ) {
return !!$.data( elem, dataName );
};
}) :
// support: jQuery <1.8
function( elem, i, match ) {
return !!$.data( elem, match[ 3 ] );
},
(Ref. https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.core.js#L160)
Note how it is using $.data
rather than $(elem).data
. This means it is only looking for data that has been stored on the element through either the $.data
or $().data
method. It does not look for data attributes on the element and i do not think it is intended for that purpose. The attribute equals selector is what you should be using. [data-foo]
Note however that it looks at the attribute, if you add data to an element with jQuery's $().data
it may not match that selector if jQuery doesn't update the attribute.
The :data selector is not part of JQuery core. It might be a bug, but the JQuery docs say that HTML5 data attributes are pulled into the internal JQuery data object (presumably on calls to .data
) rather than being available as part of a :data
pseudo-selector (which according to the JQuery UI docs queries the internal data representation as is and says nothing about HTML5 data attributes)
Alternate approach:
Use $("#container").find("a[data-some-info='foo']")
, or for if anything is set on the data attribute, .find("a[data-some-info]")
.
From Docs,
The expression
$( "div:data(foo)")
matches a<div>
if it has data stored via.data( "foo", value )
And from jquery code ->
jQuery
data()
is stored in a separate object inside the object's internal data cache in order to avoid key collisions between internal data and user-defined data (comment from jQuery code)
https://github.com/jquery/jquery/blob/master/src/data.js#L51
https://github.com/jquery/jquery/blob/master/src/data.js#L63
When it is defined in the HTML, it is just a user defined data element which will NOT be selected by the jQuery :data
selector.
However when you call .data(some-info)
, it actually reads the user defined data and copies it to the internal data and later using :data
picks up the element as it could find it in the internal data.
It is NOT a bug, as this is clearly mentioned in the docs.
You should use .length
which is a property to get the number of returned elements from the selector.
Also .size
is deprecated since as of jQuery 1.8. http://api.jquery.com/size/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With