How to detect if an HTML5 data-* attribute has empty string as value?
Asked Answered
S

5

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.

Spinner answered 25/11, 2015 at 13:17 Comment(5)
You have html, css and javascript. Just paste it into a working snippet!Possing
Note: Don't use 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. data is not just an accessor for data-* attributes, it does much more than that, and has overhead.Exerciser
@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.Spinner
@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.Exerciser
@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.Spinner
E
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.

Epstein answered 25/11, 2015 at 13:23 Comment(3)
"Your code needs a little tweak in order to work" Great. What was it? Why was it needed? Code dumps are rarely useful answers.Exerciser
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 xDEpstein
That does the trick. Plus now, I can put the hasId() function outside the document.ready() handler as @ahervin suggested.Spinner
D
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))
    };
Datura answered 25/11, 2015 at 13:24 Comment(1)
Your solution solves the issue. Just checking, if @Hackerman's solution (which came first) solves it, tooSpinner
D
2

instead of:

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

use:

$(this).attr('data-id') != ''
Dragelin answered 25/11, 2015 at 13:28 Comment(0)
C
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

Cushiony answered 25/11, 2015 at 13:30 Comment(3)
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.Spinner
@Spinner 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.readyCushiony
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.Spinner
E
-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){

}
Epigastrium answered 25/11, 2015 at 13:34 Comment(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.Spinner

© 2022 - 2024 — McMap. All rights reserved.