Skip to main content

Bug Tracker

Side navigation

#821 closed enhancement (wontfix)

Opened January 16, 2007 12:05AM UTC

Closed January 20, 2007 03:51AM UTC

Last modified March 15, 2012 06:43PM UTC

jQuery.fn.add does not add elements to current jQuery object

Reported by: p.aiello@tiscali.it Owned by:
Priority: minor Milestone:
Component: core Version:
Keywords: Cc:
Blocked by: Blocking:
Description

if I have a jQuery object 'jq' and a DOM element 'element', and I call (element is enclosed in an array: see bug #806):

jq.add([element]);

the element is NOT added to jq (as in jQuery 1.0), but to a newly created jQuery object which is returned in place of the 'this' object;

while it does not break the method chaining, it breaks all code which assumes that after a call to the add method of some jQuery object, that object contains the added element(s)

NOTE: in the documentation, is not explicitly stated when a method returns the same object, and when ia new jQuery object is returned (requiring a call to the end method to restore the previous context); in my opinion this is an important issue which should be clearly documented. Anyway, in the case of the add method, I think it should return the same object, for compatibility and to keep an intuitive behaviour.

Attachments (0)
Change History (6)

Changed January 16, 2007 03:37PM UTC by Dave comment:1

The consensus from mailing list questions was that people did not expect jq1 to be touched in situations like this:

 var jq1 = $("p");
 var jq2 = jq1.find("a");

The 1.1 behavior ensures they won't be surprised. In 1.1 you can do this to get the equivalent of the 1.0 behavior:

 var jq1 = $("p");
 var jq2 = jq1 = jq1.find("a");

For the .add case, just do this:

 jq = jq.add([element]);

Changed January 17, 2007 01:27PM UTC by joern comment:2

resolution: → worksforme
status: newclosed

jQuery now takes the fully functional approach, that is, no method modifies the object on which the method is called (though it may modify the underlying objects, eg. DOM elements).

That could be added as a "general contract" to the reference documentation.

Changed January 17, 2007 08:32PM UTC by p.aiello@tis comment:3

resolution: worksforme
status: closedreopened

There is a fundamental difference between the find method and the add method: when I use find, it is implicit that I don't want to perform an operation on the method owner, but I want to select a different element set from that of the called object, so it is natural that the method returns a new object. But when I call the add method, I want to add an element to *that* object on which I call the method, not to another object. This is a context like that in which I discovered the problem:

var jq = $('#someDiv');

for (var i = 0; i < someArray.length; i++) {

if (anything) {

jq.add(someElement);

}

}

Obviously, there are easy workarounds for that, but the point is that this behaviour is completely counterintuitive, and therefore highly error prone. It is against any logic and any object oriented principle, that calling an add method on object A, the passed objects are added to object B and not to object A.

In my opinion is very important to clearly distinguish the different types of operations, on the basis of its semantic meaning and its expectable behaviour, rather than standardize everything on the basis of general principles like 'no method modifies the object on which the method is called'.

P.S. If you have time, take also a look to the message I posted to the forum in date Jan 16 "Method return values in jQuery 1.1", for further observations on the subject

Changed January 18, 2007 11:12AM UTC by sa.cesare@gm comment:4

Changed January 20, 2007 03:51AM UTC by john comment:5

milestone: 1.1
priority: criticalminor
resolution: → wontfix
status: reopenedclosed
type: bugenhancement
version: 1.1

What you're looking for is an equivalent to .push() - .add() is not .push(). We've actively removed all destructive operations from jQuery and it would be counter-intuitive to reintroduce some at the point. For the time being, .add() should remain as it is, with some consideration given to implementing a traditional-style .push(), .slice(), etc.

You can achieve what you're looking for with the following code:

var jq = $('#someDiv');

for (var i = 0; i < someArray.length; i++) {
        if (anything) {
                jq = jq.add(someElement);
        }
}

Or with the following extra method:

jQuery.fn.push = function( elem ) {
    [].push.apply( this, elem.constructor == Array ? elem : [ elem ] );
    return this;
};

Changed December 07, 2011 12:23AM UTC by rasmus@mindplay.dk comment:6

What about performance?

When you need to collect a large number of elements in a selector, it's hardly efficient to keep constructing and throwing away the previous object...