Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery UI :data selector does not return HTML5 data attributes

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?

like image 873
Yanick Rochon Avatar asked Jan 30 '13 19:01

Yanick Rochon


3 Answers

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.

like image 175
Kevin B Avatar answered Nov 14 '22 06:11

Kevin B


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]").

like image 34
Plynx Avatar answered Nov 14 '22 06:11

Plynx


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/

like image 1
Selvakumar Arumugam Avatar answered Nov 14 '22 05:11

Selvakumar Arumugam