20

I have this button:

<button type="button" class="themeChanger" data-themeValue="grid" value="Grid">
   <img src="templateImages/Icon_200.png" />                
</button>

And this jQuery:

$(".themeChanger").click(function () { 
    alert($(this).attr("data-themeValue")); 
    alert($(this).data("themeValue")); 
});

For some reason the first alert shows "grid" like it should, but the second shows undefined. Is there something stupid I'm missing?

Adam Rackis
  • 82,527
  • 56
  • 270
  • 393

4 Answers4

33

I think data will look on lowercases: alert($(this).data("themevalue")) //grid

or if you want to use themeValue you need to use:

edit:

I was wrong, it doesnt have anything to do with lowercases, you can use themeValue if you are having the attribute: data-theme-value then you call itwith $(element).data("themeValue")

<button class="themeChanger" data-themeValue="Theme1" data-theme-value="Theme2"></button>

$(".themeChanger").click(function() {
    var el = $(this);

    alert($(this).data("themeValue")); //Theme2
    alert($(this).data("themevalue")); //Theme1
});
Vinodh
  • 5,262
  • 4
  • 38
  • 68
voigtan
  • 8,953
  • 2
  • 29
  • 30
25

As noted in this Learning jQuery article, HTML5 data-* attributes are handled by the browser->JS conversion in the same way that CSS names are handled--that is:

  1. the leading data- is removed (a step not needed in the CSS name comparison I drew above)
    • data-specialInfo becomes specialInfo
    • data-more-specialInfo becomes more-specialInfo
  2. the remaining attr name is split on -
    • specialInfo becomes [ specialInfo ]
    • more-specialInfo becomes [ more, specialInfo ]
  3. the first of the resulting split parts is dropped to all lower case
    • [ specialInfo ] becomes [ specialinfo ]
    • [ more, specialInfo ] becomes [ more, specialInfo ] (no change as first part was already lower)
  4. the rest of the resulting split parts are dropped to lower case, but their first letter is made upper case
    • [ specialinfo ] becomes [ specialinfo ] (no change because there were no other parts)
    • [ more, specialInfo ] becomes [ more, Specialinfo ]
  5. The now case-modified parts are rejoined on empty string
    • [ specialinfo ] becomes specialinfo
    • [ more, Specialinfo ] becomes moreSpecialinfo

This being the case, your data-themeValue attribute is accessible via $(this).data("themevalue"). Whereas a data-theme-value attribute would be accessible via $(this).data("themeValue").

It's terribly confusing unless you recognize the mechanism in use.

JAAulde
  • 19,250
  • 5
  • 52
  • 63
  • I don't really understand what you mean. Who is "they"? Anyway, the above process is necessary (and not actually all that complicated) due to sytanx differences between HTML and JavaScript. – JAAulde Dec 16 '12 at 12:29
  • Thanks for this answer. I find it quite annoying - why does jQuery enforce me to use a specific notation? – jbkkd Jun 30 '13 at 07:47
  • No problem, glad it helped. The data attr API exists in a certain form without jQuery in many modern browsers. jQuery is providing it where it does not already exist, and augmenting it where it does. This being the case, they must make it compatible. Its not really all that bad anyway--just gotta get used to it. It's no different than setting CSS values from JS. – JAAulde Jul 01 '13 at 00:06
  • 1
    BRAVO @JAAulde excellent examples... can't think of a better way to summarize the perils/gotchas of "data-*" attributes! I suppose that's a good reason to stick to kebab case and never use camelCase "data-" attributes. – bcmoney Nov 03 '21 at 11:16
5

The problem is the camel case. For clarity I'd stick to the data-theme-value format for your attributes.

http://jsfiddle.net/NkHEx/2/

jquery automatically converts .data('some-value') to data('someValue')

Note that both alert calls return grid

BNL
  • 7,085
  • 4
  • 27
  • 32
4

I think it is the camel casing of hyphenated words in the data tag implementation that is the gotcha here

Try this jsfiddle - http://jsfiddle.net/FloydPink/fb6Y6/

<button type="button" class="themeChanger" data-theme-value="grid" value="Grid">
   data-theme-value                
</button>

<button type="button" class="themeChanger" data-themeValue="grid" value="Grid">
   data-themeValue
</button>

$(".themeChanger").click(function () {
    alert($(this).attr("data-themeValue"));
    alert($(this).data("themeValue"));
});
Hari Pachuveetil
  • 10,294
  • 3
  • 45
  • 68