6

Is it possible to find an element that has a data attribute with the same name of an element's id in the DOM? (Is it a bad practice to give a data attribute the same value as an id?)

Example syntax:

HTML:

<li id="tab-1"></li>
<p data-tab="tab-1">Content 1</p>

Would be curious as to how to accomplish this in Vanilla Javascript. Thank you ☺

Edit: I am hoping to make my code so that if I have the ID of the element, I can just look for a data attribute of the same value if I don't have it off the top of my head.

4
  • querySelector Commented Apr 11, 2017 at 1:39
  • "is it bad practice" ... not at all if there is a close relationship between the two. Not entirely clear what you are exactly asking though. What use case are you wanting for "find same as"? Commented Apr 11, 2017 at 1:44
  • "Edit: I am hoping to make my code so that if I have the ID of the element, I can just look for a data attribute of the same value if I don't have it off the top of my head." You would need the specific .name of the data-* attribute. css selectors do not provide a means to select elements by value of attribute alone. Commented Apr 11, 2017 at 1:58
  • "Is it possible to find an element that has a data attribute with the same name of an element's id" The data-* attribute does not have .name property that is equal to .id of element at Question. Commented Apr 11, 2017 at 2:16

3 Answers 3

12

Yes, you can do that. Here's how you do it:

var usingId = document.querySelector('#tab-1');
var usingDt = document.querySelector('[data-tab="tab-1"]');
console.log(usingId);
console.log(usingDt);
<li id="tab-1">Tab</li>
<p data-tab="tab-1">P Tab</p>

Is it a bad practice?.Nope

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

Comments

1

If you are trying to select an element having an unknown html5 data-* attribute using the .id string property from a different element, you can query all elements in document, check the .name and .value of each elements' .attributes, if .value of attribute is equal to .id of element which provides .id and .name of the .attribute property is not "id", the element is matched using attribute equals selector at .querySelector()

<li id="tab-1"></li>
<p data-tab="tab-1">Content 1</p>
<script>
let id = document.getElementById("tab-1").id;
for (let el of document.querySelectorAll("*")) {
  for (let {name, value} of el.attributes) {  
  if (value === id && name !== "id") {
     document.querySelector(`[${name}="${id}"]`)
     .style.color = "green";
     break;
  }
  }
}
</script>

6 Comments

let id = document.getElementById("tab-1").id; this made my day. Thanks. (you could also do let id = document.getElementById("tab-1").id.split('').join('').replace(/a/g, 'a');)
@Kaiido Or let {id} = document.getElementById("tab-1"). Was only trying to answer Question as interpreted. That is, query document for element using only .id to match value of data-* attribute.
@Kaiido As interpreted the Question, the .name of the data-* attribute was not provided, onlt the .value being same as .id of a different element. css selectors do not select an element by value of attribute alone. Though it can be done by composing a function to do so.
Ok, css selectors are not the way then, but still this let id= ... is completely useless and funny. And instead of looping like that over all elements of quesrySelctorAll, you should use a DOMTreeWalker, it's way more efficient, and only elements can have attributes.
TreeWalker is not the best either for this use case, but you should definitely give it a try. developer.mozilla.org/en-US/docs/Web/API/Document/…
|
0

If the requisite is to not know the name of the attribute which value is the string you are looking for, then you can create an XPath query, which will return you all the elements having an attribute with such value :

//*[@*='value']

unwrapped :

'//' + // from root to anywhere in the tree
   '*' + // any kind of node
     '[@*' + // with any attribute
         ' = "value"' // which value is 'value'
                      ']'

var valueToFind = 'find-me';
var query = document.evaluate(`//*[@*='${valueToFind}']`, document, null, XPathResult.ANY_TYPE, null);
var elements = [], el;
while(el = query.iterateNext()){
  // in your case you will filter it to not be the original node 
  // if(el !== original)
  elements.push(el);
  }
console.log(elements);
<div data-id="find-me"></div>
<div data-id="do-not-find-me"></div>
<div class="find-me"></div>
<div class="do-not-find-me"></div>
<div style="find-me"></div>
<div id="find-me"></div>

And if the goal is to get only the elements with data-* attributes with such value, then the query is a bit more long :

//*[@*[starts-with(name(), 'data-')] = '${valueToFind}']

unwrapped :

 '//' + // from root to anywhere in the tree
  '*' + // any kind of node
   '[@*' + // with any attribute
      '[starts-with(name(), "data-")]' + // which starts with "data-"
         ' = "value"' // and which value is 'value'
           ']'

var valueToFind = 'find-me';
var query = document.evaluate(`//*[@*[starts-with(name(), 'data-')] = '${valueToFind}']`, document, null, XPathResult.ANY_TYPE, null);
var elements = [], el;
  
while(el = query.iterateNext()){
  elements.push(el);
  }
console.log(elements);
<div data-id="find-me"></div>
<div data-foo="find-me"></div>
<div data-id="do-not-find-me"></div>
<div class="find-me"></div>
<div class="do-not-find-me"></div>
<div style="find-me"></div>
<div id="find-me"></div>

6 Comments

OP is specifically trying to select element having data-* attribute having value equal to a different element .id. Is @* a wildcard? if yes, how to adjust to match only element having data-* attribute?
@guest271314 there is no way I know of to make partially wildcarded values, so you'd have to filter it in the while loop : you just have to check for if([].some.call(el.attributes, a=>{return a.nodeName.indexOf('data-') === 0 && a.nodeValue === "value";})); You will already have filtered a huge part of the document's nodes.
Why do you not perform the task at Answer? Granted, Question is not entirely clear as to "Is it possible to find an element that has a data attribute with the same .name of an element's id" as the data-* attribute is "data-tab", not "data-tab-1". Perhaps OP means having the same data-* value as a different elements' .id value?
@guest271314, added a new snippet with the filtering, I have to admit I'm confused too as to what is the real requirement.
@guest271314 actually there is a starts-with XPath function... I didn't know ;-) Answered the second link too, but the first one is a bit unrelated and the dataset method is probably cleaner.
|

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.