0

I am trying to set a number as my data type dynamically using .data() method in jQuery, but so far no luck. This works using the .attr() method as I have listed in below. Why does the .data() method not work with numbers?

var container = $(this).find('#container'); // element which should have the data

Attempt 1:

container.data(24, "opacity:0;");

Attempt 2:

container.data("24", "opacity:0;");

The following code works using .attr():

container.attr("data-123", 1223);

My personal code:

function loader($div, $page) {
    $div.load(siteURL + $page + '/ #container', function() {
        var container = $(this).find('#container');
        container.data("24", "opacity:0;");
        container.attr("data-24", "opacity:0;"); //this works...
    });
}

loader($('section#about'), 'about'); 

UPDATE: Here is a jsFiddle

Shivam
  • 2,208
  • 3
  • 24
  • 39
  • possible duplicate of [jQuery Data vs Attr?](http://stackoverflow.com/questions/7261619/jquery-data-vs-attr) – Ram Aug 28 '13 at 16:37
  • data attribute should start with an alphabet. Also data attribute contains a value without special characters – Manu M Aug 28 '13 at 16:38
  • attempt 2 should work fine, but the data method does not set the attribute, it sets an internal data object on that element. – adeneo Aug 28 '13 at 16:41
  • What is the end result you are trying to accomplish? Just setting the element to be:
    or are you actually trying to change the opacity of the element?
    – Jonathan Crowe Aug 28 '13 at 16:46
  • I am using a jQuery parallax plugin called skrollr.js where you can set css in the data-type to perform parallax effects based on scroll position. – Shivam Aug 28 '13 at 16:47
  • skrollr does not use jQuery's .data function it parses the DOM elements attribute list – Patrick Evans Aug 28 '13 at 16:56
  • @Patrick yes, but you can also called skrollr.init() after setting data attr dynamically. This is better if you want to create different effects based on device resolution. – Shivam Aug 28 '13 at 17:01
  • 2
    yes but doing .data("24" is different from doing .attr("data-24", the former is using jquery's inner structure to save the data where as the latter is addding it to the DOM element's attribute list. so skrollr cannot access jquery's inner data structure without using .data which it doesnt do. – Patrick Evans Aug 28 '13 at 17:04
  • @Patrick I see, makes sense now. – Shivam Aug 28 '13 at 17:12

6 Answers6

2

Historically jQuery supported the data() method by keeping track of values set using it in a separate data structure. This allowed you do store things like objects using the API.

While retrieving data, the API will check both the data attribute as well as well as its internal store for the value.

Setting, however still goes straight to the internal store.

Since the question has changed significantly:

$.data will fail when sending a number.

Doing this in the console you will see the following (none of these affect the markup of the element itself):

// Error
$('div').data(24, 'foo')
TypeError: Object 24 has no method 'replace'

// Success
$('div').data("24", 'foo')
b.fn.b.init[966]

$('div').data("24")
"foo"

// Success
$('div').data("24", 24)
b.fn.b.init[966]

$('div').data("24")
24

None of these will affect a data attribute on the element itself. The end result of the markup will be:

<div>Hello</div>

If you are looking to set a data-xxx attribute on the element, or any attribute for that matter, an elements attribute must begin with an alpha character:

// Error
$('div').attr("24", "opacity:0")
InvalidCharacterError: An invalid or illegal character was specified, such as in an XML name.

// Success
$('div').attr("data-24", "opacity:0")
b.fn.b.init[966]

The end result of the successful call will be:

<div data-24="opacity:0">Hello</div>
dc5
  • 12,341
  • 2
  • 35
  • 47
2

skrollr does not use jQuery's .data function it parses the DOM elements attribute list which is why using .attr("data-24" works as the attribute is added to the DOM attribute list

.data("24","somevalue") does not update the DOM elements attribute list,

.attr("data-24","somevalue") however does update the DOM elemetns attribute list which allows skrollr to parse the new style.

FROM SKROLLR.JS

Starting at Line 343:

//Iterate over all attributes and search for key frame attributes.
var attributeIndex = 0;
var attributesLength = el.attributes.length;

for (; attributeIndex < attributesLength; attributeIndex++) {
    var attr = el.attributes[attributeIndex];

    if(attr.name === 'data-anchor-target') {
        anchorTarget = document.querySelector(attr.value);

        if(anchorTarget === null) {
            throw 'Unable to find anchor target "' + attr.value + '"';
        }

        continue;
    }

    //Global smooth scrolling can be overridden by the element attribute.
    if(attr.name === 'data-smooth-scrolling') {
        smoothScrollThis = attr.value !== 'off';

        continue;
    }

    //Global edge strategy can be overridden by the element attribute.
    if(attr.name === 'data-edge-strategy') {
        edgeStrategy = attr.value;

        continue;
    }

    var match = attr.name.match(rxKeyframeAttribute);

    if(match === null) {
        continue;
    }

    var constant = match[1];

    //If there is a constant, get it's value or fall back to 0.
    constant = constant && _constants[constant.substr(1)] || 0;

    //Parse key frame offset. If undefined will be casted to 0.
    var offset = (match[2] | 0) + constant;
    var anchor1 = match[3];
    //If second anchor is not set, the first will be taken for both.
    var anchor2 = match[4] || anchor1;

    var kf = {
        offset: offset,
        props: attr.value,
        //Point back to the element as well.
        element: el
    };

    keyFrames.push(kf);

    //"absolute" (or "classic") mode, where numbers mean absolute scroll offset.
    if(!anchor1 || anchor1 === ANCHOR_START || anchor1 === ANCHOR_END) {
        kf.mode = 'absolute';

        //data-end needs to be calculated after all key frames are know.
        if(anchor1 === ANCHOR_END) {
            kf.isEnd = true;
        } else {
            //For data-start we can already set the key frame w/o calculations.
            //#59: "scale" options should only affect absolute mode.
            kf.frame = offset * _scale;

            delete kf.offset;
        }
    }
    //"relative" mode, where numbers are relative to anchors.
    else {
        kf.mode = 'relative';
        kf.anchors = [anchor1, anchor2];
    }
}
Patrick Evans
  • 41,991
  • 6
  • 74
  • 87
0

container.data("24", "opacity:0;"); works right? First parameter must be a String (as per jQuery spec).

Halcyon
  • 57,230
  • 10
  • 89
  • 128
0

Because the data() method expects a string.

Hence I guess it'll be breaking if you pass it a number!

Rob Schmuecker
  • 8,934
  • 2
  • 18
  • 34
0

Can you try using the jQuery object itself:

var container = $(this).find('#container');

jQuery.data(container, "24", "opacity:0;");

alert("24 is equal to: " + jQuery.data(container, "24") );

You should note this will not affect the DOM as it uses jQuery's local storage.

JSFiddle: http://jsfiddle.net/markwylde/8Q5Yh/1/

Mark
  • 2,184
  • 1
  • 16
  • 28
  • No effect to DOM, but I see the `opacity:0` in console. – Shivam Aug 28 '13 at 16:51
  • This won't affect the DOM, it will use local storage? Are you looking to set the data tag? In that case you should set an `attr("data-whatever")` – Mark Aug 28 '13 at 16:53
0

container.data("24") actually works for me.

It depends on the version of jQuery too. When you call .data as a setter, all versions will call either .split or .replace which are String methods, not Number methods. Using .data(24) as an accessor seems to work past version 1.8.

This may also be browser dependent as dataset is not available in some browsers.

My advice would be to use a descriptive name for the data rather than just a number (unless you're talking about form 24 or something, but then why not use form24?)


EDIT: Using .data does not alter the HTML if the dataset attribute is available on the element. Using .attr always sets an attribute which will alter the HTML. This has nothing to do with using strings vs. numbers.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405