1

Revive site from the unmaintainable state

Now we can again deploy it with moden Jekyll and restore lorchess.ru
archive.
This commit is contained in:
2018-10-28 17:59:15 +04:00
parent 596505bbb7
commit 15b8f3a13e
2425 changed files with 5262 additions and 301815 deletions

View File

@@ -0,0 +1,34 @@
/*! ISO-8601 date parser
* This parser will work with dates in ISO8601 format
* 2013-02-18T18:18:44+00:00
* Written by Sean Ellingham :https://github.com/seanellingham
* See https://github.com/Mottie/tablesorter/issues/247
*/
/*global jQuery: false */
;(function($){
"use strict";
var iso8601date = /^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/;
$.tablesorter.addParser({
id : 'iso8601date',
is : function(s) {
return s.match(iso8601date);
},
format : function(s) {
var result = s.match(iso8601date);
if (result) {
var date = new Date(result[1], 0, 1);
if (result[3]) { date.setMonth(result[3] - 1); }
if (result[5]) { date.setDate(result[5]); }
if (result[7]) { date.setHours(result[7]); }
if (result[8]) { date.setMinutes(result[8]); }
if (result[10]) { date.setSeconds(result[10]); }
if (result[12]) { date.setMilliseconds(Number('0.' + result[12]) * 1000); }
return date;
}
return s;
},
type : 'numeric'
});
})(jQuery);

View File

@@ -0,0 +1,33 @@
/*! Month parser
* Demo: http://jsfiddle.net/Mottie/abkNM/477/
*/
/*jshint jquery:true */
;(function($){
"use strict";
var ts = $.tablesorter;
ts.dates = $.extend({}, ts.dates, {
// *** modify this array to change match the language ***
monthCased : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
});
ts.dates.monthLower = ts.dates.monthCased.join(',').toLocaleLowerCase().split(',');
ts.addParser({
id: "month",
is: function(){
return false;
},
format: function(s, table) {
var j = -1, c = table.config,
n = c.ignoreCase ? s.toLocaleLowerCase() : s;
$.each(ts.dates[ 'month' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){
if (j < 0 && n.match(v)) { j = i; }
});
// return s (original string) if there isn't a match
// (non-weekdays will sort separately and empty cells will sort as expected)
return j < 0 ? s : j;
},
type: "numeric"
});
})(jQuery);

View File

@@ -0,0 +1,74 @@
/*! Two digit year parser
* Demo: http://jsfiddle.net/Mottie/abkNM/427/
*/
/*jshint jquery:true */
;(function($){
"use strict";
var ts = $.tablesorter,
// Make the date be within +/- range of the 2 digit year
// so if the current year is 2020, and the 2 digit year is 80 (2080 - 2020 > 50), it becomes 1980
// if the 2 digit year is 50 (2050 - 2020 < 50), then it becomes 2050.
range = 50;
ts.dates = $.extend({}, ts.dates, {
regxxxxyy: /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/,
regyyxxxx: /(\d{2})[\/\s](\d{1,2})[\/\s](\d{1,2})/
});
ts.formatDate = function(s, regex, format, table){
var n = s
// replace separators
.replace(/\s+/g," ").replace(/[-.,]/g, "/")
// reformat xx/xx/xx to mm/dd/19yy;
.replace(regex, format),
d = new Date(n),
y = d.getFullYear(),
rng = table && table.config.dateRange || range,
now = new Date().getFullYear();
// if date > 50 years old (set range), add 100 years
// this will work when people start using "50" and mean "2050"
while (now - y > rng) {
y += 100;
}
return d.setFullYear(y) || s;
};
$.tablesorter.addParser({
id: "ddmmyy",
is: function() {
return false;
},
format: function(s, table) {
// reformat dd/mm/yy to mm/dd/19yy;
return ts.formatDate(s, ts.dates.regxxxxyy, "$2/$1/19$3", table);
},
type: "numeric"
});
$.tablesorter.addParser({
id: "mmddyy",
is: function() {
return false;
},
format: function(s, table) {
// reformat mm/dd/yy to mm/dd/19yy
return ts.formatDate(s, ts.dates.regxxxxyy, "$1/$2/19$3", table);
},
type: "numeric"
});
$.tablesorter.addParser({
id: "yymmdd",
is: function() {
return false;
},
format: function(s, table) {
// reformat yy/mm/dd to mm/dd/19yy
return ts.formatDate(s, ts.dates.regyyxxxx, "$2/$3/19$1", table);
},
type: "numeric"
});
})(jQuery);

