Detect parsers in reverse order & make them hardy

This commit is contained in:
Mottie 2013-03-11 12:17:49 -05:00
parent a4fa0ed49c
commit ae267560fc
2 changed files with 60 additions and 49 deletions

View File

@ -143,7 +143,8 @@
} }
function detectParserForColumn(table, rows, rowIndex, cellIndex) { function detectParserForColumn(table, rows, rowIndex, cellIndex) {
var i, l = ts.parsers.length, var cur,
i = ts.parsers.length,
node = false, node = false,
nodeValue = '', nodeValue = '',
keepLooking = true; keepLooking = true;
@ -159,13 +160,15 @@
keepLooking = false; keepLooking = false;
} }
} }
for (i = 1; i < l; i++) { while (--i >= 0) {
if (ts.parsers[i].is && ts.parsers[i].is(nodeValue, table, node)) { cur = ts.parsers[i];
return ts.parsers[i]; // ignore the default text parser because it will always be true
if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, table, node)) {
return cur;
} }
} }
// 0 is always the generic parser (text) // nothing found, return the generic parser (text)
return ts.parsers[0]; return ts.getParserById('text');
} }
function buildParserCache(table) { function buildParserCache(table) {
@ -708,9 +711,9 @@
}; };
}); });
} }
// apply easy methods that trigger boundd events // apply easy methods that trigger bound events
$this $this
.unbind('sortReset update updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter ')) .unbind('sortReset update updateRows updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter '))
.bind("sortReset.tablesorter", function(){ .bind("sortReset.tablesorter", function(){
c.sortList = []; c.sortList = [];
setHeadersCss($t0); setHeadersCss($t0);
@ -1204,19 +1207,33 @@
}, },
format: function(s, table, cell, cellIndex) { format: function(s, table, cell, cellIndex) {
var c = table.config; var c = table.config;
s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s ); if (s) {
return c.sortLocaleCompare ? ts.replaceAccents(s) : s; s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s );
s = c.sortLocaleCompare ? ts.replaceAccents(s) : s;
}
return s;
}, },
type: "text" type: "text"
}); });
ts.addParser({
id: "digit",
is: function(s) {
return ts.isDigit(s);
},
format: function(s, table) {
return s ? ts.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table) : s;
},
type: "numeric"
});
ts.addParser({ ts.addParser({
id: "currency", id: "currency",
is: function(s) { is: function(s) {
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[,. ]/g,'')); // £$€¤¥¢ return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[,. ]/g,'')); // £$€¤¥¢
}, },
format: function(s, table) { format: function(s, table) {
return ts.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table); return s ? ts.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table) : s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1227,13 +1244,13 @@
return (/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/).test(s); return (/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/).test(s);
}, },
format: function(s, table) { format: function(s, table) {
var i, a = s.split("."), var i, a = s ? s.split(".") : '',
r = "", r = "",
l = a.length; l = a.length;
for (i = 0; i < l; i++) { for (i = 0; i < l; i++) {
r += ("00" + a[i]).slice(-3); r += ("00" + a[i]).slice(-3);
} }
return ts.formatFloat(r, table); return s ? ts.formatFloat(r, table) : s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1244,7 +1261,7 @@
return (/^(https?|ftp|file):\/\//).test(s); return (/^(https?|ftp|file):\/\//).test(s);
}, },
format: function(s) { format: function(s) {
return $.trim(s.replace(/(https?|ftp|file):\/\//, '')); return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s;
}, },
type: "text" type: "text"
}); });
@ -1255,7 +1272,7 @@
return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s); return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
}, },
format: function(s, table) { format: function(s, table) {
return ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || "") : "", table); return s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || "") : "", table) : s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1266,7 +1283,7 @@
return (/(\d\s?%|%\s?\d)/).test(s); return (/(\d\s?%|%\s?\d)/).test(s);
}, },
format: function(s, table) { format: function(s, table) {
return ts.formatFloat(s.replace(/%/g, ""), table); return s ? ts.formatFloat(s.replace(/%/g, ""), table) : s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1279,7 +1296,7 @@
return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s); return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
}, },
format: function(s, table) { format: function(s, table) {
return ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ''), table); return s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ''), table) : s;
}, },
type: "numeric" type: "numeric"
}); });
@ -1288,24 +1305,26 @@
id: "shortDate", // "mmddyyyy", "ddmmyyyy" or "yyyymmdd" id: "shortDate", // "mmddyyyy", "ddmmyyyy" or "yyyymmdd"
is: function(s) { is: function(s) {
// testing for ####-##-####, so it's not perfect // testing for ####-##-####, so it's not perfect
return (/^(\d{1,2}|\d{4})[\/\-\,\.\s+]\d{1,2}[\/\-\.\,\s+](\d{1,2}|\d{4})$/).test(s); return (/^(\d{1,2}|\d{4})[\/\-\,\.\s+]\d{1,2}[\/\-\.\,\s+](\d{1,2}|\d{4})/).test(s);
}, },
format: function(s, table, cell, cellIndex) { format: function(s, table, cell, cellIndex) {
var c = table.config, ci = c.headerList[cellIndex], if (s) {
format = ci.shortDateFormat; var c = table.config, ci = c.headerList[cellIndex],
if (typeof format === 'undefined') { format = ci.shortDateFormat;
// cache header formatting so it doesn't getData for every cell in the column if (typeof format === 'undefined') {
format = ci.shortDateFormat = ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat; // cache header formatting so it doesn't getData for every cell in the column
format = ci.shortDateFormat = ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat;
}
s = s.replace(/\s+/g," ").replace(/[\-|\.|\,]/g, "/");
if (format === "mmddyyyy") {
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
} else if (format === "ddmmyyyy") {
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1");
} else if (format === "yyyymmdd") {
s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
}
} }
s = s.replace(/\s+/g," ").replace(/[\-|\.|\,]/g, "/"); return s ? ts.formatFloat( (new Date(s).getTime() || ''), table) : s;
if (format === "mmddyyyy") {
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
} else if (format === "ddmmyyyy") {
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1");
} else if (format === "yyyymmdd") {
s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
}
return ts.formatFloat( (new Date(s).getTime() || ''), table);
}, },
type: "numeric" type: "numeric"
}); });
@ -1316,18 +1335,7 @@
return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s); return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
}, },
format: function(s, table) { format: function(s, table) {
return ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ""), table); return s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ""), table) : s;
},
type: "numeric"
});
ts.addParser({
id: "digit",
is: function(s) {
return ts.isDigit(s);
},
format: function(s, table) {
return ts.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table);
}, },
type: "numeric" type: "numeric"
}); });

