jquery datatable date sorting issue - javascript

I am using datatable plugin version 1.8.2 for displaying table on my webpage.
It is working fine except. It is not sorting dates properly, it is showing "invalid date" in Date object. below is my code snippet.
$(document).ready(function() {
jQuery.fn.dataTableExt.oSort['usdate-asc'] = function(a,b) {
/*
a and b are <div> tag with date
*/
var texta = ($(a).text()).toString(); // Here I am able to see my date in ' 03-17-2015 12:25:21 AM ' format
var textb = ($(b).text()).toString();// Here I am able to see my date in ' 03-17-2015 12:25:21 AM ' format
var usDatea = new Date(Date.parse(texta)); // Here it is showing "invalid date"
var usDateb = new Date(Date.parse(textb));
return ((usDatea < usDateb) ? -1 : ((usDatea > usDateb) ? 1 : 0));
};
jQuery.fn.dataTableExt.oSort['usdate-desc'] = function(a,b) {
/*
a and b are <div> tag with date
*/
var texta = ($(a).text()).toString(); //same as above
var textb = ($(b).text()).toString(); //same as above
var usDatea = new Date(Date.parse(texta)); //same as above
var usDateb = new Date(Date.parse(textb)); //same as above
return ((usDatea < usDateb) ? 1 : ((usDatea > usDateb) ? -1 : 0));
};
$('#tablegridname').dataTable( {
"sPaginationType": 'full_numbers',
"bJQueryUI": true,
"iDisplayLength": 50,
"aLengthMenu":[50,100,500,1000],
"aaSorting": [[ 4, 'desc' ]],
"aoColumns": [null, null, null, null, {"sType": "usdate"}]
} );
});
});

Try this fiddle:
http://jsfiddle.net/82vh6mp2/
It uses this simple function:
function parseDateForSort(d)
{
return d.substring(6,10) + d.substring(0,2) +
d.substring(3,5) + d.substring(20) +
d.substring(11,19);
}
The function takes advantage of the fact that, luckily, PM comes after AM alphabetically; hence the "d.substring(20)" in the middle of the string. So we have YYYYMMDD[AM or PM]HH:MM:SS.
In your code you can get rid of Date.parse, and replace your return with:
usDatea = parseDateForSort(texta);
usDateb = parseDateForSort(textb);
return ((usDatea < usDateb) ? -1 : ((usDatea > usDateb) ? 1 : 0));
Good luck.
Addendum:
You can create your own sort type, and then specify the column thusly:
$.extend($.fn.dataTableExt.oSort, {
"date-us-pre": function (v) {
return parseDateForSort(v);
},
"date-us-asc": function ( a, b ) { return a - b; },
"date-us-desc": function ( a, b ) { return b - a; }
} );
And then in your .dataTable call include
"aoColumnDefs": [ { "sType":"date-us", "aTargets":[6] } ]
or whatever column number it is instead of 6.

Related

Angular 5 Sort by date, text, numbers

I have implemented reusable sorting function,sorting by number and text are working fine,But it fails for sort by date.
orderBy(array: Array<any>, fieldName: string, direction: string) {
return array.sort((a, b) => {
let objectA: number|string = '';
let objectB: number|string = '';
[objectA, objectB] = [a[fieldName], b[fieldName]];
let valueA = isNaN(+objectA) ? objectA.toString().toUpperCase() : +objectA;
let valueB = isNaN(+objectB) ? objectB.toString().toUpperCase() : +objectB;
return (valueA < valueB ? -1 : 1) * (direction == 'asc' ? 1 : -1);
});
}
how to sort by date, text numbers and special char.
try this:
orderBy(array: Array<any>, fieldName: string, direction: string) {
return array.sort((a, b) => {
let objectA: number|string|Date = '';
let objectB: number|string|Date = '';
[objectA, objectB] = [a[fieldName], b[fieldName]];
// I assume that objectA and objectB are of the same type
return typeof objectA === 'string' ? objectA.localeCompare(objectB) : objectA - objectB;
});
}
if Date type is not recognized, you may need to add es6 entry to your compilerOptions, see this answer for more details
UPDATE
If all your values to be sorted are strings try this:
orderBy(array: Array<any>, fieldName: string, direction: string) {
return array.sort((a, b) => {
let objectA: number|string|Date = '';
let objectB: number|string|Date = '';
// map function here will convert '15/12/2018' into '2018/12/15'
// so we can compare values as strings, numbers and strings
// will remain unchanged
[objectA, objectB] = [a[fieldName], b[fieldName]].map(i => i.split('/').reverse().join('/'));
return isNaN(+objectA) ? objectA.localeCompare(objectB) : +objectA - +objectB;
});
}
I think this could be best since the localCompare function returns positive for after and negatives for before and 0 for equals (in this example I'm comparing .name wich is an atribute of objects a and b that are in this.array)
this.array.sort((a, b) => {
return a.name.localeCompare(b.name);
});
if you are using type script than you can do like this , havent tried but you can tryout
public orderby(fieldName : string)
{
switch (typeof obj[fieldName].constructor.name) {
case "String":
array.sort();
case "Number":
array.sort(function(a,b){
return a-b);
});
case "Date"://you can check type and add accordingly
//as suggested by #Andriy its going to be object
array.sort(function(a,b){
return new Date(b.date) - new Date(a.date);
});
default:
throw new Error("Type of T is not a valid return type!");
}
} else {
throw new Error("Key '" + key + "' does not exist!");
}
}
for date sorting i do like this , converting values in date and get value for minus operation which returns zero, plus or negative vlaue
array.sort(function(a,b){
return new Date(b.date) - new Date(a.date);
});

