1

i have page with 3 divs each div has 2 data-attribute for example

<div class="div1" data-10="some value" data-30="some value"></div>

i can change the value of the data attribute by this method

 $('.div1').attr('data-30', 'some changed values'); 

but the problem is that the second part of the data attribute is unknown (data-unknown number)

i don't know the number after this sign "-" it may will be 30,40,50 or what ever so how can i select the data attribute that i want to change it's value ?

i only want to change the second data-attribute , i don't care about the first one

how can i do it ?

big thanks in advance

user2976078
  • 75
  • 1
  • 2
  • 10
  • 1
    Instead of calling it `data-[num]` why don't you just call it `data-unknown` and target it. I mean it sounds like the name isn't relevant, just the value, so it doesn't matter what the name is ultimately. – Andy Aug 16 '15 at 13:07
  • There is something wrong here. Why a `data-*` attribute should be "unknown"? – Ram Aug 16 '15 at 13:07
  • @Vohuman the data-* is unknown because this number is changeable depends on the width and the height of the screen , i am using it for parallax approach – user2976078 Aug 16 '15 at 13:13
  • 1
    That should be a value not a key. Doesn't using `data-height` or `data-width` make more sense? – Ram Aug 16 '15 at 13:14
  • @Vohuman no i must use data-number and to make it responsive the number is not unknown – user2976078 Aug 16 '15 at 13:16

2 Answers2

3

First, I must agree with Vohuman: I wouldn't do this, I'd change the name to something consistent. I'm not seeing why you have to do this to make it responsive, since you can use not just attributes but their values in CSS, e.g.:

[data-width="100"] {
    /* Rules here */
}

But answering the question you actually asked:

Two Options:

Use the DOM

The DOM provides an attributes property for getting all of the attributes on an element:

var attrs = $(".div1")[0].attributes;    // [0] = Get the raw element

(Obviously, if you need to do this to all matching elements, use a loop and index rather than 0 directly.)

It's a NamedNodeMap that you can loop through:

var i, attr;
for (i = 0; i < attrs.length; ++i) {
    attr = attrs[i];
    if (/^data-\d+$/.test(attr.nodeName)) { // regex matches `data-nnn` where
                                            // nnn is a number of any number of digits
        // This is the attribute, change it
        attr.nodeValue = theNewValue;
        break;
    }
}

Live Example:

var attrs = $(".div1")[0].attributes; // [0] = Get the raw element
var i, attr;
for (i = 0; i < attrs.length; ++i) {
  attr = attrs[i];
  if (/^data-\d+$/.test(attr.nodeName)) { // regex matches `data-nnn` where
    // nnn is a number of any number of digits
    // This is the attribute, change it
    snippet.log("The attribute was: " + attr.nodeName);
    attr.nodeValue = "the new value";
    break;
  }
}
<div class="div1" data-10="foo"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

