I have a list of elements that I get using JQuery.
var $self = $(this);
var $fields = $('.identifier-controls', $self);
This list is the list of elements that need to be manipulated in some way when the control renders. Each element in the list of $fields contains a data attribute called "data-order". This attribute tells me what order I should arrange the elements with in the control (ah requirements). The order does not have to be in direct linear order (meaning that the first control can have an attribute value of 10 and the next one 15 and the next one 17 etc. They just need to appear in the asc order. Is there a simple way to achieve this? All the ways that I can come up with seem a bit over complicated.
Steps to sort jquery "array-like" objects by data attribute...
Html
<div class="item" data-order="2">2</div> <div class="item" data-order="1">1</div> <div class="item" data-order="4">4</div> <div class="item" data-order="3">3</div>
Plain jquery selector
$('.item');
[<div class="item" data-order="2">2</div>, <div class="item" data-order="1">1</div>, <div class="item" data-order="4">4</div>, <div class="item" data-order="3">3</div> ]
Lets sort this by data-order
function getSorted(selector, attrName) { return $($(selector).toArray().sort(function(a, b){ var aVal = parseInt(a.getAttribute(attrName)), bVal = parseInt(b.getAttribute(attrName)); return aVal - bVal; })); }
> getSorted('.item', 'data-order')
[<div class="item" data-order="1">1</div>, <div class="item" data-order="2">2</div>, <div class="item" data-order="3">3</div>, <div class="item" data-order="4">4</div> ]
See how getSorted() works.
Hope this helps!
An insertion sort would be a fairly straight-forward way of doing it.
Or being a bit subversive, you can take advantage of the JavaScript engine for this:
var $fields, $container, sorted, index;
$container = $('body');
$fields = $("div[data-order]", $container);
sorted = [];
$fields.detach().each(function() {
sorted[parseInt(this.getAttribute("data-order"), 10)] = this;
});
sorted.forEach(function(element) {
$container.append(element);
});
Live Example:
(function($) {
var $fields, $container, sorted, index;
$container = $('body');
$fields = $("div[data-order]", $container);
sorted = [];
$fields.detach().each(function() {
sorted[parseInt(this.getAttribute("data-order"), 10)] = this;
});
sorted.forEach(function(element) {
$container.append(element);
});
})(jQuery);
<div data-order="30">30</div>
<div data-order="40">40</div>
<div data-order="10">10</div>
<div data-order="20">20</div>
<div data-order="1">1</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Here's how that works:
We get the container, and get the fields from it.
We create a blank array. Remember that JavaScript arrays aren't really arrays at all, and they're inherently sparse.
We detach the fields, then loop through them, getting the data-order
from the DOM element and adding the DOM element to the array in that position. This assumes that data-order
values are unique.
Once we have the array of raw DOM elements, we loop through it using forEach
, appending them to the container. I didn't use jQuery.each
because jQuery.each
will call the callback even for non-existant array indexes, which if your data-order
values are quite sparse could be a problem. forEach
iterates the entries in numeric order, skipping over ones that don't exist.
Try this:
$(function(){
var $self = $(this);
var sortedList = $('.identifier-controls', $self).sort(function(lhs, rhs){
return parseInt($(lhs).attr("data-order"),10) - parseInt($(rhs).attr("data-order"),10);
});
});
the variable sortedList now has the sorted elements.
Something like:
$fields.sort(function(a, b) {
return a.getAttribute('data-order') > b.getAttribute('data-order');
}).appendTo($fields.parent());
Fiddle: http://jsfiddle.net/gCFzc/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With