40

Why doesn't this work?

var spans = $();
var elem = document.getElementById('someId');
spans.add(elem);

What is the proper way to start off with an empty collection and add elements to it? I want to loop through a collection of ids and find the element on the page and add it to the matched set.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Hcabnettek
  • 12,678
  • 38
  • 124
  • 190
  • Depending on the jQuery version, to create an empty jQuery object, you may need to do `$([])` instead of `$()`. See http://stackoverflow.com/questions/2003448/how-to-create-an-empty-jquery-result – allicarn Feb 03 '15 at 23:11

9 Answers9

55

Quoting from the jQuery website:

Given a jQuery object that represents a set of DOM elements, the .add() method constructs a new jQuery object from the union of those elements and the ones passed into the method.

Hence, when you do .add() it will not save the added elements, you would have to explicitly assign the element to the newly created object i.e

var $elements = $('.elements');
$elements = $elements.add($('#anotherelement'));
aziz punjani
  • 25,586
  • 9
  • 47
  • 56
  • 1
    All answers are pretty much correct. I just needed to reassign the original variable. That was the key to this solutions. Thanks all. – Hcabnettek Sep 23 '11 at 20:54
  • 1
    Just wonder since when are ppl using $ in javascript? Its most annoying part of PHP, why to use it in other languages? – Srneczek Jul 14 '15 at 09:10
  • @Srneczek They prefix it with a "sigil" to make it obvious that it is a "jQuery selection" object, and not a regular js array/object. Here is an SO question that explains more: http://stackoverflow.com/questions/846585/can-someone-explain-the-dollar-sign-in-javascript – Eric Seastrand Feb 03 '16 at 20:58
  • @Eric oh I see, well it's best practice for sure but still any sign before variable is pure evil to type – Srneczek Feb 03 '16 at 21:37
15

The .add() method returns a new jQuery object, so you'd need to overwrite the old one:

spans = spans.add( elem );

...or since you're adding DOM elements, you can modify the existing jQuery object with .push().

spans.push( elem );

EDIT: Changed .pushStack() to .push(), though I don't know if .push() is officially supported.


You could use .pushStack() to add a collection though.

spans = spans.pushStack( [elem] );

or

spans = spans.pushStack( document.getElementsByTagName('div') );
user113716
  • 318,772
  • 63
  • 451
  • 440
  • 2
    The comments in the jQuery 1.6.2 code say push() is "for internal use only" and it's not in the jQuery doc. Seems much safer to use `.add()` and assign the new jQuery object to the variable `span`. – jfriend00 Sep 23 '11 at 19:52
  • @jfriend00: Yeah there are a few like that. Would be nice if they were supported. – user113716 Sep 23 '11 at 20:17
  • 2
    I think one of the issues is that jQuery likes to maintain the DOM elements to be unique (no dups) and (I think) in DOM order and `.push()` doesn't do that as it directly just adds something to the array. The jQuery code frequently does a `.push()` followed by a `.unique()` which puts things back the way they like to keep it. – jfriend00 Sep 23 '11 at 20:20
7

I guess I don't get what you're asking. If you have an element and you want to add it to a collection, you just use the .add() method just like you've already shown. What confuses some is that this returns a new jQuery object so you would do it like this:

var spans = $();
var elem = document.getElementById('someId');
spans = spans.add(elem);

Of course, something like this would be shorter:

var spans = $();
spans = spans.add('#someId');

And, of course, you don't have to start with an empty object. You would just start with:

var spans = $('#someId');
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    " What confuses some is that this returns a new jQuery object" - In my opinion this is the best answer. – John Boe Sep 01 '16 at 20:21
5

If you're looking to push or add items selected from a jQuery object, you could also do this:

var $els = $(),
    $someEls = $(".some-els");

$els.push.apply($els, $someEls);

Just another way to do it.

marksyzm
  • 5,281
  • 2
  • 29
  • 27
  • 1
    in fact this one seems the only one that solves the problem: to add not only selected elements, but newly created elements into a empty, detached collection. I like this method when creating long lists then append the resulting detached collection to the final dom element. I wonder why just $els.push($someEls) fail. – rupps Feb 19 '15 at 12:28
  • Thanks - it's because you're pushing an array onto an array. Apply splits out the extended jQuery array and pushes each individual element onto it. Same as `var arr - []; arr.push.apply([1,2,3]);`, really. – marksyzm Feb 19 '15 at 13:19
  • 1
    `add` may also reorder the underlying array, which I can't have. – Teepeemm Mar 01 '15 at 02:13
2

What you actually want to do is use jQuery to it's full potential. You can use selectors to grab and create the collection right away. Your three lines above becomes one line:

var spans = $('#someId');

to add more ids to the collection, you can separate them with commas:

var spans = $('#someId1, #someid2, #someid3');
helloandre
  • 10,541
  • 8
  • 47
  • 64
  • To be fair, jQuery's "intended purpose" might be a little broader than you're giving it credit for... – jmar777 Sep 23 '11 at 19:38
1

While this doesn't directly answer the question of "how to append to an existing jQuery selection", I have a work-around for this particular use-case.

You can pass an array of DOM elements to jQuery, and it will create a jQuery selection out of them.

var spansArray = [];
var elem = document.getElementById('someId');
spansArray.push(elem);
var spans = $(spansArray);

I can't think of any reason why you would need to add each element to the jQuery selection one-at-a-time, as opposed to all-at-once, so this should be a "drop-in-replacement" for your use case. In theory, this must also prove more efficient, as jQuery's .add() is ultimately just calling .push() on some array behind the scenes.

Eric Seastrand
  • 2,473
  • 1
  • 29
  • 36
1

There may be better ways to do what you're trying, but if you just want to create an empty jQuery object, use this:

var $foo = $([]);


Edit: I should clarify - your code actually should work, unless you're using an older version of jQuery, in which case $() would create a collection containing the document object. In newer versions, however, there's nothing wrong with that. The code snippet I pasted above is just something that should work in older versions and newer versions of jQuery.
Edit 2: In response to this portion of the question: "I want to loop through a collection of ids and find the element on the page and add it to the matched set", the following code might be useful:
var ids = ['foo', 'bar', 'baz'],
    selector = $.map(ids, function(i, id) {
        return '#' + id;
    }).join(','),
    $collection = $(selector);
jmar777
  • 38,796
  • 11
  • 66
  • 64
0

Try

var spans = $("<span />");
var elem = $("#someId").html();
spans.append(elem).appendTo('#someAnotherId');

instead

genesis
  • 50,477
  • 20
  • 96
  • 125
0

The reason your code doesn't work is because add does not change the collection, it returns a new jQuery object with the new elements in it. If you wanted, you could instead say spans = spans.add(elem);, but what you're doing is unnecessary: the beauty of jQuery is that it makes this sort of imperative programming unnecessary. Look at helloandre's answer for a much easier way to accomplish your goal.

It's like the following, if this makes sense:

var x = [1, 2, 3];
x.concat(4);
console.log(x); // [1, 2, 3] -- concat does not mutate the original array
Ian Henry
  • 22,255
  • 4
  • 50
  • 61