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