jquery.tablesorter

Сортировка таблиц: tablesorter для jQuery

当前为 2015-05-21 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/10013/53276/jquerytablesorter.js

  1. /*
  2. *
  3. * TableSorter 2.0 - Client-side table sorting with ease!
  4. * Version 2.0.5b
  5. * @requires jQuery v1.2.3
  6. *
  7. * Copyright (c) 2007 Christian Bach
  8. * Examples and docs at: http://tablesorter.com
  9. * Dual licensed under the MIT and GPL licenses:
  10. * http://www.opensource.org/licenses/mit-license.php
  11. * http://www.gnu.org/licenses/gpl.html
  12. *
  13. */
  14. /**
  15. *
  16. * @description Create a sortable table with multi-column sorting capabilitys
  17. *
  18. * @example $('table').tablesorter();
  19. * @desc Create a simple tablesorter interface.
  20. *
  21. * @example $('table').tablesorter({ sortList:[[0,0],[1,0]] });
  22. * @desc Create a tablesorter interface and sort on the first and secound column column headers.
  23. *
  24. * @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });
  25. *
  26. * @desc Create a tablesorter interface and disableing the first and second column headers.
  27. *
  28. *
  29. * @example $('table').tablesorter({ headers: { 0: {sorter:"integer"}, 1: {sorter:"currency"} } });
  30. *
  31. * @desc Create a tablesorter interface and set a column parser for the first
  32. * and second column.
  33. *
  34. *
  35. * @param Object
  36. * settings An object literal containing key/value pairs to provide
  37. * optional settings.
  38. *
  39. *
  40. * @option String cssHeader (optional) A string of the class name to be appended
  41. * to sortable tr elements in the thead of the table. Default value:
  42. * "header"
  43. *
  44. * @option String cssAsc (optional) A string of the class name to be appended to
  45. * sortable tr elements in the thead on a ascending sort. Default value:
  46. * "headerSortUp"
  47. *
  48. * @option String cssDesc (optional) A string of the class name to be appended
  49. * to sortable tr elements in the thead on a descending sort. Default
  50. * value: "headerSortDown"
  51. *
  52. * @option String sortInitialOrder (optional) A string of the inital sorting
  53. * order can be asc or desc. Default value: "asc"
  54. *
  55. * @option String sortMultisortKey (optional) A string of the multi-column sort
  56. * key. Default value: "shiftKey"
  57. *
  58. * @option String textExtraction (optional) A string of the text-extraction
  59. * method to use. For complex html structures inside td cell set this
  60. * option to "complex", on large tables the complex option can be slow.
  61. * Default value: "simple"
  62. *
  63. * @option Object headers (optional) An array containing the forces sorting
  64. * rules. This option let's you specify a default sorting rule. Default
  65. * value: null
  66. *
  67. * @option Array sortList (optional) An array containing the forces sorting
  68. * rules. This option let's you specify a default sorting rule. Default
  69. * value: null
  70. *
  71. * @option Array sortForce (optional) An array containing forced sorting rules.
  72. * This option let's you specify a default sorting rule, which is
  73. * prepended to user-selected rules. Default value: null
  74. *
  75. * @option Boolean sortLocaleCompare (optional) Boolean flag indicating whatever
  76. * to use String.localeCampare method or not. Default set to true.
  77. *
  78. *
  79. * @option Array sortAppend (optional) An array containing forced sorting rules.
  80. * This option let's you specify a default sorting rule, which is
  81. * appended to user-selected rules. Default value: null
  82. *
  83. * @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter
  84. * should apply fixed widths to the table columns. This is usefull when
  85. * using the pager companion plugin. This options requires the dimension
  86. * jquery plugin. Default value: false
  87. *
  88. * @option Boolean cancelSelection (optional) Boolean flag indicating if
  89. * tablesorter should cancel selection of the table headers text.
  90. * Default value: true
  91. *
  92. * @option Boolean debug (optional) Boolean flag indicating if tablesorter
  93. * should display debuging information usefull for development.
  94. *
  95. * @type jQuery
  96. *
  97. * @name tablesorter
  98. *
  99. * @cat Plugins/Tablesorter
  100. *
  101. * @author Christian Bach/christian.bach@polyester.se
  102. */
  103.  
  104. (function ($) {
  105. $.extend({
  106. tablesorter: new
  107. function () {
  108.  
  109. var parsers = [],
  110. widgets = [];
  111.  
  112. this.defaults = {
  113. cssHeader: "header",
  114. cssAsc: "headerSortUp",
  115. cssDesc: "headerSortDown",
  116. cssChildRow: "expand-child",
  117. sortInitialOrder: "asc",
  118. sortMultiSortKey: "shiftKey",
  119. sortForce: null,
  120. sortAppend: null,
  121. sortLocaleCompare: true,
  122. textExtraction: "simple",
  123. parsers: {}, widgets: [],
  124. widgetZebra: {
  125. css: ["even", "odd"]
  126. }, headers: {}, widthFixed: false,
  127. cancelSelection: true,
  128. sortList: [],
  129. headerList: [],
  130. dateFormat: "us",
  131. decimal: '/\.|\,/g',
  132. onRenderHeader: null,
  133. selectorHeaders: 'thead th',
  134. debug: false
  135. };
  136.  
  137. /* debuging utils */
  138.  
  139. function benchmark(s, d) {
  140. log(s + "," + (new Date().getTime() - d.getTime()) + "ms");
  141. }
  142.  
  143. this.benchmark = benchmark;
  144.  
  145. function log(s) {
  146. if (typeof console != "undefined" && typeof console.debug != "undefined") {
  147. console.log(s);
  148. } else {
  149. alert(s);
  150. }
  151. }
  152.  
  153. /* parsers utils */
  154.  
  155. function buildParserCache(table, $headers) {
  156.  
  157. if (table.config.debug) {
  158. var parsersDebug = "";
  159. }
  160.  
  161. if (table.tBodies.length == 0) return; // In the case of empty tables
  162. var rows = table.tBodies[0].rows;
  163.  
  164. if (rows[0]) {
  165.  
  166. var list = [],
  167. cells = rows[0].cells,
  168. l = cells.length;
  169.  
  170. for (var i = 0; i < l; i++) {
  171.  
  172. var p = false;
  173.  
  174. if ($.metadata && ($($headers[i]).metadata() && $($headers[i]).metadata().sorter)) {
  175.  
  176. p = getParserById($($headers[i]).metadata().sorter);
  177.  
  178. } else if ((table.config.headers[i] && table.config.headers[i].sorter)) {
  179.  
  180. p = getParserById(table.config.headers[i].sorter);
  181. }
  182. if (!p) {
  183.  
  184. p = detectParserForColumn(table, rows, -1, i);
  185. }
  186.  
  187. if (table.config.debug) {
  188. parsersDebug += "column:" + i + " parser:" + p.id + "\n";
  189. }
  190.  
  191. list.push(p);
  192. }
  193. }
  194.  
  195. if (table.config.debug) {
  196. log(parsersDebug);
  197. }
  198.  
  199. return list;
  200. };
  201.  
  202. function detectParserForColumn(table, rows, rowIndex, cellIndex) {
  203. var l = parsers.length,
  204. node = false,
  205. nodeValue = false,
  206. keepLooking = true;
  207. while (nodeValue == '' && keepLooking) {
  208. rowIndex++;
  209. if (rows[rowIndex]) {
  210. node = getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex);
  211. nodeValue = trimAndGetNodeText(table.config, node);
  212. if (table.config.debug) {
  213. log('Checking if value was empty on row:' + rowIndex);
  214. }
  215. } else {
  216. keepLooking = false;
  217. }
  218. }
  219. for (var i = 1; i < l; i++) {
  220. if (parsers[i].is(nodeValue, table, node)) {
  221. return parsers[i];
  222. }
  223. }
  224. // 0 is always the generic parser (text)
  225. return parsers[0];
  226. }
  227.  
  228. function getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex) {
  229. return rows[rowIndex].cells[cellIndex];
  230. }
  231.  
  232. function trimAndGetNodeText(config, node) {
  233. return $.trim(getElementText(config, node));
  234. }
  235.  
  236. function getParserById(name) {
  237. var l = parsers.length;
  238. for (var i = 0; i < l; i++) {
  239. if (parsers[i].id.toLowerCase() == name.toLowerCase()) {
  240. return parsers[i];
  241. }
  242. }
  243. return false;
  244. }
  245.  
  246. /* utils */
  247.  
  248. function buildCache(table) {
  249.  
  250. if (table.config.debug) {
  251. var cacheTime = new Date();
  252. }
  253.  
  254. var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0,
  255. totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0,
  256. parsers = table.config.parsers,
  257. cache = {
  258. row: [],
  259. normalized: []
  260. };
  261.  
  262. for (var i = 0; i < totalRows; ++i) {
  263.  
  264. /** Add the table data to main data array */
  265. var c = $(table.tBodies[0].rows[i]),
  266. cols = [];
  267.  
  268. // if this is a child row, add it to the last row's children and
  269. // continue to the next row
  270. if (c.hasClass(table.config.cssChildRow)) {
  271. cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c);
  272. // go to the next for loop
  273. continue;
  274. }
  275.  
  276. cache.row.push(c);
  277.  
  278. for (var j = 0; j < totalCells; ++j) {
  279. cols.push(parsers[j].format(getElementText(table.config, c[0].cells[j]), table, c[0].cells[j]));
  280. }
  281.  
  282. cols.push(cache.normalized.length); // add position for rowCache
  283. cache.normalized.push(cols);
  284. cols = null;
  285. };
  286.  
  287. if (table.config.debug) {
  288. benchmark("Building cache for " + totalRows + " rows:", cacheTime);
  289. }
  290.  
  291. return cache;
  292. };
  293.  
  294. function getElementText(config, node) {
  295.  
  296. var text = "";
  297.  
  298. if (!node) return "";
  299.  
  300. if (!config.supportsTextContent) config.supportsTextContent = node.textContent || false;
  301.  
  302. if (config.textExtraction == "simple") {
  303. if (config.supportsTextContent) {
  304. text = node.textContent;
  305. } else {
  306. if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
  307. text = node.childNodes[0].innerHTML;
  308. } else {
  309. text = node.innerHTML;
  310. }
  311. }
  312. } else {
  313. if (typeof(config.textExtraction) == "function") {
  314. text = config.textExtraction(node);
  315. } else {
  316. text = $(node).text();
  317. }
  318. }
  319. return text;
  320. }
  321.  
  322. function appendToTable(table, cache) {
  323.  
  324. if (table.config.debug) {
  325. var appendTime = new Date()
  326. }
  327.  
  328. var c = cache,
  329. r = c.row,
  330. n = c.normalized,
  331. totalRows = n.length,
  332. checkCell = (n[0].length - 1),
  333. tableBody = $(table.tBodies[0]),
  334. rows = [];
  335.  
  336.  
  337. for (var i = 0; i < totalRows; i++) {
  338. var pos = n[i][checkCell];
  339.  
  340. rows.push(r[pos]);
  341.  
  342. if (!table.config.appender) {
  343.  
  344. //var o = ;
  345. var l = r[pos].length;
  346. for (var j = 0; j < l; j++) {
  347. tableBody[0].appendChild(r[pos][j]);
  348. }
  349.  
  350. //
  351. }
  352. }
  353.  
  354.  
  355.  
  356. if (table.config.appender) {
  357.  
  358. table.config.appender(table, rows);
  359. }
  360.  
  361. rows = null;
  362.  
  363. if (table.config.debug) {
  364. benchmark("Rebuilt table:", appendTime);
  365. }
  366.  
  367. // apply table widgets
  368. applyWidget(table);
  369.  
  370. // trigger sortend
  371. setTimeout(function () {
  372. $(table).trigger("sortEnd");
  373. }, 0);
  374.  
  375. };
  376.  
  377. function buildHeaders(table) {
  378.  
  379. if (table.config.debug) {
  380. var time = new Date();
  381. }
  382.  
  383. var meta = ($.metadata) ? true : false;
  384. var header_index = computeTableHeaderCellIndexes(table);
  385.  
  386. $tableHeaders = $(table.config.selectorHeaders, table).each(function (index) {
  387.  
  388. this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex];
  389. // this.column = index;
  390. this.order = formatSortingOrder(table.config.sortInitialOrder);
  391. this.count = this.order;
  392.  
  393. if (checkHeaderMetadata(this) || checkHeaderOptions(table, index)) this.sortDisabled = true;
  394. if (checkHeaderOptionsSortingLocked(table, index)) this.order = this.lockedOrder = checkHeaderOptionsSortingLocked(table, index);
  395.  
  396. if (!this.sortDisabled) {
  397. var $th = $(this).addClass(table.config.cssHeader);
  398. if (table.config.onRenderHeader) table.config.onRenderHeader.apply($th);
  399. }
  400.  
  401. // add cell to headerList
  402. table.config.headerList[index] = this;
  403. });
  404.  
  405. if (table.config.debug) {
  406. benchmark("Built headers:", time);
  407. log($tableHeaders);
  408. }
  409.  
  410. return $tableHeaders;
  411.  
  412. };
  413.  
  414. // from:
  415. // http://www.javascripttoolbox.com/lib/table/examples.php
  416. // http://www.javascripttoolbox.com/temp/table_cellindex.html
  417.  
  418.  
  419. function computeTableHeaderCellIndexes(t) {
  420. var matrix = [];
  421. var lookup = {};
  422. var thead = t.getElementsByTagName('THEAD')[0];
  423. var trs = thead.getElementsByTagName('TR');
  424.  
  425. for (var i = 0; i < trs.length; i++) {
  426. var cells = trs[i].cells;
  427. for (var j = 0; j < cells.length; j++) {
  428. var c = cells[j];
  429.  
  430. var rowIndex = c.parentNode.rowIndex;
  431. var cellId = rowIndex + "-" + c.cellIndex;
  432. var rowSpan = c.rowSpan || 1;
  433. var colSpan = c.colSpan || 1
  434. var firstAvailCol;
  435. if (typeof(matrix[rowIndex]) == "undefined") {
  436. matrix[rowIndex] = [];
  437. }
  438. // Find first available column in the first row
  439. for (var k = 0; k < matrix[rowIndex].length + 1; k++) {
  440. if (typeof(matrix[rowIndex][k]) == "undefined") {
  441. firstAvailCol = k;
  442. break;
  443. }
  444. }
  445. lookup[cellId] = firstAvailCol;
  446. for (var k = rowIndex; k < rowIndex + rowSpan; k++) {
  447. if (typeof(matrix[k]) == "undefined") {
  448. matrix[k] = [];
  449. }
  450. var matrixrow = matrix[k];
  451. for (var l = firstAvailCol; l < firstAvailCol + colSpan; l++) {
  452. matrixrow[l] = "x";
  453. }
  454. }
  455. }
  456. }
  457. return lookup;
  458. }
  459.  
  460. function checkCellColSpan(table, rows, row) {
  461. var arr = [],
  462. r = table.tHead.rows,
  463. c = r[row].cells;
  464.  
  465. for (var i = 0; i < c.length; i++) {
  466. var cell = c[i];
  467.  
  468. if (cell.colSpan > 1) {
  469. arr = arr.concat(checkCellColSpan(table, headerArr, row++));
  470. } else {
  471. if (table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row + 1])) {
  472. arr.push(cell);
  473. }
  474. // headerArr[row] = (i+row);
  475. }
  476. }
  477. return arr;
  478. };
  479.  
  480. function checkHeaderMetadata(cell) {
  481. if (($.metadata) && ($(cell).metadata().sorter === false)) {
  482. return true;
  483. };
  484. return false;
  485. }
  486.  
  487. function checkHeaderOptions(table, i) {
  488. if ((table.config.headers[i]) && (table.config.headers[i].sorter === false)) {
  489. return true;
  490. };
  491. return false;
  492. }
  493. function checkHeaderOptionsSortingLocked(table, i) {
  494. if ((table.config.headers[i]) && (table.config.headers[i].lockedOrder)) return table.config.headers[i].lockedOrder;
  495. return false;
  496. }
  497. function applyWidget(table) {
  498. var c = table.config.widgets;
  499. var l = c.length;
  500. for (var i = 0; i < l; i++) {
  501.  
  502. getWidgetById(c[i]).format(table);
  503. }
  504.  
  505. }
  506.  
  507. function getWidgetById(name) {
  508. var l = widgets.length;
  509. for (var i = 0; i < l; i++) {
  510. if (widgets[i].id.toLowerCase() == name.toLowerCase()) {
  511. return widgets[i];
  512. }
  513. }
  514. };
  515.  
  516. function formatSortingOrder(v) {
  517. if (typeof(v) != "Number") {
  518. return (v.toLowerCase() == "desc") ? 1 : 0;
  519. } else {
  520. return (v == 1) ? 1 : 0;
  521. }
  522. }
  523.  
  524. function isValueInArray(v, a) {
  525. var l = a.length;
  526. for (var i = 0; i < l; i++) {
  527. if (a[i][0] == v) {
  528. return true;
  529. }
  530. }
  531. return false;
  532. }
  533.  
  534. function setHeadersCss(table, $headers, list, css) {
  535. // remove all header information
  536. $headers.removeClass(css[0]).removeClass(css[1]);
  537.  
  538. var h = [];
  539. $headers.each(function (offset) {
  540. if (!this.sortDisabled) {
  541. h[this.column] = $(this);
  542. }
  543. });
  544.  
  545. var l = list.length;
  546. for (var i = 0; i < l; i++) {
  547. h[list[i][0]].addClass(css[list[i][1]]);
  548. }
  549. }
  550.  
  551. function fixColumnWidth(table, $headers) {
  552. var c = table.config;
  553. if (c.widthFixed) {
  554. var colgroup = $('<colgroup>');
  555. $("tr:first td", table.tBodies[0]).each(function () {
  556. colgroup.append($('<col>').css('width', $(this).width()));
  557. });
  558. $(table).prepend(colgroup);
  559. };
  560. }
  561.  
  562. function updateHeaderSortCount(table, sortList) {
  563. var c = table.config,
  564. l = sortList.length;
  565. for (var i = 0; i < l; i++) {
  566. var s = sortList[i],
  567. o = c.headerList[s[0]];
  568. o.count = s[1];
  569. o.count++;
  570. }
  571. }
  572.  
  573. /* sorting methods */
  574.  
  575. function multisort(table, sortList, cache) {
  576.  
  577. if (table.config.debug) {
  578. var sortTime = new Date();
  579. }
  580.  
  581. var dynamicExp = "var sortWrapper = function(a,b) {",
  582. l = sortList.length;
  583.  
  584. // TODO: inline functions.
  585. for (var i = 0; i < l; i++) {
  586.  
  587. var c = sortList[i][0];
  588. var order = sortList[i][1];
  589. // var s = (getCachedSortType(table.config.parsers,c) == "text") ?
  590. // ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ?
  591. // "sortNumeric" : "sortNumericDesc");
  592. // var s = (table.config.parsers[c].type == "text") ? ((order == 0)
  593. // ? makeSortText(c) : makeSortTextDesc(c)) : ((order == 0) ?
  594. // makeSortNumeric(c) : makeSortNumericDesc(c));
  595. var s = (table.config.parsers[c].type == "text") ? ((order == 0) ? makeSortFunction("text", "asc", c) : makeSortFunction("text", "desc", c)) : ((order == 0) ? makeSortFunction("numeric", "asc", c) : makeSortFunction("numeric", "desc", c));
  596. var e = "e" + i;
  597.  
  598. dynamicExp += "var " + e + " = " + s; // + "(a[" + c + "],b[" + c
  599. // + "]); ";
  600. dynamicExp += "if(" + e + ") { return " + e + "; } ";
  601. dynamicExp += "else { ";
  602.  
  603. }
  604.  
  605. // if value is the same keep orignal order
  606. var orgOrderCol = cache.normalized[0].length - 1;
  607. dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];";
  608.  
  609. for (var i = 0; i < l; i++) {
  610. dynamicExp += "}; ";
  611. }
  612.  
  613. dynamicExp += "return 0; ";
  614. dynamicExp += "}; ";
  615.  
  616. if (table.config.debug) {
  617. benchmark("Evaling expression:" + dynamicExp, new Date());
  618. }
  619.  
  620. eval(dynamicExp);
  621.  
  622. cache.normalized.sort(sortWrapper);
  623.  
  624. if (table.config.debug) {
  625. benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime);
  626. }
  627.  
  628. return cache;
  629. };
  630.  
  631. function makeSortFunction(type, direction, index) {
  632. var a = "a[" + index + "]",
  633. b = "b[" + index + "]";
  634. if (type == 'text' && direction == 'asc') {
  635. return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + a + " < " + b + ") ? -1 : 1 )));";
  636. } else if (type == 'text' && direction == 'desc') {
  637. return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + b + " < " + a + ") ? -1 : 1 )));";
  638. } else if (type == 'numeric' && direction == 'asc') {
  639. return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + a + " - " + b + "));";
  640. } else if (type == 'numeric' && direction == 'desc') {
  641. return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + b + " - " + a + "));";
  642. }
  643. };
  644.  
  645. function makeSortText(i) {
  646. return "((a[" + i + "] < b[" + i + "]) ? -1 : ((a[" + i + "] > b[" + i + "]) ? 1 : 0));";
  647. };
  648.  
  649. function makeSortTextDesc(i) {
  650. return "((b[" + i + "] < a[" + i + "]) ? -1 : ((b[" + i + "] > a[" + i + "]) ? 1 : 0));";
  651. };
  652.  
  653. function makeSortNumeric(i) {
  654. return "a[" + i + "]-b[" + i + "];";
  655. };
  656.  
  657. function makeSortNumericDesc(i) {
  658. return "b[" + i + "]-a[" + i + "];";
  659. };
  660.  
  661. function sortText(a, b) {
  662. if (table.config.sortLocaleCompare) return a.localeCompare(b);
  663. return ((a < b) ? -1 : ((a > b) ? 1 : 0));
  664. };
  665.  
  666. function sortTextDesc(a, b) {
  667. if (table.config.sortLocaleCompare) return b.localeCompare(a);
  668. return ((b < a) ? -1 : ((b > a) ? 1 : 0));
  669. };
  670.  
  671. function sortNumeric(a, b) {
  672. return a - b;
  673. };
  674.  
  675. function sortNumericDesc(a, b) {
  676. return b - a;
  677. };
  678.  
  679. function getCachedSortType(parsers, i) {
  680. return parsers[i].type;
  681. }; /* public methods */
  682. this.construct = function (settings) {
  683. return this.each(function () {
  684. // if no thead or tbody quit.
  685. if (!this.tHead || !this.tBodies) return;
  686. // declare
  687. var $this, $document, $headers, cache, config, shiftDown = 0,
  688. sortOrder;
  689. // new blank config object
  690. this.config = {};
  691. // merge and extend.
  692. config = $.extend(this.config, $.tablesorter.defaults, settings);
  693. // store common expression for speed
  694. $this = $(this);
  695. // save the settings where they read
  696. $.data(this, "tablesorter", config);
  697. // build headers
  698. $headers = buildHeaders(this);
  699. // try to auto detect column type, and store in tables config
  700. this.config.parsers = buildParserCache(this, $headers);
  701. // build the cache for the tbody cells
  702. cache = buildCache(this);
  703. // get the css class names, could be done else where.
  704. var sortCSS = [config.cssDesc, config.cssAsc];
  705. // fixate columns if the users supplies the fixedWidth option
  706. fixColumnWidth(this);
  707. // apply event handling to headers
  708. // this is to big, perhaps break it out?
  709. $headers.click(
  710.  
  711. function (e) {
  712. var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0;
  713. if (!this.sortDisabled && totalRows > 0) {
  714. // Only call sortStart if sorting is
  715. // enabled.
  716. $this.trigger("sortStart");
  717. // store exp, for speed
  718. var $cell = $(this);
  719. // get current column index
  720. var i = this.column;
  721. // get current column sort order
  722. this.order = this.count++ % 2;
  723. // always sort on the locked order.
  724. if(this.lockedOrder) this.order = this.lockedOrder;
  725. // user only whants to sort on one
  726. // column
  727. if (!e[config.sortMultiSortKey]) {
  728. // flush the sort list
  729. config.sortList = [];
  730. if (config.sortForce != null) {
  731. var a = config.sortForce;
  732. for (var j = 0; j < a.length; j++) {
  733. if (a[j][0] != i) {
  734. config.sortList.push(a[j]);
  735. }
  736. }
  737. }
  738. // add column to sort list
  739. config.sortList.push([i, this.order]);
  740. // multi column sorting
  741. } else {
  742. // the user has clicked on an all
  743. // ready sortet column.
  744. if (isValueInArray(i, config.sortList)) {
  745. // revers the sorting direction
  746. // for all tables.
  747. for (var j = 0; j < config.sortList.length; j++) {
  748. var s = config.sortList[j],
  749. o = config.headerList[s[0]];
  750. if (s[0] == i) {
  751. o.count = s[1];
  752. o.count++;
  753. s[1] = o.count % 2;
  754. }
  755. }
  756. } else {
  757. // add column to sort list array
  758. config.sortList.push([i, this.order]);
  759. }
  760. };
  761. setTimeout(function () {
  762. // set css for headers
  763. setHeadersCss($this[0], $headers, config.sortList, sortCSS);
  764. appendToTable(
  765. $this[0], multisort(
  766. $this[0], config.sortList, cache)
  767. );
  768. }, 1);
  769. // stop normal event by returning false
  770. return false;
  771. }
  772. // cancel selection
  773. }).mousedown(function () {
  774. if (config.cancelSelection) {
  775. this.onselectstart = function () {
  776. return false
  777. };
  778. return false;
  779. }
  780. });
  781. // apply easy methods that trigger binded events
  782. $this.bind("update", function () {
  783. var me = this;
  784. setTimeout(function () {
  785. // rebuild parsers.
  786. me.config.parsers = buildParserCache(
  787. me, $headers);
  788. // rebuild the cache map
  789. cache = buildCache(me);
  790. }, 1);
  791. }).bind("updateCell", function (e, cell) {
  792. var config = this.config;
  793. // get position from the dom.
  794. var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex];
  795. // update cache
  796. cache.normalized[pos[0]][pos[1]] = config.parsers[pos[1]].format(
  797. getElementText(config, cell), cell);
  798. }).bind("sorton", function (e, list) {
  799. $(this).trigger("sortStart");
  800. config.sortList = list;
  801. // update and store the sortlist
  802. var sortList = config.sortList;
  803. // update header count index
  804. updateHeaderSortCount(this, sortList);
  805. // set css for headers
  806. setHeadersCss(this, $headers, sortList, sortCSS);
  807. // sort the table and append it to the dom
  808. appendToTable(this, multisort(this, sortList, cache));
  809. }).bind("appendCache", function () {
  810. appendToTable(this, cache);
  811. }).bind("applyWidgetId", function (e, id) {
  812. getWidgetById(id).format(this);
  813. }).bind("applyWidgets", function () {
  814. // apply widgets
  815. applyWidget(this);
  816. });
  817. if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) {
  818. config.sortList = $(this).metadata().sortlist;
  819. }
  820. // if user has supplied a sort list to constructor.
  821. if (config.sortList.length > 0) {
  822. $this.trigger("sorton", [config.sortList]);
  823. }
  824. // apply widgets
  825. applyWidget(this);
  826. });
  827. };
  828. this.addParser = function (parser) {
  829. var l = parsers.length,
  830. a = true;
  831. for (var i = 0; i < l; i++) {
  832. if (parsers[i].id.toLowerCase() == parser.id.toLowerCase()) {
  833. a = false;
  834. }
  835. }
  836. if (a) {
  837. parsers.push(parser);
  838. };
  839. };
  840. this.addWidget = function (widget) {
  841. widgets.push(widget);
  842. };
  843. this.formatFloat = function (s) {
  844. var i = parseFloat(s);
  845. return (isNaN(i)) ? 0 : i;
  846. };
  847. this.formatInt = function (s) {
  848. var i = parseInt(s);
  849. return (isNaN(i)) ? 0 : i;
  850. };
  851. this.isDigit = function (s, config) {
  852. // replace all an wanted chars and match.
  853. return /^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g, '')));
  854. };
  855. this.clearTableBody = function (table) {
  856. if ($.browser.msie) {
  857. function empty() {
  858. while (this.firstChild)
  859. this.removeChild(this.firstChild);
  860. }
  861. empty.apply(table.tBodies[0]);
  862. } else {
  863. table.tBodies[0].innerHTML = "";
  864. }
  865. };
  866. }
  867. });
  868.  
  869. // extend plugin scope
  870. $.fn.extend({
  871. tablesorter: $.tablesorter.construct
  872. });
  873.  
  874. // make shortcut
  875. var ts = $.tablesorter;
  876.  
  877. // add default parsers
  878. ts.addParser({
  879. id: "text",
  880. is: function (s) {
  881. return true;
  882. }, format: function (s) {
  883. return $.trim(s.toLocaleLowerCase());
  884. }, type: "text"
  885. });
  886.  
  887. ts.addParser({
  888. id: "digit",
  889. is: function (s, table) {
  890. var c = table.config;
  891. return $.tablesorter.isDigit(s, c);
  892. }, format: function (s) {
  893. return $.tablesorter.formatFloat(s);
  894. }, type: "numeric"
  895. });
  896.  
  897. ts.addParser({
  898. id: "currency",
  899. is: function (s) {
  900. return /^[£$€?.]/.test(s);
  901. }, format: function (s) {
  902. return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g), ""));
  903. }, type: "numeric"
  904. });
  905.  
  906. ts.addParser({
  907. id: "ipAddress",
  908. is: function (s) {
  909. return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);
  910. }, format: function (s) {
  911. var a = s.split("."),
  912. r = "",
  913. l = a.length;
  914. for (var i = 0; i < l; i++) {
  915. var item = a[i];
  916. if (item.length == 2) {
  917. r += "0" + item;
  918. } else {
  919. r += item;
  920. }
  921. }
  922. return $.tablesorter.formatFloat(r);
  923. }, type: "numeric"
  924. });
  925.  
  926. ts.addParser({
  927. id: "url",
  928. is: function (s) {
  929. return /^(https?|ftp|file):\/\/$/.test(s);
  930. }, format: function (s) {
  931. return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//), ''));
  932. }, type: "text"
  933. });
  934.  
  935. ts.addParser({
  936. id: "isoDate",
  937. is: function (s) {
  938. return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);
  939. }, format: function (s) {
  940. return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(
  941. new RegExp(/-/g), "/")).getTime() : "0");
  942. }, type: "numeric"
  943. });
  944.  
  945. ts.addParser({
  946. id: "percent",
  947. is: function (s) {
  948. return /\%$/.test($.trim(s));
  949. }, format: function (s) {
  950. return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g), ""));
  951. }, type: "numeric"
  952. });
  953.  
  954. ts.addParser({
  955. id: "usLongDate",
  956. is: function (s) {
  957. return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));
  958. }, format: function (s) {
  959. return $.tablesorter.formatFloat(new Date(s).getTime());
  960. }, type: "numeric"
  961. });
  962.  
  963. ts.addParser({
  964. id: "shortDate",
  965. is: function (s) {
  966. return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);
  967. }, format: function (s, table) {
  968. var c = table.config;
  969. s = s.replace(/\-/g, "/");
  970. if (c.dateFormat == "us") {
  971. // reformat the string in ISO format
  972. s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2");
  973. } else if (c.dateFormat == "uk") {
  974. // reformat the string in ISO format
  975. s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1");
  976. } else if (c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") {
  977. s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3");
  978. }
  979. return $.tablesorter.formatFloat(new Date(s).getTime());
  980. }, type: "numeric"
  981. });
  982. ts.addParser({
  983. id: "time",
  984. is: function (s) {
  985. return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);
  986. }, format: function (s) {
  987. return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime());
  988. }, type: "numeric"
  989. });
  990. ts.addParser({
  991. id: "metadata",
  992. is: function (s) {
  993. return false;
  994. }, format: function (s, table, cell) {
  995. var c = table.config,
  996. p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
  997. return $(cell).metadata()[p];
  998. }, type: "numeric"
  999. });
  1000. // add default widgets
  1001. ts.addWidget({
  1002. id: "zebra",
  1003. format: function (table) {
  1004. if (table.config.debug) {
  1005. var time = new Date();
  1006. }
  1007. var $tr, row = -1,
  1008. odd;
  1009. // loop through the visible rows
  1010. $("tr:visible", table.tBodies[0]).each(function (i) {
  1011. $tr = $(this);
  1012. // style children rows the same way the parent
  1013. // row was styled
  1014. if (!$tr.hasClass(table.config.cssChildRow)) row++;
  1015. odd = (row % 2 == 0);
  1016. $tr.removeClass(
  1017. table.config.widgetZebra.css[odd ? 0 : 1]).addClass(
  1018. table.config.widgetZebra.css[odd ? 1 : 0])
  1019. });
  1020. if (table.config.debug) {
  1021. $.tablesorter.benchmark("Applying Zebra widget", time);
  1022. }
  1023. }
  1024. });
  1025. })(jQuery);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址