70

I have an XHTML page where each HTML element has a unique custom attribute, like this:

<div class="logo" tokenid="14"></div>

I need a way to find this element by ID, similar to document.getElementById(), but instead of using a general ID, I want to search for the element using my custom "tokenid" attribute. Something like this:

document.getElementByTokenId('14'); 

Is that possible? If yes - any hint would be greatly appreciated.

0

7 Answers 7

80

It is not good to use custom attributes in the HTML. If any, you should use HTML5's data attributes.

Nevertheless you can write your own function that traverses the tree, but that will be quite slow compared to getElementById because you cannot make use of any index:

function getElementByAttribute(attr, value, root) {
    root = root || document.body;
    if(root.hasAttribute(attr) && root.getAttribute(attr) == value) {
        return root;
    }
    var children = root.children, 
        element;
    for(var i = children.length; i--; ) {
        element = getElementByAttribute(attr, value, children[i]);
        if(element) {
            return element;
        }
    }
    return null;
}

In the worst case, this will traverse the whole tree. Think about how to change your concept so that you can make use browser functions as much as possible.

In newer browsers you use of the querySelector method, where it would just be:

var element = document.querySelector('[tokenid="14"]');

This will be much faster too.


Update: Please note @Andy E's comment below. It might be that you run into problems with IE (as always ;)). If you do a lot of element retrieval of this kind, you really should consider using a JavaScript library such as jQuery, as the others mentioned. It hides all these browser differences.

Sign up to request clarification or add additional context in comments.

5 Comments

+1 for the hard work, but bear in mind that children has a <IE9 quirk where it returns comment nodes and was only added to Firefox in version 3.5. childNodes with a nodeType check would be a "safer" approach. Also, hasAttribute() isn't supported by IE7 and lower. For those browsers, you'd have to do something like root.attributes.getNamedItem(attr).specified.
@Andy: Uh, I did not know about these issues... thanks! I will leave it as exercise for the reader though ;)
var element = document.querySelector('[tokenid="14"]'); --- not in safari 5.1.4
@Andrei: Mmmh, according to caniuse.com it should be supported. Have you tried document.querySelector('[tokenid=14]') (value without quotation marks)?
How is this done with Angular? ng-bind is custom too
58
<div data-automation="something">
</div>

document.querySelector("div[data-automation]")

=> finds the div

document.querySelector("div[data-automation='something']")

=> finds the div with a value

Comments

6

If you're using jQuery, you can use some of their selector magic to do something like this:

    $('div[tokenid=14]')

as your selector.

Comments

5

Doing this with vanilla JavaScript will do the trick:

  const something = document.querySelectorAll('[data-something]')

3 Comments

When adding an answer to a nine year old question with an accepted answer it is important to point out what new aspect of the question your answer addresses. Code only answers can generally be improved by adding explanation of how and why they work.
Well it's just a summary of some of the answers It's just the way I like to do it Thanks anyway for the comment
@AnthonyHellberg sure, but "just the way I like to do it" isn't helpful to anyone else if they don't understand the syntax of what you just wrote. The question asked to find elements with a tokenid attribute equal to 14, which I think would be '[tokenid=14]' Yours is '[data-something'] and I'm not sure what that does. Is that returning elements with an attribute named data-something? Or did you typo and meant to write data=something?
2

You can accomplish this with JQuery:

$('[tokenid=14]')

Here's a fiddle for an example.

Comments

1

If you're willing to use JQuery, then:

var myElement = $('div[tokenid="14"]').get();

Comments

1

Use this more stable Function:

function getElementsByAttribute(attr, value) {
  var match = [];
  /* Get the droids we are looking for*/
  var elements = document.getElementsByTagName("*");
  /* Loop through all elements */
  for (var ii = 0, ln = elements.length; ii < ln; ii++) {
    if (elements[ii].nodeType === 1){      
      if (elements[ii].name != null){        
      /* If a value was passed, make sure it matches the elements */
        if (value) {
          if (elements[ii].getAttribute(attr) === value) 
           match.push(elements[ii]);           
      } else {
        /* Else, simply push it */
         match.push(elements[ii]);          
      }
     }
   }
  }
return match;
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.