Reputation: 40719
I have this HTML code:
<div id="main">
<div id="dv_7">...</div>
<div id="dv_1">...</div>
<div id="dv_8">...</div>
<div id="dv_4">...</div>
<div id="dv_11">...</div>
<div id="dv_2">...</div>
</div>
How to order the divs in the maindiv with javascript? I have no idea :(
thanks in advance,
Upvotes: 7
Views: 17534
Reputation: 156
<div id="main">
<div id="dv_7" data-order=7>7</div>
<div id="dv_1" data-order=1>1</div>
<div id="dv_8" data-order=8>8</div>
<div id="dv_4" data-order=4>4</div>
<div id="dv_11" data-order=11>11</div>
<div id="dv_2" data-order=2>2</div>
</div>
<button onclick="sort()">
Sort
</button>
function sort() {
var main = document.getElementById( 'main' );
[].map.call( main.children, Object ).sort( function ( a, b ) {
console.log(a.dataset.order);
return +a.dataset.order - +b.dataset.order;
}).forEach( function ( elem ) {
main.appendChild( elem );
});
}
Updated @Šime Vidas answer to support dynamic order with button and Data Attribute
Upvotes: 0
Reputation: 2695
function sortChildren(parent, comparator) {
parent.replaceChildren(...Array.from(parent.children).sort(comparator));
}
That's all you need. Example:
const main = document.getElementById('main');
sortChildren(main, (a, b) => +a.id.match( /\d+/ ) - +b.id.match( /\d+/ ));
Upvotes: 0
Reputation: 185933
How about:
var main = document.getElementById( 'main' );
[].map.call( main.children, Object ).sort( function ( a, b ) {
return +a.id.match( /\d+/ ) - +b.id.match( /\d+/ );
}).forEach( function ( elem ) {
main.appendChild( elem );
});
Live demo: http://jsfiddle.net/ZEKrH/6/
(You'll need to shim those array methods for IE8.)
Upvotes: 7
Reputation: 147383
The following is compatible with browsers back to IE 5 and similar, no shims or libraries. The sort function can be modified to sort numerically, at present it will sort the divs as 1, 11, 2, 4, etc. It's not too hard to change it so they are sorted 1, 2, 4, ... 11.
function sortDivs(div) {
var divs = div.getElementsByTagName('div');
var a = [];
for (var i=0, iLen=divs.length; i<iLen; i++) {
a[i] = divs[i];
}
a.sort(function(a, b) {
return a.id < b.id? -1 : a.id == b.id? 0 : 1;
});
while (iLen--) {
div.insertBefore(a[iLen], div.firstChild);
}
}
window.onload = function() {
sortDivs(document.getElementById('main'));
}
Minimalist version for those who think it matters with comments and numeric sort.
function sortDivs(div) {
var divs = div.getElementsByTagName('div');
// Convert divs collection to an array
for (var i=0, iLen=divs.length, a=[]; i<iLen; i++) a[i] = divs[i];
// Sort the array numerically
a.sort(function(a, b) {
return a.id.split('_')[1] - b.id.split('_')[1];
});
// Move elements to sorted order
while (iLen--) div.insertBefore(a[iLen], div.firstChild);
}
Upvotes: 1
Reputation: 4180
the following might work:
var main = document.getElementById("main");
for(var i = 11; i > -1; i--) {
var div = document.getElementById("dv_" + i);
if(div != null)
main.appendChild(div);
}
Upvotes: 2
Reputation: 531
Hope this helps. Updated the id to account for alphabetical ordering 1 and 11.
<div id="main">
<div id="dv_07">7...</div>
<div id="dv_01">1...</div>
<div id="dv_08">8...</div>
<div id="dv_04">4...</div>
<div id="dv_11">11...</div>
<div id="dv_02">2...</div>
</div>
jQuery option:
var mylist = $('#main');
var listitems = mylist.children('div').get();
listitems.sort(function(a, b) {
var compA = $(a).attr('id').toUpperCase();
var compB = $(b).attr('id').toUpperCase();
return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
})
$.each(listitems, function(idx, itm) {
mylist.append(itm);
});
Javascript option:
var mylist = document.getElementById('main');
var divs = mylist.getElementsByTagName('div');
var listitems = [];
for (i = 0; i < divs.length; i++) {
listitems.push(divs.item(i));
}
listitems.sort(function(a, b) {
var compA = a.getAttribute('id').toUpperCase();
var compB = b.getAttribute('id').toUpperCase();
return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
});
for (i = 0; i < listitems.length; i++) {
mylist.appendChild(listitems[i]);
}
Upvotes: 8
Reputation: 707318
For a solution that works for any arbitrary number of child divs with numbers in any range, you can use a function like this (that actually parses the number of our the ID and does a true numeric sort on it):
function sortChildrenDivsById(parentId) {
var parent = document.getElementById(parentId);
// get child divs
var children = parent.getElementsByTagName("div");
var ids = [], obj, i, len;
// build an array of objects that has both the element
// and a parsed div number in it so we can sort
for (i = 0, len = children.length; i < len; i++) {
obj = {};
obj.element = children[i];
obj.idNum = parseInt(children[i].id.replace(/[^\d]/g, ""), 10);
ids.push(obj);
}
// sort the array
ids.sort(function(a, b) {return(a.idNum - b.idNum);});
// append in sorted order
for (i = 0; i < ids.length; i++) {
parent.appendChild(ids[i].element);
}
}
Working example here: http://jsfiddle.net/jfriend00/v9mCM/
FYI, this is cross-browser, plain javascript and will even work in old browsers without shims.
Here's another way of doing it with slightly less code:
function sortChildrenDivsById(parentId) {
var parent = document.getElementById(parentId);
var children = parent.getElementsByTagName("div");
var ids = [], i, len;
for (i = 0, len = children.length; i < len; i++) {
ids.push(parseInt(children[i].id.replace(/^.*_/g, ""), 10));
}
ids.sort(function(a, b) {return(a - b);});
for (i = 0, len = ids.length; i < len; i++) {
parent.appendChild(document.getElementById("dv_" + ids[i]));
}
}
Working example: http://jsfiddle.net/jfriend00/TqJVb/
All the ids nums are parsed out and put into an array which is sorted and then each object is looked up by id and reinserted in sorted order. This wouldn't be quite as fast as the first one, but it's less code.
Upvotes: 2