10

Preamble

The question is about HTML element creation with an HTML data attribute, like <object data="foo"></object>.

The Question

Quick question as I stumbled across this a few minutes ago; If I write

$('<div>', { id:"foo", 'class':"bar" });
// <div id="foo" class="bar"></div>

However

$('<object>', { id:"foo", data:"some+data+string" });
// [ <object id="foo"></object> ]

where I expected the output to be

// [ <object id="foo" data="some+data+string"></object> ]

I know about .data. My problem is that

$('<object>', { id:"foo", data:"some+data+string" }).data();
// Object {}
$('<object>', { id:"foo", 'data-foo':"some+data+string" }).data();
// Object {foo:"some+data+string"}

So... why does it not create the HTML attribute data since it is not a data-xxxx attribute name, and therefore does not create any actual data?

Update

I'll reiterate what's written in this question once more.

[...] If I write

$('<div>', { id:"foo", 'class':"bar" });
// <div id="foo" class="bar"></div>

However

$('<object>', { id:"foo", data:"some+data+string" });
// [ <object id="foo"></object> ]

where I expected the output to be

// [ <object id="foo" data="some+data+string"></object> ]

... and once again, I know about .data.

Why doesn't $('<div>', { data: 'foo' }) create <div data="foo"></div>, or in other word, why does it ignore the attribute altogether when creating the element?

Edit

For all those arguing that data is not a valid HTML attribute, well, it is.

Update

As of today, the solution I am using for this use case is

$('<div>', {
  attr: {
    data: 'foo'
  }
});
18
  • 1
    The object passed when creating elements contains attributes and/or methods, and the attribute name is data-foo, not data. Just because the jQuery data() function takes the second part of the data attribute as an argument doesn't mean that it would work that way anywhere else. Commented Apr 5, 2014 at 20:05
  • 1
    jsfiddle.net/adeneo/kC9QG Commented Apr 5, 2014 at 20:09
  • @adeneo can you read the question once more? This has nothing to do with me wanting to create data-foo. Commented Apr 5, 2014 at 20:10
  • 1
    Had you asked the question outlining exactly why you're using the object tag and what you're expecting in a much better way, me and @j08691 wouldn't have misunderstood you, and you're being somewhat rude when it's you that are not able to get your point across. Commented Apr 5, 2014 at 20:34
  • 1
    Well, that's true, I'm not a native english speaker and still didn't understand the question, but I somewhat get it now after all the comments, and the answer is simple, jQuery looks for methods in the object passed first, that's why you can use on() and css() directly in the object, like this, and data() is a method as well, and it only sets data internally, and jQuery has to look for the methods before it uses the keys as attributes, as it would be too late after the attributes are set, and if the key matches a method, no attribute is set. Commented Apr 5, 2014 at 20:43

1 Answer 1

10

When creating an element and passing an object with attributes and methods, any jQuery method is valid, so you can do

$('<div />', { 
    id      : "foo",  
    'class' : "bar",
    text    : "test",          // jQuery text() is called,
    html    : '<span></span>', // jQuery html() is called,
    css     : {                // jQuery css() is called,
        color: 'red'
    },
    on : {                     // calls jQuery's .on('click' ...
        click: function() {
             alert
        }
    }
});

In the same way, data="" is not a common attribute, it's only valid on a few elements, like <object>, and jQuery doesn't seem to account for this, so you can't set a data="" attribute as jQuery will catch the data() method first.

In other words, this doesn't work, instead it sets the internal data object using data()

$('<object />', {data : 'somedata'});

A rather strange workaround is that this seems to be case sensitive, so jQuery will only look for the methods if the key is all lowercase, and on the other hand, jQuery attr() will always lowercase attributes, so doing any of these

$('<object>', { id:"foo", 'Data' : "some+data+string" });
$('<object>', { id:"foo", 'daTa' : "some+data+string" });

will actually work, and the attribute will be lower cased when set, so you end up with

<object id="foo" data="some+data+string"></object>

FIDDLE

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the thorough explanation.
@YanickRochon - You're welcome, and it is really a rather interesting question on how jQuery works, it was just a little hard to grok at first.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.