Following this post jQuery table sort (github link: https://github.com/padolsey/jQuery-Plugins/blob/master/sortElements/jquery.sortElements.js), I am successfully sort columns,
Conditions for the code to work:
td
s with rowspan
must all be on the left of the tabletd
s in these columns must have a rowspan
, even if it's 1jsFiddle: http://jsfiddle.net/5GrAC/77/
var inverse = false;
function sortColumn(index) {
var trs = $('#resultsTable > tbody > tr'),
nbRowspans = trs.first().children('[rowspan]').length,
offset = trs.first().children('[rowspan]').last().offset().left;
var tds = trs.children('[rowspan]').each(function() {
$(this).data('row', $(this).parent().index());
$(this).data('column', $(this).index());
$(this).data('offset', $(this).offset().left)
}).each(function() {
if($(this).data('offset') != offset)
return;
var rowMin = $(this).data('row'),
rowMax = rowMin + parseInt($(this).attr('rowspan'));
trs.slice(rowMin, rowMax).children().filter(function() {
return $(this).index() == index + $(this).parent().children('[rowspan]').length - nbRowspans;
}).sortElements(function(a, b) {
a = convertToNum($(a).text());
b = convertToNum($(b).text());
return (
isNaN(a) || isNaN(b) ?
a > b : +a > +b
) ?
inverse ? -1 : 1 :
inverse ? 1 : -1;
}, function() {
return this.parentNode;
});
});
var trs = $('#resultsTable > tbody > tr');
tds.each(function() {
if($(this).parent().index() != $(this).data('row'))
$(this).insertBefore(trs.eq($(this).data('row')).children().eq($(this).data('column')));
});
inverse = !inverse;
}
Quick explanations:
td
s with rowspan
td
s are saved, including left offsettd
s are filtered by their original offset
to work only with the rightmost onestr
s related to each kept td
are sorted using the wanted columntd
s with rowspan
are finally moved back to their original position if necessaryAbout question 2, I will only complete bartlaarhoven's answer by saying, the code can also be written like the following:
return (
(isNaN(a) || isNaN(b) ? a > b : +a > +b) ? 1 : -1
) * (inverse ? -1 : 1);
You can easily read that inverse
is used to inverse the result.
Considering question 1, try this code:
var inverse = false;
var curRowSpan = 0;
var curIndex = 0;
var doRowSpan = false;
function sortColumn(index){
index = index + 1;
var table = jQuery('#resultsTable');
table.find('td').filter(function() {
var result = false;
// if it is a column before the sorting column, watch the rowSpan
if (curRowSpan == 0 && jQuery(this).index() < index && jQuery(this).attr("rowspan") > 1) {
curRowSpan = jQuery(this).attr("rowspan");
doRowSpan = true;
// we are not in the sorting column so we can safely continue
continue;
}
if(!doRowSpan) curIndex = index - (curRowSpan?1:0);
else curIndex = index;
if(jQuery(this).index() == curIndex) {
// we are at the sorting column
if(curRowSpan > 0) {
curRowSpan--;
}
// set this to false for the following row
doRowSpan = false;
result = true;
}
return result;
}).sortElements(function(a, b){
a = convertToNum($(a).text());
b = convertToNum($(b).text());
return (
isNaN(a) || isNaN(b) ?
a > b : +a > +b
) ?
inverse ? -1 : 1 :
inverse ? 1 : -1;
},function(){
return this.parentNode;
});
inverse = !inverse;
}
function convertToNum(str){
if(isNaN(str)){
var holder = "";
for(i=0; i<str.length; i++){
if(!isNaN(str.charAt(i))){
holder += str.charAt(i);
}
}
return holder;
}else{
return str;
}
}
Considering question 2; let's deduct where it comes from. First of all we would like to check whether a > b, and, as you already saw correctly, we make a difference between string comparison and number comparison.
We would then simply give:
return (
isNaN(a) || isNaN(b) ?
a > b : +a > +b
) ? 1 : -1;
This checks whether a > b (either string-wise or number-wise) and then returns 1 on true and -1 on false.
Now we insert the inverse
parameter, which should inverse the result. This means that if inverse == true, then 1 becomes -1 and -1 becomes 1. In code, this bold piece of text would replace each occurrence of 1
with inverse ? -1 : 1
and each occurrence of -1
with inverse ? 1 : -1
. Which is exactly what is done in the resulting code.
UPDATE: Added doRowSpan
in the code because it should not adapt the index if we are in the <tr>
that contains the rowspan-td
.