Javascript sorting a date (mm/dd/yyyy) not working in chrome browser

How do I sort below array of dates in ascending as well as descending order? For example, I have:
var value = [
{"ID":"3","date":null},
{"ID":"24","date":"07/28/2017"},
{"ID":"65","date":"05/14/2018"},
{"ID":"36","date":"06/11/2017"},
{"ID":"27","date":null},
{"ID":"18","date":"02/26/2018"},
{"ID":"37","date":null},
{"ID":"39","date":"05/15/2017"},
{"ID":"10","date":"06/11/2017"},
{"ID":"4","date":null},
{"ID":"8","date":null},
{"ID":"12","date":"05/15/2017"},
{"ID":"14","date":"07/28/2017"},
{"ID":"19","date":"06/11/2017"}
];
I'd like the resultant array to look like:
var result = [
{"ID":"3","date":null},
{"ID":"27","date":null},
{"ID":"4","date":null},
{"ID":"8","date":null},
{"ID":"39","date":"05/15/2017"},
{"ID":"12","date":"05/15/2017"},
{"ID":"36","date":"06/11/2017"},
{"ID":"10","date":"06/11/2017"},
{"ID":"19","date":"06/11/2017"}
{"ID":"24","date":"07/28/2017"},
{"ID":"14","date":"07/28/2017"},
{"ID":"18","date":"02/26/2018"},
{"ID":"65","date":"05/14/2018"}
];
Javascript sorting function :
function sortArray(desc, value) {
if (desc) {
value.sort(function(a: any, b: any) {
let aValue = (a["date"]) ? Number(new Date(a["date"])) : Number(new Date(0));
let bValue = (b["date"]) ? Number(new Date(b["date"])) : Number(new Date(0));
return bValue - aValue;
});
} else {
value.sort(function(a: any, b: any) {
let aValue = (a["date"]) ? Number(new Date(a["date"])) : Number(new Date(0));
let bValue = (b["date"]) ? Number(new Date(b["date"])) : Number(new Date(0));
return aValue - bValue;
});
}
}
I have mention input array as well as expected array.Thanks in advance.
You can use ES6 syntax, and play with .reverse() to get ASC or DESC
value.sort((a, b) => new Date(b.date) - new Date(a.date)).reverse()
Demo - https://jsfiddle.net/zkcsdv01/
or look here for more extended answer Sort Javascript Object Array By Date

Sorting 'human' numbers in tablesorter

I'm using tablesorter to sort a set of values whose formats vary from things like 710,231 to 6.39 million, 37.3 million, 5.3 million, and so forth. Currently, the plugin sorts simply ignores the million and otherwise sorts fine, but consequently you get something like `5.3 million, 6.39 million, 37.3 million, 710,231,
You'll need to add a parser to replace the names with their value (demo):
// see big list here: http://www.unc.edu/~rowlett/units/large.html
var numbers = {
'zero' : 0,
'hundred' : 100,
'thousand' : 1e3,
'million' : 1e6,
'billion' : 1e9,
'trillion' : 1e12,
'quadrillion' : 1e15,
'quintillion' : 1e18,
'sextillion' : 1e21,
'septillion' : 1e24,
'octillion' : 1e27,
'nonillion' : 1e30,
'decillion' : 1e33
};
$.tablesorter.addParser({
id: "namedNumbers",
is: function () {
return false;
},
format: function (s, table) {
var v,
result = 1,
arry = (s || '').split(/[\-\s]+/),
len = arry.length;
while (len) {
v = $.tablesorter.formatFloat( (arry[--len] || '').toLowerCase(), table );
if ( numbers.hasOwnProperty(v) ) {
result *= numbers[v];
} else {
result *= parseFloat(v);
}
}
return result !== 1 ? result : s;
},
type: "numeric"
});
$(function () {
$('table').tablesorter({
theme: 'blue',
headers : {
1 : { sorter : 'namedNumbers' }
}
});
});

DataTables and ColumnFilter with percentage column

I've added percent column to my datatable using below code:
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
"percent-pre": function (a) {
var x = (a == "-") ? 0 : a.replace(/%/, "");
return parseFloat(x);
},
"percent-asc": function (a, b) {
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
},
"percent-desc": function (a, b) {
return ((a < b) ? 1 : ((a > b) ? -1 : 0));
}
});
This way I can sort column that has '%'.
I also added ColumnFilter plugin (Plugin Link) to my table to be able to filter individual columns.
When I save and display percentage value as numeric I'm able to filter that column:
Fiddle Demo
But when I set that column type to percentage and try to filter same column I always get empty data:
Fiddle Demo
Open first fiddle and click 'Load data' and try to set range for '%' column - everything is working. Now do the same with second one - You'll get empty table.
How can I apply range filter to column with percent values?
As it turned out it is quite easy.
Store percent value as numeric and declare column as follows:
{
sTitle: "%",
sType: "numeric",
sWidth: "40px",
sClass: "center",
mData: "percent",
mRender: function (data, type, full) {
if (type === 'display') {//this is available in DataTables 1.9+
return data + ' %';
}
return data;
}
}
This is my updated and working jsFiddle

