开发者

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

开发者 https://www.devze.com 2023-03-28 18:34 出处:网络
Using only pure JavaScript, what is the most efficient way to sele开发者_如何学Cct all DOM elements that have a certain data- attribute (let\'s say data-foo).

Using only pure JavaScript, what is the most efficient way to sele开发者_如何学Cct 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>


You can use querySelectorAll:

document.querySelectorAll('[data-foo]');


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.


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? For example, if I want to get the elements where 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:

  • MDN: data-*
  • MDN: Using data attributes


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>


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.


Native JavaScript's querySelector and querySelectorAll methods can be used to target the element(s). Use a template string if your dataset value is a variable.

var str = "term";
var term = document.querySelectorAll(`[data-type=${str}]`);
console.log(term[0].textContent);

var details = document.querySelector('[data-type="details"]');
console.log(details.textContent);
<dl>
  <dt data-type="term">Thing</dt>
  <dd data-type="details">The most generic type.</dd>
</dl>


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/


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

0

精彩评论

暂无评论...
验证码 换一张
取 消