-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.sortberg.js
166 lines (142 loc) · 3.96 KB
/
jquery.sortberg.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
(function($)
{
var getSortIndex = function(elem) {
var extraColspan = 0;
var extraRowspan = 0;
// take colspan of columns to the left of this column into account
$(elem).prevAll().each(function(idx) {
var colspan = $(this).prop("colSpan");
if (colspan) {
extraColspan += colspan-1;
}
});
// take rowspan of columns "above" into account by adding 1 for each rowspan column
// until we have found maxCols non-rowspan columns (taking colspans into account too)
var $prevRow = $(elem).parent().prev();
var maxCols = $(elem).index() + 1;
$prevRow.find("th").each(function(idx) {
var rowspan = $(this).prop("rowSpan");
var colspan = $(this).prop("colSpan");
if (rowspan && rowspan > 1 && maxCols > 0) {
extraRowspan += 1;
} else {
maxCols -= colspan;
}
});
return $(elem).index() + extraColspan + extraRowspan;
};
var getSortValue = function($elem) {
// returns the value of the data-sort-value attribute if set, otherwise the text of the element
var value = $elem.data("sort-value");
if (value !== undefined) {
return value;
}
return $elem.text();
};
$.fn.sortberg = function(params)
{
return this.each(function() {
var $this = $(this);
var options = params || {};
var defaults = {groupClass: 'details', ignoreCase: false};
options = $.extend(defaults, options);
var comparators = {};
comparators.text = function($a, $b)
{
var a = getSortValue($a);
var b = getSortValue($b);
if (options.ignoreCase) {
a = a.toLowerCase();
b = b.toLowerCase();
}
if (a < b) return -1;
if (a > b) return 1;
return 0;
};
comparators.number = function($a, $b)
{
var a = parseFloat(getSortValue($a));
var b = parseFloat(getSortValue($b));
if (isNaN(a)) { a = 0 }
if (isNaN(b)) { b = 0 }
return a - b;
};
$this.on('click', 'thead th', function(e)
{
var $self = $(this);
var idx = getSortIndex(this);
var rows = [];
var comparator;
// only sort if the th is clicked, not child elements inside the th
if (e.target != this) {
return;
}
// disable sorting on headers that span multiple columns since it wouldn't be clear what is being sorted
if ($self.prop('colSpan') > 1) {
return this;
}
$this.find('tbody tr').each(function()
{
if ($(this).hasClass(options.groupClass))
{
return true;
}
var details = $(this).nextUntil(':not(.' + options.groupClass + ')', 'tr').get();
var row = {row: $(this).get(), details: details};
rows.push(row);
});
if (options.comparator)
{
comparator = options.comparator;
}
else if ($(this).data('sorting'))
{
var sorting = $(this).data('sorting');
comparator = comparators[sorting];
}
rows.sort(function(a, b)
{
$a = $(a.row).children('th,td').eq(idx);
$b = $(b.row).children('th,td').eq(idx);
if (! comparator)
{
if (isNaN(parseFloat(getSortValue($a))))
comparator = comparators['text'];
else
comparator = comparators['number'];
}
var result = comparator($a, $b);
//which direction should we sort in? if not currently sorted, we default to ascending
if ($self.hasClass('sort-asc'))
{
return -result;
}
else
{
return result;
}
});
//set correct css class to currently sorted column
if ($self.hasClass('sort-asc'))
{
$self.removeClass('sort-asc').addClass('sort-desc');
}
else
{
$self.removeClass('sort-desc').addClass('sort-asc');
}
//other columns are not sorted
$this.find('th').not($self).removeClass('sort-desc').removeClass('sort-asc');
//update the actual table
for (var i = 0; i < rows.length; i++)
{
$this.find('tbody').append(rows[i].row);
if (rows[i].details.length > 0)
{
$this.find('tbody').append(rows[i].details);
}
}
});
})
}
})(jQuery);