jQuery DataTables - sorting does not work when date is also a link

I notices that UK date sorting does not work when a date is also a link.
Example 1. (demo)
Here the date is pure test. Works complete fine.
<tr>
<td>01/01/01</td>
<td>Tarik</td>
<td>Rashad Kidd</td>
<td>1 34 238 6239-0509</td>
</tr>
Example 2. (demo)
Here the date is also a link. Does not work at all. Not throwing any errors though.
<tr>
<td>01/01/01</td>
<td>Tarik</td>
<td>Rashad Kidd</td>
<td>1 34 238 6239-0509</td>
</tr>
I also noticed that the sorting does work on any other elements even if they are a link. Only the date as a link are the issue.
I'm using the following JS code:
// UK Date Sorting
jQuery.fn.dataTableExt.oSort['uk_date-asc'] = function(a,b) {
var ukDatea = a.split('/');
var ukDateb = b.split('/');
var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
};
jQuery.fn.dataTableExt.oSort['uk_date-desc'] = function(a,b) {
var ukDatea = a.split('/');
var ukDateb = b.split('/');
var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
}
$(document).ready(function() {
$('#table').dataTable( {
"bPaginate": true,
"bLengthChange": true,
"bFilter": true,
"aoColumnDefs" : [
{ "aTargets" : ["uk-date-column"] , "sType" : "uk_date"}
]
});
});
Any help much appreciated.
The problem is that you sorting function is confused by the extra html. You should modify your functions like this:
// UK Date Sorting
jQuery.fn.dataTableExt.oSort['uk_date-asc'] = function(a,b) {
//use text()
var ukDatea = $(a).text().split('/');
var ukDateb = $(b).text().split('/');
var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
};
jQuery.fn.dataTableExt.oSort['uk_date-desc'] = function(a,b) {
//use text()
var ukDatea = $(a).text().split('/');
var ukDateb = $(b).text().split('/');
var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
}
fiddle here http://jsfiddle.net/GUb2n/
You can try to put the date (in ISO Format) in an invisible container in front of the link:
<span style="display: none;">2001-01-01</span>01/01/01
Then alphabetic sort should work.
IIRC, improper sorting of linkified data has to do with the way DataTables attempts to strip HTML from the content of a table cell (using a simplified regexp) which seems unable to completely extract date data from the cell.
DataTables 1.10+ can use HTML 5 data attributes to avoid this problem.
If you have a link in a set of <td> tags, like this:
<td>28 July 2015</td>
you can add a data-order attribute to your <td> tag:
<td data-order="2015-07-28">28 July 2015</td>
This data-order attribute lets DataTables sort on the data-order attribute and use the content between your <td> tags as display data only.
(v1.9.4) This solution not only fixes your sorting woes but also fixes filtering issues because normally the filter matches against the HTML, so searching for things like href or divend up matching all the rows.
It strips away the HTML inside the mRender option and then caches the result since DataTables runs the mRender function multiple times.
JsFiddle Example
Warning for Editable Tables
An editable table may have issues due to the Caching mechanism.
Step1
Include the following javascript somewhere:
var stripHtml = (function() {
var tmpDiv = document.createElement("DIV");
return function(html) {
tmpDiv.innerHTML = html;
return $.trim(tmpDiv.textContent || tmpDiv.innerText);
};
})();
var mRenderFactory = function (colIndex) {
return function (data, type, full) {
var cache = MRenderCache.getCache(full);
if (type === "filter" || type === "sort" || type === "type") {
return cache.getOrElse(colIndex, data, stripHtml)
}
return data;
};
};
var MRenderCache = function () {
this.full = [];
}
MRenderCache.getCache = function (full) {
var cache = full[full.length - 1];
if (cache == null || !cache.MRenderCache) {
cache = new MRenderCache();
full.push(cache);
}
return cache;
}
MRenderCache.prototype.MRenderCache = true;
MRenderCache.prototype.getOrElse = function (colIndex, rawData, convert) {
var result = this.full[colIndex];
if (result === undefined) {
result = convert(rawData);
this.full[colIndex] = result;
}
return result;
}
Step 2
Set "mRender": mRenderFactory(i) inside aoColumns on any columns you want the HTML stripped where i is the index of the column. It is VERY important you get the right i because if you don't then the table will display fine but will sort and filter on the wrong column.
You're initialization code would look something like this:
$(document).ready(function() {
$('#example').dataTable( {
"aoColumns": [
null,
null,
{ "mRender": mRenderFactory(2) },
{ "mRender": mRenderFactory(3) },
null
]
} );
} );

Categories

Resources