I'm currently using jQuery Tablesorter for my project's tables, and I want to have it handle a custom sort so that:
A, AA, B, BB, 1, 2
Would sort as:
1, 2, A, B, AA, BB
I'm able to achieve this through the textSorter option during the initialization like so:
$(".tablesorter").tablesorter({
textSorter: {
3: function (a, b) {
return b.length > a.length ? -1 : b.length < a.length ? 1 : b.toString() > a.toString() ? -1 : 1;
}
}
}
Or more clearly:
if (b.length > a.length) {
return -1;
} else if (b.length < a.length) {
return 1;
} else {
if (b.toString() > a.toString()) {
return -1;
} else {
return 1;
}
}
But what I'd like to do is be able to have this be default sort when a classname is specified, similar to how I'm able to add sorter-floats as a clas to any th like this <th class='sorter-floats'>COL NAME</th> and use the addParser method to handle parsing the value by which to sort like this:
$.tablesorter.addParser({
id: "floats",
is: function (s) {
return false;
},
format: function (s) {
return $.tablesorter.formatFloat(s.replace(/,/g, ''));
},
type: "numeric"
});
I haven't been able to find any methods in the tablesorter plugin that allow custom sorting in this way. Is this possible, or is the approach I've already used my best option?
Tablesorter wasn't set up to allow the textSorter option to contain anything other than an overall function, or an object containing zero-based column indexes.
I just updated the master branch with a patch that will also allow adding a column class name (demo):
$(function() {
$("table").tablesorter({
theme: 'blue',
textSorter: {
'.sorter-float': function(a, b) {
return b.length > a.length ? -1 :
b.length < a.length ? 1 :
b.toString() > a.toString() ? -1 : 1;
}
}
});
});
I haven't decided when the next release will be available, but it won't be too long.
Related
I am using this jQuery plugin to sort elements:
http://james.padolsey.com/javascript/sorting-elements-with-jquery/
It works well with this code:
function sortGallery(element, sorting) {
$('input.sort').removeClass('active');
$(element).addClass('active');
if (sorting === 'bydate') {
$('#gallery-js > div').sortElements(function(a, b){
return $(a).find('img').attr('data-date') < $(b).find('img').attr('data-date') ? 1 : -1;
});
} else if (sorting === 'random') {
console.log('TODO');
}
}
The problem is I do not understand the return statement. Can someone tell me how the return value for the "random" part should look like and if possible a short description how it works?
Alright, first you might want to read up on how Array#sort works.
In the documentation, they provide this code as an example as to how the sort order works
function compare(a, b) {
if (a is less than b by some ordering criterion)
return -1;
if (a is greater than b by the ordering criterion)
return 1;
// a must be equal to b
return 0;
}
Since you want to just order randomly, all we need to do is generate a random integer from -1 to 1
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
Then you simply call the method like this
} else if (sorting === 'random') {
return randomInt(-1, 1);
}
I am using a jquery drop down table filter plug in for table filters:
https://github.com/rbayliss/Dropdown-Table-Filter
When I have a column in my table that is numerical however, the numbers are sorted as text, e.g. 1, 10, 100, 2, 20, 200 ...
in the code the sorter looks like:
if(options.sortOpt) {
opts.sort(options.sortOptCallback);
}
I think this is a recursive call to:
sortOptCallback: function(a, b) {
return a.text.toLowerCase() > b.text.toLowerCase();
},
how should I amend this so that it will sort numerical fields correctly? I have tried the following:
sortOptCallback: function (a, b) {
if (isNaN(parseInt(a)) || isNaN(parseInt(b))) {
return a.text.toLowerCase() > b.text.toLowerCase();
} else {
return a > b;
}
},
Thanks,
Your attempt is almost correct. The only problem is that you are still comparing the elements as strings after having determined that they are numeric. Furthermore, sort callbacks expect:
A positive number if a > b
A negative number if a < b
Zero if they are equal.
With this in mind, try this callback:
if( a == b) return 0;
var anum = parseInt(a,10);
var bnum = parseInt(b,10);
if( isNaN(anum) || isNaN(bnum)) {
return a.toLowerCase() > b.toLowerCase() ? 1 : -1;
}
return anum > bnum ? 1 : -1;
EDIT: #PaoloMoretti brought my attention to the fact that all your items are numerical. In that case, you can just do this:
return a-b;
I am using jquery datatable to display data. I display '--' when there is no data. Currently when the table sorts the data all the '--' comes in the beginning and the order looks like below:
--
--
10
20
400
800
But I need to make '--' to be displayed last when sorted in ascending order and should look something like below:
10
20
400
800
--
--
Please let me know how can we get this behavior in jquery datatable?
you can use an exstension
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
"myorder-pre": function (a) {
},
"myorder-asc": function (a, b) {
if(a == '--' && b != '--')
return 1;
else if(b == '--' && a != '--')
return -1;
else if(b == '--'&& a == '--')
return 0;
else
{
a = parseFloat(a);
b = parseFloat(b);
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
}
},
"myorder-desc": function (a, b) {
if(a == '--' && b != '--')
return -1;
else if(b == '--' && a != '--')
return 1;
else if(b == '--'&& a == '--')
return 0;
else
{
a = parseFloat(a);
b = parseFloat(b);
return ((a < b) ? 1 : ((a > b) ? -1 : 0));
}
}
});
myorder-pre is used before all the order call.
myorder-asc when you order asc. Return number negative if a minor b, positive if a major b, 0 if equal.
Desc work adverse
then in the definition of columns of datatable, use
"aoColumnDefs": [{ "sType": 'myorder'}]
You can make use of the following code :
$('#example').dataTable( {
"aaSorting": [[ 4, "desc" ]]
} );
For the reference
I'm trying to sort numbers like these:
<1E-8
0.000027
0.000061
0.0018
0.0094
<8.64e-12
0.049
'<' means that the true value is less than the number given.
Here is my "descent function," which I have a very high confidence in:
$.fn.dataTableExt.oSort['scientific-desc'] = function(a,b) {
var x = a.replace(/^[<>]/g,"");
var y = b.replace(/^[<>]/g,"");
x = parseFloat(x);
y = parseFloat(y);
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
}
And I defined an "ascent function" similarly:
$.fn.dataTableExt.oSort['scientific-asc'] = function(a,b) {
var x = a.replace(/^[<>]/g,"");
var y = b.replace(/^[<>]/g,"");
x = parseFloat(x);
y = parseFloat(y);
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
I've played with just about everything in the initialization code and with the above sorting functions but nothing seems to be able to get the numbers to sort correctly in the table. The numbers <1E-8 always tend to stay together and so do the ones with a lowercase 'e'.
The code to initialize the dataTable is as follows. It's probably worth noting that this is code is called inside of an AJAX call:
$.get('xyz.json',
function(data) {
// deal with json data
// get it ready for dataTable
// ...
$('.table').dataTable( {
"sScrollY": "200px",
"aoColumns": [
null,
null,
{"bSortable": true, "sType": "scientific"},
{"bSortable": false}
],
"aaSorting": [ [2,'asc'] ],
"bPaginate": false,
"bFilter": false,
"iDisplayLength": 5,
"bRetrieve": true,
"bDestroy": true
} );
});
In your example, the numbers with '<' signs are next to each other in the sorted list.
var A= ['<1E-8', 0.000027, 0.000061, 0.0018, 0.0094, '<8.64e-12', 0.049];
A.sort(function(a, b){
var a1= String(a).replace(/^(<|>)/, ''),
b1= String(b).replace(/^(<|>)/, '');
return a1-b1;
}).join('\n');
<8.64e-12
<1E-8
0.000027
0.000061
0.0018
0.0094
0.049
//To have a decending sort, just reverse it-
A.sort(function(a, b){
var a1= String(a).replace(/^(<|>)/, ''),
b1= String(b).replace(/^(<|>)/, '');
return a1-b1;
}).reverse().join('\n');
0.049
0.0094
0.0018
0.000061
0.000027
<1E-8
<8.64e-12
Serves me right for having "high confidence" in my sorting function. Quickly printing out a and b on the console revealed that the sorting functions were getting passed html entities
<
and not "<".
Thanks to another stackoverflow thread:
varTitle = $('<div />').html("Chris' corner").text();
Another way to do custom sorting in DataTables is to include something hidden in the table cell:
<tr>
<td>Large<input type="hidden" value="3"></td>
</tr>
<tr>
<td>Small<input type="hidden" value="1"></td>
</tr>
<tr>
<td>Medium<input type="hidden" value="2"></td>
</tr>
And then sort by the hidden value instead of the displayed value:
// Tell DataTables to use this sort type always
$.fn.dataTableExt.aTypes.unshift(
function () {
return 'custom-sort';
}
);
$.extend($.fn.dataTableExt.oSort, {
// The selector
"custom-sort-pre": function(a) {
var sortValue = $(a).val();
if (sortValue === undefined) {
return a;
}
if (sortValue == 'NaN') {
return NaN;
}
var floatValue = parseFloat(sortValue);
if (isNaN(floatValue)) {
return sortValue;
}
return floatValue;
},
// Asc sorting
"custom-sort-asc": function (a, b) {
if (isNaN(a) && !isNaN(b)) return 1;
if (!isNaN(a) && isNaN(b)) return -1;
if (isNaN(a) && isNaN(b)) return 0;
if (a > b) return 1;
if (a < b) return -1;
return 0;
},
// Desc sorting
"custom-sort-desc": function(a, b) {
return $.fn.dataTableExt.oSort['custom-sort-asc'](a, b) * -1;
}
});
This example will work on both strings and numbers.
I'm sorting an object array that has a primary contact name, among other things. Sometimes this has a blank value and when I use the function below it sorts it all correctly, but all the blanks go at the top of the list instead of the bottom. I thought that adding the condition shown below would work, but it does not.
this.comparePrimaryContactName = function (a, b)
{
if(a.PrimaryContactName == "") return -1;
return a.PrimaryContactName > b.PrimaryContactName ? 1 : -1;
}
What am I missing?
I usually use something like this:
this.comparePrimaryContactName = function(a, b) {
a = a.PrimaryContactName || '';
b = b.PrimaryContactName || '';
if(a.length == 0 && b.length == 0)
return 0;
else if(a.length == 0)
return 1;
else if(b.length == 0)
return -1;
else if(a > b)
return 1;
else if(a < b)
return -1;
return 0;
}
Comparison functions must be reflective, transitive, and anti-symmetric. Your function does not satisfy these criteria. For example, if two blank entries are compared with each other, you must return 0, not -1.
this.comparePrimaryContactName = function (a, b)
{
var aName = a.PrimaryContactName;
var bName = b.PrimaryContactName;
return aName === bName ? 0 :
aName.length===0 ? -1 :
bName.length===0 ? 1 :
aName > bName ? 1 : -1;
}
Return 1 instead of -1 for blanks.
this.comparePrimaryContactName = function (a, b) {
if (a.PrimaryContactName == b.PrimaryContactName)
return 0;
if(a.PrimaryContactName == "") return 1;
return a.PrimaryContactName > b.PrimaryContactName ? 1 : -1;
}
Your sort function should return 0 if the two are equal, -1 if a comes before b, and 1 if a comes after b.
See the MDN sort doco for more information.