View File

@ -24,7 +24,7 @@
table2 = $table2[0], table2 = $table2[0],
th0 = $table1.find('th')[0], // first table header cell th0 = $table1.find('th')[0], // first table header cell
init = false, init = false,
c1, c2, i, l, t; undef, c1, c2, i, l, t;
$('.tester:eq(0)') $('.tester:eq(0)')
.bind('tablesorter-initialized', function(){ .bind('tablesorter-initialized', function(){
@ -154,7 +154,7 @@
************************************************/ ************************************************/
var p = ts.parsers, var p = ts.parsers,
// test by parser // test by parser
parserTests = 54, parserTests = 84,
// skipping metadata parser // skipping metadata parser
sample1 = { sample1 = {
'text' : { 'test': 'test', 'TesT': 'test', '\u00e1 test': 'á test' }, 'text' : { 'test': 'test', 'TesT': 'test', '\u00e1 test': 'á test' },
@ -164,7 +164,7 @@
'isoDate' : { '2012/12/12': 1355292000000, '2012-12/12': 1355292000000, '2013-1-1': 1357020000000, '2013/1/1 12:34:56 AM': 1357022096000 }, 'isoDate' : { '2012/12/12': 1355292000000, '2012-12/12': 1355292000000, '2013-1-1': 1357020000000, '2013/1/1 12:34:56 AM': 1357022096000 },
'percent' : { '100%': 100, '22%': 22, '%2': 2, '2 %': 2, '(4%)': -4 }, 'percent' : { '100%': 100, '22%': 22, '%2': 2, '2 %': 2, '(4%)': -4 },
'usLongDate': { 'Feb 23, 1999': 919749600000, 'Feb 23, 1999 12:34': 919794840000, 'Feb 23, 1999 12:34 AM': 919751640000, 'Feb 23, 1999 12:34:56 PM': 919794896000, '01 Jan 2013': 1357020000000 }, 'usLongDate': { 'Feb 23, 1999': 919749600000, 'Feb 23, 1999 12:34': 919794840000, 'Feb 23, 1999 12:34 AM': 919751640000, 'Feb 23, 1999 12:34:56 PM': 919794896000, '01 Jan 2013': 1357020000000 },
'shortDate' : { '1/2/2001': 978415200000, '1 2 2001': 978415200000, '1.2.2001': 978415200000, '1-2-2001': 978415200000 }, 'shortDate' : { '1/2/2001': 978415200000, '1 2 2001': 978415200000, '1.2.2001': 978415200000, '1-2-2001': 978415200000, '1/2/2001 12:34 PM' : 978460440000, '1.2.2001 13:34' : 978464040000 },
'time' : { '12:34 AM': 946708440000, '1:00 pm': 946753200000 }, 'time' : { '12:34 AM': 946708440000, '1:00 pm': 946753200000 },
'digit' : { '12': 12, '$23': 23, '&44^': 44, '#(33)': -33, '1,000': 1000, '12.34': 12.34 } 'digit' : { '12': 12, '$23': 23, '&44^': 44, '#(33)': -33, '1,000': 1000, '12.34': 12.34 }
}, },
@ -190,6 +190,9 @@
equal( p[i].format(k, table1, th0, 0), v, t + ' parser **NOT DETECTED**: "' + k + '", but returns ' + v ); equal( p[i].format(k, table1, th0, 0), v, t + ' parser **NOT DETECTED**: "' + k + '", but returns ' + v );
} }
}); });
// test for undefined & null - probably overkill
strictEqual( p[i].format(undef, table1, th0, 0), undef, t + ' parser: will return undefined values properly' );
strictEqual( p[i].format(null, table1, th0, 0), null, t + ' parser: will return null values properly' );
} }
} }
}; };
@ -209,9 +212,9 @@
report(sample3); report(sample3);
// undocumented sortValue // undocumented sortValue
equal( p[10].format(null, table1, th0, 0), 'zzz', 'metadata parser found sortValue'); equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'zzz', 'metadata parser found sortValue');
c1.parserMetadataName = 'poe'; c1.parserMetadataName = 'poe';
equal( p[10].format(null, table1, th0, 0), 'nevermore', 'metadata parser found poe'); equal( ts.getParserById('metadata').format(null, table1, th0, 0), 'nevermore', 'metadata parser found poe');
}); });