sortabletable.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /*----------------------------------------------------------------------------\
  2. | Sortable Table 1.1 |
  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 - 2003 Erik Arvidsson |
  11. |-----------------------------------------------------------------------------|
  12. | This software is provided "as is", without warranty of any kind, express or |
  13. | implied, including but not limited to the warranties of merchantability, |
  14. | fitness for a particular purpose and noninfringement. In no event shall the |
  15. | authors or copyright holders be liable for any claim, damages or other |
  16. | liability, whether in an action of contract, tort or otherwise, arising |
  17. | from, out of or in connection with the software or the use or other |
  18. | dealings in the software. |
  19. | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
  20. | This software is available under the three different licenses mentioned |
  21. | below. To use this software you must chose, and qualify, for one of those. |
  22. | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
  23. | The WebFX Non-Commercial License http://webfx.eae.net/license.html |
  24. | Permits anyone the right to use the software in a non-commercial context |
  25. | free of charge. |
  26. | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
  27. | The WebFX Commercial license http://webfx.eae.net/commercial.html |
  28. | Permits the license holder the right to use the software in a commercial |
  29. | context. Such license must be specifically obtained, however it's valid for |
  30. | any number of implementations of the licensed software. |
  31. | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
  32. | GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
  33. | Permits anyone the right to use and modify the software without limitations |
  34. | as long as proper credits are given and the original and modified source |
  35. | code are included. Requires that the final product, software derivate from |
  36. | the original source or any software utilizing a GPL component, such as |
  37. | this, is also licensed under the GPL license. |
  38. |-----------------------------------------------------------------------------|
  39. | 2003-01-10 | First version |
  40. | 2003-01-19 | Minor changes to the date parsing |
  41. | 2003-01-28 | JScript 5.0 fixes (no support for 'in' operator) |
  42. | 2003-02-01 | Sloppy typo like error fixed in getInnerText |
  43. | 2003-07-04 | Added workaround for IE cellIndex bug. |
  44. | 2003-11-09 | The bDescending argument to sort was not correctly working |
  45. | | Using onclick DOM0 event if no support for addEventListener |
  46. | | or attachEvent |
  47. | 2004-01-13 | Adding addSortType and removeSortType which makes it a lot |
  48. | | easier to add new, custom sort types. |
  49. | 2004-01-27 | Switch to use descending = false as the default sort order. |
  50. | | Change defaultDescending to suit your needs. |
  51. |-----------------------------------------------------------------------------|
  52. | Created 2003-01-10 | All changes are in the log above. | Updated 2004-01-27 |
  53. \----------------------------------------------------------------------------*/
  54. var tooltipDiv = null;
  55. var tooltipPopup = null;
  56. var tooltipX = 0;
  57. var tooltipY = 0;
  58. var tooltipSrcObj = null;
  59. var tooltipCaptionColor = "#6699FF"; //"#808080";
  60. var tooltipBodyColor = "#FFFF99"; //"#C0C0C0";
  61. var tooltipBodyTextColor = "black";
  62. var tooltipMaxWidth = screen.width;
  63. var sortImagePath = '/esp/files_/img/';
  64. /*----------------------------------------------------------------------------\
  65. | Handle Split Tables |
  66. | Table header and body are in separate tables in their own divs. |
  67. \----------------------------------------------------------------------------*/
  68. var a_fixedTableNames = [];
  69. function initFixedTables(fixedTableNames)
  70. {
  71. if (typeof fixedTableNames != 'undefined')
  72. a_fixedTableNames = a_fixedTableNames.concat( fixedTableNames );
  73. var nFixedTables = a_fixedTableNames.length;
  74. if (nFixedTables) {
  75. document.body.onresize=resizeFixedTableBodyDivs;
  76. for (var i=0; i<nFixedTables; i++) {
  77. bDiv = document.getElementById('DB.' + a_fixedTableNames[i]);
  78. bDiv.onscroll = new Function( "scrollFixedTableHeaderDiv(this, '" + a_fixedTableNames[i] + "')" );
  79. }
  80. resizeFixedTableBodyDivs();
  81. }
  82. }
  83. function resizeFixedTableBodyDivs() {
  84. if (a_fixedTableNames.length == 0)
  85. return;
  86. var hfooter = document.getElementById('pageFooter');
  87. var bottom = hfooter ? hfooter.offsetTop : document.body.offsetHeight;
  88. var bDiv = document.getElementById('DB.' + a_fixedTableNames[0]);
  89. var bTable = document.getElementById(a_fixedTableNames[0]);
  90. var h = bottom - bDiv.offsetTop - 35;
  91. h /= a_fixedTableNames.length;
  92. h = Math.max(h, 50);
  93. if (bDiv.offsetHeight > h)
  94. bDiv.style.height = h;
  95. else
  96. {
  97. var tw = bTable.offsetWidth;
  98. var th = bTable.offsetHeight;
  99. var dw = bDiv.offsetWidth;
  100. var doubleBorder = 2;
  101. if (dw < tw+doubleBorder)
  102. bDiv.style.height = Math.min(h, th+20);//add height to fit horiz scrollbar to avoid vertical scrollbar
  103. else
  104. if (dw > tw+doubleBorder)
  105. bDiv.style.height = th+doubleBorder;
  106. }
  107. resizeFixedTableHeaderDiv(bDiv, a_fixedTableNames[0])
  108. for (var i=1; i<a_fixedTableNames.length; i++) {
  109. bDiv = document.getElementById('DB.' + a_fixedTableNames[i]);
  110. bDiv.style.height = h;
  111. resizeFixedTableHeaderDiv(bDiv, a_fixedTableNames[i]);
  112. }
  113. }
  114. function scrollFixedTableHeaderDiv(bodyDiv, tableId)
  115. {
  116. var htable = document.getElementById('H.' + tableId);
  117. if (htable)
  118. htable.style.left = -bodyDiv.scrollLeft;
  119. }
  120. function resizeFixedTableHeaderDiv(bodyDiv, tableId)
  121. {
  122. var hdiv = document.getElementById('DH.' + tableId);
  123. if (hdiv)
  124. {
  125. var htable = document.getElementById('H.' + tableId);
  126. var btable = bodyDiv.getElementsByTagName('table')[0];
  127. hdiv.style.width = bodyDiv.offsetWidth;
  128. htable.style.width = btable.offsetWidth;
  129. //resize individual column headers based on first row's cells in body table
  130. if (htable.style.tableLayout != 'fixed')
  131. {
  132. var bCells = btable.rows[0].cells;
  133. var hCells = htable.rows[0].cells;
  134. var n_bCells = bCells.length;
  135. var n_hCells = hCells.length;
  136. for (var i=0; i<n_bCells; i++)
  137. hCells[i].style.width = bCells[i].offsetWidth;
  138. }
  139. scrollFixedTableHeaderDiv(bodyDiv, tableId);
  140. }
  141. }
  142. /*----------------------------------------------------------------------------\
  143. | Handle Column Resizing |
  144. \----------------------------------------------------------------------------*/
  145. function makeColumnsResizable(htable) {
  146. var rows = htable.rows;
  147. var nRows = rows.length;
  148. if (nRows) {
  149. var cells = rows[0].cells;
  150. var nCells = cells.length;
  151. for (var i=0; i<nCells; i++) {
  152. var cell = cells[i];
  153. //cells with no text lose border so add text
  154. if (cell.innerText == '')
  155. {
  156. var textNode = document.createTextNode(' ');
  157. cell.appendChild( textNode );
  158. }
  159. var span = document.createElement('SPAN');
  160. span.className = 'resizer';
  161. span.style.height = cell.offsetHeight;
  162. //span.style.border='red 1px solid';
  163. span.innerText = ' ';
  164. span.onmousedown = resizeColumn;
  165. cell.style.position = 'relative';
  166. cell.style.paddingRight = 0;
  167. cell.appendChild(span);
  168. }
  169. }
  170. }
  171. function resizeColumn(resizer) {
  172. var resizer = event.srcElement;
  173. var th = resizer.parentElement;
  174. th._resizing = true;
  175. var hTable = th.parentElement;
  176. while (hTable.tagName != 'TABLE')
  177. hTable = hTable.parentElement;
  178. var size = th.offsetWidth;
  179. var firstX = event.clientX;// + resizer.offsetWidth + 10;
  180. var lastX = firstX;
  181. var prevHeaderHeight = th.offsetHeight;
  182. function doResize() {
  183. var newX = event.clientX;
  184. if (Math.abs(newX - lastX) > 2) {//resize every 2 pixels
  185. var delta = event.clientX - firstX;
  186. var sz = Math.max(5, size + delta);
  187. th.style.width = sz;
  188. lastX = newX;
  189. }
  190. };
  191. function finishResizing() {
  192. var newWidth = Math.max(size + event.clientX - firstX, 5);
  193. th.style.width = newWidth;
  194. if (typeof resizer.onmouseleave == "function")
  195. resizer.onmouseleave()
  196. resizer.detachEvent("onmousemove", doResize);
  197. resizer.detachEvent("onmouseup", finishResizing);
  198. resizer.detachEvent("onlosecapture", finishResizing);
  199. resizer.releaseCapture();
  200. var hTableId = hTable.id;
  201. if (hTableId && hTableId.indexOf('H.') == 0)
  202. {
  203. var bTableId = hTableId.substring(2);
  204. var bTable = document.getElementById( bTableId );
  205. var hDiv = document.getElementById( 'DH.' + bTableId );
  206. var bDiv = document.getElementById( 'DB.' + bTableId );
  207. hDiv.style.width = bDiv.offsetWidth;
  208. bTable.style.width = hTable.offsetWidth;
  209. var hCells = hTable.rows[0].cells;
  210. var nCells = hCells.length;
  211. var nCol = th.cellIndex;
  212. var rows = bTable.rows;
  213. var nRows = rows.length;
  214. for (var r=0; r<nRows; r++)
  215. if (rows[r].id)
  216. rows[r].cells[ nCol ].style.width = newWidth;
  217. var newHeaderHeight = th.offsetHeight;
  218. if (newHeaderHeight != prevHeaderHeight)
  219. for (var c=0; c<nCells; c++)
  220. {
  221. var span = hCells[c].getElementsByTagName('SPAN')[0];
  222. span.style.height = newHeaderHeight;
  223. }
  224. resizeFixedTableBodyDivs();
  225. }
  226. event.cancelBubble = true;
  227. };
  228. resizer.attachEvent("onmouseup", finishResizing);
  229. resizer.attachEvent("onlosecapture", finishResizing);
  230. resizer.attachEvent("onmousemove", doResize);
  231. resizer.setCapture();
  232. event.cancelBubble = true;
  233. }
  234. /*----------------------------------------------------------------------------\
  235. | SortableTable implementation |
  236. \----------------------------------------------------------------------------*/
  237. function SortableTable(hTable, oTable, oSortTypes, dataIslandParent) {
  238. this.element = oTable;
  239. this.tHead = hTable.tHead;
  240. if (!this.tHead)
  241. this.tHead = hTable.tBodies[0];
  242. this.tBody = oTable.tBodies[0];
  243. this.document = oTable.ownerDocument || oTable.document;
  244. this.dataIslandParent = dataIslandParent;
  245. this.sortColumn = null;
  246. this.descending = null;
  247. var oThis = this;
  248. this._headerOnclick = function (e) {
  249. oThis.headerOnclick(e);
  250. };
  251. // only IE needs this
  252. var win = this.document.defaultView || this.document.parentWindow;
  253. this._onunload = function () {
  254. oThis.destroy();
  255. };
  256. if (win && typeof win.attachEvent != "undefined") {
  257. win.attachEvent("onunload", this._onunload);
  258. }
  259. this.initHeader(oSortTypes || []);
  260. // IE does not remember input values when moving DOM elements
  261. if (/MSIE/.test(navigator.userAgent)) {
  262. // backup check box values
  263. this.onbeforesort = function () {
  264. var table = this.element;
  265. var inputs = table.getElementsByTagName("INPUT");
  266. var l = inputs.length;
  267. for (var i = 0; i < l; i++) {
  268. inputs[i].parentNode._checked = inputs[i].checked;
  269. }
  270. };
  271. // restore check box values
  272. this.onsort = function () {
  273. var table = this.element;
  274. var inputs = table.getElementsByTagName("INPUT");
  275. var l = inputs.length;
  276. for (var i = 0; i < l; i++) {
  277. inputs[i].checked = inputs[i].parentNode._checked;
  278. }
  279. handleOddEven(this);
  280. };
  281. }
  282. makeColumnsResizable(hTable);
  283. }
  284. SortableTable.gecko = navigator.product == "Gecko";
  285. SortableTable.msie = /msie/i.test(navigator.userAgent);
  286. // Mozilla is faster when doing the DOM manipulations on
  287. // an orphaned element. MSIE is not
  288. SortableTable.removeBeforeSort = SortableTable.gecko;
  289. SortableTable.prototype.onsort = function () {};
  290. // default sort order. true -> descending, false -> ascending
  291. SortableTable.prototype.defaultDescending = false;
  292. // shared between all instances. This is intentional to allow external files
  293. // to modify the prototype
  294. SortableTable.prototype._sortTypeInfo = {};
  295. // adds arrow containers and events
  296. // also binds sort type to the header cells so that reordering columns does
  297. // not break the sort types
  298. SortableTable.prototype.initHeader = function (oSortTypes) {
  299. var cells = this.tHead.rows[0].cells;
  300. var l = cells.length;
  301. var img, c;
  302. for (var i = 0; i < l; i++) {
  303. c = cells[i];
  304. if (oSortTypes[i] && oSortTypes[i] == "None")
  305. continue;
  306. img = document.createElement("IMG");
  307. img.src = sortImagePath + "blank.png";
  308. img.className = 'sort-arrow';
  309. c.appendChild(img);
  310. if (oSortTypes[i] != null && oSortTypes[i] != "None") {
  311. c._sortType = oSortTypes[i];
  312. }
  313. if (typeof c.addEventListener != "undefined")
  314. c.addEventListener("click", this._headerOnclick, false);
  315. else if (typeof c.attachEvent != "undefined")
  316. c.attachEvent("onclick", this._headerOnclick);
  317. else
  318. c.onclick = this._headerOnclick;
  319. c.onmouseover=function() {this.bgColor = this._resizing ? "#CCCCCC" : "#FFFFFF";};
  320. c.onmouseout=function() {this.bgColor = "#CCCCCC";};
  321. }
  322. this.updateHeaderArrows();
  323. };
  324. // remove arrows and events
  325. SortableTable.prototype.uninitHeader = function () {
  326. var cells = this.tHead.rows[0].cells;
  327. var l = cells.length;
  328. for (var i = 0; i < l; i++) {
  329. var c = cells[i];
  330. var imgs = c.getElementsByTagName('img');
  331. var nImages = imgs.length;
  332. for (var j=0; j<nImages; j++)
  333. {
  334. var img = imgs[j];
  335. var className = img.className;
  336. if (className.indexOf('sort-arrow')==0)
  337. {
  338. c.removeChild(img);
  339. break;
  340. }
  341. }
  342. if (typeof c.removeEventListener != "undefined")
  343. c.removeEventListener("click", this._headerOnclick, false);
  344. else if (typeof c.detachEvent != "undefined")
  345. c.detachEvent("onclick", this._headerOnclick);
  346. }
  347. };
  348. SortableTable.prototype.updateHeaderArrows = function () {
  349. var cells = this.tHead.rows[0].cells;
  350. var l = cells.length;
  351. for (var i = 0; i < l; i++) {
  352. var imgs = cells[i].getElementsByTagName('img');
  353. var nImages = imgs.length;
  354. for (var j=0; j<nImages; j++)
  355. {
  356. var img = imgs[j];
  357. var className = img.className;
  358. if (className && className.indexOf('sort-arrow')==0)
  359. {
  360. if (i == this.sortColumn)
  361. img.className = "sort-arrow " + (this.descending ? "descending" : "ascending");
  362. else
  363. img.className = "sort-arrow";
  364. break;
  365. }
  366. }
  367. }
  368. };
  369. SortableTable.prototype.headerOnclick = function (e) {
  370. // find TD element
  371. var el = e.target || e.srcElement;
  372. while (el.tagName != "TH")
  373. el = el.parentNode;
  374. if (el._resizing)
  375. el._resizing = false;
  376. else
  377. this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : el.cellIndex);
  378. };
  379. // IE returns wrong cellIndex when columns are hidden
  380. SortableTable.getCellIndex = function (oTd) {
  381. var cells = oTd.parentNode.childNodes
  382. var l = cells.length;
  383. var i;
  384. for (i = 0; cells[i] != oTd && i < l; i++)
  385. ;
  386. return i;
  387. };
  388. SortableTable.prototype.getSortType = function (nColumn) {
  389. var cell = this.tHead.rows[0].cells[nColumn];
  390. var val = cell._sortType;
  391. if (val != "")
  392. return val;
  393. return "String";
  394. };
  395. // only nColumn is required
  396. // if bDescending is left out the old value is taken into account
  397. // if sSortType is left out the sort type is found from the sortTypes array
  398. SortableTable.prototype.sort = function (nColumn, bDescending, sSortType) {
  399. if (sSortType == null)
  400. sSortType = this.getSortType(nColumn);
  401. // exit if None
  402. if (sSortType == "None")
  403. return;
  404. if (bDescending == null) {
  405. if (this.sortColumn != nColumn)
  406. this.descending = this.defaultDescending;
  407. else
  408. this.descending = !this.descending;
  409. }
  410. else
  411. this.descending = bDescending;
  412. this.sortColumn = nColumn;
  413. if (typeof this.onbeforesort == "function")
  414. this.onbeforesort();
  415. var f = this.getSortFunction(sSortType, nColumn);
  416. var a = this.getCache(sSortType, nColumn);
  417. var tBody = this.tBody;
  418. a.sort(f);
  419. if (this.descending)
  420. a.reverse();
  421. if (SortableTable.removeBeforeSort) {
  422. // remove from doc
  423. var nextSibling = tBody.nextSibling;
  424. var p = tBody.parentNode;
  425. p.removeChild(tBody);
  426. }
  427. var l = a.length;
  428. if (this.dataIslandParent)
  429. {
  430. var domElements = this.dataIslandParent.childNodes;
  431. for (var i = 0; i < l; i++)
  432. this.dataIslandParent.removeChild( domElements.item(0) );
  433. }
  434. // insert in the new order
  435. for (var i = 0; i < l; i++)
  436. {
  437. tBody.appendChild(a[i].element);//automatically removes item before appending
  438. if (this.dataIslandParent)
  439. this.dataIslandParent.appendChild( a[i].domElement );
  440. }
  441. if (SortableTable.removeBeforeSort) {
  442. // insert into doc
  443. p.insertBefore(tBody, nextSibling);
  444. }
  445. this.updateHeaderArrows();
  446. this.destroyCache(a);
  447. if (typeof this.onsort == "function")
  448. this.onsort();
  449. };
  450. SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) {
  451. var oThis = this;
  452. this._asyncsort = function () {
  453. oThis.sort(nColumn, bDescending, sSortType);
  454. };
  455. window.setTimeout(this._asyncsort, 1);
  456. };
  457. SortableTable.prototype.getCache = function (sType, nColumn) {
  458. var rows = this.tBody.rows;
  459. var l = rows.length;
  460. var a = new Array(l);
  461. var r;
  462. var domElements = this.dataIslandParent ? this.dataIslandParent.childNodes : null;
  463. for (var i = 0; i < l; i++) {
  464. r = rows[i];
  465. a[i] = {
  466. value: this.getRowValue(r, sType, nColumn),
  467. element: r,
  468. domElement: domElements ? domElements.item(i) : null
  469. };
  470. };
  471. return a;
  472. };
  473. SortableTable.prototype.destroyCache = function (oArray) {
  474. var l = oArray.length;
  475. for (var i = 0; i < l; i++) {
  476. oArray[i].value = null;
  477. oArray[i].element = null;
  478. oArray[i].domElement = null;
  479. oArray[i] = null;
  480. }
  481. };
  482. SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
  483. // if we have defined a custom getRowValue use that
  484. if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
  485. return this._sortTypeInfo[sType].getRowValue(oRow, sType, nColumn);
  486. var s;
  487. var c = oRow.cells[nColumn];
  488. if (c==null)
  489. s = "";
  490. else
  491. if (typeof c.innerText != "undefined")
  492. s = c.innerText;
  493. else
  494. s = SortableTable.getInnerText(c);
  495. return this.getValueFromString(s, sType);
  496. };
  497. // define a custom getRowValue handler for HTML objects
  498. //
  499. SortableTable.prototype.getHtmlObjRowValue = function (oRow, sType, nColumn) {
  500. var s;
  501. var c = oRow.cells[nColumn];
  502. if (c==null)
  503. s = "";
  504. else {
  505. var obj = c.firstChild;
  506. if (obj) {
  507. var tagName = obj.tagName;
  508. if (tagName == 'INPUT' && obj.type=='checkbox')
  509. s = obj.checked ? '1' : '0';
  510. else if (tagName == 'SELECT')
  511. s = obj.options[obj.selectedIndex].value;
  512. else
  513. s = obj.value;
  514. }
  515. else
  516. s = "";
  517. }
  518. return this.getValueFromString(s, sType);
  519. };
  520. SortableTable.getInnerText = function (oNode) {
  521. var s = "";
  522. var cs = oNode.childNodes;
  523. var l = cs.length;
  524. for (var i = 0; i < l; i++) {
  525. switch (cs[i].nodeType) {
  526. case 1: //ELEMENT_NODE
  527. s += SortableTable.getInnerText(cs[i]);
  528. break;
  529. case 3: //TEXT_NODE
  530. s += cs[i].nodeValue;
  531. break;
  532. }
  533. }
  534. return s;
  535. };
  536. SortableTable.prototype.getValueFromString = function (sText, sType) {
  537. if (this._sortTypeInfo[sType])
  538. return this._sortTypeInfo[sType].getValueFromString( sText );
  539. return sText;
  540. /*
  541. switch (sType) {
  542. case "Number":
  543. return Number(sText);
  544. case "CaseInsensitiveString":
  545. return sText.toUpperCase();
  546. case "Date":
  547. var parts = sText.split("-");
  548. var d = new Date(0);
  549. d.setFullYear(parts[0]);
  550. d.setDate(parts[2]);
  551. d.setMonth(parts[1] - 1);
  552. return d.valueOf();
  553. }
  554. return sText;
  555. */
  556. };
  557. SortableTable.prototype.getSortFunction = function (sType, nColumn) {
  558. if (this._sortTypeInfo[sType])
  559. return this._sortTypeInfo[sType].compare;
  560. return SortableTable.basicCompare;
  561. };
  562. SortableTable.prototype.destroy = function () {
  563. this.uninitHeader();
  564. var win = this.document.parentWindow;
  565. if (win && typeof win.detachEvent != "undefined") { // only IE needs this
  566. win.detachEvent("onunload", this._onunload);
  567. }
  568. this._onunload = null;
  569. this.element = null;
  570. this.tHead = null;
  571. this.tBody = null;
  572. this.document = null;
  573. this._headerOnclick = null;
  574. this.sortTypes = null;
  575. this._asyncsort = null;
  576. this.onsort = null;
  577. };
  578. // Adds a sort type to all instance of SortableTable
  579. // sType : String - the identifier of the sort type
  580. // fGetValueFromString : function ( s : string ) : T - A function that takes a
  581. // string and casts it to a desired format. If left out the string is just
  582. // returned
  583. // fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort
  584. // compare function. Takes two values and compares them. If left out less than,
  585. // <, compare is used
  586. // fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A function
  587. // that takes the row and the column index and returns the value used to compare.
  588. // If left out then the innerText is first taken for the cell and then the
  589. // fGetValueFromString is used to convert that string the desired value and type
  590. SortableTable.prototype.addSortType = function (sType, fGetValueFromString, fCompareFunction, fGetRowValue) {
  591. this._sortTypeInfo[sType] = {
  592. type: sType,
  593. getValueFromString: fGetValueFromString || SortableTable.idFunction,
  594. compare: fCompareFunction || SortableTable.basicCompare,
  595. getRowValue: fGetRowValue
  596. };
  597. };
  598. // this removes the sort type from all instances of SortableTable
  599. SortableTable.prototype.removeSortType = function (sType) {
  600. delete this._sortTypeInfo[sType];
  601. };
  602. SortableTable.basicCompare = function compare(n1, n2) {
  603. if (n1.value < n2.value)
  604. return -1;
  605. if (n2.value < n1.value)
  606. return 1;
  607. return 0;
  608. };
  609. SortableTable.idFunction = function (x) {
  610. return x;
  611. };
  612. SortableTable.toUpperCase = function (s) {
  613. return s.toUpperCase();
  614. };
  615. SortableTable.toDate = function (s) {
  616. var parts = s.split("-");
  617. var d = new Date(0);
  618. d.setFullYear(parts[0]);
  619. d.setDate(parts[2]);
  620. d.setMonth(parts[1] - 1);
  621. return d.valueOf();
  622. };
  623. // restore the class names
  624. function handleOddEven(st) {
  625. var rows = st.tBody.rows;
  626. var l = rows.length;
  627. for (var i = 0; i < l; i++)
  628. {
  629. rows[i].bgColor = i % 2 ? "#FFFFFF" : "#F0F0F0";
  630. rows[i].onmouseleave = i % 2 ? function() {this.bgColor = "#FFFFFF";} : function() {this.bgColor = "#F0F0F0";};
  631. }
  632. };
  633. // Thanks to Bernhard Wagner for submitting this function
  634. function replace8a8(str) {
  635. //remove commas, if any
  636. str = removeCharacter(str, ',');
  637. str = str.toUpperCase();
  638. var splitstr = "____";
  639. var ar = str.replace(
  640. /(([0-9]*\.)?[0-9]+([eE][-+]?[0-9]+)?)(.*)/,
  641. "$1"+splitstr+"$4").split(splitstr);
  642. var num = Number(ar[0]).valueOf();
  643. var ml = ar[1].replace(/\s*([KMGB])\s*/, "$1");
  644. if (ml == "K")
  645. num *= 1024;
  646. else if(ml == "M")
  647. num *= 1024 * 1024;
  648. else if (ml == "G")
  649. num *= 1024 * 1024 * 1024;
  650. else if (ml == "T")
  651. num *= 1024 * 1024 * 1024 * 1024;
  652. // B and no prefix
  653. return num;
  654. }
  655. function removeCharacter(str, ch) {
  656. var temp = str.split(ch);
  657. str = "";
  658. for (i=0; i<temp.length; i++)
  659. str += temp[i];
  660. return str;
  661. }
  662. function numberWithCommas(str)
  663. {
  664. return Number( removeCharacter(str, ',') ).valueOf();
  665. }
  666. function percentage(str)
  667. {
  668. return Number( removeCharacter(str, '%') ).valueOf();
  669. }
  670. function ipAddress(str)
  671. {
  672. var temp = str.split('.');
  673. var num = 0;
  674. for (i=temp.length-1; i>=0; i--)
  675. num += (256*i)*Number(temp[i]);
  676. return num.valueOf();
  677. }
  678. function timePeriod(s) {
  679. //handle format: [15 days, ]21:52:32.86
  680. //
  681. var i = s.indexOf(' days');
  682. var period = i > 0 ? 86400 * Number(s.substring(0, i)).valueOf() : 0;
  683. i += 7; //skip ' days, '
  684. s = s.substr( i, s.length - i);
  685. var parts = s.split(":");
  686. period += Number(parts[0])*3600 + Number(parts[1])*60 + Number(parts[2]);
  687. return period;
  688. };
  689. // add sort types
  690. SortableTable.prototype.addSortType("Number", Number);
  691. SortableTable.prototype.addSortType("CaseInsensitiveString", SortableTable.toUpperCase);
  692. SortableTable.prototype.addSortType("Date", SortableTable.toDate);
  693. SortableTable.prototype.addSortType("String");
  694. SortableTable.prototype.addSortType("NumberK", replace8a8 );
  695. SortableTable.prototype.addSortType("NumberWithCommas", numberWithCommas );
  696. SortableTable.prototype.addSortType("IP_Address", ipAddress);
  697. SortableTable.prototype.addSortType("TimePeriod", timePeriod);
  698. SortableTable.prototype.addSortType("DateTime", String);
  699. SortableTable.prototype.addSortType("Percentage", percentage);
  700. SortableTable.prototype.addSortType("Html", String, SortableTable.basicCompare, SortableTable.prototype.getHtmlObjRowValue)
  701. SortableTable.prototype.addSortType("iHtml", SortableTable.toUpperCase, SortableTable.basicCompare, SortableTable.prototype.getHtmlObjRowValue)
  702. SortableTable.prototype.addSortType("nHtml", Number, SortableTable.basicCompare, SortableTable.prototype.getHtmlObjRowValue)
  703. // None is a special case
  704. function createTableSorter(tableId, columnSortTypes, dataIslandParent)
  705. {
  706. var hTable = document.getElementById('H.' + tableId);
  707. var bTable = document.getElementById(tableId);
  708. if (!hTable)
  709. hTable = bTable;
  710. return new SortableTable(hTable, bTable, columnSortTypes, dataIslandParent);
  711. }