jQuery selectors on custom data attributes using HTML5

725,520

Solution 1

$("ul[data-group='Companies'] li[data-company='Microsoft']") //Get all elements with data-company="Microsoft" below "Companies"

$("ul[data-group='Companies'] li:not([data-company='Microsoft'])") //get all elements with data-company!="Microsoft" below "Companies"

Look in to jQuery Selectors :contains is a selector

here is info on the :contains selector

Solution 2

jQuery UI has a :data() selector which can also be used. It has been around since Version 1.7.0 it seems.

You can use it like this:

Get all elements with a data-company attribute

var companyElements = $("ul:data(group) li:data(company)");

Get all elements where data-company equals Microsoft

var microsoft = $("ul:data(group) li:data(company)")
                    .filter(function () {
                        return $(this).data("company") == "Microsoft";
                    });

Get all elements where data-company does not equal Microsoft

var notMicrosoft = $("ul:data(group) li:data(company)")
                       .filter(function () {
                           return $(this).data("company") != "Microsoft";
                       });

etc...

One caveat of the new :data() selector is that you must set the data value by code for it to be selected. This means that for the above to work, defining the data in HTML is not enough. You must first do this:

$("li").first().data("company", "Microsoft");

This is fine for single page applications where you are likely to use $(...).data("datakey", "value") in this or similar ways.

Solution 3

jsFiddle Demo

jQuery provides several selectors (full list) in order to make the queries you are looking for work. To address your question "In other cases is it possible to use other selectors like "contains, less than, greater than, etc..."." you can also use contains, starts with, and ends with to look at these html5 data attributes. See the full list above in order to see all of your options.

The basic querying has been covered above, and using John Hartsock's answer is going to be the best bet to either get every data-company element, or to get every one except Microsoft (or any other version of :not).

In order to expand this to the other points you are looking for, we can use several meta selectors. First, if you are going to do multiple queries, it is nice to cache the parent selection.

var group = $('ul[data-group="Companies"]');

Next, we can look for companies in this set who start with G

var google = $('[data-company^="G"]',group);//google

Or perhaps companies which contain the word soft

var microsoft = $('[data-company*="soft"]',group);//microsoft

It is also possible to get elements whose data attribute's ending matches

var facebook = $('[data-company$="book"]',group);//facebook

//stored selector
var group = $('ul[data-group="Companies"]');

//data-company starts with G
var google = $('[data-company^="G"]',group).css('color','green');

//data-company contains soft
var microsoft = $('[data-company*="soft"]',group).css('color','blue');

//data-company ends with book
var facebook = $('[data-company$="book"]',group).css('color','pink');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul data-group="Companies">
  <li data-company="Microsoft">Microsoft</li>
  <li data-company="Google">Google</li>
  <li data-company ="Facebook">Facebook</li>
</ul>

Solution 4

Pure/vanilla JS solution (working example here)

// All elements with data-company="Microsoft" below "Companies"
let a = document.querySelectorAll("[data-group='Companies'] [data-company='Microsoft']"); 

// All elements with data-company!="Microsoft" below "Companies"
let b = document.querySelectorAll("[data-group='Companies'] :not([data-company='Microsoft'])"); 

In querySelectorAll you must use valid CSS selector (currently Level3)

SPEED TEST (2018.06.29) for jQuery and Pure JS: test was performed on MacOs High Sierra 10.13.3 on Chrome 67.0.3396.99 (64-bit), Safari 11.0.3 (13604.5.6), Firefox 59.0.2 (64-bit). Below screenshot shows results for fastest browser (Safari):

enter image description here

PureJS was faster than jQuery about 12% on Chrome, 21% on Firefox and 25% on Safari. Interestingly speed for Chrome was 18.9M operation per second, Firefox 26M, Safari 160.9M (!).

So winner is PureJS and fastest browser is Safari (more than 8x faster than Chrome!)

Here you can perform test on your machine: https://jsperf.com/js-selectors-x

Share:
725,520
Jose3d
Author by

Jose3d

Working as software engineer in a consumer organization.

Updated on February 12, 2022

Comments

  • Jose3d
    Jose3d over 2 years

    I would like to know what selectors are available for these data attributes that come with HTML5.

    Taking this piece of HTML as an example:

    <ul data-group="Companies">
      <li data-company="Microsoft"></li>
      <li data-company="Google"></li>
      <li data-company ="Facebook"></li>
    </ul>
    

    Are there selectors to get:

    • All elements with data-company="Microsoft" below "Companies"
    • All elements with data-company!="Microsoft" below "Companies"
    • In other cases is it possible to use other selectors like "contains, less than, greater than, etc...".
  • Luuuud
    Luuuud over 11 years
    will this work? $('div[data-col="1"][data-row="2"]') Will this select the div where data-col equals 1 and data-row equals 2, or will it select on either of those?
  • AaronLS
    AaronLS about 11 years
    Will this work if data is set via .data('something',value)? Often this does not create an actual attribute when attaching the value. I know the OP was pretty specific regarding attributes, but thought I'd raise awareness in case others have issue with this selector.
  • Matty J
    Matty J almost 11 years
    @AaronLS No it doesn't (at least not with older versions of jQuery eg. 1.4.4) - you need to set the data using .attr('data-something', 'value') to see the update in the HTML. As per stackoverflow.com/questions/6827810/…
  • Relaxing In Cyprus
    Relaxing In Cyprus about 10 years
    I don't get your caveat. This works fine for me, and I make no other reference to data in the js. $('#id').text($('#mydatasource').data('empty')); This will populate the #id element with the contents of the data-empty tag on the #mydatasource element.
  • rhughes
    rhughes about 10 years
    @FacebookAnswers Did you use the :data() selector, or the .data() method?
  • Relaxing In Cyprus
    Relaxing In Cyprus about 10 years
    I see what you mean. I was using the method, whereas your caveat referred to the method.
  • ahnbizcad
    ahnbizcad almost 10 years
    ^you mean his caveat referred to the selector.
  • ahnbizcad
    ahnbizcad almost 10 years
    Isn't there a way to get data attribute values without typing data in the call?
  • Gaui
    Gaui almost 10 years
    @gwho $('#element').data('something')
  • Levent Yumerov
    Levent Yumerov over 7 years
    I want to add the note: That syntax can be used for any html attribute.
  • Andrew Zhuk
    Andrew Zhuk about 7 years
    John, I like your explanations because in example used Microsoft like NOT in selection
  • Anjana Silva
    Anjana Silva over 6 years
    We don't need to use quotes for those values in the custom data attribute. We can use like this $("ul[data-group=Companies] li[data-company=Microsoft]").
  • Avatar
    Avatar almost 5 years
    Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: data with Jquery 3.
  • rhughes
    rhughes almost 5 years
    @KaiNoack Could you please provide some sample code? If needed, it may be good to ask a separate question.
  • Avatar
    Avatar almost 5 years
    Weird, now it seems to work in the fiddle with Jquery 3.3.1: jsfiddle.net/kai_noack/q6nzLs20/1
  • Romualdo
    Romualdo about 3 years
    @Avatar The :data() selector is from jQueryUI, it's not in jQuery. That's why you get that syntax error. In the fiddle you are using the data attribute selector ul[data-group] which is a CSS selector and it works with jQuery (and the one used in the accepted answer).
  • Tyler2P
    Tyler2P over 2 years
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.