At work this past week, a client requested something that I wasn’t sure how to achieve: a reversed ordered list. So basically, they wanted to have a top 10 list, with the first item being numbered 10 and the last 1.
If you want to skip ahead to the demo, go ahead.
Now sure, I could have just written the numbers in as text, but it’s a list, and it’s ordered! Here is an example of what the client wanted:
10. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
9. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
8. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
…
1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
After some digging around, I found out that you can add the value attribute to each list item to specify the number to display. So basically, I just needed to code my list like this:
<ol>
<li value="10">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
<li value="9">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
<li value="8">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
…
<li value="1">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
</ol>
Pretty straightforward, but also pretty ugly. So what happens when the client decides they want to insert another bullet in the middle of the list? Yep, that’s right, they would have to adjust the numbering for the rest of the list.
Pretty crappy, so let’s use the powerfulness of jQuery to make this a little better.
The Markup
So just like before, we just want to create an ordered list, but this time, we will leave off the value attribute. We are also going to add a class to the ordered list that we will use as a hook to add in the jQuery functionality:
<ol class="reversed">
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
…
<li>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
</ol>
The jQuery
Mapping out the code a bit: we want to select each element with a class of reversed, and count the total number of children list items. Then, we want to loop through the children, and update the value attribute to be the value of the total number of children minus a counter variable that we started at zero and increment each time through the loop.
That seems relatively straightforward, so I’ll just show the code that I wrote:
$(document).ready(function() {
$('.reversed').each(function() {
var $children = $(this).children('li');
var totalChildren = $children.length;
var start = 0;
$children.each(function() {
$(this).val(totalChildren - start);
start++;
});
});
});
It looks like with HTML 5, we get a reversed attribute that accomplishes the same thing, but until it’s fully supported, this quick & easy solution seems to work.
On a Personal Note
I have been severely neglecting my blog, but for good reason. I have been teaching some intro to web development courses at CDIABU in Georgetown. Also, I will be starting a new job on December 1st. I will be joining the amazing team at Viget Labs as their new front-end developer.
20 Comments
Tom
11.11.2009Cool. Just in time for the end of year ‘best of’ lists to start up.
Nate
11.11.2009Sometimes it’s the simple things in life. One of the things I love about jQuery is finding out how effortless and straightforward it is to do deeply satisfying things like this to one’s code.
The only, very small, concern I have about this is that the meaning of the ordered list in so far as the mark-up is concerned is exactly opposite what you intend it to be. The javascript doesn’t just enhance the presentation of the list, it flips the meaning. I’m not sure how terribly concerned I am about the browsers that view our sites without javascript, but violating the philosophical separation of meaning:markup / behavior:script bothers me a little bit.
Nate
11.11.2009I’d suggest, as an alternative, actually reordering the items in the list as well as adding values, so that the meaning that’s in the mark-up—that list of 1-10 items—is accurate, but simply presented in a different order than you’ll accomplish via javascript.
Tweets that mention Reversed Ordered List with jQu
11.11.2009[...] This post was mentioned on Twitter by Mike Lane, Dimox and Trevor Davis, Dimox. Dimox said: Reversed Ordered List with #jQuery - http://bit.ly/3aF6G2 [...]
Nate
11.11.2009This is the sort of thing I mean:
This is number one.This is number two.
This is number three.
This is number four.
$(document).ready(function() {
$('.reversed').each(function() {
var children = $(this).children('li').get();
$(this).empty();
children.reverse();
$(this).append(children);
$(children).each(function() {
$(this).val(children.length - $(children).index(this));
});
});
});
Nate
11.11.2009Hmm—that code didn’t exactly format the way I would’ve liked. Help a brother out?
Trevor
11.11.2009@Nate-
<pre> tag sir…
I guess reordering the list does add some sort of semantic value, but how much really? It depends if there is any value given to item 10 vs. item 1.
Nate
11.11.2009I had <pre> tags, man: I think it was stripped out by your demon CMS. (Don’t be sad, WordPress, I didn’t mean it.)
I guess technically there’s nothing but order necessarily implied by an unordered list, but there are default ways, as far as browsers are concerned, of interpreting them, and the default is as a numbered list. In this instance, I think browsers behave just like any reader would: unless we’re explicitly told otherwise, the numbers start at one and proceed upwards.
Nate
11.11.2009@Nate-
Of course, by “unordered” above, I mean “ordered”.
Trevor
11.11.2009@Nate-
Stupid WordPress.
Agreed, so I guess it just depends on whether there is a reference somewhere on the page saying that this list is presented in a certain order for a specific reason. If not, then I don’t think too much value is added in reversing it for non-JavaScript users.
I wonder what kind of load reversing the list adds to the page. I’m sure it’s trivial in this example since the list is so short, but what about a list with 100 items?
Nate
11.11.2009@Trevor-
I think if you say, “This is our list of $whatevers”, and you have an ordered list of items, the meaning of those items is the same as if they had an invisible #1-10 next to them. Whether that ranking means “best” or “worst” or “funniest” or whatever is, of course, subject to the nature of the content. But it makes me feel like it’s still well worth having the script reverse the actual items.
That said, there’s no denying there’s a performance difference between just setting the value and rearranging the elements. I profiled the four-item ordered list and then a 120-item ordered list with each of our scripts, with these results:
Your script:
4: 1.37ms
120: 21.164ms
My script:
4: 3.608ms
120: 63.695ms
uberVU - social comments
11.11.2009Social comments and analytics for this post…
This post was mentioned on Twitter by davist11: Just wrote a short blog article about creating a reversed ordered list with jQuery http://bit.ly/4z4E5V...
Reversed Ordered List with jQuery | Trevor Davis
11.11.2009[...] Reversed Ordered List with jQuery | Trevor Davis – [...]
Trevor
11.11.2009@Nate-
Wow, thanks for running the performance tests. Your point about reversing the list items is certainly valid and a nice addition to the example.
CSS Brigit | Reversed Ordered List with jQuery
11.12.2009Reversed Ordered List with jQuery…
How to create an ordered list that counts in reverse with jQuery.
...
Judd Lyon
11.13.2009Nice little trick, thanks!
Congrats on teaching and the new gig with Viget, they are an impressive outfit that just got better.
Cheers.
Trevor
11.14.2009@Judd Lyon-
Thanks, I’m excited!
Steward
11.23.2009May be better without unnecessary variable “start”?
$(document).ready(function() {$('.reversed').each(function() {
var $children = $(this).children('li');
var totalChildren = $children.length;
$children.each(function() {
$(this).val(totalChildren--);
});
});
});
I don’t understand - what what do you use “var start = 0;”?
Twitted by Mixedmedia
12.05.2009[...] This post was Twitted by Mixedmedia [...]
David Betz
12.11.2009Thanks! This got me half way there. The challenge I was given: a reverse ordered list of articles grouped by year, so basically a series of ordered lists separated by headers with the reverse count preserved.
$(document).ready(function() {var totalAll = 0;
$('.reversed').each(function() {
var children = $(this).children('li');
var totalChildren = children.length;
totalAll+= totalChildren;
});
$('.reversed').each(function() {
var children = $(this).children('li');
var totalChildren = children.length;
children.each(function() {
$(this).val(totalAll--);
});
});
});
——-