I have a blog which produces a list like this on a php/html page
<div id="unique-id-4" class="blog-entry">Bert blah blah</div>
<div id="unique-id-2" class="blog-entry">Andy blah blah</div>
<div id="unique-id-3" class="blog-entry">Chas blah blah</div>
<div id="unique-id-1" class="blog-entry">Dave blah blah</div>
I want to reorder the divs on the page using javascript.
Firstly, to see how it works, an alphabetical sort. (That may be enough for this question). But secondly (what I really want to do) sort them by "age". I have an array of each person's name and age which I can reference. Is this even possible?
I found this when looking for finding by class
var content = document.getElementsByClassName('blog-entry')
The sorted output could be on the same page, or on a different page - it doesn't matter. thanks for any help. I know very little about javascript.
I'd like to sort in the order 1) Andy, Bert, Chas, Dave (i.e. "alphabetically) producing:
<div id="unique-id-2" class="blog-entry">Andy blah blah</div>
<div id="unique-id-4" class="blog-entry">Bert blah blah</div>
<div id="unique-id-3" class="blog-entry">Chas blah blah</div>
<div id="unique-id-1" class="blog-entry">Dave blah blah</div>
and ideally
2) By their ages, where in a separate array: Andy = 42, Bert =18, Chas = 73, Dave = 56; producing
<div id="unique-id-4" class="blog-entry">Bert blah blah</div>
<div id="unique-id-2" class="blog-entry">Andy blah blah</div>
<div id="unique-id-1" class="blog-entry">Dave blah blah</div>
<div id="unique-id-3" class="blog-entry">Chas blah blah</div>
I have a blog which produces a list like this on a php/html page
<div id="unique-id-4" class="blog-entry">Bert blah blah</div>
<div id="unique-id-2" class="blog-entry">Andy blah blah</div>
<div id="unique-id-3" class="blog-entry">Chas blah blah</div>
<div id="unique-id-1" class="blog-entry">Dave blah blah</div>
I want to reorder the divs on the page using javascript.
Firstly, to see how it works, an alphabetical sort. (That may be enough for this question). But secondly (what I really want to do) sort them by "age". I have an array of each person's name and age which I can reference. Is this even possible?
I found this when looking for finding by class
var content = document.getElementsByClassName('blog-entry')
The sorted output could be on the same page, or on a different page - it doesn't matter. thanks for any help. I know very little about javascript.
I'd like to sort in the order 1) Andy, Bert, Chas, Dave (i.e. "alphabetically) producing:
<div id="unique-id-2" class="blog-entry">Andy blah blah</div>
<div id="unique-id-4" class="blog-entry">Bert blah blah</div>
<div id="unique-id-3" class="blog-entry">Chas blah blah</div>
<div id="unique-id-1" class="blog-entry">Dave blah blah</div>
and ideally
2) By their ages, where in a separate array: Andy = 42, Bert =18, Chas = 73, Dave = 56; producing
<div id="unique-id-4" class="blog-entry">Bert blah blah</div>
<div id="unique-id-2" class="blog-entry">Andy blah blah</div>
<div id="unique-id-1" class="blog-entry">Dave blah blah</div>
<div id="unique-id-3" class="blog-entry">Chas blah blah</div>
Share
Improve this question
edited Jan 15, 2012 at 21:14
Gabe
asked Jan 15, 2012 at 17:39
GabeGabe
511 gold badge1 silver badge4 bronze badges
1
- See this working jsfiddle. – Shiplu Mokaddim Commented Jan 15, 2012 at 18:40
6 Answers
Reset to default 3While I'm not entirely sure what you intend to sort by this should cover all angles.
/*Sort my entries
sortProperty = DOM object property that is to be used to sort in ascending order
*/
function sortMyEntries(sortProperty)
{
var blogEntries = document.getElementsByClassName("blog-entry");
blogEntries = Array.prototype.slice.call(blogEntries,0)
blogEntries.sort(function(a,b)
{
return (a[sortProperty] > b[sortProperty]);
})
return blogEntries;
}
This method is currently limited to dealing with a question specific selector but it is fairly flexible. For example both of the following are applicable
sortMyEntries("id"); //Sort blog entries by DOM object id
sortMyEntries("innerHTML"); //Sort blog entries by DOM object innerHTML
Using no magic or unsupport methods:
var elements = document.getElementsByTagName('div');
var filtered = [];
for (var i = 0; i < elements.length; i++) {
if (elements[i].className === "blog-entry") {
filtered.push(elements[i]);
}
}
var sorted = filtered.sort(function (a, b) {
return a.innerHTML > b.innerHTML;
});
var parent = elements[0].parentNode;
for (i = 0; i < sorted.length; i++) {
parent.appendChild(sorted[i]);
}
JsFiddle demo
Node information
For an array based sort:
var people = [{name: "Andy", age: 20}, {name: "Bob", age: 67}];
var sorted = filtered.sort(function (a, b) {
return people[a.innerHTML].age > people[b.innerHTML].age;
});
First thing, content
is not an array here. It is NodeList. So the steps to do.
- Convert NodeList to array
- Sort array
- Remove all blog entries
Add from sorted array
<div id="blogs"> <div id="unique-id-4" class="blog-entry">Bert blah blah</div> <div id="unique-id-2" class="blog-entry">Andy blah blah</div> <div id="unique-id-3" class="blog-entry">Chas blah blah</div> <div id="unique-id-1" class="blog-entry">Dave blah blah</div> </div> var blogs = document.getElementById("blogs"); var blogEntries = blogs.getElementsByClassName('blog-entry'); blogEntries = Array.prototype.slice.call(blogEntries); if(blogEntries && blogEntries.length){ blogEntries.sort(sortBlogs); while (blogs.hasChildNodes()) { blogs.removeChild(blogs.lastChild); } while(blogEntries.length){ var blogEntry = blogEntries.shift(); blogs.appendChild(blogEntry); } } function sortBlogs(a, b){ var aid = parseInt(a.id.replace("unique-id-", "")); var bid = parseInt(b.id.replace("unique-id-", "")); return aid - bid; }
See a demo here : http://jsfiddle/diode/8W6AU/7/
Modify the function sortBlogs
for the sorting needed. Now it uses id for sorting.
var content = document.getElementsByClassName('blog-entry')
will give you node list ofHTMLElement
object in content.- Convert it to
Array
. - Sort it using the
Array.sort
function. - On the callback, pare the objects using their
innerHTML
property.
http://jsfiddle/myk2X/3/ is a working example. The silver container holds the initial objects, and the light green container holds the result.
It depends how your arrays are stored (does unique-id-X
correspond to ages[X]
?) but here's the general method: pass a custom parison function to Array.sort
.
function toArray(obj) {
var r = [], i = 0, l = obj.length;
for(; i < l; i++) {
if(i in obj) {
r[i] = obj[i];
}
}
return r;
}
var elements = toArray(document.getElementsByClassName('blog-entry')); // Doesn't have full browser support, so you might want to use jQuery, e.g. here.
var ages = [...];
var names = [...];
elements.sort(function(element1, element2) {
var index1 = elements.indexOf(element1);
var index2 = elements.indexOf(element2);
// Sort by name first:
if(names[index1] < names[index2]) { // Can do case-insensitive parison here, too.
return -1;
} else if(names[index1] > names[index2]) {
return 1;
} else if(ages[index1] < ages[index2]) {
// Names were equal, sort by age.
return -1;
} else if(ages[index1] > ages[index2]) {
return 1;
} else {
// They're equal.
return 0;
}
}).forEach(function(element) {
// This is where the magic happens! appendChild() is just called in order.
// The best part is that it looks like it does almost nothing.
element.parentNode.appendChild(element);
});
Of course, there are two things that might not work in IE. (Happy, Raynos?) One is document.getElementsByClassName
, and the other is Array.forEach
. Those aren't supported in some browsers, i.e. IE. Here's a patibility script for Array.forEach
:
if(![].forEach) {
Array.prototype.forEach = function(action, thisArg) {
for(var i = 0, l = this.length; i < l; i++) {
if(i in this) {
action.call(thisArg, this[i], i, this);
}
}
};
}
Seems like the ideal opportunity to use jQuery and a plugin along the lines of TinySort.