Scott Greenfield
Scott Greenfield

Reputation: 2828

Turn array of jQuery elements into jQuery wrapped set of elements

Is there any elegant way of turning [$(div), $(span), $(li)] into $(div, span, li)?

What I need is a jQuery-wrapped set of elements instead of an array of jQuery elements. I would like to do this in as few lines of code as possible, and with minimal (if any) looping.

Edit: For those of you confused by this question, this code is copied and pasted from firebug using console.log on an array of elements that have already been selected.

Upvotes: 52

Views: 24063

Answers (11)

Daniel
Daniel

Reputation: 9504

Say you have an array of jQuery elements:

let elementList = [$("selector1"), $("selector2"), $("selector3"), ...];

You can simply use the jQuery function ($()) directly on the array which will return a jQuery set:

let jQuerySetOfElements = $(elementList);

Upvotes: 3

jfriend00
jfriend00

Reputation: 707716

If what you really mean is how to convert:

[$(a), $(b), $(c)]

into the result of:

$(a, b, c)

then you can use the add function to add each jQuery object to another jQuery object:

var x = $();  // empty jQuery object
$.each([$(a), $(b), $(c)], function(i, o) {x = x.add(o)});

At this point, x will contain a combined jQuery object that is the combination of the previous a, b and c jQuery objects in the array.

I couldn't find any way to do it without the each() loop. The add() function accepts an array of DOM elements as an argument, but (at least according to the documentation), not an array of jQuery objects.


Or, you could convert each jQuery object to a DOM element, which would likely be a little more efficient because it only makes one new jQuery object at the end:

$([$(".a"), $(".b"), $(".c")].map(function(o) { return o.get() }));

Upvotes: 18

Teocci
Teocci

Reputation: 8915

I have a similar problem long time ago. I have a huge form and I need to get every input. So, my idea was take each input as jQuery object and turn it into jQuery wrapped set of elements. How can I do that? Well this is the solution for your question.

  1. First you need to create an empty array as a jQuery object like this: let fields = $([]);.
  2. Now, use a string containing a selector expression to get the elements that you need in this example: 'form#details :input' as jQuery Objects.
  3. Then use .each method to extract the information that you need, and add the jQuery object to the jQuery set wrapper: fields = fields.add(input);

How do you apply to this question?

If you have a list of elements let elements = [$('#gw_id'), $('#erv_id'), $('#name')]; you can replace $('form#details :input') with elements;

Another, alternative is to use .reduce vanilla js. in this let set = $(elements.reduce((acc, cur) => {return acc.concat(cur.get())}, [])); snippet we use the array of elements and apply reduce reduce has 4 parameters but we can use the first two that are accumulator as acc and currentValue as cur also we use the Arrow function (=>) to reduce the callback. In this callback we concatenate each current value in a new array. Finally, the return array is wrapped into a jQuery object $(). You can replace elements with $('form#details :input') also.

let fields = $([]);
let elements = [$('#gw_id'), $('#erv_id'), $('#name')];

