BoundForGlory
BoundForGlory

Reputation: 4427

Making a div sort like a table

I have data thats being laid out to the page in divs and the main div is set to auto scroll when the user mouses over the up/down buttons. Here a simple example of what i have:

http://troycomptonworld.com/sorting

Now I need to add the ability to sort the divs ascending or descending if the user clicks on one of the column names (first name, salary etc). How can I do this with jQuery/javascript but keeping all of my other functionality (i.e the auto scrolling and the column headers being frozen)

Upvotes: 3

Views: 8284

Answers (4)

qpaycm
qpaycm

Reputation: 932

I found Datatables and Tinysort a little bit too much heavy. I totally agree with @SpoonMeiser as he already mensioned is easier to stick to table. That's why I want recommend you tablesort.js that I don't remember who actually wrote this, sorry, I edited this code a little for my own needs and here it is :

(function(){
    var a_re = /[cdu]\_\d+\_[cdu]/
    function hc(s, c){return (" " + s + " ").indexOf(" " + c + " ") !== -1}
    prepTabs = function (t) {
        var el, th, ts = (t && t.className) ? [t] : document.getElementsByTagName("table")
        for (var e in ts) {
            el = ts[e]
            if (hc(el.className, "sortable")) {
                th = el.tHead
                th.onclick = clicktab
                el.sorted = NaN
            }
        }
    }
    var clicktab = function (e) {
        e = e || window.event
        var obj = e.target || e.srcElement
        while (!obj.tagName.match(/^(th)$/i)) obj = obj.parentNode
        var i = obj.cellIndex, t = obj.parentNode
        while (!t.tagName.match(/^table$/i)) t = t.parentNode
        var cn = obj.className, verse = /d\_\d+\_d/.test(cn), dir = (verse) ? "u" : "d", new_cls = dir + "_1_" + dir
        if (a_re.test(cn)) obj.className = cn.replace(a_re, new_cls)
        else obj.className = new_cls
        var j = 0, tb = t.tBodies[0], rows = tb.rows, l = rows.length, c, v, vi, si, arr
        if (i !== t.sorted) {
            t.sarr = []
            for (j; j < l; j++) {
                c = rows[j].cells[i]
        v = (c) ? (c.innerHTML) : ""
        v = v.match(/txt-edit/mi) && (arr = v.match(/ value="(.+)"/mi)) ? arr[1] : v;
        v = v.match(/select-indot/mi) && (arr = v.match(/selected="selected">(.+)/mi)) ? arr[1] : v;
                vi = Math.round(100 * parseFloat(v)).toString()
        if (!isNaN(vi)) while (vi.length < 10) vi = "0" + vi
                else vi = v
                t.sarr[j] = [vi + (j/1000000000).toFixed(10), rows[j]]
      }
        }
    t.sarr = t.sarr.sort()
        if (verse) t.sarr = t.sarr.reverse()
        t.sorted = i
        for (j = 0; j < l; j++) tb.appendChild(t.sarr[j][1])
    }
    window.onload = prepTabs
})()

JSFIDDLE

UPDATE :

CSS

col {overflow:hidden !important;}
THEAD TD {background:#000;}
.sortable {clear:both;border-collapse:collapse;}
.sortable td, .sortable th {border:1px solid #000;padding:0 9px 0 9px;}
.sortable TBODY TR:hover {background-color:#ffe;}
.sortable .even {background-color:#f0f0f0;}
.sortable .odd {background-color:#fff;}
.sortable thead {cursor:pointer;}

/* arrows */
.c_0_c TH {
background:url(images/c1.gif) no-repeat right center;
background-color:#eee;
}
.c_0_c .d_1_d {
background:url(images/d10.gif) no-repeat right center;
background-color:#eee;
}
.c_0_c .u_1_u {
background:url(images/u10.gif) no-repeat right center;
background-color:#eee;
}

c1.gif

d10.gif

u10.gif

Upvotes: 1

SpoonMeiser
SpoonMeiser

Reputation: 20457

First of all, I'd suggest laying out your HTML to better represent the data. Right now, you have a number of divs sequentially that represent cells, and the only information that divides them into rows is the style. Generally, you want the structure of the HTML to represent the structure of the data (try looking at the page with CSS turned off!).

The way I'd prefer to lay it out, would be to use an actual HTML table with <thead>, <tfoot> and <tbody>, because it is tabular data, and then set the style on the tbody to be a particular height with scrolling.

The trouble with this is that it doesn't work in older browsers. I don't know what your requirements for browser compatibility is.

If you're going to stick to <div>s though, at least stick a containing div around each row.

Once you have a structure where each child of a certain element represents a row, sorting is trivial. You can grab all the elements, stick them in an array, sort it, and then bung them back into the DOM.

If all the cells in your header are also in a container of some sort (again, preferably <th>s in a <tr>, if possible) then you can figure out the index of the child within that container that was clicked, and then sort your rows using the value of the child with the same index in each row.

Upvotes: 3

IsisCode
IsisCode

Reputation: 2490

May I recommend tinysort?

Upvotes: 1

Downpour046
Downpour046

Reputation: 1671

Normally I'd suggest jQuery UI - but they are still in the process of implementing datagrid tables into the UI.

Take a look at this plugin for jQuery:

http://datatables.net/

You're going to want to use some sort of datagrid plugin for the type of sorting you are looking for.

At the very least, go to the site, and investigate how they do the function calls for sorting. Cheers.

Upvotes: 2

Related Questions