2

I have this small code that put some preset style to a div with custom attributes, that attributes set the src and an APA text to an img tag, also generate a button with a zoom option using FancyBox... I'm kinda new in the jquery world, so maybe I'm using the data attribute in in a wrong way...

The question is, is possible to set a data HTML5 attribute with a default value, even before the $(document).ready? I mean:

<!--In the text editor:-->
<div data-boolean></div>
<!--In the code inspector after browser render:-->
<div data-boolean="true"></div>

I tried it using the following method:

var $me = $(this),    
    $meData = $me.data(),
    $meZoom  = ($meData.sgImgzoom) ? $meData.sgImgZoom : true ;

But didn't work, when I make a console.log() of that attr I get an empty string, not a boolean variable. it only appear as a boolean when I set manually the value to true..

For

<div data-sg-img-zoom data-sg-src="img/test.jpg" data-sg-apa="APA Test Text!"></div> 

console.log code:

$.each($meData, function(i,v) {
             console.log(i + ' = ' + v + ' (' + typeof(v) + ')');
        }); 

Browser response:

sgApa = APA Test Text! (string)
sgSrc = img/test.jpg (string)
sgImgZoom =  (string)

For:

<div data-sg-img-zoom="false" data-sg-src="img/test-2.jpg" data-sg-apa="APA Test Text!"></div>

Browser response:

sgApa = APA Test Text! (string)
sgSrc = img/test-2.jpg (string)
sgImgZoom = false (boolean)

And I tried the same method with a different attribute like APA, and seems to work... so I don't know..

for

 <div data-sg-img-zoom="false" data-sg-src="img/test-3.jpg" data-sg-apa></div>

and

$meApa  = ($meData.sgApa) ? $meData.sgApa : "You must use APA text if data-sg-apa attr used";

data-sg-apa will be "You must use APA text if data-sg-apa attr used" until if you left the attribute empty...

EDIT Reading some similar questions on this site I think I can tell that I "solve" the problem. It is mentioned in the .data() documentation

The data- attributes are pulled in the first time the data property is >accessed and then are no longer accessed or mutated (all data values are >then stored internally in jQuery)

Also as you can see in this post

Using the Chrome DevTools Console to inspect the DOM, the $('#foo').data('helptext', 'Testing 123'); does not update the value as seen in the Console but $('#foo').attr('data-helptext', 'Testing 123'); does.

So you have to change it before setting all the data like this:

var tempVar = false;        
        if( $(this).data("sgImgZoom" ) === ""){
            tempVar = true;
            $(this).attr("data-sg-img-zoom",true);//optional if you want to see the "value" of that attribute, but really doesn't matters because that value and the real data value are two completely different things..
        }
        var $me     = $(this),
            $meData = $me.data(),
            $meZoom = $meData.sgImgZoom = tempVar;//set default value for data-sg-zoom

So now I can validate the function easier like this:

if($meZoom){ /*do the thing*/ }

Now the code work as expected but is clear that .attr() and .data() are a way two different things and should be used in very specific situations.

So the question now is: Should I use the HTML5 data- for this particular case? or is easier handle it with jquery.attr()

see the update code here

Community
  • 1
  • 1
  • It seems that your question is more about querying than setting the attribute. Not sure why you're trying to set the attribute when all you need is to retrieve its data to initialize fancyBox later. – Gyrocode.com May 03 '15 at 12:09

1 Answers1

0

You're seeing this behavior because jQuery data() method attempts to convert attributes into Javasript values, below is an excerpt from the manual:

Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null).

To retrieve the value's attribute as a string without any attempt to convert it, use the attr() method.

According to HTML5 specification regarding boolean attributes:

If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.

The values "true" and "false" are not allowed on boolean attributes. To represent a false value, the attribute has to be omitted altogether.

This is probably the reason why jQuery returns empty string as value for data-sg-img-zoom attribute.

Testing for presence of the attribute

If you would like to test only initial presence of the attribute data-attr such as <div data-attr> then both jQuery data() and attr() return undefined, so the following code could be used:

var is_set = (typeof $(el).attr('data-attr') === 'undefined') ? true : false;

or

var is_set = (typeof $(el).data('attr') === 'undefined') ? true : false;

Testing for presence of the attribute and true/false values

If you would like to test for presence of the attribute data-attr AND values true/false such as <div data-attr>, <div data-attr="true"> and <div data-attr="false">, use the code below.

var el_data_attr = $(el).data('attr');
var is_set = (
      // If attribute is specified
      typeof el_data_attr !== 'undefined' 
      // And no value is given or value is evaluated to true
      && (el_data_attr === '' || el_data_attr)
   ) ? true : false;

As a side effect, attribute values 1, foo will also be treated as true; and 0, null, NaN will be treated as false.

Solution for your example

Since you retrieve all data- attributes with single data() call, you need to use the following code:

var $meZoom = (
      $meData.hasOwnProperty('sgImgZoom') 
      && ($meData.sgImgZoom === '' || $meData.sgImgZoom)
) ? true : false;
Gyrocode.com
  • 57,606
  • 14
  • 150
  • 185
  • It works perfect and way more easier with the last method, but `console.log` still show sgImgZoom as empty string unless you put a value directly on the atribute, so, if `if($meZoom)` works, where is really stored the actual value of $meZoom? –  May 03 '15 at 06:58
  • Variable `$meZoom` now holds `true` or `false` values. You're using this variable only to initialize fancyBox once, therefore there is no need to store it for later use using `data()` or `attr()` methods. – Gyrocode.com May 03 '15 at 12:14