2

I have data attributes I'm using for options on a table, for example:

<table data-do-something-neat>
...
</table>

I'm using HAML to define them:

%table{ data: { do_something_neat: true } }
  ...

In HAML it's an HTML5 formatted page, so it's behavior is to drop the value if it's a boolean and true. If it were set to false, it would be gone, like so:

<table>
...
</table>

All this seems fine, but accessing whether that flag is true or false in jQuery is a bit of a pain, and I can't find any definitive reference on how to do it.

For the first table, the following is true:

table.is('[data-do-something-neat]') # true
table.attr('data-do-something-neat') # '' (empty string)
table.data('do-something-neat')      # '' (empty string)

And for the second table:

table.is('[data-do-something-neat]') # false
table.attr('data-do-something-neat') # undefined
table.data('do-something-neat')      # undefined

So attr and data return something falsy for a true HTML5 data attribute. Is this expected? Is there another data method that could be used? Or am I stuck using is in this way? It's unfortunate to have to use a special method for boolean attributes, instead of just using data for all data attributes.

Nick Veys
  • 23,458
  • 4
  • 47
  • 64

3 Answers3

1

I would just use a selector and check for the existance of a correctly selected element:

$('table[data-do-something-neat]').length !== 0

or

$('#A').attr('myattr') !== undefined // If attribute exists

That's what's noted in this SO question: Select elements by attribute

Or if you can go without jQuery there are native DOM methods that will suffice:

Element.hasAttribute('data-do-something-neat');
Community
  • 1
  • 1
chrisjlee
  • 21,691
  • 27
  • 82
  • 112
1

The difference is that if the attribute is not there, $.attr and $.data return undefined, if it's there without a value, it returns an empty string, which is the expected behavior, as far as I know.

What is the problem with checking?

if (typeof table.attr('data-do-something-neat') !== 'undefined') {
    // attribute exists, but it could be the empty string
}

If you want a more straight forward way to test it, you can use Element.hasAttribute

if (table[0].hasAttribute('data-do-something-neat')) {
     // attribute exists, but it could be the empty string
}
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • Nothing wrong with checking that way of course, but when things are inconsistent I figure I must not know everything I need to. I guess it's not jQuery's fault that `""` is falsy. `hasAttribute` may come in handy. Thanks! – Nick Veys Apr 23 '14 at 20:31
1

It kind of makes sense that you're stuck using .is(). Some data attributes should be treated as Booleans, and some should be treated as strings.

Imagine if attr() returned true for an empty string; it would be difficult to test for, and in order to have it properly appear as 'null', your server code would need to write:

<table
<?php if $accountId != null {?>
  data-accountId="<?php echo $accountId; ?>"
<?php } ?> >

(The emphasis being on the outside null-checking condition). But, since it returns an empty string, you can simply use javascript and use any standard "is empty string" method you prefer, or just check "if length == 0" if you know the attribute should always be printed from the server.

Katana314
  • 8,429
  • 2
  • 28
  • 36
  • Fair enough. The argument that it would be more difficult to test for does make a lot of sense. I guess my beef is with Javascript treating an empty string as falsy. – Nick Veys Apr 23 '14 at 20:33
  • 1
    @NickVeys In fact, I have to admit - I was halfway through a reply in which I explained that the inverse was true ("" evaluates true). Then, just to be sure, I did a test in another browser and was surprised to find it wasn't the case. – Katana314 Apr 23 '14 at 20:36