If you use ES5 methods in your environment (you don't have to support really old browsers or you use a shim for them), we can make that a tiny bit more concise but quite possibly less clear:

Array.prototype.some.call($(".div1")[0].attributes, function(attr) {
  if (/^data-\d+$/.test(attr.nodeName)) { // regex matches `data-nnn` where
                                          // nnn is a number of any number of digits
    // This is the attribute, change it
    snippet.log("The attribute was: " + attr.nodeName);
    attr.nodeValue = "the new value";
    return true;
  }
});

Array.prototype.some.call($(".div1")[0].attributes, function(attr) {
  if (/^data-\d+$/.test(attr.nodeName)) { // regex matches `data-nnn` where
    // nnn is a number of any number of digits
    // This is the attribute, change it
    snippet.log("The attribute was: " + attr.nodeName);
    attr.nodeValue = "the new value";
    return true;
  }
});
<div class="div1" data-10="foo"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Use jQuery's data to figure out the name, then attr to change it

Note: This is inefficient.

jQuery's data method will return an object that is initialized from all of the data-* attributes. So you can get that object, loop through its property names, and find the name that corresponds.

var div = $(".div1");
var data = div.data();
var name;
for (name in data) {
  if (/^\d+$/.test(name) && data.hasOwnProperty(name)) {
    // This is it
    div.attr("data-" + name, "the new value");
    break;
  }
}

This will not work if the names have other thing after the digits, such as data-10-foo-bar, because jQuery converts dashed-names into camelCase.

Why this is inefficient:

  1. jQuery just has to do the attributes thing to build the data object

  2. It then stores the data object in its cache of data for that element

So on the whole, I wouldn't do it this way.

Live Example:

var div = $(".div1");
var data = div.data();
var name;
for (name in data) {
  if (/^\d+$/.test(name) && data.hasOwnProperty(name)) {
    // This is it
    snippet.log("The attribute was data-" + name);
    div.attr("data-" + name, "the new value");
    break;
  }
}
<div class="div1" data-10="foo"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • i can't use fixed names because the name depends on the height of the screen , also the value of the data-attribute will not be the same every time, that's why i am looking for solution , i think your jQuery solution would work for me , thank you :) – user2976078 Aug 16 '15 at 13:28
1

Edit, Updated

still doesn't change the value of the data-attr

jQuery .data() does not change data-* attributes , see jQuery's .data() doesn't append attribute to DOMElement , jQuery Data vs Attr? .

Try utilizing HTMLElement.dataset (ie11) to set actual html dataset , e.g.,

elem[0].dataset[key] = "margin-top:100px";

only want to change the second data-attribute , i don't care about the first one

Try utilizing .data() , $.map()

var index = 0, elem = $(".div1");
$.map(elem.data(), function(value, key) {
  ++index;
  // if `index` is `2`
  if (index === 2) {
    // do stuff with second `data-*` attribute
    // change the value of that data-attribute
    // for example to `margin-top:100px`
    elem.data(key, "margin-top:100px");
    // still doesn't change the value of the data-attr
    elem[0].dataset[key] = "margin-top:100px";
  }
});

console.log(elem.data(), elem[0].dataset["30"]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="div1" data-10="some value" data-30="some value"></div>
Community
  • 1
  • 1
guest271314
  • 1
  • 15
  • 104
  • 177
  • that's exactly what i want but could you please give me an example of how to change the value of that data-attribute for example to `margin-top:100px` – user2976078 Aug 16 '15 at 13:41
  • @user2976078 _"that's exactly what i want but could you please give me an example of how to change the value of that data-attribute for example to `margin-top:100px`"_ See updated post. – guest271314 Aug 16 '15 at 13:46
  • still doesn't change the value of the data-attr – user2976078 Aug 16 '15 at 14:01
  • @user2976078 _"still doesn't change the value of the data-attr"_ ? Can create jsfiddle http://jsfiddle.net to demonstrate ? Is requirement to change actual `html` `data-*` attribute ? , not jQuery `.data()` object ? – guest271314 Aug 16 '15 at 14:04
  • @guest271314: Note that `elem.data(key, "margin-top:100px")` doesn't change the attribute (and using `data` for this is very inefficient, as I called out in my answer when showing how to do it). – T.J. Crowder Aug 16 '15 at 14:06
  • @T.J.Crowder _"Note that elem.data(key, "margin-top:100px") doesn't change the attribute"_ Yes, see updated post. Was not certain if jQuery `.data()` object or `HTMLElement.dataset` was used to process `data-*` attribute , see updated post – guest271314 Aug 16 '15 at 14:13
  • @user2976078: Just note, again, that this is *really inefficient*. In the above, it also relies on `dataset`, [for which support is quite spotty](http://caniuse.com/#feat=dataset). Recommend A) Not using jQuery for this, it's massive overkill; and B) If you do, use `attr`, not `dataset`, to update the attribute. – T.J. Crowder Aug 16 '15 at 14:20