View File

@@ -0,0 +1,33 @@
/*! Weekday parser
* Demo: http://jsfiddle.net/Mottie/abkNM/477/
*/
/*jshint jquery:true */
;(function($){
"use strict";
var ts = $.tablesorter;
ts.dates = $.extend({}, ts.dates, {
// *** modify this array to change match the language ***
weekdayCased : [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
});
ts.dates.weekdayLower = ts.dates.weekdayCased.join(',').toLocaleLowerCase().split(',');
ts.addParser({
id: "weekday",
is: function(){
return false;
},
format: function(s, table) {
var j = -1, c = table.config;
s = c.ignoreCase ? s.toLocaleLowerCase() : s;
$.each(ts.dates[ 'weekday' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){
if (j < 0 && s.match(v)) { j = i; }
});
// return s (original string) if there isn't a match
// (non-weekdays will sort separately and empty cells will sort as expected)
return j < 0 ? s : j;
},
type: "numeric"
});
})(jQuery);

View File

@@ -0,0 +1,36 @@
/*!
* Extract dates using popular natural language date parsers
*/
/*jshint jquery:true */
;(function($){
"use strict";
/*! Sugar (http://sugarjs.com/dates#comparing_dates)
* demo: http://jsfiddle.net/Mottie/abkNM/551/
*/
$.tablesorter.addParser({
id: "sugar",
is: function() {
return false;
},
format: function(s) {
return Date.create ? Date.create(s).getTime() || s : new Date(s).getTime() || s;
},
type: "numeric"
});
/*! Datejs (http://www.datejs.com/)
* demo: http://jsfiddle.net/Mottie/abkNM/550/
*/
$.tablesorter.addParser({
id: "datejs",
is: function() {
return false;
},
format: function(s) {
return Date.parse && Date.parse(s) || s;
},
type: "numeric"
});
})(jQuery);

View File

@@ -0,0 +1,63 @@
/*! Distance parser
* This parser will parser numbers like 5'10" (5 foot 10 inches)
* and 31½ into sortable values.
* Demo: http://jsfiddle.net/Mottie/abkNM/154/
*/
/*global jQuery: false */
;(function($){
"use strict";
var ts = $.tablesorter;
ts.symbolRegex = /[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g;
ts.processFractions = function(n, table) {
if (n) {
var t, p = 0;
n = $.trim(n.replace(/\"/,''));
// look for a space in the first part of the number: "10 3/4" and save the "10"
if (/\s/.test(n)) {
p = ts.formatFloat(n.split(' ')[0], table);
// remove stuff to the left of the space
n = $.trim(n.substring(n.indexOf(' '), n.length));
}
// look for a "/" to calculate fractions
if (/\//g.test(n)) {
t = n.split('/');
// turn 3/4 into .75; make sure we don't divide by zero
n = p + parseInt(t[0], 10) / parseInt(t[1] || 1, 10);
// look for fraction symbols
} else if (ts.symbolRegex.test(n)) {
n = p + n.replace(ts.symbolRegex, function(m){
return {
'\u215b' : '.125', // 1/8
'\u215c' : '.375', // 3/8
'\u215d' : '.625', // 5/8
'\u215e' : '.875', // 7/8
'\u00bc' : '.25', // 1/4
'\u00bd' : '.5', // 1/2
'\u00be' : '.75' // 3/4
}[m];
});
}
}
return n || 0;
};
$.tablesorter.addParser({
id: 'distance',
is: function() {
// return false so this parser is not auto detected
return false;
},
format: function(s, table) {
if (s === '') { return ''; }
// look for feet symbol = '
// very generic test to catch 1.1', 1 1/2' and 1½'
var d = (/^\s*\S*(\s+\S+)?\s*\'/.test(s)) ? s.split("'") : [0,s],
f = ts.processFractions(d[0], table), // feet
i = ts.processFractions(d[1], table); // inches
return (/[\'\"]/).test(s) ? parseFloat(f) + (parseFloat(i)/12 || 0) : parseFloat(f) + parseFloat(i);
},
type: 'numeric'
});
})(jQuery);

View File

@@ -0,0 +1,73 @@
/*! File Type parser
* When a file type extension is found, the equivalent name is
* prefixed into the parsed data, so sorting occurs in groups
*/
/*global jQuery: false */
;(function($){
"use strict";
// basic list from http://en.wikipedia.org/wiki/List_of_file_formats
// To add a custom equivalent, define:
// $.tablesorter.fileTypes.equivalents['xx'] = "A|B|C";
$.tablesorter.fileTypes = {
// divides filetype extensions in the equivalent list below
separator : '|',
equivalents : {
"3D Image" : "3dm|3ds|dwg|max|obj",
"Audio" : "aif|aac|ape|flac|la|m4a|mid|midi|mp2|mp3|ogg|ra|raw|rm|wav|wma",
"Compressed" : "7z|bin|cab|cbr|gz|gzip|iso|lha|lz|rar|tar|tgz|zip|zipx|zoo",
"Database" : "csv|dat|db|dbf|json|ldb|mdb|myd|pdb|sql|tsv|wdb|wmdb|xlr|xls|xlsx|xml",
"Development" : "asm|c|class|cls|cpp|cc|cs|cxx|cbp|cs|dba|fla|h|java|lua|pl|py|pyc|pyo|sh|sln|r|rb|vb",
"Document" : "doc|docx|odt|ott|pages|pdf|rtf|tex|wpd|wps|wrd|wri",
"Executable" : "apk|app|com|exe|gadget|lnk|msi",
"Fonts" : "eot|fnt|fon|otf|ttf|woff",
"Icons" : "ani|cur|icns|ico",
"Images" : "bmp|gif|jpg|jpeg|jpe|jp2|pic|png|psd|tga|tif|tiff|wmf|webp",
"Presentation" : "pps|ppt",
"Published" : "chp|epub|lit|pub|ppp|fm|mobi",
"Script" : "as|bat|cgi|cmd|jar|js|lua|scpt|scptd|sh|vbs|vb|wsf",
"Styles" : "css|less|sass",
"Text" : "info|log|md|markdown|nfo|tex|text|txt",
"Vectors" : "awg|ai|eps|cdr|ps|svg",
"Video" : "asf|avi|flv|m4v|mkv|mov|mp4|mpe|mpeg|mpg|ogg|rm|rv|swf|vob|wmv",
"Web" : "asp|aspx|cer|cfm|htm|html|php|url|xhtml"
}
};
$.tablesorter.addParser({
id: 'filetype',
is: function() {
return false;
},
format: function(s, table) {
var t,
c = table.config,
wo = c.widgetOptions,
i = s.lastIndexOf('.'),
sep = $.tablesorter.fileTypes.separator,
m = $.tablesorter.fileTypes.matching,
types = $.tablesorter.fileTypes.equivalents;
if (!m) {
// make a string to "quick" match the existing equivalents
var t = [];
$.each(types, function(i,v){
t.push(v);
});
m = $.tablesorter.fileTypes.matching = sep + t.join(sep) + sep;
}
if (i >= 0) {
t = sep + s.substring(i + 1, s.length) + sep;
if (m.indexOf(t) >= 0) {
for (i in types) {
if ((sep + types[i] + sep).indexOf(t) >= 0) {
return i + (wo.group_separator ? wo.group_separator : '-') + s;
}
}
}
}
return s;
},
type: 'text'
});
})(jQuery);

View File

@@ -0,0 +1,47 @@
/*! Title parser
* This parser will remove "The", "A" and "An" from the beginning of a book
* or movie title, so it sorts by the second word or number
* Demo: http://jsfiddle.net/Mottie/abkNM/5/
*/
/*global jQuery: false */
;(function($){
"use strict";
// basic list from http://en.wikipedia.org/wiki/Article_%28grammar%29
$.tablesorter.ignoreArticles = {
"en" : "the, a, an",
"de" : "der, die, das, des, dem, den, ein, eine, einer, eines, einem, einen",
"nl" : "de, het, de, een",
"es" : "el, la, lo, los, las, un, una, unos, unas",
"pt" : "o, a, os, as, um, uma, uns, umas",
"fr" : "le, la, l'_, les, un, une, des",
"it" : "il, lo, la, l'_, i, gli, le, un', uno, una, un",
"hu" : "a, az, egy"
};
// To add a custom parser, define:
// $.tablesorter.ignoreArticles['xx'] = "A, B, C";
// and then set the language id 'xx' in the headers option
// ignoreArticles : 'xx'
$.tablesorter.addParser({
id: 'ignoreArticles',
is: function() {
return false;
},
format: function(s, table, cell, cellIndex) {
var c = table.config, art, lang;
if ( !(c.headers && c.headers[cellIndex] && c.headers[cellIndex].ignoreArticlesRegex) ) {
// initialize - save regex in c.headers[cellIndex].ignoreArticles
if (!c.headers) { c.headers = {}; }
if (!c.headers[cellIndex]) { c.headers[cellIndex] = {}; }
lang = $.tablesorter.getData(c.$headers.eq(cellIndex), c.headers[cellIndex], 'ignoreArticles');
art = ($.tablesorter.ignoreArticles[lang] || "the, a, an" ) + "";
c.headers[cellIndex].ignoreArticlesRegex = new RegExp('^(' + $.trim( art.split(/\s*\,\s*/).join('\\s|') + "\\s" ).replace("_\\s","") + ')', 'i');
}
return (s || '').replace(c.headers[cellIndex].ignoreArticlesRegex, '');
},
type: 'text'
});
})(jQuery);

View File

@@ -0,0 +1,87 @@
/*! input & select parsers for jQuery 1.7+ & tablesorter 2.7.11+
* Updated 2/19/2014 (v2.15.0)
* Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html
*/
/*jshint browser: true, jquery:true, unused:false */
;(function($){
"use strict";
var resort = true, // resort table after update
updateServer = function(event, $table, $input){
// do something here to update your server, if needed
// event = change event object
// $table = jQuery object of the table that was just updated
// $input = jQuery object of the input or select that was modified
};
// Custom parser for parsing input values
// updated dynamically using the "change" function below
$.tablesorter.addParser({
id: "inputs",
is: function(){
return false;
},
format: function(s, table, cell) {
return $(cell).find('input').val() || s;
},
parsed : true, // filter widget flag
type: "text"
});
// Custom parser for including checkbox status if using the grouping widget
// updated dynamically using the "change" function below
$.tablesorter.addParser({
id: "checkbox",
is: function(){
return false;
},
format: function(s, table, cell, cellIndex) {
var $c = $(cell),
$input = $c.find('input[type="checkbox"]'),
isChecked = $input.length ? $input[0].checked : '';
// adding class to row, indicating that a checkbox is checked; includes
// a column index in case more than one checkbox happens to be in a row
$c.closest('tr').toggleClass('checked-' + cellIndex, isChecked);
// returning plain language here because this is what is shown in the
// group headers - change it as desired
return $input.length ? isChecked ? 'checked' : 'unchecked' : s;
},
parsed : true, // filter widget flag
type: "text"
});
// Custom parser which returns the currently selected options
// updated dynamically using the "change" function below
$.tablesorter.addParser({
id: "select",
is: function(){
return false;
},
format: function(s, table, cell) {
return $(cell).find('select').val() || s;
},
parsed : true, // filter widget flag
type: "text"
});
// update select and all input types in the tablesorter cache when the change event fires.
// This method only works with jQuery 1.7+
// you can change it to use delegate (v1.4.3+) or live (v1.3+) as desired
// if this code interferes somehow, target the specific table $('#mytable'), instead of $('table')
$(window).load(function(){
// this flag prevents the updateCell event from being spammed
// it happens when you modify input text and hit enter
var alreadyUpdating = false;
$('table').find('tbody').on('change', 'select, input', function(e){
if (!alreadyUpdating) {
var $tar = $(e.target),
$table = $tar.closest('table');
alreadyUpdating = true;
$table.trigger('updateCell', [ $tar.closest('td'), resort ]);
updateServer(e, $table, $tar);
setTimeout(function(){ alreadyUpdating = false; }, 10);
}
});
});
})(jQuery);

View File

@@ -0,0 +1,76 @@
/*! IPv6 Address parser (WIP)
* IPv6 Address (ffff:0000:0000:0000:0000:0000:0000:0000)
* needs to support short versions like "::8" or "1:2::7:8"
* and "::00:192.168.10.184" (embedded IPv4 address)
* see http://www.intermapper.com/support/tools/IPV6-Validator.aspx
*/
/*global jQuery: false */
;(function($){
"use strict";
var ts = $.tablesorter;
$.extend( ts.regex, {}, {
ipv4Validate : /((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/,
ipv4Extract : /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/,
// simplified regex from http://www.intermapper.com/support/tools/IPV6-Validator.aspx
// (specifically from http://download.dartware.com/thirdparty/ipv6validator.js)
ipv6Validate : /^\s*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/i
});
ts.addParser({
id: "ipv6Address",
is: function(s) {
return ts.regex.ipv6Validate.test(s);
},
format: function(address, table) {
// code modified from http://forrst.com/posts/JS_Expand_Abbreviated_IPv6_Addresses-1OR
var i, t, sides, groups, groupsPresent,
hex = table ? (typeof table === "boolean" ? table : table && table.config.ipv6HexFormat || false) : false,
fullAddress = '',
expandedAddress = '',
validGroupCount = 8,
validGroupSize = 4;
// remove any extra spaces
address = address.replace(/\s*/g, '');
// look for embedded ipv4
if (ts.regex.ipv4Validate.test(address)) {
groups = address.match(ts.regex.ipv4Extract);
t = '';
for (i = 1; i < groups.length; i++){
t += ('00' + (parseInt(groups[i], 10).toString(16)) ).slice(-2) + ( i === 2 ? ':' : '' );
}
address = address.replace( ts.regex.ipv4Extract, t );
}
if (address.indexOf("::") == -1) {
// All eight groups are present
fullAddress = address;
} else {
// Consecutive groups of zeroes have been collapsed with "::".
sides = address.split("::");
groupsPresent = 0;
for (i = 0; i < sides.length; i++) {
groupsPresent += sides[i].split(":").length;
}
fullAddress += sides[0] + ":";
for (i = 0; i < validGroupCount - groupsPresent; i++) {
fullAddress += "0000:";
}
fullAddress += sides[1];
}
groups = fullAddress.split(":");
for (i = 0; i < validGroupCount; i++) {
// it's fastest & easiest for tablesorter to sort decimal values (vs hex)
groups[i] = hex ? ('0000' + groups[i]).slice(-4) :
('00000' + (parseInt(groups[i], 16) || 0)).slice(-5);
expandedAddress += ( i != validGroupCount-1) ? groups[i] + ':' : groups[i];
}
return hex ? expandedAddress : expandedAddress.replace(/:/g, '');
},
// uses natural sort hex compare
type: "numeric"
});
})(jQuery);

View File

@@ -0,0 +1,77 @@
/*! Metric parser
* Demo: http://jsfiddle.net/Mottie/abkNM/382/
* Set the metric name in the header (defaults to "m|meter"), e.g.
* <th data-metric-name="b|byte">HDD Size</th>
* <th data-metric-name="m|meter">Distance</th>
*/
/*jshint jquery:true */
;(function($){
"use strict";
var prefixes = {
// "prefix" : [ base 10, base 2 ]
// skipping IEEE 1541 defined prefixes: kibibyte, mebibyte, etc, for now.
"Y|Yotta|yotta" : [ 1e24, Math.pow(1024, 8) ], // 1024^8
"Z|Zetta|zetta" : [ 1e21, Math.pow(1024, 7) ], // 1024^7
"E|Exa|exa" : [ 1e18, Math.pow(1024, 6) ], // 1024^6
"P|Peta|peta" : [ 1e15, Math.pow(1024, 5) ], // 1024^5
"T|Tera|tera" : [ 1e12, Math.pow(1024, 4) ], // 1024^4
"G|Giga|giga" : [ 1e9, Math.pow(1024, 3) ], // 1024^3
"M|Mega|mega" : [ 1e6, Math.pow(1024, 2) ], // 1024^2
"k|Kilo|kilo" : [ 1e3, 1024 ], // 1024
// prefixes below here are rarely, if ever, used in binary
"h|hecto" : [ 1e2, 1e2 ],
"da|deka" : [ 1e1, 1e1 ],
"d|deci" : [ 1e-1, 1e-1 ],
"c|centi" : [ 1e-2, 1e-2],
"m|milli" : [ 1e-3, 1e-3 ],
"µ|micro" : [ 1e-6, 1e-6 ],
"n|nano" : [ 1e-9, 1e-9 ],
"p|pico" : [ 1e-12, 1e-12 ],
"f|femto" : [ 1e-15, 1e-15 ],
"a|atto" : [ 1e-18, 1e-18 ],
"z|zepto" : [ 1e-21, 1e-21 ],
"y|yocto" : [ 1e-24, 1e-24 ]
},
// the \\d+ will not catch digits with spaces, commas or decimals; so use the value from n instead
RegLong = "(\\d+)(\\s+)?([Zz]etta|[Ee]xa|[Pp]eta|[Tt]era|[Gg]iga|[Mm]ega|kilo|hecto|deka|deci|centi|milli|micro|nano|pico|femto|atto|zepto|yocto)(",
RegAbbr = "(\\d+)(\\s+)?(Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)(";
$.tablesorter.addParser({
id: 'metric',
is: function() {
return false;
},
format: function(s, table, cell, cellIndex) {
var v = 'm|meter',
b, t,
// process number here to get a numerical format (us or eu)
n = $.tablesorter.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table),
$t = table.config.$headers.filter('[data-column="' + cellIndex + '"]'),
m = $t.data('metric');
if (!m) {
// stored values
t = ($t.attr('data-metric-name') || v).split('|');
m = [ t[1] || t[0].substring(1), t[0] ];
m[2] = new RegExp(RegLong + m[0] + "|" + m[1] + ")");
m[3] = new RegExp(RegAbbr + m[1] + ")");
$t.data('metric', m);
}
// find match to full name or abbreviation
t = s.match(m[2]) || s.match(m[3]);
if (t) {
for (v in prefixes) {
if (t[3].match(v)) {
// exception when using binary prefix
// change base for binary use
b = /^[b|bit|byte|o|octet]/.test(t[4]) ? 1 : 0;
return n * prefixes[v][b];
}
}
}
return n;
},
type: 'numeric'
});
})(jQuery);