Skip to main content

Bug Tracker

Side navigation

#7818 closed bug (fixed)

Opened December 21, 2010 04:48PM UTC

Closed June 29, 2011 07:31PM UTC

Last modified November 22, 2011 12:26AM UTC

META: Define validity of plain JS objects for jQuery() and its methods

Reported by: dmethvin Owned by:
Priority: low Milestone: 1.6.1
Component: core Version: 1.4.4
Keywords: Cc:
Blocked by: Blocking:
Description

In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use .attr() on plain JS objects.

We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, $(obj).removeAttr("x") when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to delete obj.x instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare?

PS, How does .data() differ from attr() on a plain object?

PPS, TEST CASES.

Attachments (0)
Change History (26)

Changed December 22, 2010 03:15PM UTC by dmethvin comment:1

The jquery-datalink plugin depends on the use of $(jsobj).data() and the data events it fires in order to do its synchronization with a form.

Changed December 26, 2010 09:58PM UTC by snover comment:2

component: unfiledcore
milestone: 1.next1.5
priority: undecidedblocker
status: newopen

.data really doesn’t make much sense in the context of a non-jQuery object at this point since it just ends up pointing the data cache to the object itself. I don’t feel like this is necessarily the right thing to do (it seems to me that it’s proper to let JS objects have metadata too instead of just hooking directly onto the object in a way that is likely to collide), but it is what happens currently, and I’m not sure I have the gumption to deal with it.

.attr will break completely on JS objects in 1.5 without a compatibility sim because it is being changed to always only set attributes via the DOM attribute manipulation methods, not properties or attributes. I have no idea what .val does currently.

.bind/.trigger are used for custom event dispatching, even though JS objects can’t bubble, so most of the event system just ends up being overhead. .delegate/.live makes no sense.

.animate works on JS objects as well as DOM elements, and just cycles properties. .queue and friends needs to work.

.serialize documentation should probably have a link to jQuery.param, since that is the appropriate way to serialize objects, but otherwise should not function on JS objects.

Since we currently perform pub/sub, etc. using $(jsObj), it seems like that paradigm will need to stick around for a long time, even though it doesn’t make a lot of sense.

Changed January 05, 2011 03:58AM UTC by paul.irish comment:3

.data() i have used on plain objects. specifically XHR objects. i'd like to retain that.

.attr() and .removeAttr() i would expect to not do anything to plain objects. i don't think jquery core should tackle it.

.bind() and trigger() should work on plain objects so people have a way of rolling their own pub/sub until one is provided.

.animate() on a plain object was explored by james padolsey and should continue to work.

Changed January 05, 2011 01:16PM UTC by seankoole comment:4

_comment0: to give some more perspective on what the current situation is \ \ attr: http://jsfiddle.net/Gs8LU/1/ \ - attr (get), yes \ - attr (set), no \ - removeAttr, no \ \ data: http://jsfiddle.net/Gs8LU/ \ \ If you choose to let data store $.fn.data outside of the element, then $.fn.attr should support plain objects.. it would make no sense to create a suggest $.fn.prop just for this, I'd rather see it in $.fn.attr and document it properly. \ \ If the choice is to keep data the same way as is, then $.fn.attr needs to be only for dom elements. \ \ Like I said, I like the first option as it normalizes everything to how the dom works.1294233529322663

to give some more perspective on what the current situation is

attr: http://jsfiddle.net/Gs8LU/1/

  • attr (get), yes
  • attr (set), no
  • removeAttr, no

data: http://jsfiddle.net/Gs8LU/

  • also animate and bind

If you choose to let data store $.fn.data outside of the element, then $.fn.attr should support plain objects.. it would make no sense to create a suggest $.fn.prop just for this, I'd rather see it in $.fn.attr and document it properly.

If the choice is to keep data the same way as is, then $.fn.attr needs to be only for dom elements.

Like I said, I like the first option as it normalizes everything to how the dom works.

Changed January 05, 2011 06:19PM UTC by snover comment:5

@paul_irish: As of 1.4.3, calling .data on anything (like an XHR) just attaches properties directly to the object, so there is no benefit to doing that vs simply setting the property directly. Furthermore, if you were doing that in 1.4.2, you were leaking memory every time you had an XHR.

Changed January 05, 2011 06:53PM UTC by john comment:6

Replying to [comment:5 snover]:

"As of 1.4.3, calling .data on anything (like an XHR) just attaches properties directly to the object, so there is no benefit to doing that vs simply setting the property directly." Sure there is - it triggers events if they're bound - like in the case of the official jQuery plugin "Data Link".

http://api.jquery.com/category/plugins/data-link/

Making this change (which was intentionally introduced) as to make this sort of functionality possible would be a MAJOR change and break a lot of code.

Changed January 14, 2011 04:43PM UTC by scottgonzalez comment:7

I'm not sure if this is expected behavior or not, but .trigger() will execute functions of the same name as the event. This can be handy because you can use event.preventDefault() to prevent the method from executing, or this can be confusing because you're not expecting it. I think the current implementation is fine, since it can be a nice feature and can be avoided by using .triggerHandler().

http://jsbin.com/enahu4/edit

