summaryrefslogtreecommitdiffstats
path: root/abs/core/local-website/htdocs/linhes/js/table_sort.js
diff options
context:
space:
mode:
Diffstat (limited to 'abs/core/local-website/htdocs/linhes/js/table_sort.js')
-rw-r--r--abs/core/local-website/htdocs/linhes/js/table_sort.js569
1 files changed, 569 insertions, 0 deletions
diff --git a/abs/core/local-website/htdocs/linhes/js/table_sort.js b/abs/core/local-website/htdocs/linhes/js/table_sort.js
new file mode 100644
index 0000000..26208b1
--- /dev/null
+++ b/abs/core/local-website/htdocs/linhes/js/table_sort.js
@@ -0,0 +1,569 @@
+/**
+ * Javascript Table sorting lib
+ *
+ * @url $URL: http://cvs.mythtv.org/svn/branches/release-0-22-fixes/mythplugins/mythweb/js/table_sort.js $
+ * @date $Date: 2008-06-22 02:21:08 +0000 (Sun, 22 Jun 2008) $
+ * @version $Revision: 17560 $
+ * @author $Author: kormoc $
+ * @license LGPL
+ *
+/**/
+
+document.observe('dom:loaded', function () {
+// Not a dom v3 supported browser?
+ if (typeof document.body.textContent == 'undefined') {
+ // Let's work around for IE
+ if (typeof document.body.innerText != 'undefined') {
+ HTMLElement.prototype.__defineGetter__('textContent', function () {
+ return this.innerText;
+ });
+ }
+ // And now Safari
+ else {
+ HTMLElement.prototype.__defineGetter__('textContent', function () {
+ return this.innerHTML;
+ });
+ }
+ }
+});
+
+var SortableTables = {
+ tables: [],
+ callback_presort: null,
+ callback_postsort: null,
+ callback_preload: null,
+ callback_postload: null,
+
+ currently_sorting_table: null,
+
+ start: function () {
+ $$('table[sortable=true]').each(SortableTables.setupTable);
+ },
+
+ setupTable: function (table) {
+ if (this.callback_preload)
+ this.callback_preload(table);
+ // We require a unique id
+ if (table.id == '' || ( this.tables && this.tables[table.id] ))
+ return;
+ SortableTables.tables[table.id] = new SortableTable(table);
+ if (this.callback_postload)
+ this.callback_postload(table);
+ },
+
+ sort: function (table_id, header_index) {
+ // 25% speed boost on large tables (900 rows+) by not allowing multiple sorts at the same time.
+ if (this.currently_sorting_table != null)
+ return;
+ if (this.callback_presort)
+ this.callback_presort(table_id, heder_index);
+ if (this.tables[table_id].callback_presort)
+ this.tables[table_id].callback_presort(table_id, header_index);
+ this.tables[table_id].sort(header_index);
+ if (this.tables[table_id].callback_postsort)
+ this.tables[table_id].callback_postsort(table_id, header_index);
+ if (this.callback_postsort)
+ this.callback_postsort(table_id, header_index);
+ }
+};
+
+document.observe('dom:loaded', SortableTables.start);
+
+var SortableTable = Class.create({
+ initialize: function (table) {
+ // Class vars
+ this.table = null;
+ this.header = null;
+ this.body = null;
+ this.rows = null;
+
+ this.cache_sort_functions = new Array();
+ this.cache_has_attribute = new Array();
+ this.cache_sorted_index = null;
+ this.cache_previous_sorts = new Array();
+ this.cache_sort_hash = new Array();
+ this.cache_sort_direction = false;
+
+ this.multisort = false;
+ this.zebra_stripe = false;
+
+ this.sort_cell_index = null;
+ this.sort_header_index = null;
+
+ this.callback_presort = null;
+ this.callback_postsort = null;
+
+ // Make sure the table is valid for sorting
+ if (table.tBodies[0].rows.length < 2)
+ return;
+
+ this.table = $(table);
+ this.header = this.table.tHead.rows[table.tHead.rows.length-1];
+ this.body = this.table.tBodies[0]
+ this.rows = this.body.rows;
+
+ this.multisort = this.table.readAttribute('multisort');
+
+ if (this.rows[0].className.match(/even/) || this.rows[0].className.match(/odd/))
+ this.zebra_stripe = true;
+
+ // Setup the header with links
+ var cells = this.header.cells;
+ var cells_count = cells.length;
+ var cell_coloffset = 0;
+ for (var i = 0; i < cells_count; i++) {
+ var cell = cells[i];
+ var cell_colspan = 1;
+ var cell_index = i + cell_coloffset;
+ var header_index = i;
+ this.cache_sort_hash[i] = cell_index;
+ // Handle colspans...
+ if (cell.hasAttribute('colspan'))
+ cell_coloffset += cell.readAttribute('colspan')-1;
+
+ if (cell.readAttribute('sortable') == 'false')
+ continue;
+ // This should fix a bug with safari (as of version 2.0.2 at least), which does not understand cellIndex correctly
+ cell.setAttribute('onclick','SortableTables.sort("'+this.table.id+'","'+header_index+'");return false;');
+ cell.addClassName('link');
+ // Heat the cache...
+ this.cache_has_attribute[cell_index] = false;
+ // Precache the sort function...
+ this.cache_sort_functions[cell_index] = this.getSortFunction(header_index, cell_index);
+ }
+ },
+
+ getSortFunction: function (header_index) {
+ var cell_index = this.cache_sort_hash[header_index];
+ // Default sort function to use
+ var sort_function = 'sortCaseInsensitive';
+ // Do we have sort_values?
+ this.cache_has_attribute[header_index] = this.rows[0].cells[cell_index].hasAttribute('sort_value');
+ if (this.header.cells[header_index].hasAttribute('sort_hint'))
+ sort_function = this.header.cells[header_index].readAttribute('sort_hint');
+ else {
+ if (this.cache_has_attribute[header_index])
+ var value = this.rows[0].cells[cell_index].readAttribute('sort_value');
+ else
+ var value = this.rows[0].cells[cell_index].textContent;
+
+ // Figure out the function to use...
+ if (value.match(/^\w+ \d+[,] \d\d\d\d/))
+ sort_function = 'sortEnglishDate';
+ else if (value.match(/^\w+[,] \w+ \d+[,] \d+[:]\d+ \w+$/))
+ sort_function = 'sortLongEnglishDate';
+ else if (value.match(/^\d+ days$/) || value=='Today' || value=='Tomorrow' || value=='Yesterday')
+ sort_function = 'sortExpiration';
+ else if (value.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/))
+ sort_function = 'sortDate';
+ else if (value.match(/^\d\d[\/-]\d\d[\/-]\d\d$/))
+ sort_function = 'sortDate';
+ else if (value.match(/^\W+ \d+$/))
+ sort_function = 'sortMonthDay';
+ else if (value.match(/^[\d\.]+[%]*$/))
+ sort_function = 'sortNumeric';
+ else if (value.match(/^[£$]/))
+ sort_function = 'sortCurrency';
+ }
+ return eval('SortableTableSorts.'+sort_function);
+ },
+
+ sort: function (header_index) {
+ this.sort_header_index = header_index;
+ this.sort_cell_index = this.cache_sort_hash[header_index]
+
+ // Spawn into an array
+ var row_length = this.rows.length;
+ var rows = new Array();
+ for (var i=0; i<row_length; i++)
+ rows.push(this.rows[i]);
+
+ // Check to see if we're already sorted, and if so, just invert it
+ if (this.cache_previous_sorts.last() == this.sort_cell_index)
+ rows.reverse();
+ else {
+ SortableTables.currently_sorting_table = this;
+ var sort_function = SortableTables.tables[this.table.id].doSort;
+ rows.sort(sort_function);
+ SortableTables.currently_sorting_table = null;
+ }
+
+ // Move back to the table...
+ for (var i=0; i<row_length; i++)
+ this.body.appendChild(rows[i]);
+
+ // Setup the arrows...
+ this.doHeaderArrows();
+ // Fix any zebra striping
+ this.fixZebraStripes();
+ // Remove the current index fromt he previous sorts and make sure it's uniq
+ this.cache_previous_sorts = this.cache_previous_sorts.without(this.sort_cell_index).uniq();
+ // Add in the sorted col
+ this.cache_previous_sorts.push(this.sort_cell_index);
+ },
+
+ doSort: function (a, b, cell_index) {
+ // Are we overriding the cell index (for multisort)
+ if (!cell_index)
+ cell_index = SortableTables.currently_sorting_table.sort_cell_index;
+
+ // Use the sort hint?
+ if (SortableTables.currently_sorting_table.cache_has_attribute[cell_index]) {
+ var value_a = a.cells[cell_index].readAttribute('sort_value');
+ var value_b = b.cells[cell_index].readAttribute('sort_value');
+ }
+ else {
+ var value_a = a.cells[cell_index].textContent;
+ var value_b = b.cells[cell_index].textContent;
+ }
+
+ if ( value_a != value_b)
+ var comparison = SortableTables.currently_sorting_table.cache_sort_functions[cell_index](value_a,value_b);
+ else
+ var comparison = 0;
+
+ if (SortableTables.currently_sorting_table.multisort && !comparison && SortableTables.currently_sorting_table.cache_previous_sorts.length) {
+ var multisort_index = SortableTables.currently_sorting_table.cache_previous_sorts.pop();
+ comparison = SortableTables.currently_sorting_table.doSort(a, b, multisort_index);
+ SortableTables.currently_sorting_table.cache_previous_sorts.push(multisort_index);
+ }
+ return comparison;
+ },
+
+ doHeaderArrows: function () {
+ // Remove any current span arrows
+ $$('#'+this.table.id+' thead span.sortArrow').each(function (span) {span.update('&nbsp;&nbsp;&nbsp;');});
+ var arrow_span = this.header.cells[this.sort_header_index].select('span.sortArrow').reduce();
+ if (!arrow_span) {
+ arrow_span = new Element('span', { 'class': 'sortArrow'});
+ this.header.cells[this.sort_header_index].insert(arrow_span);
+ }
+ if (this.cache_previous_sorts.last() == this.sort_cell_index && this.cache_sort_direction) {
+ arrow_span.update('&nbsp;&nbsp;&uarr;');
+ this.cache_sort_direction = false;
+ }
+ else {
+ arrow_span.update('&nbsp;&nbsp;&darr;');
+ this.cache_sort_direction = true;
+ }
+ },
+
+ fixZebraStripes: function () {
+ if (!this.zebra_stripe)
+ return;
+ var length = this.rows.length;
+ var even = false;
+ for (var i=0; i<length; i++) {
+ var row = this.rows[i];
+ if (even)
+ row.className = row.className.replace(/odd/g, 'even');
+ else
+ row.className = row.className.replace(/even/g, 'odd');
+ even = !even;
+ }
+ }
+});
+
+var SortableTableSorts = {
+// Sort: DD-MM-YY or DD-MM-YYYY
+// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
+ sortDate: function (a,b) {
+ if (a.length == 10)
+ dt1 = a.substr(6,4)+a.substr(3,2)+a.substr(0,2);
+ else {
+ yr = a.substr(6,2);
+ if (parseInt(yr) < 50)
+ yr = '20'+yr;
+ else
+ yr = '19'+yr;
+ dt1 = yr+a.substr(3,2)+a.substr(0,2);
+ }
+ if (b.length == 10)
+ dt2 = b.substr(6,4)+b.substr(3,2)+b.substr(0,2);
+ else {
+ yr = b.substr(6,2);
+ if (parseInt(yr) < 50)
+ yr = '20'+yr;
+ else
+ yr = '19'+yr;
+ dt2 = yr+b.substr(3,2)+b.substr(0,2);
+ }
+ if (dt1==dt2)
+ return 0;
+ if (dt1<dt2)
+ return -1;
+ return 1;
+ },
+
+// Sort MM-DD-YY or MM-DD-YYYY
+// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
+ sortDateUs: function (a,b) {
+ if (a.length == 10)
+ dt1 = a.substr(6,4)+a.substr(0,2)+a.substr(3,2);
+ else {
+ yr = a.substr(6,2);
+ if (parseInt(yr) < 50)
+ yr = '20'+yr;
+ else
+ yr = '19'+yr;
+ dt1 = yr+a.substr(0,2)+a.substr(3,2);
+ }
+ if (b.length == 10)
+ dt2 = b.substr(6,4)+b.substr(0,2)+b.substr(3,2);
+ else {
+ yr = b.substr(6,2);
+ if (parseInt(yr) < 50)
+ yr = '20'+yr;
+ else
+ yr = '19'+yr;
+ dt2 = yr+b.substr(0,2)+b.substr(3,2);
+ }
+ if (dt1 == dt2)
+ return 0;
+ if (dt1 < dt2)
+ return -1;
+ return 1;
+ },
+
+// This function handles Mon day, year sorting
+// Falls back to alpha-comparison, if date-comparison can't make a decision.
+ sortEnglishDate: function (a,b) {
+ if (a == 'none' || a.length == 0)
+ return -1;
+ if (b == 'none' || b.length == 0)
+ return 1;
+
+ var aa_mon = SortableTableSorts.englishMonthToNumber (a.substr(0,3));
+ aa = a.substr(4);
+ var aa_year = parseFloat(aa.substr(aa.length-4));
+ var aa_day = parseFloat(aa.substr(0, aa.length-6));
+
+ var bb_mon = SortableTableSorts.englishMonthToNumber (b.substr(0,3));
+ bb = b.substr(4);
+ var bb_year = parseFloat(bb.substr(bb.length-4));
+ var bb_day = parseFloat(bb.substr(0, bb.length-6));
+ if (!aa_year || !aa_mon || !aa_day || !bb_year || !bb_mon || !bb_day)
+ return SortableTableSorts.sortCaseSensitive(a,b);
+ if (aa_year < bb_year)
+ return -1;
+ if (aa_year > bb_year)
+ return 1;
+ if (aa_mon < bb_mon)
+ return -1;
+ if (aa_mon > bb_mon)
+ return 1;
+ if (aa_day < bb_day)
+ return -1;
+ return 1;
+ },
+
+// This function handles Mon day, year sorting
+// Jan 21, 2006
+ sortEnglishDateInvert: function (a,b) {
+ return SortableTableSorts.sortEnglishDate(b,a);
+ },
+
+// This function sorts based on month day format
+// Jan 21
+ sortMonthDay: function (a, b) {
+ if (a.length == 0)
+ return -1;
+ if (b.length == 0)
+ return 1;
+
+ var a_mon = SortableTableSorts.englishMonthToNumber (a.substr(0,3));
+ a = parseFloat(a.substr(4));
+ var b_mon = SortableTableSorts.englishMonthToNumber (b.substr(0,3));
+ b = parseFloat(b.substr(4));
+ if (a_mon < b_mon)
+ return -1;
+ if (a_mon > b_mon)
+ return 1;
+ if (a < b)
+ return -1;
+ return 1;
+ },
+
+// This function handles DDD, Mon Day, Hour:Min A/PM
+// we also assume it's the same year, as we can't figure it out otherwise
+ sortLongEnglishDate: function (a,b) {
+ var aa = a.substr(5).split(/,/);
+ var bb = b.substr(5).split(/,/);
+ var aatmp = aa[1].split(/:/);
+ var aa_hour = aatmp[0];
+ var aa_min = aatmp[1].substr(0,2);
+ if (aatmp[1].substr(3).toLowerCase() == 'pm')
+ aa_hour += 12;
+ var bbtmp = bb[1].split(/:/);
+ var bb_hour = bbtmp[0];
+ var bb_min = bbtmp[1].substr(0,2);
+ if (bbtmp[1].substr(3).toLowerCase() == 'pm')
+ bb_hour += 12;
+ aa = aa[0];
+ bb = bb[0];
+ if (aa == bb)
+ return 0;
+ if (aa == 'none' || aa.length == 0)
+ return -1;
+ if (bb == 'none' || bb.length == 0)
+ return 1;
+ var aa_mon = SortableTableSorts.englishMonthToNumber (aa.substr(0,3));
+ var aa_day = aa.substr(4);
+ var bb_mon = SortableTableSorts.englishMonthToNumber (bb.substr(0,3));
+ var bb_day = bb.substr(4);
+ if (!aa_mon || !aa_day || !bb_mon || !bb_day)
+ return -1;
+ if (aa_mon < bb_mon)
+ return -1;
+ if (aa_mon > bb_mon)
+ return 1;
+ if (aa_day < bb_day)
+ return -1;
+ if (aa_day > bb_day)
+ return 1;
+ if (aa_hour < bb_hour)
+ return -1;
+ if (aa_hour > bb_hour)
+ return 1;
+ if (aa_minute < bb_minute)
+ return -1;
+ return 1;
+ },
+
+// This function sorts expiration dates, such as in the quote list
+ sortExpiration: function (a,b) {
+ a = a.split(/ /)[0];
+ b = b.split(/ /)[0];
+ switch (a) {
+ case 'Yesterday': a = -1; break;
+ case 'Today': a = 0; break;
+ case 'Tomorrow': a = 1; break;
+ default: a = parseFloat(a);
+ }
+ switch (b) {
+ case 'Yesterday': b = -1; break;
+ case 'Today': b = 0; break;
+ case 'Tomorrow': b = 1; break;
+ default: b = parseFloat(b);
+ }
+
+ if (a > b)
+ return 1;
+ if (a < b)
+ return -1;
+ return 0;
+ },
+
+ englishMonthToNumber: function (mon) {
+ switch (mon.toLowerCase()) {
+ case 'jan' : return 1;
+ case 'feb' : return 2;
+ case 'mar' : return 3;
+ case 'apr' : return 4;
+ case 'may' : return 5;
+ case 'jun' : return 6;
+ case 'jul' : return 7;
+ case 'aug' : return 8;
+ case 'sep' : return 9;
+ case 'oct' : return 10;
+ case 'nov' : return 11;
+ case 'dec' : return 12;
+ }
+ return 0;
+ },
+
+ sortCurrency: function (a,b) {
+ return parseFloat(a.replace(/[^0-9.]/g,'')) - parseFloat(b.replace(/[^0-9.]/g,''));
+ },
+
+// A non number or a blank is always less then a number.
+ sortNumeric: function (a,b) {
+ b = parseFloat(b);
+ if (isNaN(b))
+ return 1;
+ a = parseFloat(a);
+ if (isNaN(a))
+ return -1;
+ return a-b;
+ },
+
+// A non number or a blank is always less then a number.
+ sortNumericInvert: function (a,b) {
+ return SortableTableSorts.sortNumeric(b,a);
+ },
+
+ sortCaseInsensitive: function (a,b) {
+ a = a.toLowerCase();
+ b = b.toLowerCase();
+
+ if (a > b)
+ return 1;
+ if (a < b)
+ return -1;
+ return 0;
+ },
+
+ sortCaseSensitive: function (a,b) {
+ if (a > b)
+ return 1;
+ if (a < b)
+ return -1;
+ return 0;
+ },
+
+ sortMythwebPlayTime: function (a,b) {
+ if (a == b)
+ return 0;
+
+ var a_hrs = a.match(/([0-9]*) hr/);
+ var a_min = a.match(/([0-9]*) min/);
+ var a_val = 0;
+ if (a_hrs)
+ a_val += a_hrs[1]*60;
+ if (a_min)
+ a_val += a_min[1]*1;
+
+ var b_hrs = b.match(/([0-9]*) hr/);
+ var b_min = b.match(/([0-9]*) min/);
+ var b_val = 0;
+ if (b_hrs)
+ b_val += b_hrs[1]*60;
+ if (b_min)
+ b_val += b_min[1]*1;
+
+ return SortableTableSorts.sortNumeric(a_val, b_val);
+ },
+
+ sortMythwebChannel: function (a,b) {
+ if (a == b)
+ return 0;
+ var a_channel = a.match(/([0-9]*) -/);
+
+ if (a_channel)
+ a_channel = a_channel[1];
+ else
+ a_channel = 0;
+
+ var b_channel = b.match(/([0-9]*) -/);
+
+ if (b_channel)
+ b_channel = b_channel[1];
+ else
+ b_channel = 0;
+
+ return SortableTableSorts.sortNumeric(a_channel, b_channel);
+ },
+
+// Some compat wrappers
+ date_us: function (a,b) {
+ return SortableTableSorts.sortDateUs(a,b);
+ },
+
+ numeric: function (a,b) {
+ return SortableTableSorts.sortNumeric(a,b);
+ },
+
+ numeric_invert: function (a,b) {
+ return SortableTableSorts.sortNumericInvert(a,b);
+ }
+};