1

Inside of a jQuery click event listener I have some code like this:

function (evt) { evt.preventDefault(); var reportbox = $(this).closest('.activityItem'); var id = reportbox.data('questionId'); ... } 

This works fine for data-question-id attributes, but I'm generalizing the function now and I need to grab the value from any of the following:

data-question-id data-answer-id data-comment-id data-user-id data-company-id 

What's the best way to do this?

7
  • 2
    I don't quite understand the question, why can you not use the data() method for those too? Commented Jan 29, 2016 at 16:34
  • Use a partial match on the end -id? Commented Jan 29, 2016 at 16:35
  • @RoryMcCrossan I just need a one-liner that can grab the value from any of those regardless. The .activityItem element has exclusively one of these but I won't know which one before-hand. Commented Jan 29, 2016 at 16:37
  • I'm afraid that's not possible. You would need to retrieve all of those data attributes and then perform some logic to check those which have values and proceed from there. Commented Jan 29, 2016 at 16:39
  • 1
    But that will just arbitrarily get the first data attribute on the element, in no guaranteed order - it may not be any of those you've listed. Although, if that works for you then all the better :) Commented Jan 29, 2016 at 16:56

3 Answers 3

2

If you know only one of those attributes will be present and you want to retrieve that single value you can use this:

var element = $(el); var dataAttrs = ['question-id', 'answer-id', 'comment-id', 'user-id', 'company-id']; var data = getUnknownAttr(element, dataAttrs); function getUnknownAttr(element, potentialAttrs) { var $element = element instanceof $ ? element : $(element); var result = null; potentialAttrs.forEach(function (attr) { var temp = $element.data(attr); if (typeof temp !== 'undefined') { result = temp; } }); return result; } 
Sign up to request clarification or add additional context in comments.

2 Comments

I like this but I actually just came up with a much simpler way.
@PatrickRoberts please post it! I've got a couple use cases for it. I actually just came up with what I wrote without even implementing it but I was about to. EDIT: I just saw you posted it, thanks
2

As Brian points out, you could access the dataset property to retrieve all the element's data-* attributes:

$('.activityItem').each(function () { var dataAttributes = this.dataset; Object.keys(dataAttributes).forEach(function (key) { console.log(key, dataAttributes[key]); // key, value }); }); 

Since you only want the first data attribute, you could simply use:

var dataAttributes = this.dataset; var id = dataAttributes[Object.keys(dataAttributes)[0]]; 

It's important to note that the dataset property returns the attribute names in camel case without the data prefix. In other words, data-question-id would be questionId.

If you want to retrieve all of an element's attributes, access the attributes property and check which attributes start with data-* and end with -id. It's definitely more verbose, but it may work better in other scenarios.

$('.activityItem').each(function () { var attributes = this.attributes; Object.keys(attributes).forEach(function (key) { var attribute = attributes[key]; if (/^data-.*-id$/.test(attribute.name)) { console.log(attribute.name, attribute.value); } }) }); 

4 Comments

Having a regex inside a for-loop isn't exactly the "simple" solution I was looking for, but I appreciate the attempt.
@PatrickRoberts You're right--1+ to your answer. I was under the impression that it had to end with *-id.
Your impression was correct, but see my comment to Rory.
Using this.dataset would be more targeted for this use case. The attributes object contains all of the elements attributes, not just data-* attributes. Your regex takes care of the others but you could eliminate it completely using dataset if (like in this case) you knew there was only one data-* attribute.
1

I just thought of what I was looking for. I guess my question confused you, but here's what I wanted:

$('#test').children().each(function () { var reportbox = $(this); var id = reportbox.data(Object.keys(reportbox.data())[0]); reportbox.text(id); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="test"> <div data-question-id="1"></div> <div data-answer-id="2"></div> <div data-comment-id="3"></div> <div data-user-id="4"></div> <div data-company-id="5"></div> </div>

The line of focus being:

var id = reportbox.data(Object.keys(reportbox.data())[0]); 

Edit

Alternatively thanks to @Brian's comment I can rewrite this to:

var id = this.dataset(Object.keys(this.dataset)[0]); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.