Changed January 17, 2011 08:58PM UTC by john comment:8

milestone: 1.51.6

We should look into this for 1.6.

Changed February 14, 2011 09:48PM UTC by TrippingTheBits comment:9

There are already jQuery.data( element, ... ) functions. I'm curious what people think about having jQuery.data( plainObject, ... ) and jQuery.bind( plainObject, eventType, ... ) functions instead of allowing jQuery to wrap plain objects.

Changed March 26, 2011 01:35AM UTC by timmywil comment:10

_comment0: attr no longer works on plain objects in the attrhooks updates1301103339106155

attr no longer works on plain objects in the attrhooks updates, since we are mainly using get/setAttribute.

Changed March 26, 2011 01:39AM UTC by timmywil comment:11

However, the new jQuery.fn.prop AND jQuery.fn.removeProp work for getting, setting, removing for plain objects.

Changed April 17, 2011 08:41PM UTC by john comment:12

milestone: 1.61.next

Changed May 22, 2011 07:27PM UTC by john comment:13

keywords: → 1.7-discuss

Nominating ticket for 1.7 discussion.

Changed May 22, 2011 09:33PM UTC by rwaldron comment:14

description: In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects. \ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare? \ \ PS, How does `.data()` differ from `attr()` on a plain object? \ \ PPS, TEST CASES. \ In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects.\ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare?\ \ PS, How does `.data()` differ from `attr()` on a plain object?\ \ PPS, TEST CASES.\

+0,

Changed May 23, 2011 12:27AM UTC by jaubourg comment:15

-1, I'm not sure we encourage wrapping plain objects. We rather see people making use of it in some creative ways (pub/sub).

Changed May 23, 2011 04:09AM UTC by timmywil comment:16

+0, Work needs to be done to figure out what doesn't already work and see if it would actually take much work. FYI, prefer prop over attr.

Changed May 24, 2011 09:06PM UTC by dmethvin comment:17

description: In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects.\ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare?\ \ PS, How does `.data()` differ from `attr()` on a plain object?\ \ PPS, TEST CASES.\ In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects. \ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare? \ \ PS, How does `.data()` differ from `attr()` on a plain object? \ \ PPS, TEST CASES. \

+1, I still don't think we have this under control, I would prefer to see us use $() for DOM objects only. Is the hack we put in for the now-unsupported .datalink plugin the way we want to do that long term?

Changed June 03, 2011 01:45PM UTC by john comment:18

description: In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects. \ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare? \ \ PS, How does `.data()` differ from `attr()` on a plain object? \ \ PPS, TEST CASES. \ In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects.\ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare?\ \ PS, How does `.data()` differ from `attr()` on a plain object?\ \ PPS, TEST CASES.\

+1, I think we pretty much took care of this in 1.6 with the separation of attr and prop.

Changed June 05, 2011 09:11PM UTC by ajpiano comment:19

description: In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects.\ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare?\ \ PS, How does `.data()` differ from `attr()` on a plain object?\ \ PPS, TEST CASES.\ In the past a jQuery collection has mainly been DOM elements, with document or window allowed in some cases. We are starting to encourage wrapping plain JS objects in jQuery for purposes like pub/sub, and also seeing tickets like #7500 where people expect to use `.attr()` on plain JS objects. \ \ We need to document the extent to which we support JS objects and decide the behavior of methods that don't accept JS objects. For example, `$(obj).removeAttr("x")` when used on a JS object currently sets the property to an empty string, it seems like the correct semantic action is to `delete obj.x` instead. BUT ... is it worth taking the size/performance/complexity hit to orthogonally handle something that is relatively rare? \ \ PS, How does `.data()` differ from `attr()` on a plain object? \ \ PPS, TEST CASES. \

+0, So what would actually have to happen here, Dave, John - Guess we'll find out in the meeting

Changed June 06, 2011 06:43PM UTC by rwaldron comment:20

keywords: 1.7-discussneedsdocs
milestone: 1.next1.6.1
priority: blockerlow

Changed June 07, 2011 04:41AM UTC by timmywil comment:21

milestone: 1.6.11.next

Changed June 07, 2011 02:14PM UTC by rwaldron comment:22

milestone: 1.next1.6.1

The milestone was set to 1.6.1 to reflect the resolution from yesterday's meeting.

Changed June 27, 2011 04:14PM UTC by timmywil comment:23

can this ticket be closed?

Changed June 29, 2011 07:31PM UTC by timmywil comment:24

resolution: → fixed
status: openclosed

Changed July 28, 2011 05:51PM UTC by dmethvin comment:25

To clarify the docs, the only operations allowed on plain objects after they are wrapped in jQuery() are:

.data()
.prop()
.bind()
.unbind()
.trigger()
.triggerHandler()

Note that using .data() -- or any method that requires .data() such as .bind() -- on a plain object will create a jQuery123456789 (random number) property on the object.

If .trigger("eventName") is used, it will look for a "eventName" property on the object and attempt to execute it after any attached jQuery handlers are executed. (Note that it does *not* check to see if the property represents a function.) To avoid this behavior, use .triggerHandler("eventName").

Changed November 22, 2011 12:26AM UTC by dmethvin comment:26

keywords: needsdocs