thiswebshoprules

git clone https://git.tarina.org/thiswebshoprules
Log | Files | Refs

sortable.js (9553B)


      1 /*
      2 Table sorting script  by Joost de Valk, check it out at http://www.joostdevalk.nl/code/sortable-table/.
      3 Based on a script from http://www.kryogenix.org/code/browser/sorttable/.
      4 Distributed under the MIT license: http://www.kryogenix.org/code/browser/licence.html .
      5 
      6 Copyright (c) 1997-2007 Stuart Langridge, Joost de Valk.
      7 
      8 Version 1.5.7
      9 */
     10 
     11 /* You can change these values */
     12 var image_path = "";
     13 var image_up = "arrow-up.gif";
     14 var image_down = "arrow-down.gif";
     15 var image_none = "arrow-none.gif";
     16 var europeandate = true;
     17 var alternate_row_colors = true;
     18 
     19 /* Don't change anything below this unless you know what you're doing */
     20 addEvent(window, "load", sortables_init);
     21 
     22 var SORT_COLUMN_INDEX;
     23 var thead = false;
     24 
     25 function sortables_init() {
     26 	// Find all tables with class sortable and make them sortable
     27 	if (!document.getElementsByTagName) return;
     28 	tbls = document.getElementsByTagName("table");
     29 	for (ti=0;ti<tbls.length;ti++) {
     30 		thisTbl = tbls[ti];
     31 		if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
     32 			ts_makeSortable(thisTbl);
     33 		}
     34 	}
     35 }
     36 
     37 function ts_makeSortable(t) {
     38 	if (t.rows && t.rows.length > 0) {
     39 		if (t.tHead && t.tHead.rows.length > 0) {
     40 			var firstRow = t.tHead.rows[t.tHead.rows.length-1];
     41 			thead = true;
     42 		} else {
     43 			var firstRow = t.rows[0];
     44 		}
     45 	}
     46 	if (!firstRow) return;
     47 	
     48 	// We have a first row: assume it's the header, and make its contents clickable links
     49 	for (var i=0;i<firstRow.cells.length;i++) {
     50 		var cell = firstRow.cells[i];
     51 		var txt = ts_getInnerText(cell);
     52 		if (cell.className != "unsortable" && cell.className.indexOf("unsortable") == -1) {
     53 			cell.innerHTML = '<a href="#" class="sortheader" onclick="ts_resortTable(this, '+i+');return false;">'+txt+'<span class="sortarrow">&nbsp;&nbsp;<img src="'+ image_path + image_none + '" alt="&darr;"/></span></a>';
     54 		}
     55 	}
     56 	if (alternate_row_colors) {
     57 		alternate(t);
     58 	}
     59 }
     60 
     61 function ts_getInnerText(el) {
     62 	if (typeof el == "string") return el;
     63 	if (typeof el == "undefined") { return el };
     64 	if (el.innerText) return el.innerText;	//Not needed but it is faster
     65 	var str = "";
     66 	
     67 	var cs = el.childNodes;
     68 	var l = cs.length;
     69 	for (var i = 0; i < l; i++) {
     70 		switch (cs[i].nodeType) {
     71 			case 1: //ELEMENT_NODE
     72 				str += ts_getInnerText(cs[i]);
     73 				break;
     74 			case 3:	//TEXT_NODE
     75 				str += cs[i].nodeValue;
     76 				break;
     77 		}
     78 	}
     79 	return str;
     80 }
     81 
     82 function ts_resortTable(lnk, clid) {
     83 	var span;
     84 	for (var ci=0;ci<lnk.childNodes.length;ci++) {
     85 		if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
     86 	}
     87 	var spantext = ts_getInnerText(span);
     88 	var td = lnk.parentNode;
     89 	var column = clid || td.cellIndex;
     90 	var t = getParent(td,'TABLE');
     91 	// Work out a type for the column
     92 	if (t.rows.length <= 1) return;
     93 	var itm = "";
     94 	var i = 1;
     95 	while (itm == "" && i < t.tBodies[0].rows.length) {
     96 		var itm = ts_getInnerText(t.tBodies[0].rows[i].cells[column]);
     97 		itm = trim(itm);
     98 		if (itm.substr(0,4) == "<!--" || itm.length == 0) {
     99 			itm = "";
    100 		}
    101 		i++;
    102 	}
    103 	if (itm == "") return; 
    104 	sortfn = ts_sort_caseinsensitive;
    105 	if (itm.match(/^\d\d[\/\.-][a-zA-z][a-zA-Z][a-zA-Z][\/\.-]\d\d\d\d$/)) sortfn = ts_sort_date;
    106 	if (itm.match(/^\d\d[\/\.-]\d\d[\/\.-]\d\d\d{2}?$/)) sortfn = ts_sort_date;
    107 	if (itm.match(/^-?[£$€Û¢´]\d/)) sortfn = ts_sort_numeric;
    108 	// ignore stuff in () after the numbers.
    109 	if (itm.match(/^-?(\d+[,\.]?)+(E[-+][\d]+)?%?( \(.*\))?$/)) sortfn = ts_sort_numeric;
    110 	SORT_COLUMN_INDEX = column;
    111 	var firstRow = new Array();
    112 	var newRows = new Array();
    113 	for (k=0;k<t.tBodies.length;k++) {
    114 		for (i=0;i<t.tBodies[k].rows[0].length;i++) { 
    115 			firstRow[i] = t.tBodies[k].rows[0][i]; 
    116 		}
    117 	}
    118 	for (k=0;k<t.tBodies.length;k++) {
    119 		if (!thead) {
    120 			// Skip the first row
    121 			for (j=1;j<t.tBodies[k].rows.length;j++) { 
    122 				newRows[j-1] = t.tBodies[k].rows[j];
    123 			}
    124 		} else {
    125 			// Do NOT skip the first row
    126 			for (j=0;j<t.tBodies[k].rows.length;j++) { 
    127 				newRows[j] = t.tBodies[k].rows[j];
    128 			}
    129 		}
    130 	}
    131 	newRows.sort(sortfn);
    132 	if (span.getAttribute("sortdir") == 'down') {
    133 			ARROW = '&nbsp;&nbsp;<img src="'+ image_path + image_down + '" alt="&darr;"/>';
    134 			newRows.reverse();
    135 			span.setAttribute('sortdir','up');
    136 	} else {
    137 			ARROW = '&nbsp;&nbsp;<img src="'+ image_path + image_up + '" alt="&uarr;"/>';
    138 			span.setAttribute('sortdir','down');
    139 	} 
    140     // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
    141     // don't do sortbottom rows
    142     for (i=0; i<newRows.length; i++) { 
    143 		if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
    144 			t.tBodies[0].appendChild(newRows[i]);
    145 		}
    146 	}
    147     // do sortbottom rows only
    148     for (i=0; i<newRows.length; i++) {
    149 		if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) 
    150 			t.tBodies[0].appendChild(newRows[i]);
    151 	}
    152 	// Delete any other arrows there may be showing
    153 	var allspans = document.getElementsByTagName("span");
    154 	for (var ci=0;ci<allspans.length;ci++) {
    155 		if (allspans[ci].className == 'sortarrow') {
    156 			if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
    157 				allspans[ci].innerHTML = '&nbsp;&nbsp;<img src="'+ image_path + image_none + '" alt="&darr;"/>';
    158 			}
    159 		}
    160 	}		
    161 	span.innerHTML = ARROW;
    162 	alternate(t);
    163 }
    164 
    165 function getParent(el, pTagName) {
    166 	if (el == null) {
    167 		return null;
    168 	} else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) {
    169 		return el;
    170 	} else {
    171 		return getParent(el.parentNode, pTagName);
    172 	}
    173 }
    174 
    175 function sort_date(date) {	
    176 	// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    177 	dt = "00000000";
    178 	if (date.length == 11) {
    179 		mtstr = date.substr(3,3);
    180 		mtstr = mtstr.toLowerCase();
    181 		switch(mtstr) {
    182 			case "jan": var mt = "01"; break;
    183 			case "feb": var mt = "02"; break;
    184 			case "mar": var mt = "03"; break;
    185 			case "apr": var mt = "04"; break;
    186 			case "may": var mt = "05"; break;
    187 			case "jun": var mt = "06"; break;
    188 			case "jul": var mt = "07"; break;
    189 			case "aug": var mt = "08"; break;
    190 			case "sep": var mt = "09"; break;
    191 			case "oct": var mt = "10"; break;
    192 			case "nov": var mt = "11"; break;
    193 			case "dec": var mt = "12"; break;
    194 			// default: var mt = "00";
    195 		}
    196 		dt = date.substr(7,4)+mt+date.substr(0,2);
    197 		return dt;
    198 	} else if (date.length == 10) {
    199 		if (europeandate == false) {
    200 			dt = date.substr(6,4)+date.substr(0,2)+date.substr(3,2);
    201 			return dt;
    202 		} else {
    203 			dt = date.substr(6,4)+date.substr(3,2)+date.substr(0,2);
    204 			return dt;
    205 		}
    206 	} else if (date.length == 8) {
    207 		yr = date.substr(6,2);
    208 		if (parseInt(yr) < 50) { 
    209 			yr = '20'+yr; 
    210 		} else { 
    211 			yr = '19'+yr; 
    212 		}
    213 		if (europeandate == true) {
    214 			dt = yr+date.substr(3,2)+date.substr(0,2);
    215 			return dt;
    216 		} else {
    217 			dt = yr+date.substr(0,2)+date.substr(3,2);
    218 			return dt;
    219 		}
    220 	}
    221 	return dt;
    222 }
    223 
    224 function ts_sort_date(a,b) {
    225 	dt1 = sort_date(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    226 	dt2 = sort_date(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
    227 	
    228 	if (dt1==dt2) {
    229 		return 0;
    230 	}
    231 	if (dt1<dt2) { 
    232 		return -1;
    233 	}
    234 	return 1;
    235 }
    236 function ts_sort_numeric(a,b) {
    237 	var aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    238 	aa = clean_num(aa);
    239 	var bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    240 	bb = clean_num(bb);
    241 	return compare_numeric(aa,bb);
    242 }
    243 function compare_numeric(a,b) {
    244 	var a = parseFloat(a);
    245 	a = (isNaN(a) ? 0 : a);
    246 	var b = parseFloat(b);
    247 	b = (isNaN(b) ? 0 : b);
    248 	return a - b;
    249 }
    250 function ts_sort_caseinsensitive(a,b) {
    251 	aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    252 	bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    253 	if (aa==bb) {
    254 		return 0;
    255 	}
    256 	if (aa<bb) {
    257 		return -1;
    258 	}
    259 	return 1;
    260 }
    261 function ts_sort_default(a,b) {
    262 	aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    263 	bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    264 	if (aa==bb) {
    265 		return 0;
    266 	}
    267 	if (aa<bb) {
    268 		return -1;
    269 	}
    270 	return 1;
    271 }
    272 function addEvent(elm, evType, fn, useCapture)
    273 // addEvent and removeEvent
    274 // cross-browser event handling for IE5+,	NS6 and Mozilla
    275 // By Scott Andrew
    276 {
    277 	if (elm.addEventListener){
    278 		elm.addEventListener(evType, fn, useCapture);
    279 		return true;
    280 	} else if (elm.attachEvent){
    281 		var r = elm.attachEvent("on"+evType, fn);
    282 		return r;
    283 	} else {
    284 		alert("Handler could not be removed");
    285 	}
    286 }
    287 function clean_num(str) {
    288 	str = str.replace(new RegExp(/[^-?0-9.]/g),"");
    289 	return str;
    290 }
    291 function trim(s) {
    292 	return s.replace(/^\s+|\s+$/g, "");
    293 }
    294 function alternate(table) {
    295 	// Take object table and get all it's tbodies.
    296 	var tableBodies = table.getElementsByTagName("tbody");
    297 	// Loop through these tbodies
    298 	for (var i = 0; i < tableBodies.length; i++) {
    299 		// Take the tbody, and get all it's rows
    300 		var tableRows = tableBodies[i].getElementsByTagName("tr");
    301 		// Loop through these rows
    302 		// Start at 1 because we want to leave the heading row untouched
    303 		for (var j = 0; j < tableRows.length; j++) {
    304 			// Check if j is even, and apply classes for both possible results
    305 			if ( (j % 2) == 0  ) {
    306 				if ( !(tableRows[j].className.indexOf('odd') == -1) ) {
    307 					tableRows[j].className = tableRows[j].className.replace('odd', 'even');
    308 				} else {
    309 					if ( tableRows[j].className.indexOf('even') == -1 ) {
    310 						tableRows[j].className += " even";
    311 					}
    312 				}
    313 			} else {
    314 				if ( !(tableRows[j].className.indexOf('even') == -1) ) {
    315 					tableRows[j].className = tableRows[j].className.replace('even', 'odd');
    316 				} else {
    317 					if ( tableRows[j].className.indexOf('odd') == -1 ) {
    318 						tableRows[j].className += " odd";
    319 					}
    320 				}
    321 			} 
    322 		}
    323 	}
    324 }