Reputation: 30015
<div class="myClass">1</div>
<div class="myClass">2</div>
<div class="myClass">3</div>
<div class="myClass">4</div>
<div class="myClass">5</div>
<div class="myClass">6</div>
var $myClass = $('.myClass');
$myClass.eq(0).text() //returns '1'
$myClass.eq(4).text() //returns '5'
$myClass.eq(5).text() //returns '6'
What I want to do is reorder the objects in jQuery manually.
//fantasy command reversing
$myClass.eqSorter([5,4,3,2,1,0]);
$myClass.eq(0).text() //returns '6'
$myClass.eq(5).text() //returns '1'
What I really want is to allow a fully custom order input
//fantasy command custom ordering
$myClass.eqSorter([3,5,4,2,0,1]);
$myClass.eq(0).text() //returns '4'
$myClass.eq(5).text() //returns '2'
Now I've looked at basic ways of doing this like .sort
as a part of javascript, but .sort
takes a dynamic argument the compares things, and does not allow for a fully custom order. I also looked at making a new blank jquery object that I could pass elements into like this $newObjectVar.eq(0) = $myClass.eq(3);
for example. But as of yet I have not found a way to make a blank jQuery object like this.
Upvotes: 1
Views: 3196
Reputation: 707326
You could make a custom method like this that would reorder the existing DOM elements in the jQuery object. One issue is that many operations on jQuery objects sort them into DOM order so they may not stay in this order if you carry out other operations on the jQuery object.
jQuery.fn.eqSorter = function(array) {
// get copy of DOM element array
var copy = this.toArray();
// don't exceed bounds of arrays
var len = Math.min(array.length, copy.length);
for (var i = 0; i < len; i++) {
var index = array[i];
// make sure incoming index is within bounds of DOM object array
if (index < copy.length) {
// put the index item into the i location
this[i] = copy[index];
}
}
return this;
}
$myClass.eqSorter([5,4,3,2,1,0]);
After some more thinking, here's another way of doing things that is also a lot more robust as it prevents dups and holes even if the array passed in has errors in it. The result will be only the elements that match the indexes in the passed in array. Any dups or indexes out of range will be ignored.
The jQuery way of doing things is generally not to change the DOM elements in a given jQuery object, but to modify the existing jQuery object into a new jQuery object. To implement it that way, with the added robustness you could do this:
jQuery.fn.eqSorter = function(array) {
var elems = [], doneIndexes = {}, index;
for (var i = 0, len = array.length; i < len; i++) {
index = array[i];
// if the index is not out of range and it's not a dup,
// then get the corresponding DOM element from the jQuery object
// and put it into the new array
if (!doneIndexes[index] && index < this.length && index >= 0) {
elems.push(this[index]);
doneIndexes[index] = true;
}
}
return this.pushStack(elems, "eqSorter", arguments);
}
var $myOrderedObj = $myClass.eqSorter([5,4,3,2,1,0]);
This has the following behavior:
.end()
There's a working testbed here: http://jsfiddle.net/jfriend00/DPhc9/
Upvotes: 4