[javascript] Select all elements with a "data-xxx" attribute without using jQuery

Using only pure JavaScript, what is the most efficient way to select all DOM elements that have a certain data- attribute (let's say data-foo).

The elements may be different, for example:

<p data-foo="0"></p><br/><h6 data-foo="1"></h6>

This question is related to javascript html dom

The answer is


While not as pretty as querySelectorAll (which has a litany of issues), here's a very flexible function that recurses the DOM and should work in most browsers (old and new). As long as the browser supports your condition (ie: data attributes), you should be able to retrieve the element.

To the curious: Don't bother testing this vs. QSA on jsPerf. Browsers like Opera 11 will cache the query and skew the results.

Code:

function recurseDOM(start, whitelist)
{
    /*
    *    @start:        Node    -    Specifies point of entry for recursion
    *    @whitelist:    Object  -    Specifies permitted nodeTypes to collect
    */

    var i = 0, 
    startIsNode = !!start && !!start.nodeType, 
    startHasChildNodes = !!start.childNodes && !!start.childNodes.length,
    nodes, node, nodeHasChildNodes;
    if(startIsNode && startHasChildNodes)
    {       
        nodes = start.childNodes;
        for(i;i<nodes.length;i++)
        {
            node = nodes[i];
            nodeHasChildNodes = !!node.childNodes && !!node.childNodes.length;
            if(!whitelist || whitelist[node.nodeType])
            {
                //condition here
                if(!!node.dataset && !!node.dataset.foo)
                {
                    //handle results here
                }
                if(nodeHasChildNodes)
                {
                    recurseDOM(node, whitelist);
                }
            }
            node = null;
            nodeHasChildNodes = null;
        }
    }
}

You can then initiate it with the following:

recurseDOM(document.body, {"1": 1}); for speed, or just recurseDOM(document.body);

Example with your specification: http://jsbin.com/unajot/1/edit

Example with differing specification: http://jsbin.com/unajot/2/edit


Here is an interesting solution: it uses the browsers CSS engine to to add a dummy property to elements matching the selector and then evaluates the computed style to find matched elements:

It does dynamically create a style rule [...] It then scans the whole document (using the much decried and IE-specific but very fast document.all) and gets the computed style for each of the elements. We then look for the foo property on the resulting object and check whether it evaluates as “bar”. For each element that matches, we add to an array.


Try it ? here

    <!DOCTYPE html>
    <html>
        <head></head>
        <body>
            <p data-foo="0"></p>
            <h6 data-foo="1"></h6>
            <script>
                var a = document.querySelectorAll('[data-foo]');

                for (var i in a) if (a.hasOwnProperty(i)) {
                    alert(a[i].getAttribute('data-foo'));
                }
            </script>
        </body>
    </html>

document.querySelectorAll('data-foo')

to get list of all elements having attribute data-foo

If you want to get element with data attribute which is having some specific value e.g

<div data-foo="1"></div>
<div data-foo="2" ></div>

and I want to get div with data-foo set to "2"

document.querySelector('[data-foo="2"]')

But here comes the twist what if I want to match the data attirubte value with some variable's value like I want to get element if data-foo attribute is set to i

var i=2;

so you can dynamically select the element having specific data element using template literals

document.querySelector(`[data-foo="${i}"]`)

Note even if you don't write value in string it gets converted to string like if I write

<div data-foo=1></div>

and then inspect the element in Chrome developer tool the element will be shown as below

<div data-foo="1"></div>

You can also cross verify by writing below code in console

console.log(typeof document.querySelector(`[data-foo]="${i}"`).dataset('dataFoo'))

why I have written 'dataFoo' though the attribute is data-foo reason dataset properties are converted to camelCase properties

I have referred below links

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-* https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

This is my first answer on stackoverflow please let me know how can I improve my answer writing way.


document.querySelectorAll("[data-foo]")

will get you all elements with that attribute.

document.querySelectorAll("[data-foo='1']")

will only get you ones with a value of 1.


var matches = new Array();

var allDom = document.getElementsByTagName("*");
for(var i =0; i < allDom.length; i++){
    var d = allDom[i];
    if(d["data-foo"] !== undefined) {
         matches.push(d);
    }
}

Not sure who dinged me with a -1, but here's the proof.

http://jsfiddle.net/D798K/2/


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to dom

How do you set the document title in React? How to find if element with specific id exists or not Cannot read property 'style' of undefined -- Uncaught Type Error adding text to an existing text element in javascript via DOM Violation Long running JavaScript task took xx ms How to get `DOM Element` in Angular 2? Angular2, what is the correct way to disable an anchor element? React.js: How to append a component on click? Detect click outside React component DOM element to corresponding vue.js component