So, I wanted to drop in some basic column sorting without having to rip out the innards of something like streamlined. I googled and came across this blogpost on SCSCS - which is so worth it for super-cool simple column sorting...
But I'm just not satisfied by what it can do. As ever, I want more. In this example, I wanted to be able to display neato little up/down arrow widgety thingies on the column heads by giving the th the appropriate "up/down" class - so the user can see which column it's all sorting by.
Arrowy goodness
We want a way to stuff a CSS class into the table's column-heads so we can show the sorty arrows. We need to indicate two things. Firstly, when the data has been sorted by a particular column, we want to indicate "this is the current sort colum". Secondly, we want to be able to indicate the sorting direction of a column (up, down or indifferent).
So the first step is to create (or appropriate) arrow-images. I'm not going to show an example here (you can figure that out for yourself) but I'll assume you have three images: SortUp.gif, SortDown.gif (to show that the current column is sorted up or down), and SortAny.gif (a double-arrow to indicate that the column could be sorted if they want to).
Stylish stuff
Then you need to put something appropriate in your stylesheet. eg:
/* what an ordinary column-head looks like */
.dataTable th {
background-color: grey;
color: white;
padding-left: 15px;
padding-right: 4px;
}
/* colour for currently sorted column */
.dataTable th.current {
background-color: black;
color: white;
}
/* the sorting link */
.dataTable th a {
color: white;
text-decoration: none;
display: block;
width: 100%;
}
.dataTable th.current a {
color: grey;
}
/* pretty colours when hovering */
.dataTable th a:hover {
color: blue;
background-color: grey;
}
.dataTable th:hover {
background-color: grey;
}
/* display of up and down arrows for sortable columns */
.dataTable th.up {
background-image: url("/images/SortUp.gif");
background-repeat: no-repeat;
background-position: center left;
}
.dataTable th.down {
background-image: url("/images/SortDown.gif");
background-repeat: no-repeat;
background-position: center left;
}
/* display for "any" sort - eg up and down arrows */
.dataTable th.any {
background-image: url("/images/SortAny.gif");
background-repeat: no-repeat;
background-position: center left;
}
Stuff to note:
- The "current" column head is a distinctively different colour to a normal column - this makes it stand out.
- The "hover" colours provide good feedback for users - they pick up the idea that clicking here will probably do something.
- The anchor within the column head has display:block; and width:100%; this makes the anchor stretch to the full width of the column-head - which is nicer than having to click just the word itself.
- There's a padding-left on the anchor columns - this gives room for the arrow images. I've specified 15px as it's big enough for the images I use - YMMV.
Classy heads
So now we need to adapt the sort_link method to make it actually use this stuff. But we don't want it just on the link - the class needs to go on the whole column-head. So write a wrapper-function that will generate the whole <th> for you (class and all):
# generate appropriate class for current sort options
def sortlink_class(col)
return "any" unless params[:col] || params[:dir]
return "current #{params[:dir] == 'up' ? 'up' : 'down'}" if params[:col] == col.to_s
"any"
end
# Generates a column head tag that contains a sort link and is given the
# appropriate class for the current sorting options.
def column_sort_link(title, column, options = {})
content_tag 'th', sort_link(title, column, options),
:class => sortlink_class(column)
end
def sort_link(title, column, options = {})
if options.has_key?(:unless)
condition = options[:unless]
options.delete(:unless)
end
new_sort_dir = params[:dir] == 'down' ? 'up' : 'down'
link_to_unless condition, title, request.parameters.merge(options.merge(:col => column, :dir => new_sort_dir))
end
So, the currently sorted column will get something like class="current up", wheras most of the columns will be class="any". You'll also note I updated the badly-named "d" and "c" to "dir" and "col" so that unsuspecting maintenance people might have a clue as to the actual purpose of the options. Self-documenting code being a Good Thing.
Finally, I've modified it to pass through any extra options to the controller by merging the options into the link. This can be used to pass through requests for special sorts, extra parameters etc.
0 comments:
Post a Comment