My code:
<th class="sorter-shortDate">Date</th>
$('table').tablesorter({dateFormat: "yyyymmdd"});
Sorting is working on numbers, but it is not working on dates,
My date format is y-m-d H:i,
I also tried to add custom parser:
$.tablesorter.addParser({
id: "customDate",
is: function(s) {
return false;
//use the above line if you don't want table sorter to auto detected this parser
//else use the below line.
//attention: doesn't check for invalid stuff
//2009-77-77 77:77:77.0 would also be matched
//if that doesn't suit you alter the regex to be more restrictive
//return /\d{1,4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}/.test(s);
},
format: function(s) {
s = s.replace(/\-/g," ");
s = s.replace(/:/g," ");
s = s.replace(/\./g," ");
s = s.split(" ");
return $.tablesorter.formatFloat(new Date(s[0], s[1]-1, s[2], s[3]).getTime()+parseInt(s[6]));
},
type: "numeric"
});
Can anyone help me please?
There's a minor bug in the shortDate parser; it replaces all . with a / while converting the date into something the built-in JS date parser can understand (e.g. 2009-12-31 08:09:10.1 becomes 12/31/2009 08:09:10/1 - that last decimal place getting changed into a slash is breaking everything.
You can get around this by modifying the short date parser's regular expression - demo
$.tablesorter.regex.shortDateReplace = /-/g;
$(function() {
$('table').tablesorter({
theme: 'blue',
dateFormat: 'yyyymmdd'
});
});
Related
I am developing using fullcalendar.js, and in the week view, when a week is from 2 different months (for example 27 july - 2 august) the fullcalendar week view shows the two months text. I am searching everywhere but there is no solution for this. Maybe stackoverflow users can help me.
That's what I have:
And that's what I need:
I see the date format but is MMMM YYYY, and it returns two months or one automatically and it seems impossible to change this.
In Calendar.defaults (aprox. line 8300 in non-minimized code) object I can notice this:
titleRangeSeparator: ' \u2014 ', // emphasized dash
monthYearFormat: 'MMMM YYYY', // required for en. other languages rely on datepicker computable option
As I explained, monthYearFormat seems to only be one month, but in a specific moment it merges with titleRangeSeparator to become two months.
Do you know how this is solvable?
Thank you.
EDIT
I found the functions that make this complex string, but is used by month and day views that I don't want to change (I need only to week view). The code is the next. How can I modify this code to solve it?
// Date Range Formatting
// -------------------------------------------------------------------------------------------------
// TODO: make it work with timezone offset
// Using a formatting string meant for a single date, generate a range string, like
// "Sep 2 - 9 2013", that intelligently inserts a separator where the dates differ.
// If the dates are the same as far as the format string is concerned, just return a single
// rendering of one date, without any separator.
function formatRange(date1, date2, formatStr, separator, isRTL) {
var localeData;
date1 = fc.moment.parseZone(date1);
date2 = fc.moment.parseZone(date2);
localeData = (date1.localeData || date1.lang).call(date1); // works with moment-pre-2.8
// Expand localized format strings, like "LL" -> "MMMM D YYYY"
formatStr = localeData.longDateFormat(formatStr) || formatStr;
// BTW, this is not important for `formatDate` because it is impossible to put custom tokens
// or non-zero areas in Moment's localized format strings.
separator = separator || ' - ';
return formatRangeWithChunks(
date1,
date2,
getFormatStringChunks(formatStr),
separator,
isRTL
);
}
fc.formatRange = formatRange; // expose
function formatRangeWithChunks(date1, date2, chunks, separator, isRTL) {
var chunkStr; // the rendering of the chunk
var leftI;
var leftStr = '';
var rightI;
var rightStr = '';
var middleI;
var middleStr1 = '';
var middleStr2 = '';
var middleStr = '';
// Start at the leftmost side of the formatting string and continue until you hit a token
// that is not the same between dates.
for (leftI=0; leftI<chunks.length; leftI++) {
chunkStr = formatSimilarChunk(date1, date2, chunks[leftI]);
if (chunkStr === false) {
break;
}
leftStr += chunkStr;
}
// Similarly, start at the rightmost side of the formatting string and move left
for (rightI=chunks.length-1; rightI>leftI; rightI--) {
chunkStr = formatSimilarChunk(date1, date2, chunks[rightI]);
if (chunkStr === false) {
break;
}
rightStr = chunkStr + rightStr;
}
// The area in the middle is different for both of the dates.
// Collect them distinctly so we can jam them together later.
for (middleI=leftI; middleI<=rightI; middleI++) {
middleStr1 += formatDateWithChunk(date1, chunks[middleI]);
middleStr2 += formatDateWithChunk(date2, chunks[middleI]);
}
if (middleStr1 || middleStr2) {
if (isRTL) {
middleStr = middleStr2 + separator + middleStr1;
}
else {
middleStr = middleStr1 + separator + middleStr2;
}
}
return leftStr + middleStr + rightStr;
}
This isn't directly supported unfortunately, but there is still a better way than modifying the FC source (that get's messy with patches and stuff).
There are several render hooks available that we can use to fix the formatting after the fact. viewRender doesn't work because it's called before the title changes. So we can use eventAfterAllRender instead.
eventAfterAllRender:function(){
if(view.name!=="agendaWeek")
return;
var $title = $("#calendar").find(".fc-toolbar h2"); //Make sure this is the right selector
var text = $title.text();
text = text.match(/.*? /)+text.match(/[0-9]+/);
$title.text(text); //replace text
}
JSFiddle - titleFormat hack
Not the most elegant thing in the world, but it should work better than modifying the source. Let me know if there are any issues.
Edit:
Also, if you're having problems with it flashing the wrong dateformat before the correct one, use css the make the title invisible. Then add a class to the element in eventAfterAllRender that makes it visible again.
I have a column in my table that shows variations of the following text, where the dates vary
Requested Statement 7/1/2014 - 9/16/2014
tablesorter has trouble sorting this properly, as you can see in this fiddle. The first column will sort when clicked, but the second will not. I also included a table of some string comparisons to show that javascript properly recognizes the order they should be in.
http://jsfiddle.net/kfu4ragh/1/
I tried adding a custom textExtraction function but I'm still getting the same results.
It seems that tablesorter is doing something different than a simple > or < to determine the order of the string values. Is there a way I can alter tablesorter to sort this column correctly?
The problem is that the second column ("Requested Statement...") is being detected as a date column and the parser is trying to turn that entire string into a date; which is invalid.
Here is a demo with the relevant extracted out functions from tablesorter. The result is:
// start with "Requested Statement 7/1/2014 - 9/16/2014"
"Requested Statement 2014/7/1 / 9/16/2014" => 0
So you'll need to use the textExtraction function to target the date (demo):
$('table').tablesorter({
textExtraction : function(node){
var txt = $(node).text();
if (/request/i.test(txt)) {
// return the 3rd block (first date in range)
txt = txt.split(' ')[2];
}
return txt;
}
});
Note that the second date in the string is completely ignored. If you would like to make the second date matter, try this code (demo):
$('table').tablesorter({
textExtraction : function(node){
var d1, d2,
txt = $(node).text();
if (/request/i.test(txt)) {
// return the 3rd block (first date in range)
txt = txt.split(' ');
d1 = $.tablesorter.formatFloat(new Date(txt[2]).getTime());
d2 = $.tablesorter.formatFloat(new Date(txt[4]).getTime());
// add the times together - there is likely a better
// method but this works in this situation
txt = d1 + d2;
}
return txt;
}
});
I am using the table sorter plugin to sort my tables.
I want to be able to catch date column in format:
dd/MM/yyyy HH:mm
and then sort them correctly (for this I have to switch days with years).
Here is what I've so far:
ts.addParser({
id: "hebreLongDate",
is: function (s) {
return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4} d{1,2}:d{1,2}/.test(s);
}, format: function (s, table) {
var c = table.config;
s = s.replace(/\-/g, "/");
// reformat the string in ISO format
s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1");
return $.tablesorter.formatFloat(new Date(s).getTime());
}, type: "numeric"
});
It does not work.
I would appreciate any help, especially if it comes with an explantation on the meaning of the correct regex.
Thanks,
Omer
The parser doesn't really validate the date. The is function only detects if the format matches the pattern for the format function which is why it is just easier to make it return false and manually set the parser for a column using the headers option:
headers: {
1: { sorter: "hebreLongDate" }
},
The is function above is requiring a HH:mm within the pattern, so if the first table cell in the column doesn't match, it ignores that parser. So either way it would be better to manually set the parser.
Anyway, here is how I would write the parser you are describing (demo):
$.tablesorter.addParser({
id: "hebreLongDate",
is: function(s) {
return false;
},
format: function(s, table, cell, cellIndex) {
s = s
// replace separators
.replace(/\s+/g," ").replace(/[\-.,]/g, "/")
// reformat dd/mm/yyyy to yyyy/mm/dd
.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1");
return s ? $.tablesorter.formatFloat( (new Date(s).getTime() || ''), table) : s;
},
type: "numeric"
});
As for explaining the regex, there isn't that much of a difference between the code above and what you have in your question. The biggest difference is that the above code ensures that only one space exists between the date and time and that the date can be separated by a slash, dash, period, comma or space (i.e. 1-1-2000, 1 1 2000 etc).
Update: if you want to have this parser be autodetected, then use the following is regex (updated demo). But it is important to note, that this regex cannot distinguish mmddyyyy from ddmmyyyy so it will always detect ddmmyyyy. To override this, set the header sorter option to "shortDate":
is: function(s) {
// testing for ##-##-####, so it's not perfect; time is optional
return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})/).test((s || '').replace(/\s+/g," ").replace(/[\-.,]/g, "/"));
},
I have created a table and sorted it with tablesorter. One of the columns is a mix of letters and numbers (chr1, chr2, ..., chr10, ... , chrM). I want this column to be sorted as if it were only numbers (from 1 to 22 and then X, Y and M in this order).
I have created my own parser and it works but just for some rows. Then, I find another block of rows which are correctly sorted followed by some other blocks. I do not know why this blocks are formed.
The code is here. Maybe with a smaller table it would work properly, because of that I have shown a big one.
Thanks in advance!
Try this parser (demo)
$.tablesorter.addParser({
// set a unique id
id: 'chrom',
is: function (s) {
// return false so this parser is not auto detected
return false;
},
format: function (s) {
// format your data for normalization
return s.toLowerCase()
.replace('chr', '')
.replace('x', '97')
.replace('y', '98')
.replace('m', '99');
},
// set type, either numeric or text
type: 'numeric'
});
This one may be a bit specialized, but here goes anyway:
Page for reference: http://greg-j.com/icvm/anticartel/search-results.html
Plugin for reference: http://tablesorter.com/
If you look at the last two columns for "Total Fines", you'll see the currency output includes $x.xxx billions and $x.xxx millions. The built-in currency parser does not account for this format. The plugin, fortunately, allows for you to write your own parser. However, I'm not getting anywhere.
See if this works, I haven't tested it:
$.tablesorter.addParser({
id: 'monetary',
'is': function(s) {
return false;
},
format: function(s) {
var i = s.split('$').join('');
var suffixes = [
{name:'thousand', mult: 1000},
{name:'million', mult: 1000000},
{name:'billion', mult: 1000000000},
{name:'trillion', mult: 1000000000000}
];
for (var j in suffixes) {
if (i.indexOf(' '+suffixes[j].name) != -1) {
i = i.split(' '+suffixes[j].name).join('');
val = parseFloat(i) * suffixes[j].mult;
}
}
return val;
},
type: 'numeric'
});
$("#cartels").tablesorter({
widgets: ['zebra'],
sortList: [[0,0]],
headers: {
4: {
sorter:'monetary'
},
5: {
sorter:'monetary'
}
}
});
Can you post the code you've tried?
It looks like what they are doing in the example you posted is assigning each word with a number representation, and then sorting by that:
return s.toLowerCase().replace(/good/,2).replace(/medium/,1).replace(/bad/,0);
So in your case one way might be to replace million with the correct number of zeros and the same for billion. So essentially $1 million gets evaluated to $1,000,000 as far as the parser is concerned.
return s.toLowerCase().replace(/million/,000000).replace(/billion/,000000000);
So s is evaluating to $1000000 once the replace function is evaluated.
Just a thought. Not sure if it works, but it might get you on the right track.