Jquery select all elements that have $jquery.data()

JavascriptJqueryJquery Selectors

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

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); (only for elements that have their data attribute set in HTML not via jQuery)

you could also use filter() (which works for data attributes set from jQuery)

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

Solution 2 - Javascript

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.

Solution 3 - Javascript

You can use filter():

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

Solution 4 - Javascript

You could use this jQuery Selector extention: Querying element data

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

Solution 5 - Javascript

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>

  1. 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>

Solution 6 - Javascript

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

Solution 7 - Javascript

> 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/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArgiropoulos StavrosView Question on Stackoverflow
Solution 1 - JavascriptNicola PeluchettiView Answer on Stackoverflow
Solution 2 - JavascriptAshkan Mobayen KhiabaniView Answer on Stackoverflow
Solution 3 - JavascriptFrédéric HamidiView Answer on Stackoverflow
Solution 4 - JavascriptroberkulesView Answer on Stackoverflow
Solution 5 - JavascriptdevconceptView Answer on Stackoverflow
Solution 6 - JavascriptKhalidView Answer on Stackoverflow
Solution 7 - Javascriptguest271314View Answer on Stackoverflow