$(function() {
  console.log('List of fields: ');
  $('form#details :input').each((index, value) => {
    let input = $(value);
    let id = input.attr('id');
    let type = input.attr('type');

    fields = fields.add(input);
    if (id && type == 'text') {
      console.log('Input: ' + id + ' | Text: ' + type);
    }
  });
  fields.addClass('ui-state-error');


  let set = $(elements.reduce((acc, cur) => {
    return acc.concat(cur.get())
  }, []));

  console.log('Set list: ');
  set.each((index, value) => {
    let input = $(value);
    let id = input.attr('id');
    let type = input.attr('type');
    console.log('Input: ' + id + ' | Text: ' + type);
  });
});
.ui-state-error {
  background: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="details">
  <fieldset>
    <p>
      <label for="gw_id">GW Id</label>
      <input type="text" name="gw_id" id="gw_id" value="" class="text ui-widget-content ui-corner-all">
    </p>
    <p>
      <label for="erv_id">ERV Id</label>
      <input type="text" name="erv_id" id="erv_id" value="" class="text ui-widget-content ui-corner-all">
    </p>
    <p>
      <label for="name">Name</label>
      <input type="text" name="name" id="name" value="" class="text ui-widget-content ui-corner-all">
    </p>
    <p>
      <label for="description">Description</label>
      <input type="text" name="description" id="description" value="" class="text ui-widget-content ui-corner-all">
    </p>
    <input type="hidden" name="no" id="no" value="23" disabled readonly>
    <!-- Allow form submission with keyboard without duplicating the dialog button -->
    <input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
  </fieldset>
</form>

Upvotes: 0

user3638471
user3638471

Reputation:

A bit more concise than the accepted answer, one can use the $.fn.toArray as the argument passed to $.fn.map:

var list = [$('<a>'), $('<b>'), $('<i>')];

$(list).map($.fn.toArray);

Or perhaps (this is really inferior, but only has one function call in your code):

$.fn.map.call(list, $.fn.toArray);

Upvotes: 9

alex
alex

Reputation: 490423

If Array.prototype.reduce() is supported in your environment.

var jQueryCollection = [$("a"), $("div")]
                          .reduce(function (masterCollection, collection) {
                               return masterCollection.add(collection);
                          }, $());

jsFiddle.

Upvotes: 1

kayz1
kayz1

Reputation: 7434

To add single element:

var $previousElements = $();
$previousElements.add($element); 

to convert array to jQuery set of elements:

var myjQueryElementArray = [$element1, $element2, $elementN];
$(myjQueryElementArray ).map (function () {return this.toArray(); } );

to add array of elements to existing elements:

var $previousElements = $(),
     myjQueryElementArray = [$element1, $element2, $elementN];

$previousElements.add($(myjQueryElementArray).map (function () {return this.toArray(); } ));

Upvotes: 2

Brock Adams
Brock Adams

Reputation: 93533

jQuery's map() function is perfect for reshaping arrays and/or jQuery collections.

So, given an array set like so:

var arrayOfJQ_Objects = [$("div"), $("span"), $("li")];


This one line of code is all you need (See it in action at jsFiddle):

$(arrayOfJQ_Objects).map (function () {return this.toArray(); } );

Resulting in this console display in Firebug:

jQuery(div, span, li)


Reference, also, jQuery's .toArray() function.

Upvotes: 51

Guffa
Guffa

Reputation: 700562

You can use the add method to copy the elements in a jQuery object to another. This will copy all elements from each of the jQuery objects in the array source into the jQuery object items:

// Create an empty jQuery object
var items = $([]);
// Add the elements from each jQuery object to it
$.each(source, function(){ items = items.add(this); });

(Prior to version 1.3.2 the add method doesn't support adding a jQuery object, so you would need to use items.add(this.get()); instead.)

Upvotes: 5

fncomp
fncomp

Reputation: 6188

Edit: I thought jQuery supported all Array methods, but nay, so here's a working version of my initial solution, albeit it's a bit odd since I am sticking to the same methods:

var set; // The array of jQuery objects, 
         // but make sure it's an Array.
var output = set.pop();
$.each(set, function (_, item) { 
    return [].push.call(output, [].pop.call(item));
});

Upvotes: 1

meo
meo

Reputation: 31249

you could do something like this:

var $temp = $();
$.each([$("li"), $("li"), $("li")], function(){
    $temp.push(this[0]);
})

$temp all your elements in one jQuery selector

But i am curious what brings you to this situation having an array of different jQuery elements. You know that you can select different elements using a comma? like $("li, ul > li:eq(0), div")

edit as Guffa pointed out, this only adds the first element of each section. .add() is a better choice then .push() here.

Upvotes: 0

Rik de Vos
Rik de Vos

Reputation: 3517

$('li').each(function(){
    $(this).doSomething();

})

Upvotes: -2

Related Questions