Select all elements with the "data-" attribute without using jQuery

Using only JavaScript, what is the most efficient way to select all DOM elements that have a specific data- (say, data-foo ). Elements can be various elements of a tag.

 <p data-foo="0"></p><br/><h6 data-foo="1"></h6> 
+133
javascript dom html5
Aug 16 '11 at 20:27
source share
6 answers

You can use querySelectorAll :

 document.querySelectorAll('[data-foo]'); 
+270
Aug 16 '11 at 20:29
source share
 document.querySelectorAll("[data-foo]") 

will provide you with all the elements with this attribute.

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

will only receive those whose value is 1.

+139
Aug 16 '11 at 20:30
source share

Try β†’ 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> 
+8
Aug 16 2018-11-11T00:
source share

While it is not as pretty as querySelectorAll (which has a lot of problems), here is 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 (i.e.: data attributes), you can get the item.

Curious: don't bother testing this and QSA on jsPerf. Browsers such as Opera 11 cache the query and distort the results.

the 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; } } } 

Then you can run 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

An example with a different specification: http://jsbin.com/unajot/2/edit

+1
Aug 16 '11 at 10:24
source share
 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 sketched me with -1, but here's the proof.

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

0
Aug 16 '11 at 20:29
source share

Here's an interesting solution: it uses the CSS browser mechanism to add the property of the dummy element to the elements matching the selector, and then computes the computed style to look for matching elements:

It dynamically creates a style rule [...] Then it scans the entire document (using a highly convicted and IE-specific, but very fast document.all) and gets the computed style for each of the elements. Then we look for the foo property on the resulting object and check if it evaluates to β€œbar”. For each element that matches, we add to the array.

-one
Aug 16 2018-11-11T00:
source share



All Articles