Jquery select all elements that have $jquery.data(

2019-01-30 21:12发布

问题:

Select elements that i have previously set with jquery.data();

i.e. Select all elements with .data('myAttr') already been set.

SOLUTION

A jsfiddle to demostrate is Fiddle

回答1:

You could do

$('[data-myAttr!=""]'); 

this selects all elements which have an attribute data-myAttr which is not equal to '' (so it must have been set);

you could also use filter()

$('*').filter(function() {
    return $(this).data('myAttr') !== undefined;
});


回答2:

The best and simple way to select them is:

$('[data-myAttr]')

More Information:

I tested a lot of things.

Using $('[data-myAttr!=""]') doesn't work for all cases. Because elements that do not have a data-myAttr set, will have their data-myAttr equal to undefined and $('[data-myAttr!=""]') will select those as well, which is incorrect.



回答3:

You can use filter():

var elements = $("*").filter(function() {
    return $(this).data("myAttr") !== undefined;
});


回答4:

You could use this jQuery Selector extention: Querying element data

$(':data');       // All elements with data  
$(':not(:data)'); // All elements without data


回答5:

You can use JQuery UI with the :data() selector

Selects elements which have data stored under the specified key.

Check this jsfiddle for an example

To get all elements matching .data('myAttr') you can use

var matches = $(':data(myAttr)');

This should work for both elements with data- attributes and elements with data stored using $.data() because

As of jQuery 1.4.3 HTML 5 data- attributes will be automatically pulled in to jQuery's data object.

But this doesn't work very well. Check this jsfiddle and you will see that the second time the selector is called it should match 2 elements and is only matching one. This is due to "a bug" in the jquery-ui library.

This is taken from the core jquery-ui file.

 $.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 ] );
        }
});

As you can see they are using $.data(elem, match) instead $(elem).data(match) which causes the cache not to be updated in case you are requesting elements with data- attributes. If the element has been tested for data() storage this works well but if not it will not be included in the resulting matches.

This might not be a bug at all if what you want is to match only elements with data information set by you but if not you are left with two options.

  1. Don't use jquery-ui and extend your own pseudo-selector $(:mydata(myAttr))

    $.extend($.expr[":"], {
       mydata: $.expr.createPseudo ?
       $.expr.createPseudo(function(dataName) {
          return function(elem) {
             return !!$(elem).data(dataName);
          };
       }) : function(elem, i, match) {
           return !!$(elem).data(match[3]);
       }
    });
    

     // pseudoselector code
     $.extend($.expr[":"], {
       mydata: $.expr.createPseudo ?
         $.expr.createPseudo(function(dataName) {
           return function(elem) {
             return !!$(elem).data(dataName);
           };
         }) : function(elem, i, match) {
           return !!$(elem).data(match[3]);
         }
     });
     // end pseudoselector
    
     testSelector = function() {
       var matched = $(':mydata(test)'),
         results = $('#results');
       results.append('<div>You matched ' + matched.length + ' elements</div>');
       matched.css('border', 'black 3px solid');
       console.log(matched);
       console.log('You matched ' + matched.length + ' elements');
     };
    
     testSelector();
     $('#addData').click(function() {
       $(".bar").data('test', 'value2');
       testSelector();
     });
    
     
     .foo {
       background-color: red;
       color: white;
     }
     .bar {
       background-color: blue;
       color: white;
     }
     #addData {
       margin-top: 20px;
     }
    
     
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
     <div>
       <span class="bar">without data attribute</span>
       <span class="foo" data-test="value1">with data attribute</span>
     </div>
     <button id="addData" type="button">Add data</button>
     <div id="results"></div>
    
     

  2. Use jquery-ui with the :data pseudoselector and join the results of selecting [data-myAttr] to include the ones that might be skipped

    var matches = $(':data(myAttr)', '[data-myAttr]')
    

     testSelector = function() {
       var matched = $(':data(test), [data-test]'),
           results = $('#results');
       results.append('<div>You matched ' + matched.length + ' elements</div>');
       matched.css('border', 'black 3px solid');
       console.log(matched);
       console.log('You matched ' + matched.length + ' elements');
     };
    
     testSelector();
     $('#addData').click(function() {
       $(".bar").data('test', 'value2');
       testSelector();
     });
    
     
     .foo {
       background-color: red;
       color: white;
     }
     .bar {
       background-color: blue;
       color: white;
     }
     #addData {
       margin-top: 20px;
     }
    
     
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
     <script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
     <div>
       <span class="bar">without data attribute</span>
       <span class="foo" data-test="value1">with data attribute</span>
     </div>
     <button id="addData" type="button">Add data</button>
     <div id="results"></div>
    
     



回答6:

$('[data-myAttr]').each(function() {
       var element = $(this);
       // Do something with the element
});


回答7:

Select elements that i have previously set with jquery.data();


The question is for finding all elements with a specific key and not any data.


Try utilizing jQuery.data()

$(".myClass").each(function(i){
    if( i % 2 == 0 ){
        $(this).data("myAttr",i + 1);                
    }
});
    
var res = $(".myClass").map(function(i) {
    console.log($(this).data("myAttr"));
    return $.data(this, "myAttr") !== undefined ? this : null
});    

console.log(res);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div class="myClass">1</div>
<div class="myClass">2</div>
<div class="myClass">3</div>
<div class="myClass">4</div>
<div class="myClass">5</div>

jsfiddle http://jsfiddle.net/xynZA/142/