PageSourceSearch

https://megido72wiki.com/skin/sortabletable.js

js megido72wiki.com collected 2026-09-28 10:36:02 UTC 15,330 bytes, 458 lines download raw bytes

1/*----------------------------------------------------------------------------\
2|                            Sortable Table 1.12+02                           |
3|-----------------------------------------------------------------------------|
4|                         Created by Erik Arvidsson                           |
5|                  (http://webfx.eae.net/contact.html#erik)                   |
6|                      For WebFX (http://webfx.eae.net/)                      |
7|-----------------------------------------------------------------------------|
8| A DOM 1 based script that allows an ordinary HTML table to be sortable.     |
9|-----------------------------------------------------------------------------|
10|                  Copyright (c) 1998 - 2006 Erik Arvidsson                   |
11|-----------------------------------------------------------------------------|
12| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
13| use this file except in compliance with the License.  You may obtain a copy |
14| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
15| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
16| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
17| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
18| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
19| License  for the  specific language  governing permissions  and limitations |
20| under the License.                                                          |
21|-----------------------------------------------------------------------------|
22| 2003-01-10 | First version                                                  |
23| 2003-01-19 | Minor changes to the date parsing                              |
24| 2003-01-28 | JScript 5.0 fixes (no support for 'in' operator)               |
25| 2003-02-01 | Sloppy typo like error fixed in getInnerText                   |
26| 2003-07-04 | Added workaround for IE cellIndex bug.                         |
27| 2003-11-09 | The bDescending argument to sort was not correctly working     |
28|            | Using onclick DOM0 event if no support for addEventListener    |
29|            | or attachEvent                                                 |
30| 2004-01-13 | Adding addSortType and removeSortType which makes it a lot     |
31|            | easier to add new, custom sort types.                          |
32| 2004-01-27 | Switch to use descending = false as the default sort order.    |
33|            | Change defaultDescending to suit your needs.                   |
34| 2004-03-14 | Improved sort type None look and feel a bit                    |
35| 2004-08-26 | Made the handling of tBody and tHead more flexible. Now you    |
36|            | can use another tHead or no tHead, and you can chose some      |
37|            | other tBody.                                                   |
38| 2006-04-25 | Changed license to Apache Software License 2.0                 |  
39|-----------------------------------------------------------------------------|
40| 2005-10-06 | condition check (&& c.firstChild.nodeType != 3) [email protected] |
41| 2005-10-15 | multiple tHead (and related tBody) rows support [email protected] |
42| 2006-09-05 | sortTypes existing check / safari support       [email protected] |
43|-----------------------------------------------------------------------------|
44| Created 2003-01-10 | All changes are in the log above. | Updated 2006-09-05 |
45\----------------------------------------------------------------------------*/
46
47
48function SortableTable(oTable, oSortTypes) {
49
50	this.sortTypes = oSortTypes || [];
51
52	this.sortColumn = null;
53	this.sortRow = null;
54	this.descending = null;
55
56	var oThis = this;
57	this._headerOnclick = function (e) {
58		oThis.headerOnclick(e);
59	};
60
61	if (oTable) {
62		this.setTable( oTable );
63		this.document = oTable.ownerDocument || oTable.document;
64	}
65	else {
66		this.document = document;
67	}
68
69
70	// only IE needs this
71	var win = this.document.defaultView || this.document.parentWindow;
72	this._onunload = function () {
73		oThis.destroy();
74	};
75	if (win && typeof win.attachEvent != "undefined") {
76		win.attachEvent("onunload", this._onunload);
77	}
78}
79
80SortableTable.gecko = navigator.product == "Gecko";
81SortableTable.safari = (navigator.userAgent.indexOf("Safari") != -1);
82SortableTable.msie = /msie/i.test(navigator.userAgent);
83// Mozilla is faster when doing the DOM manipulations on
84// an orphaned element. MSIE is not
85SortableTable.removeBeforeSort = SortableTable.gecko;
86
87SortableTable.prototype.onsort = function () {};
88
89// default sort order. true ->
89 descending, false -> ascending
90SortableTable.prototype.defaultDescending = false;
91
92// shared between all instances. This is intentional to allow external files
93// to modify the prototype
94SortableTable.prototype._sortTypeInfo = {};
95
96SortableTable.prototype.setTable = function (oTable) {
97	if ( this.tHead )
98		this.uninitHeader();
99	this.element = oTable;
100	this.setTHead( oTable.tHead );
101	this.setTBody( oTable.tBodies[0] );
102};
103
104SortableTable.prototype.setTHead = function (oTHead) {
105	if (this.tHead && this.tHead != oTHead )
106		this.uninitHeader();
107	this.tHead = oTHead;
108	this.step = oTHead.rows.length;
109	this.initHeader( this.sortTypes );
110};
111
112SortableTable.prototype.setTBody = function (oTBody) {
113	this.tBody = oTBody;
114};
115
116SortableTable.prototype.setSortTypes = function ( oSortTypes ) {
117	if ( this.tHead )
118		this.uninitHeader();
119	this.sortTypes = oSortTypes || [];
120	if ( this.tHead )
121		this.initHeader( this.sortTypes );
122};
123
124// adds arrow containers and events
125// also binds sort type to the header cells so that reordering columns does
126// not break the sort types
127SortableTable.prototype.initHeader = function (oSortTypes) {
128	if (!this.tHead) return;
129
130	this.sortTypes = new Array(this.tHead.rows.length);
131	this.head
132	var index = 0;
133
134	var doc = this.tHead.ownerDocument || this.tHead.document;
135	var sortTypes = oSortTypes || [];
136
137	for (var row = 0; row < this.tHead.rows.length; row++) {
138		var cells = this.tHead.rows[row].cells;
139		this.sortTypes[row] = new Array(cells.length);
140		for (var column = 0; column < cells.length; column++) {
141			var c = cells[column];
142			var sortType = sortTypes[index++] || 'None';
143			this.sortTypes[row][column] = sortType;
144			if (sortType == 'None') { continue; }
145
146			if (c.firstChild.nodeName == 'A') { c.firstChild.href='javascript:void(0)'; }
147
148			var img = doc.createElement('IMG');
149			img.src = 'image/blank.png';
150			c.appendChild(img);
151
152			if (typeof c.addEventListener != "undefined") {
153				c.addEventListener("click", this._headerOnclick, false);
154			} else if (typeof c.attachEvent != "undefined") {
155				c.attachEvent("onclick", this._headerOnclick);
156			} else {
157				c.onclick = this._headerOnclick;
158			}
159		}
160	}
161	this.updateHeaderArrows();
162};
163
164// remove arrows and events
165SortableTable.prototype.uninitHeader = function () {
166	if (! this.tHead) { return; }
167	for (var row = 0; row < this.tHead.rows.length; row++) {
168		var cells = this.tHead.rows[row].cells;
169		for (var column = 0; column < cells.length; column++) {
170			var c = cells[column];
171			if (this.getSortType(row, column) == 'None') { continue; }
172			c.removeChild(c.lastChild);
173			if (typeof c.removeEventListener != "undefined") {
174				c.removeEventListener("click", this._headerOnclick, false);
175			} else if (typeof c.detachEvent != "undefined") {
176				c.detachEvent("onclick", this._headerOnclick);
177			}
178		}
179	}
180};
181
182SortableTable.prototype.updateHeaderArrows = function () {
183	if (! this.tHead) { return; }
184	for (var row = 0; row < this.tHead.rows.length; row++) {
185		var cells = this.tHead.rows[row].cells;
186		for (var column = 0; column < cells.length; column++) {
187			var c = cells[column];
188			if (this.getSortType(row, column) == 'None') { continue; }
189			var img = c.lastChild;
190			if (row == this.sortRow && column == this.sortColumn) {
191				img.className = "sort-arrow " + (this.descending ? "descending" : "ascending");
192			} else {
193				img.className = "sort-arrow";
194			}
195		}
196	}
197};
198
199SortableTable.prototype.headerOnclick = function (e) {
200	// find TD element
201	var cell = e.target || e.srcElement;
202	while (cell.nodeName != "TD" && cell.nodeName != "TH") { cell = cell.parentNode; }
203	var row = cell.parentNode;
204	while (row.nodeName != 'TR') { row = row.parentNode; }
205
206	var row = row.rowIndex;
207	var column = (SortableTable.msie || SortableTable.safari)
208		? SortableTable.getCellIndex(cell)
209		: cell.cellIndex;
210	this.sort(row, column);
211};
212
213// IE returns wrong cellIndex when columns are hidden
214SortableTable.getCellIndex = function (cell) {
215	var cells = cell.parentNode.childNodes;
216	for (var column = 0; cells[column] != cell && column < cells.length; column++)
217		;
218	return column;
219};
220
221SortableTable.prototype.getSortType = function (row, column) {
222	if (! this.sortTypes[row]) { return "None"; }
223	return this.sortTypes[row][column] || "String";
224};
225
226// only nRow, nColumn is required
227// if bDescending is left out the old value is taken into account
228// if sSortType is left out the sort type is found from the sortTypes array
229
230SortableTable.prototype.sort = function (nRow, nColumn, bDescending, sSortType) {
231	if (! this.tBody) { return; }
232	if (sSortType == null) { sSortType = this.getSortType(nRow, nColumn); }
233
234	// exit if None
235	if (sSortType == 'None') { return; }
236
237	if (bDescending == null) {
238		this.descending = (this.sortRow == nRow && this.sortColumn == nColumn)
239			? ! this.descending : this.defaultDescending;
240	} else {
241		this.descending = bDescending;
242	}
243
244	this.sortRow = nRow;
245	this.sortColumn = nColumn;
246
247	if (typeof this.onbeforesort == "function") {
248		this.onbeforesort();
249	}
250
251	var f = this.getSortFunction(sSortType, nRow, nColumn);
252	var a = this.getCache(sSortType, nRow, nColumn);
253	var tBody = this.tBody;
254
255	a.sort(f);
256
257	if (this.descending) {
258		a.reverse();
259	}
260
261	if (SortableTable.removeBeforeSort) {
262		// remove from doc
263		var nextSibling = tBody.nextSibling;
264		var p = tBody.parentNode;
265		p.removeChild(tBody);
266	}
267
268	// insert in the new order
269	for (var i = 0; i < a.length; i++) {
270		for (var j = 0; j < a[i].elements.length; j++) {
271			tBody.appendChild(a[i].elements[j]);
272		}
273	}
274
275	if (SortableTable.removeBeforeSort) {
276		// insert into doc
277		p.insertBefore(tBody, nextSibling);
278	}
279
280	this.updateHeaderArrows();
281
282	this.destroyCache(a);
283
284	if (typeof this.onsort == "function") {
285		this.onsort();
286	}
287};
288
289SortableTable.prototype.asyncSort = function (nRow, nColumn, bDescending, sSortType) {
290	var oThis = this;
291	this._asyncsort = function () {
292		oThis.sort(nRow, nColumn, bDescending, sSortType);
293	};
294	window.setTimeout(this._asyncsort, 1);
295};
296
297SortableTable.prototype.getCache = function (sType, nRow, nColumn) {
298	if (!this.tBody) { return []; }
299	var rows = this.tBody.rows;
300	var a = new Array;
301	for (var i = 0; i < rows.length; i += this.step) {
302		var r = [];
303		for (var j = 0; j < this.step; j++) { r.push(rows[i + j]); }
304		a.push({
305			value:		this.getRowValue(r[nRow], sType, nColumn),
306			elements:	r
307		});
308	};
309	return a;
310};
311
312SortableTable.prototype.destroyCache = function (oArray) {
313	var l = oArray.length;
314	for (var i = 0; i < l; i++) {
315		oArray[i].value = null;
316		oArray[i].elements = null;
317		oArray[i] = null;
318	}
319};
320
321SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
322	// if we have defined a custom getRowValue use that
323	if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
324		return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);
325
326	var s;
327	var c = oRow.cells[nColumn];
328	// add condition (&& c.firstChild.nodeType != 3) 2005-10-06 [email protected]
329	if (c.firstChild && c.firstChild.nodeType != 3) { c = c.firstChild; }
330	if (typeof c.innerText != "undefined")
331		s = c.innerText;
332	else
333		s = SortableTable.getInnerText(c);
334	return this.getValueFromString(s, sType);
335};
336
337SortableTable.getInnerText = function (oNode) {
338	var s = "";
339	var cs = oNode.childNodes;
340	var l = cs.length;
341	for (var i = 0; i < l; i++) {
342		switch (cs[i].nodeType) {
343			case 1: //ELEMENT_NODE
344				s += SortableTable.getInnerText(cs[i]);
345				break;
346			case 3:	//TEXT_NODE
347				s += cs[i].nodeValue;
348				break;
349		}
350	}
351	return s;
352};
353
354SortableTable.prototype.getValueFromString = function (sText, sType) {
355	if (this._sortTypeInfo[sType])
356		return this._sortTypeInfo[sType].getValueFromString( sText );
357	return sText;
358	/*
359	switch (sType) {
360		case "Number":
361			return Number(sText);
362		case "CaseInsensitiveString":
363			return sText.toUpperCase();
364		case "Date":
365			var parts = sText.split("-");
366			var d = new Date(0);
367			d.setFullYear(parts[0]);
368			d.setDate(parts[2]);
369			d.setMonth(parts[1] - 1);
370			return d.valueOf();
371	}
372	return sText;
373	*/
374	};
375
376SortableTable.prototype.getSortFunction = function (sType, nRow, nColumn) {
377	if (this._sortTypeInfo[sType])
378		return this._sortTypeInfo[sType].compare;
379	return SortableTable.basicCompare;
380};
381
382SortableTable.prototype.destroy = function () {
383	this.uninitHeader();
384	var win = this.document.parentWindow;
385	if (win && typeof win.detachEvent != "undefined") {	// only IE needs this
386		win.detachEvent("onunload", this._onunload);
387	}
388	this._onunload = null;
389	this.element = null;
390	this.tHead = null;
391	this.step = null;
392	this.tBody = null;
393	this.document = null;
394	this._headerOnclick = null;
395	this.sortTypes = null;
396	this._asyncsort = null;
397	this.onsort = null;
398};
399
400// Adds a sort type to all instance of SortableTable
401// sType : String - the identifier of the sort type
402// fGetValueFromString : function ( s : string ) : T - A function that takes a
403//    string and casts it to a desired format. If left out the string is just
404//    returned
405// fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort
406//    compare function. Takes two values and compares them. If left out less than,
407//    <, compare is used
408// fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A function
409//    that takes the row and the column index and returns the value used to compare.
410//    If left out then the innerText is first taken for the cell and then the
411//    fGetValueFromString is used to convert that string the desired value and type
412
413SortableTable.prototype.addSortType = function (sType, fGetValueFromString, fCompareFunction, fGetRowValue) {
414	this._sortTypeInfo[sType] = {
415		type:				sType,
416		getValueFromString:	fGetValueFromString || SortableTable.idFunction,
417		compare:			fCompareFunction || SortableTable.basicCompare,
418		getRowValue:		fGetRowValue
419	};
420};
421
422// this removes the sort type from all instances of SortableTable
423SortableTable.prototype.removeSortType = function (sType) {
424	delete this._sortTypeInfo[sType];
425};
426
427SortableTable.basicCompare = function compare(n1, n2) {
428	if (n1.value < n2.value)
429		return -1;
430	if (n2.value < n1.value)
431		return 1;
432	return 0;
433};
434
435SortableTable.idFunction = function (x) {
436	return x;
437};
438
439SortableTable.toUpperCase = function (s) {
440	return s.toUpperCase();
441};
442
443SortableTable.toDate = function (s) {
444	var parts = s.split("-");
445	var d = new Date(0);
446	d.setFullYear(parts[0]);
447	d.setDate(parts[2]);
448	d.setMonth(parts[1] - 1);
449	return d.valueOf();
450};
451
452
453// add sort types
454SortableTable.prototype.addSortType("Number", Number);
455SortableTable.prototype.addSortType("CaseInsensitiveString", SortableTable.toUpperCase);
456SortableTable.prototype.addSortType("Date", SortableTable.toDate);
457SortableTable.prototype.addSortType("String");
458// None is a special case

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.