6

How can I detect with jQuery / JavaScript, if a given data-* Attribute of a certain DOM element has an empty string as a value? Common comparison operators do not seem to work properly, as the example below shows. I

May be close to: Checking for HTML5 data attribute with no value or set data- html5 value by default

But none of these answers matched this issue.

The HTML

<ul class="list">
  <li class="list--item" data-id="x6gftcc-44">First entry</li>
  <li class="list--item" data-id="">Last entry</li>
</ul>
<div class="message"></div>

Some CSS

.list{
    list-style-type: none;
  }
  .list--item{
    display: inline-block;
    min-width: 200px;
    padding: 20px;
    border: 1px solid rgb(60,64,73);
    cursor: pointer;
  }
  .message{
    display: none;
  }
  .message.active{
    display: block;
  }
  .true{
    color: green;
  }
  .false{
    color: red;
  }

The JavaScript

$(document).ready(function(){
  $('.list--item').click(function(event, target){
    function hasId(){
      if ($(this).data('id') != ''){
            return true;
        }
        else{
            return false;
        }
    };
    var entry = {
      id: $(this).data('id'),
      hasId: hasId()
    };
    if (entry.hasId){
      $('.message').addClass('active true');
      $('.message').text('Picked entry ID: ' + entry.id);
    }
    else{
      $('.message').addClass('active false');
      $('.message').text('Entry ID not available');
    }
  })
});

Example available at CodePen.

Community
  • 1
  • 1
Bunjip
  • 297
  • 5
  • 14
  • 2
    You have html, css and javascript. Just paste it into a working snippet! – Jon Surrell Nov 25 '15 at 13:25
  • Note: Don't use [`data`](http://api.jquery.com/data) unless you're really using it for what it's meant to be used for. If you're just accessing the attribute vaule, use [`attr`](http://api.jquery.com/attr). `data` is **not** just an accessor for `data-*` attributes, it does much more than that, and has overhead. – T.J. Crowder Nov 25 '15 at 13:25
  • @T.J. Crowder jQuery API docs say regarding data(): _Description: Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute._ – Bunjip Nov 25 '15 at 14:36
  • @Bunjip: Right. It's not just an accessor for `data-*` attributes. It's for managing jQuery's internal data store, which it will cause to be *initialized* (only) from `data-*` attributes. Using it as an accessor just to get the attribute value is not correct usage, and makes jQuery do extra work and consume extra memory. It also leads to confusion, since `data` never *sets* `data-*` attributes. – T.J. Crowder Nov 25 '15 at 16:53
  • @T.J. Crowder: Okay, that is good to know! Thank you for this insights. I have had troubles before with data() not actually _setting_ data-* attributes but only initializing the invisible data store. IMO, the jQuery docs should be more precise on this point. – Bunjip Nov 26 '15 at 09:32

5 Answers5

5

Your code needs a little tweak in order to work:

$(document).ready(function(){
  $('.list--item').click(function(event, target){
   function hasId(my){
    if (my.data('id') != ''){
        return true;
    }
    else{
        return false;
    }
  };
 var entry = {
  id: $(this).data('id'),
  hasId: hasId($(this))
 };
 if (entry.hasId){
  $('.message').addClass('active true');
  $('.message').text('Picked entry ID: ' + entry.id);
 }
 else{
  $('.message').addClass('active false');
  $('.message').text('Entry ID not available');
 }
});
});

Working fiddle: http://codepen.io/anon/pen/meZbqQ

Basically was just a mather of scope; inside your hasId function you are referencing to $(this) and asking for the data('id') attribute, but in that scope $(this) isn't referencing the initial entry object.

Hackerman
  • 12,139
  • 2
  • 34
  • 45
  • 7
    *"Your code needs a little tweak in order to work"* Great. What *was* it? Why was it needed? Code dumps are rarely *useful* answers. – T.J. Crowder Nov 25 '15 at 13:24
  • Done @T.J.Crowder; as a non native english speaker, sometimes i just add that info when i get the certain words to describe the issue...that is how i works, first my answer and later the explanation...sorry, is just an issue about finding the right words xD – Hackerman Nov 25 '15 at 13:37
  • That does the trick. Plus now, I can put the hasId() function outside the document.ready() handler as @ahervin suggested. – Bunjip Nov 25 '15 at 14:12
5

The Problem is, inside your hasId() function $(this) is not referring to the right element. Try this:

   function hasId(element){
      if (element.data('id') != ''){

            return true;
        }
        else{
            return false;
        }
    };

    var entry = {
      id: $(this).data('id'),
      hasId: hasId($(this))
    };
om1
  • 166
  • 11
  • Your solution solves the issue. Just checking, if @Hackerman's solution (which came first) solves it, too – Bunjip Nov 25 '15 at 13:48
2

instead of:

$(this).data('id') != ''

use:

$(this).attr('data-id') != ''
1

You need to reference the element your passing to hasId and also though not compulsory functions would go outside of $(document).ready(function(){ });

See an updated Codepen where I've removed the function and made shortened the code

ahervin
  • 461
  • 2
  • 15
  • I understand that this will work now as long as no additional function is involved. However, my code snippet just simplified a more complex piece of code, where the hasId() function cannot be left out. – Bunjip Nov 25 '15 at 13:44
  • @Bunjip I admit I actually overwrote the codepen I did before tidying it up. If that function is going to be used elsewhere other than the click event you should move it out of document.ready – ahervin Nov 25 '15 at 13:47
  • Alrighty, the reason for defining that function within document.ready was, that I thought it needs to be inside the click-event-handler to access the picked element. However, I've just learned, that $(this) would not work within a child function of the handler anyway. So, agree to move the hasId() function out of document.ready handler. – Bunjip Nov 25 '15 at 13:53
-1

I believe JQuery's data() method returns undefined if the value is blank. So in your comparison you want to use:

if ($(this).data('id') !== undefined){

}
mcgraphix
  • 2,723
  • 1
  • 11
  • 15
  • 1
    This does not work. I think, as long as the data attribute is physically in the code, it is not undefined, even if the value is empty. – Bunjip Nov 25 '15 at 13:41