From 42fb4fcaa4c9ee1410c1950a5bfc79ed7a87b5d8 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 22 May 2013 17:44:10 -0700 Subject: [PATCH] Removed tablesorter --- UI/Content/tablesorter.bootstrap.css | 136 -- UI/Content/tablesorter.pager.css | 17 - UI/Index.html | 6 - .../jquery.tablesorter.bootstrap.js | 981 ------------ UI/JsLibraries/jquery.tablesorter.js | 1383 ----------------- UI/JsLibraries/jquery.tablesorter.pager.js | 575 ------- UI/Mixins/tablesorter.extensions.js | 50 - 7 files changed, 3148 deletions(-) delete mode 100644 UI/Content/tablesorter.bootstrap.css delete mode 100644 UI/Content/tablesorter.pager.css delete mode 100644 UI/JsLibraries/jquery.tablesorter.bootstrap.js delete mode 100644 UI/JsLibraries/jquery.tablesorter.js delete mode 100644 UI/JsLibraries/jquery.tablesorter.pager.js delete mode 100644 UI/Mixins/tablesorter.extensions.js diff --git a/UI/Content/tablesorter.bootstrap.css b/UI/Content/tablesorter.bootstrap.css deleted file mode 100644 index 5f199f591..000000000 --- a/UI/Content/tablesorter.bootstrap.css +++ /dev/null @@ -1,136 +0,0 @@ -/************* - Bootstrap theme - *************/ -/* jQuery Bootstrap Theme */ -.tablesorter-bootstrap { - width: 100%; -} - -.tablesorter-bootstrap .tablesorter-header, -.tablesorter-bootstrap tfoot th, -.tablesorter-bootstrap tfoot td { - font: bold 14px/20px Arial, Sans-serif; - position: relative; - padding: 8px; - margin: 0 0 18px; - list-style: none; - background-color: #fbfbfb; - background-image: -moz-linear-gradient(top, white, #efefef); - background-image: -ms-linear-gradient(top, white, #efefef); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(white), to(#efefef)); - background-image: -webkit-linear-gradient(top, white, #efefef); - background-image: -o-linear-gradient(top, white, #efefef); - background-image: linear-gradient(to bottom, white, #efefef); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#efefef', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 1px 0 white; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 white; -} - -.tablesorter-bootstrap .tablesorter-header { - cursor: pointer; -} - -.tablesorter-bootstrap .tablesorter-header-inner { - position: relative; - padding: 4px 18px 4px 4px; -} - -/* bootstrap uses for icons */ -.tablesorter-bootstrap .tablesorter-header i { - position: absolute; - right: 2px; - top: 50%; - margin-top: -7px; /* half the icon height; older IE doesn't like this */ - width: 14px; - height: 14px; - background-repeat: no-repeat; - line-height: 14px; - display: inline-block; -} - -.tablesorter-bootstrap .bootstrap-icon-unsorted { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAOCAYAAAD5YeaVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWVJREFUeNqUUL9Lw2AUTGP8mqGlpBQkNeCSRcckEBcHq1jImMElToKuDvpHFMGhU0BQcHBwLji6CE1B4uB/INQsDi4d2jQ/fPeZxo764OV6915f7lLJ81xot9tCURXqdVEUr7IsO6ffH9Q5BlEUCaLwWxWqTcbYnaIoh0Dw4gAvcWlxq1qt9hqNxg6hUGAP+uIPUrGs0qXLer2+v/pTX6QpxLtkc2U2m53ACb8sSdIDXerSEms2m6+DweAICA4d89KGbduf9MpEVdXQ9/2LVqv1CASHjjn3iq/x1xKFfxQPqGnada1W86bT6SiO42OS3qk3KPStLMvbk8nkfjwen/LLuq6blFymMB0KdUPSGhAcOualjX6/f0bCiC7NaWGPQr0BwaFjzn0gYJqmLAiCA8/zni3LmhuGkQPBoWPOPwQeaPIqD4fDruu6L6Zp5kBw6IudchmdJAkLw3DXcZwnIPjy/FuAAQCiqqWWCAFKcwAAAABJRU5ErkJggg==); -} - -/* since bootstrap (table-striped) uses nth-child(), we just use this to add a zebra stripe color */ -.tablesorter-bootstrap tr.odd td { - background-color: #f9f9f9; -} - -.tablesorter-bootstrap tbody > .odd:hover > td, -.tablesorter-bootstrap tbody > .even:hover > td { - background-color: #f5f5f5; -} - -.tablesorter-bootstrap tr.even td { - background-color: #ffffff; -} - -/* processing icon */ -.tablesorter-bootstrap .tablesorter-processing { - background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs='); - position: absolute; - z-index: 1000; -} - -/* filter widget */ -.tablesorter-bootstrap .tablesorter-filter-row .tablesorter-filter { - width: 98%; - height: inherit; - margin: 0 auto; - padding: 4px 6px; - background-color: #ffffff; - color: #333333; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: height 0.1s ease; - -moz-transition: height 0.1s ease; - -o-transition: height 0.1s ease; - transition: height 0.1s ease; -} - -.tablesorter-bootstrap .tablesorter-filter-row td { - background: #eeeeee; - line-height: normal; - text-align: center; - padding: 4px 6px; - vertical-align: middle; - -webkit-transition: line-height 0.1s ease; - -moz-transition: line-height 0.1s ease; - -o-transition: line-height 0.1s ease; - transition: line-height 0.1s ease; -} - -/* hidden filter row */ -.tablesorter-bootstrap .tablesorter-filter-row.hideme td { - padding: 2px; /* change this to modify the thickness of the closed border row */ - margin: 0; - line-height: 0; -} - -.tablesorter-bootstrap .tablesorter-filter-row.hideme .tablesorter-filter { - height: 1px; - min-height: 0; - border: 0; - padding: 0; - margin: 0; - /* don't use visibility: hidden because it disables tabbing */ - opacity: 0; - filter: alpha(opacity=0); -} - -/* pager plugin */ -.tablesorter-bootstrap .tablesorter-pager select { - padding: 4px 6px; -} - -.tablesorter-bootstrap .tablesorter-pager .pagedisplay { - border: 0; -} - -th { - background-repeat: no-repeat; -} diff --git a/UI/Content/tablesorter.pager.css b/UI/Content/tablesorter.pager.css deleted file mode 100644 index 3d94e9a02..000000000 --- a/UI/Content/tablesorter.pager.css +++ /dev/null @@ -1,17 +0,0 @@ -/*** css used when "updateArrows" option is true ***/ -/* the pager itself gets a disabled class when the number of rows is less than the size */ -.tablesorter-pager.disabled { - display: none; -} - -/* hide or fade out pager arrows when the first or last row is visible */ -.tablesorter-pager .disabled { - /* visibility: hidden */ - opacity: 0.5; - filter: alpha(opacity=50); - cursor: default; -} - -.pagedisplay-container { - padding-top: 5px; -} \ No newline at end of file diff --git a/UI/Index.html b/UI/Index.html index 82b50d3e7..f27193482 100644 --- a/UI/Index.html +++ b/UI/Index.html @@ -12,8 +12,6 @@ - - @@ -92,9 +90,6 @@ - - - @@ -105,7 +100,6 @@ - diff --git a/UI/JsLibraries/jquery.tablesorter.bootstrap.js b/UI/JsLibraries/jquery.tablesorter.bootstrap.js deleted file mode 100644 index 5dae16a44..000000000 --- a/UI/JsLibraries/jquery.tablesorter.bootstrap.js +++ /dev/null @@ -1,981 +0,0 @@ -/*! tableSorter 2.4+ widgets - updated 1/29/2013 - * - * Column Styles - * Column Filters - * Column Resizing - * Sticky Header - * UI Theme (generalized) - * Save Sort - * ["zebra", "uitheme", "stickyHeaders", "filter", "columns"] - */ -/*jshint browser:true, jquery:true, unused:false, loopfunc:true */ -/*global jQuery: false, localStorage: false, navigator: false */ -;(function($){ - "use strict"; - $.tablesorter = $.tablesorter || {}; - - $.tablesorter.themes = { - "bootstrap" : { - table : 'table table-bordered table-striped', - header : 'bootstrap-header', // give the header a gradient background - footerRow : '', - footerCells: '', - icons : '', // add "icon-white" to make them white; this icon class is added to the in the header - sortNone : 'bootstrap-icon-unsorted', - sortAsc : 'icon-chevron-up', - sortDesc : 'icon-chevron-down', - active : '', // applied when column is sorted - hover : '', // use custom css here - bootstrap class may not override it - filterRow : '', // filter row class - even : '', // even row zebra striping - odd : '' // odd row zebra striping - }, - "jui" : { - table : 'ui-widget ui-widget-content ui-corner-all', // table classes - header : 'ui-widget-header ui-corner-all ui-state-default', // header classes - footerRow : '', - footerCells: '', - icons : 'ui-icon', // icon class added to the in the header - sortNone : 'ui-icon-carat-2-n-s', - sortAsc : 'ui-icon-carat-1-n', - sortDesc : 'ui-icon-carat-1-s', - active : 'ui-state-active', // applied when column is sorted - hover : 'ui-state-hover', // hover class - filterRow : '', - even : 'ui-widget-content', // even row zebra striping - odd : 'ui-state-default' // odd row zebra striping - } - }; - - // *** Store data in local storage, with a cookie fallback *** - /* IE7 needs JSON library for JSON.stringify - (http://caniuse.com/#search=json) - if you need it, then include https://github.com/douglascrockford/JSON-js - - $.parseJSON is not available is jQuery versions older than 1.4.1, using older - versions will only allow storing information for one page at a time - - // *** Save data (JSON format only) *** - // val must be valid JSON... use http://jsonlint.com/ to ensure it is valid - var val = { "mywidget" : "data1" }; // valid JSON uses double quotes - // $.tablesorter.storage(table, key, val); - $.tablesorter.storage(table, 'tablesorter-mywidget', val); - - // *** Get data: $.tablesorter.storage(table, key); *** - v = $.tablesorter.storage(table, 'tablesorter-mywidget'); - // val may be empty, so also check for your data - val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : ''; - alert(val); // "data1" if saved, or "" if not - */ - $.tablesorter.storage = function(table, key, val){ - var d, k, ls = false, v = {}, - id = table.id || $('.tablesorter').index( $(table) ), - url = window.location.pathname; - try { ls = !!(localStorage.getItem); } catch(e) {} - // *** get val *** - if ($.parseJSON){ - if (ls){ - v = $.parseJSON(localStorage[key]) || {}; - } else { - k = document.cookie.split(/[;\s|=]/); // cookie - d = $.inArray(key, k) + 1; // add one to get from the key to the value - v = (d !== 0) ? $.parseJSON(k[d]) || {} : {}; - } - } - // allow val to be an empty string to - if ((val || val === '') && window.JSON && JSON.hasOwnProperty('stringify')){ - // add unique identifiers = url pathname > table ID/index on page > data - if (!v[url]) { - v[url] = {}; - } - v[url][id] = val; - // *** set val *** - if (ls){ - localStorage[key] = JSON.stringify(v); - } else { - d = new Date(); - d.setTime(d.getTime() + (31536e+6)); // 365 days - document.cookie = key + '=' + (JSON.stringify(v)).replace(/\"/g,'\"') + '; expires=' + d.toGMTString() + '; path=/'; - } - } else { - return v && v[url] ? v[url][id] : {}; - } - }; - - // Widget: General UI theme - // "uitheme" option in "widgetOptions" - // ************************** - $.tablesorter.addWidget({ - id: "uitheme", - format: function(table){ - var time, klass, $el, $tar, - t = $.tablesorter.themes, - $t = $(table), - c = table.config, - wo = c.widgetOptions, - theme = c.theme !== 'default' ? c.theme : wo.uitheme || 'jui', // default uitheme is 'jui' - o = t[ t[theme] ? theme : t[wo.uitheme] ? wo.uitheme : 'jui'], - $h = $(c.headerList), - sh = 'tr.' + (wo.stickyHeaders || 'tablesorter-stickyHeader'), - rmv = o.sortNone + ' ' + o.sortDesc + ' ' + o.sortAsc; - if (c.debug) { time = new Date(); } - if (!$t.hasClass('tablesorter-' + theme) || c.theme === theme || !table.hasInitialized){ - // update zebra stripes - if (o.even !== '') { wo.zebra[0] += ' ' + o.even; } - if (o.odd !== '') { wo.zebra[1] += ' ' + o.odd; } - // add table/footer class names - t = $t - // remove other selected themes; use widgetOptions.theme_remove - .removeClass( c.theme === '' ? '' : 'tablesorter-' + c.theme ) - .addClass('tablesorter-' + theme + ' ' + o.table) // add theme widget class name - .find('tfoot'); - if (t.length) { - t - .find('tr').addClass(o.footerRow) - .children('th, td').addClass(o.footerCells); - } - // update header classes - $h - .addClass(o.header) - .filter(':not(.sorter-false)') - .hover(function(){ - $(this).addClass(o.hover); - }, function(){ - $(this).removeClass(o.hover); - }); - if (!$h.find('.tablesorter-wrapper').length) { - // Firefox needs this inner div to position the resizer correctly - $h.wrapInner('
'); - } - if (c.cssIcon){ - // if c.cssIcon is '', then no is added to the header - $h.find('.' + c.cssIcon).addClass(o.icons); - } - if ($t.hasClass('hasFilters')){ - $h.find('.tablesorter-filter-row').addClass(o.filterRow); - } - } - $.each($h, function(i){ - $el = $(this); - $tar = (c.cssIcon) ? $el.find('.' + c.cssIcon) : $el; - if (this.sortDisabled){ - // no sort arrows for disabled columns! - $el.removeClass(rmv); - $tar.removeClass(rmv + ' tablesorter-icon ' + o.icons); - } else { - t = ($t.hasClass('hasStickyHeaders')) ? $t.find(sh).find('th').eq(i).add($el) : $el; - klass = ($el.hasClass(c.cssAsc)) ? o.sortAsc : ($el.hasClass(c.cssDesc)) ? o.sortDesc : $el.hasClass(c.cssHeader) ? o.sortNone : ''; - $el[klass === o.sortNone ? 'removeClass' : 'addClass'](o.active); - $tar.removeClass(rmv).addClass(klass); - } - }); - if (c.debug){ - $.tablesorter.benchmark("Applying " + theme + " theme", time); - } - }, - remove: function(table, c, wo){ - var $t = $(table), - theme = typeof wo.uitheme === 'object' ? 'jui' : wo.uitheme || 'jui', - o = typeof wo.uitheme === 'object' ? wo.uitheme : $.tablesorter.themes[ $.tablesorter.themes.hasOwnProperty(theme) ? theme : 'jui'], - $h = $t.children('thead').children(), - rmv = o.sortNone + ' ' + o.sortDesc + ' ' + o.sortAsc; - $t - .removeClass('tablesorter-' + theme + ' ' + o.table) - .find(c.cssHeader).removeClass(o.header); - $h - .unbind('mouseenter mouseleave') // remove hover - .removeClass(o.hover + ' ' + rmv + ' ' + o.active) - .find('.tablesorter-filter-row').removeClass(o.filterRow); - $h.find('.tablesorter-icon').removeClass(o.icons); - } - }); - - // Widget: Column styles - // "columns", "columns_thead" (true) and - // "columns_tfoot" (true) options in "widgetOptions" - // ************************** - $.tablesorter.addWidget({ - id: "columns", - format: function(table){ - var $tb, $tr, $td, $t, time, last, rmv, i, k, l, - $tbl = $(table), - c = table.config, - wo = c.widgetOptions, - b = c.$tbodies, - list = c.sortList, - len = list.length, - css = [ "primary", "secondary", "tertiary" ]; // default options - // keep backwards compatibility, for now - css = (c.widgetColumns && c.widgetColumns.hasOwnProperty('css')) ? c.widgetColumns.css || css : - (wo && wo.hasOwnProperty('columns')) ? wo.columns || css : css; - last = css.length-1; - rmv = css.join(' '); - if (c.debug){ - time = new Date(); - } - // check if there is a sort (on initialization there may not be one) - for (k = 0; k < b.length; k++ ){ - $tb = $.tablesorter.processTbody(table, b.eq(k), true); // detach tbody - $tr = $tb.children('tr'); - l = $tr.length; - // loop through the visible rows - $tr.each(function(){ - $t = $(this); - if (this.style.display !== 'none'){ - // remove all columns class names - $td = $t.children().removeClass(rmv); - // add appropriate column class names - if (list && list[0]){ - // primary sort column class - $td.eq(list[0][0]).addClass(css[0]); - if (len > 1){ - for (i = 1; i < len; i++){ - // secondary, tertiary, etc sort column classes - $td.eq(list[i][0]).addClass( css[i] || css[last] ); - } - } - } - } - }); - $.tablesorter.processTbody(table, $tb, false); - } - // add classes to thead and tfoot - $tr = wo.columns_thead !== false ? 'thead tr' : ''; - if (wo.columns_tfoot !== false) { - $tr += ($tr === '' ? '' : ',') + 'tfoot tr'; - } - if ($tr.length) { - $t = $tbl.find($tr).children().removeClass(rmv); - if (list && list[0]){ - // primary sort column class - $t.filter('[data-column="' + list[0][0] + '"]').addClass(css[0]); - if (len > 1){ - for (i = 1; i < len; i++){ - // secondary, tertiary, etc sort column classes - $t.filter('[data-column="' + list[i][0] + '"]').addClass(css[i] || css[last]); - } - } - } - } - if (c.debug){ - $.tablesorter.benchmark("Applying Columns widget", time); - } - }, - remove: function(table, c, wo){ - var k, $tb, - b = c.$tbodies, - rmv = (c.widgetOptions.columns || [ "primary", "secondary", "tertiary" ]).join(' '); - c.$headers.removeClass(rmv); - $(table).children('tfoot').children('tr').children('th, td').removeClass(rmv); - for (k = 0; k < b.length; k++ ){ - $tb = $.tablesorter.processTbody(table, b.eq(k), true); // remove tbody - $tb.children('tr').each(function(){ - $(this).children().removeClass(rmv); - }); - $.tablesorter.processTbody(table, $tb, false); // restore tbody - } - } - }); - - /* Widget: filter - widgetOptions: - filter_childRows : false // if true, filter includes child row content in the search - filter_columnFilters : true // if true, a filter will be added to the top of each table column - filter_cssFilter : 'tablesorter-filter' // css class name added to the filter row & each input in the row - filter_functions : null // add custom filter functions using this option - filter_hideFilters : false // collapse filter row when mouse leaves the area - filter_ignoreCase : true // if true, make all searches case-insensitive - filter_reset : null // jQuery selector string of an element used to reset the filters - filter_searchDelay : 300 // typing delay in milliseconds before starting a search - filter_startsWith : false // if true, filter start from the beginning of the cell contents - filter_useParsedData : false // filter all data using parsed content - filter_serversideFiltering : false // if true, server-side filtering should be performed because client-side filtering will be disabled, but the ui and events will still be used. - **************************/ - $.tablesorter.addWidget({ - id: "filter", - format: function(table){ - if (table.config.parsers && !$(table).hasClass('hasFilters')){ - var i, j, k, l, val, ff, x, xi, st, sel, str, - ft, ft2, $th, rg, s, t, dis, col, - last = '', // save last filter search - ts = $.tablesorter, - c = table.config, - $ths = $(c.headerList), - wo = c.widgetOptions, - css = wo.filter_cssFilter || 'tablesorter-filter', - $t = $(table).addClass('hasFilters'), - b = c.$tbodies, - cols = c.parsers.length, - reg = [ // regex used in filter "check" functions - /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/, // 0 = regex to test for regex - new RegExp(c.cssChildRow), // 1 = child row - /undefined|number/, // 2 = check type - /(^[\"|\'|=])|([\"|\'|=]$)/, // 3 = exact match - /[\"\'=]/g, // 4 = replace exact match flags - /[^\w,. \-()]/g, // 5 = replace non-digits (from digit & currency parser) - /[<>=]/g // 6 = replace operators - ], - parsed = $ths.map(function(i){ - return (ts.getData) ? ts.getData($ths.filter('[data-column="' + i + '"]:last'), c.headers[i], 'filter') === 'parsed' : $(this).hasClass('filter-parsed'); - }).get(), - time, timer, - - // dig fer gold - checkFilters = function(filter){ - var arry = $.isArray(filter), - $inpts = $t.find('thead').eq(0).children('tr').find('select.' + css + ', input.' + css), - v = (arry) ? filter : $inpts.map(function(){ - return $(this).val() || ''; - }).get(), - cv = (v || []).join(''); // combined filter values - // add filter array back into inputs - if (arry) { - $inpts.each(function(i,el){ - $(el).val(filter[i] || ''); - }); - } - if (wo.filter_hideFilters === true){ - // show/hide filter row as needed - $t.find('.tablesorter-filter-row').trigger( cv === '' ? 'mouseleave' : 'mouseenter' ); - } - // return if the last search is the same; but filter === false when updating the search - // see example-widget-filter.html filter toggle buttons - if (last === cv && filter !== false) { return; } - $t.trigger('filterStart', [v]); - if (c.showProcessing) { - // give it time for the processing icon to kick in - setTimeout(function(){ - findRows(filter, v, cv); - return false; - }, 30); - } else { - findRows(filter, v, cv); - return false; - } - }, - findRows = function(filter, v, cv){ - var $tb, $tr, $td, cr, r, l, ff, time, arry; - if (c.debug) { time = new Date(); } - - for (k = 0; k < b.length; k++ ){ - $tb = $.tablesorter.processTbody(table, b.eq(k), true); - $tr = $tb.children('tr'); - l = $tr.length; - if (cv === '' || wo.filter_serversideFiltering){ - $tr.show().removeClass('filtered'); - } else { - // loop through the rows - for (j = 0; j < l; j++){ - // skip child rows - if (reg[1].test($tr[j].className)) { continue; } - r = true; - cr = $tr.eq(j).nextUntil('tr:not(.' + c.cssChildRow + ')'); - // so, if "table.config.widgetOptions.filter_childRows" is true and there is - // a match anywhere in the child row, then it will make the row visible - // checked here so the option can be changed dynamically - t = (cr.length && (wo && wo.hasOwnProperty('filter_childRows') && - typeof wo.filter_childRows !== 'undefined' ? wo.filter_childRows : true)) ? cr.text() : ''; - t = wo.filter_ignoreCase ? t.toLocaleLowerCase() : t; - $td = $tr.eq(j).children('td'); - for (i = 0; i < cols; i++){ - // ignore if filter is empty or disabled - if (v[i]){ - // check if column data should be from the cell or from parsed data - if (wo.filter_useParsedData || parsed[i]){ - x = c.cache[k].normalized[j][i]; - } else { - // using older or original tablesorter - x = $.trim($td.eq(i).text()); - } - xi = !reg[2].test(typeof x) && wo.filter_ignoreCase ? x.toLocaleLowerCase() : x; - ff = r; // if r is true, show that row - // val = case insensitive, v[i] = case sensitive - val = wo.filter_ignoreCase ? v[i].toLocaleLowerCase() : v[i]; - if (wo.filter_functions && wo.filter_functions[i]){ - if (wo.filter_functions[i] === true){ - // default selector; no "filter-select" class - ff = ($ths.filter('[data-column="' + i + '"]:last').hasClass('filter-match')) ? xi.search(val) >= 0 : v[i] === x; - } else if (typeof wo.filter_functions[i] === 'function'){ - // filter callback( exact cell content, parser normalized content, filter input value, column index ) - ff = wo.filter_functions[i](x, c.cache[k].normalized[j][i], v[i], i); - } else if (typeof wo.filter_functions[i][v[i]] === 'function'){ - // selector option function - ff = wo.filter_functions[i][v[i]](x, c.cache[k].normalized[j][i], v[i], i); - } - // Look for regex - } else if (reg[0].test(val)){ - rg = reg[0].exec(val); - try { - ff = new RegExp(rg[1], rg[2]).test(xi); - } catch (err){ - ff = false; - } - // Look for quotes or equals to get an exact match - } else if (reg[3].test(val) && xi === val.replace(reg[4], '')){ - ff = true; - // Look for a not match - } else if (/^\!/.test(val)){ - val = val.replace('!',''); - s = xi.search($.trim(val)); - ff = val === '' ? true : !(wo.filter_startsWith ? s === 0 : s >= 0); - // Look for operators >, >=, < or <= - } else if (/^[<>]=?/.test(val)){ - // xi may be numeric - see issue #149 - rg = isNaN(xi) ? $.tablesorter.formatFloat(xi.replace(reg[5], ''), table) : $.tablesorter.formatFloat(xi, table); - s = $.tablesorter.formatFloat(val.replace(reg[5], '').replace(reg[6],''), table); - if (/>/.test(val)) { ff = />=/.test(val) ? rg >= s : rg > s; } - if (/= 0) || (wo.filter_startsWith && x === 0) ); - } - r = (ff) ? (r ? true : false) : false; - } - } - $tr[j].style.display = (r ? '' : 'none'); - $tr.eq(j)[r ? 'removeClass' : 'addClass']('filtered'); - if (cr.length) { cr[r ? 'show' : 'hide'](); } - } - } - $.tablesorter.processTbody(table, $tb, false); - } - - last = cv; // save last search - if (c.debug){ - ts.benchmark("Completed filter widget search", time); - } - $t.trigger('applyWidgets'); // make sure zebra widget is applied - $t.trigger('filterEnd'); - }, - buildSelect = function(i, updating){ - var o, arry = []; - i = parseInt(i, 10); - o = ''; - for (k = 0; k < b.length; k++ ){ - l = c.cache[k].row.length; - // loop through the rows - for (j = 0; j < l; j++){ - // get non-normalized cell content - if (wo.filter_useParsedData){ - arry.push( '' + c.cache[k].normalized[j][i] ); - } else { - t = c.cache[k].row[j][0].cells[i]; - if (t){ - arry.push( $.trim(c.supportsTextContent ? t.textContent : $(t).text()) ); - } - } - } - } - - // get unique elements and sort the list - // if $.tablesorter.sortText exists (not in the original tablesorter), - // then natural sort the list otherwise use a basic sort - arry = $.grep(arry, function(v, k){ - return $.inArray(v ,arry) === k; - }); - arry = (ts.sortText) ? arry.sort(function(a,b){ return ts.sortText(table, a, b, i); }) : arry.sort(true); - - // build option list - for (k = 0; k < arry.length; k++){ - o += ''; - } - $t.find('thead').find('select.' + css + '[data-column="' + i + '"]')[ updating ? 'html' : 'append' ](o); - }, - buildDefault = function(updating){ - // build default select dropdown - for (i = 0; i < cols; i++){ - t = $ths.filter('[data-column="' + i + '"]:last'); - // look for the filter-select class; build/update it if found - if ((t.hasClass('filter-select') || wo.filter_functions && wo.filter_functions[i] === true) && !t.hasClass('filter-false')){ - if (!wo.filter_functions) { wo.filter_functions = {}; } - wo.filter_functions[i] = true; // make sure this select gets processed by filter_functions - buildSelect(i, updating); - } - } - }; - - if (c.debug){ - time = new Date(); - } - wo.filter_ignoreCase = wo.filter_ignoreCase !== false; // set default filter_ignoreCase to true - wo.filter_useParsedData = wo.filter_useParsedData === true; // default is false - // don't build filter row if columnFilters is false or all columns are set to "filter-false" - issue #156 - if (wo.filter_columnFilters !== false && $ths.filter('.filter-false').length !== $ths.length){ - t = ''; // build filter row - for (i = 0; i < cols; i++){ - dis = false; - $th = $ths.filter('[data-column="' + i + '"]:last'); // assuming last cell of a column is the main column - sel = (wo.filter_functions && wo.filter_functions[i] && typeof wo.filter_functions[i] !== 'function') || $th.hasClass('filter-select'); - t += ''; - if (sel){ - t += '' : '>') + ''; - } - $t.find('thead').eq(0).append(t += ''); - } - $t - // add .tsfilter namespace to all BUT search - .bind('addRows updateCell update appendCache search'.split(' ').join('.tsfilter '), function(e, filter){ - if (e.type !== 'search'){ - buildDefault(true); - } - checkFilters(e.type === 'search' ? filter : ''); - return false; - }) - .find('input.' + css).bind('keyup search', function(e, filter){ - // ignore arrow and meta keys; allow backspace - if ((e.which < 32 && e.which !== 8) || (e.which >= 37 && e.which <=40)) { return; } - // skip delay - if (typeof filter !== 'undefined'){ - checkFilters(filter); - return false; - } - // delay filtering - clearTimeout(timer); - timer = setTimeout(function(){ - checkFilters(); - }, wo.filter_searchDelay || 300); - }); - - // reset button/link - if (wo.filter_reset && $(wo.filter_reset).length){ - $(wo.filter_reset).bind('click', function(){ - $t.find('.' + css).val(''); - checkFilters(); - return false; - }); - } - if (wo.filter_functions){ - // i = column # (string) - for (col in wo.filter_functions){ - if (wo.filter_functions.hasOwnProperty(col) && typeof col === 'string'){ - t = $ths.filter('[data-column="' + col + '"]:last'); - ff = ''; - if (wo.filter_functions[col] === true && !t.hasClass('filter-false')){ - buildSelect(col); - } else if (typeof col === 'string' && !t.hasClass('filter-false')){ - // add custom drop down list - for (str in wo.filter_functions[col]){ - if (typeof str === 'string'){ - ff += ff === '' ? '' : ''; - ff += ''; - } - } - $t.find('thead').find('select.' + css + '[data-column="' + col + '"]').append(ff); - } - } - } - } - // not really updating, but if the column has both the "filter-select" class & filter_functions set to true, - // it would append the same options twice. - buildDefault(true); - - $t.find('select.' + css).bind('change search', function(){ - checkFilters(); - }); - - if (wo.filter_hideFilters === true){ - $t - .find('.tablesorter-filter-row') - .addClass('hideme') - .bind('mouseenter mouseleave', function(e){ - // save event object - http://bugs.jquery.com/ticket/12140 - var all, evt = e; - ft = $(this); - clearTimeout(st); - st = setTimeout(function(){ - if (/enter|over/.test(evt.type)){ - ft.removeClass('hideme'); - } else { - // don't hide if input has focus - // $(':focus') needs jQuery 1.6+ - if ($(document.activeElement).closest('tr')[0] !== ft[0]){ - // get all filter values - all = $t.find('.' + (wo.filter_cssFilter || 'tablesorter-filter')).map(function(){ - return $(this).val() || ''; - }).get().join(''); - // don't hide row if any filter has a value - if (all === ''){ - ft.addClass('hideme'); - } - } - } - }, 200); - }) - .find('input, select').bind('focus blur', function(e){ - ft2 = $(this).closest('tr'); - clearTimeout(st); - st = setTimeout(function(){ - // don't hide row if any filter has a value - if ($t.find('.' + (wo.filter_cssFilter || 'tablesorter-filter')).map(function(){ return $(this).val() || ''; }).get().join('') === ''){ - ft2[ e.type === 'focus' ? 'removeClass' : 'addClass']('hideme'); - } - }, 200); - }); - } - - // show processing icon - if (c.showProcessing) { - $t.bind('filterStart filterEnd', function(e, v) { - var fc = (v) ? $t.find('.' + c.cssHeader).filter('[data-column]').filter(function(){ - return v[$(this).data('column')] !== ''; - }) : ''; - ts.isProcessing($t[0], e.type === 'filterStart', v ? fc : ''); - }); - } - - if (c.debug){ - ts.benchmark("Applying Filter widget", time); - } - // filter widget initialized - $t.trigger('filterInit'); - } - }, - remove: function(table, c, wo){ - var k, $tb, - $t = $(table), - b = c.$tbodies; - $t - .removeClass('hasFilters') - // add .tsfilter namespace to all BUT search - .unbind('addRows updateCell update appendCache search'.split(' ').join('.tsfilter')) - .find('.tablesorter-filter-row').remove(); - for (k = 0; k < b.length; k++ ){ - $tb = $.tablesorter.processTbody(table, b.eq(k), true); // remove tbody - $tb.children().removeClass('filtered').show(); - $.tablesorter.processTbody(table, $tb, false); // restore tbody - } - if (wo.filterreset) { $(wo.filter_reset).unbind('click'); } - } - }); - - // Widget: Sticky headers - // based on this awesome article: - // http://css-tricks.com/13465-persistent-headers/ - // and https://github.com/jmosbech/StickyTableHeaders by Jonas Mosbech - // ************************** - $.tablesorter.addWidget({ - id: "stickyHeaders", - format: function(table){ - if ($(table).hasClass('hasStickyHeaders')) { return; } - var $table = $(table).addClass('hasStickyHeaders'), - c = table.config, - wo = c.widgetOptions, - win = $(window), - header = $(table).children('thead:first'), //.add( $(table).find('caption') ), - hdrCells = header.children('tr:not(.sticky-false)').children(), - css = wo.stickyHeaders || 'tablesorter-stickyHeader', - innr = '.tablesorter-header-inner', - firstRow = hdrCells.eq(0).parent(), - tfoot = $table.find('tfoot'), - t2 = wo.$sticky = $table.clone(), // clone table, but don't remove id... the table might be styled by css - // clone the entire thead - seems to work in IE8+ - stkyHdr = t2.children('thead:first') - .addClass(css) - .css({ - width : header.outerWidth(true), - position : 'fixed', - margin : 0, - top : 0, - visibility : 'hidden', - zIndex : 1 - }), - stkyCells = stkyHdr.children('tr:not(.sticky-false)').children(), // issue #172 - laststate = '', - spacing = 0, - resizeHdr = function(){ - var bwsr = navigator.userAgent; - spacing = 0; - // yes, I dislike browser sniffing, but it really is needed here :( - // webkit automatically compensates for border spacing - if ($table.css('border-collapse') !== 'collapse' && !/(webkit|msie)/i.test(bwsr)) { - // Firefox & Opera use the border-spacing - // update border-spacing here because of demos that switch themes - spacing = parseInt(hdrCells.eq(0).css('border-left-width'), 10) * 2; - } - stkyHdr.css({ - left : header.offset().left - win.scrollLeft() - spacing, - width: header.outerWidth() - }); - stkyCells - .each(function(i){ - var $h = hdrCells.eq(i); - $(this).css({ - width: $h.width() - spacing, - height: $h.height() - }); - }) - .find(innr).each(function(i){ - var hi = hdrCells.eq(i).find(innr), - w = hi.width(); // - ( parseInt(hi.css('padding-left'), 10) + parseInt(hi.css('padding-right'), 10) ); - $(this).width(w); - }); - }; - // clear out cloned table, except for sticky header - t2.find('thead:gt(0),tr.sticky-false,tbody,tfoot,caption').remove(); - t2.css({ height:0, width:0, padding:0, margin:0, border:0 }); - // remove rows you don't want to be sticky - stkyHdr.find('tr.sticky-false').remove(); - // remove resizable block - stkyCells.find('.tablesorter-resizer').remove(); - // update sticky header class names to match real header after sorting - $table - .bind('sortEnd.tsSticky', function(){ - hdrCells.each(function(i){ - var t = stkyCells.eq(i); - t.attr('class', $(this).attr('class')); - if (c.cssIcon){ - t - .find('.' + c.cssIcon) - .attr('class', $(this).find('.' + c.cssIcon).attr('class')); - } - }); - }) - .bind('pagerComplete.tsSticky', function(){ - resizeHdr(); - }); - // set sticky header cell width and link clicks to real header - hdrCells.find('*').andSelf().filter(c.selectorSort).each(function(i){ - var t = $(this); - stkyCells.eq(i) - // clicking on sticky will trigger sort - .bind('mouseup', function(e){ - t.trigger(e, true); // external mouseup flag (click timer is ignored) - }) - // prevent sticky header text selection - .bind('mousedown', function(){ - this.onselectstart = function(){ return false; }; - return false; - }); - }); - // add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned. - $table.after( t2 ); - // make it sticky! - win - .bind('scroll.tsSticky', function(){ - var offset = firstRow.offset(), - sTop = win.scrollTop(), - tableHt = $table.height() - (stkyHdr.height() + (tfoot.height() || 0)), - vis = (sTop > offset.top) && (sTop < offset.top + tableHt) ? 'visible' : 'hidden'; - stkyHdr - .css({ - // adjust when scrolling horizontally - fixes issue #143 - left : header.offset().left - win.scrollLeft() - spacing, - visibility : vis - }); - if (vis !== laststate){ - // make sure the column widths match - resizeHdr(); - laststate = vis; - } - }) - .bind('resize.tsSticky', function(){ - resizeHdr(); - }); - }, - remove: function(table, c, wo){ - var $t = $(table), - css = wo.stickyHeaders || 'tablesorter-stickyHeader'; - $t - .removeClass('hasStickyHeaders') - .unbind('sortEnd.tsSticky pagerComplete.tsSticky') - .find('.' + css).remove(); - if (wo.$sticky) { wo.$sticky.remove(); } // remove cloned thead - $(window).unbind('scroll.tsSticky resize.tsSticky'); - } - }); - - // Add Column resizing widget - // this widget saves the column widths if - // $.tablesorter.storage function is included - // ************************** - $.tablesorter.addWidget({ - id: "resizable", - format: function(table){ - if ($(table).hasClass('hasResizable')) { return; } - $(table).addClass('hasResizable'); - var $t, t, i, j, s, $c, $cols, w, tw, - $tbl = $(table), - c = table.config, - wo = c.widgetOptions, - position = 0, - $target = null, - $next = null, - fullWidth = Math.abs($tbl.parent().width() - $tbl.width()) < 20, - stopResize = function(){ - if ($.tablesorter.storage && $target){ - s[$target.index()] = $target.width(); - s[$next.index()] = $next.width(); - $target.width( s[$target.index()] ); - $next.width( s[$next.index()] ); - if (wo.resizable !== false){ - $.tablesorter.storage(table, 'tablesorter-resizable', s); - } - } - position = 0; - $target = $next = null; - $(window).trigger('resize'); // will update stickyHeaders, just in case - }; - s = ($.tablesorter.storage && wo.resizable !== false) ? $.tablesorter.storage(table, 'tablesorter-resizable') : {}; - // process only if table ID or url match - if (s){ - for (j in s){ - if (!isNaN(j) && j < c.headerList.length){ - $(c.headerList[j]).width(s[j]); // set saved resizable widths - } - } - } - $t = $tbl.children('thead:first').children('tr'); - // add resizable-false class name to headers (across rows as needed) - $t.children().each(function(){ - t = $(this); - i = t.attr('data-column'); - j = $.tablesorter.getData( t, c.headers[i], 'resizable') === "false"; - $t.children().filter('[data-column="' + i + '"]').toggleClass('resizable-false', j); - }); - // add wrapper inside each cell to allow for positioning of the resizable target block - $t.each(function(){ - $c = $(this).children(':not(.resizable-false)'); - if (!$(this).find('.tablesorter-wrapper').length) { - // Firefox needs this inner div to position the resizer correctly - $c.wrapInner('
'); - } - $c = $c.slice(0,-1); // don't include the last column of the row - $cols = $cols ? $cols.add($c) : $c; - }); - $cols - .each(function(){ - $t = $(this); - j = parseInt($t.css('padding-right'), 10) + 10; // 8 is 1/2 of the 16px wide resizer grip - t = '
'; - $t - .find('.tablesorter-wrapper') - .append(t); - }) - .bind('mousemove.tsresize', function(e){ - // ignore mousemove if no mousedown - if (position === 0 || !$target) { return; } - // resize columns - w = e.pageX - position; - tw = $target.width(); - $target.width( tw + w ); - if ($target.width() !== tw && fullWidth){ - $next.width( $next.width() - w ); - } - position = e.pageX; - }) - .bind('mouseup.tsresize', function(){ - stopResize(); - }) - .find('.tablesorter-resizer,.tablesorter-resizer-grip') - .bind('mousedown', function(e){ - // save header cell and mouse position; closest() not supported by jQuery v1.2.6 - $target = $(e.target).closest('th'); - t = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]'); - if (t.length > 1) { $target = $target.add(t); } - // if table is not as wide as it's parent, then resize the table - $next = e.shiftKey ? $target.parent().find('th:not(.resizable-false)').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0); - position = e.pageX; - }); - $tbl.find('thead:first') - .bind('mouseup.tsresize mouseleave.tsresize', function(e){ - stopResize(); - }) - // right click to reset columns to default widths - .bind('contextmenu.tsresize', function(){ - $.tablesorter.resizableReset(table); - // $.isEmptyObject() needs jQuery 1.4+ - var rtn = $.isEmptyObject ? $.isEmptyObject(s) : s === {}; // allow right click if already reset - s = {}; - return rtn; - }); - }, - remove: function(table, c, wo){ - $(table) - .removeClass('hasResizable') - .find('thead') - .unbind('mouseup.tsresize mouseleave.tsresize contextmenu.tsresize') - .find('tr').children() - .unbind('mousemove.tsresize mouseup.tsresize') - // don't remove "tablesorter-wrapper" as uitheme uses it too - .find('.tablesorter-resizer,.tablesorter-resizer-grip').remove(); - $.tablesorter.resizableReset(table); - } - }); - $.tablesorter.resizableReset = function(table){ - $(table.config.headerList).filter(':not(.resizable-false)').css('width',''); - if ($.tablesorter.storage) { $.tablesorter.storage(table, 'tablesorter-resizable', {}); } - }; - - // Save table sort widget - // this widget saves the last sort only if the - // saveSort widget option is true AND the - // $.tablesorter.storage function is included - // ************************** - $.tablesorter.addWidget({ - id: 'saveSort', - init: function(table, thisWidget){ - // run widget format before all other widgets are applied to the table - thisWidget.format(table, true); - }, - format: function(table, init){ - var sl, time, c = table.config, - wo = c.widgetOptions, - ss = wo.saveSort !== false, // make saveSort active/inactive; default to true - sortList = { "sortList" : c.sortList }; - if (c.debug){ - time = new Date(); - } - if ($(table).hasClass('hasSaveSort')){ - if (ss && table.hasInitialized && $.tablesorter.storage){ - $.tablesorter.storage( table, 'tablesorter-savesort', sortList ); - if (c.debug){ - $.tablesorter.benchmark('saveSort widget: Saving last sort: ' + c.sortList, time); - } - } - } else { - // set table sort on initial run of the widget - $(table).addClass('hasSaveSort'); - sortList = ''; - // get data - if ($.tablesorter.storage){ - sl = $.tablesorter.storage( table, 'tablesorter-savesort' ); - sortList = (sl && sl.hasOwnProperty('sortList') && $.isArray(sl.sortList)) ? sl.sortList : ''; - if (c.debug){ - $.tablesorter.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time); - } - } - // init is true when widget init is run, this will run this widget before all other widgets have initialized - // this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice. - if (init && sortList && sortList.length > 0){ - c.sortList = sortList; - } else if (table.hasInitialized && sortList && sortList.length > 0){ - // update sort change - $(table).trigger('sorton', [sortList]); - } - } - }, - remove: function(table, c, wo){ - // clear storage - if ($.tablesorter.storage) { $.tablesorter.storage( table, 'tablesorter-savesort', '' ); } - } - }); - -})(jQuery); \ No newline at end of file diff --git a/UI/JsLibraries/jquery.tablesorter.js b/UI/JsLibraries/jquery.tablesorter.js deleted file mode 100644 index 7820a3e66..000000000 --- a/UI/JsLibraries/jquery.tablesorter.js +++ /dev/null @@ -1,1383 +0,0 @@ -/*! - * TableSorter 2.7.12 - Client-side table sorting with ease! - * @requires jQuery v1.2.6+ - * - * Copyright (c) 2007 Christian Bach - * Examples and docs at: http://tablesorter.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * @type jQuery - * @name tablesorter - * @cat Plugins/Tablesorter - * @author Christian Bach/christian.bach@polyester.se - * @contributor Rob Garrison/https://github.com/Mottie/tablesorter - */ -/*jshint browser:true, jquery:true, unused:false, expr: true */ -/*global console:false, alert:false */ -!(function($) { - "use strict"; - $.extend({ - /*jshint supernew:true */ - tablesorter: new function() { - - var ts = this; - - ts.version = "2.7.12"; - - ts.parsers = []; - ts.widgets = []; - ts.defaults = { - - // *** appearance - theme : 'default', // adds tablesorter-{theme} to the table for styling - widthFixed : false, // adds colgroup to fix widths of columns - showProcessing : false, // show an indeterminate timer icon in the header when the table is sorted or filtered. - - headerTemplate : '{content}',// header layout template (HTML ok); {content} = innerHTML, {icon} = (class from cssIcon) - onRenderTemplate : null, // function(index, template){ return template; }, (template is a string) - onRenderHeader : null, // function(index){}, (nothing to return) - - // *** functionality - cancelSelection : true, // prevent text selection in the header - dateFormat : 'mmddyyyy', // other options: "ddmmyyy" or "yyyymmdd" - sortMultiSortKey : 'shiftKey', // key used to select additional columns - sortResetKey : 'ctrlKey', // key used to remove sorting on a column - usNumberFormat : true, // false for German "1.234.567,89" or French "1 234 567,89" - delayInit : false, // if false, the parsed table contents will not update until the first sort - serverSideSorting: false, // if true, server-side sorting should be performed because client-side sorting will be disabled, but the ui and events will still be used. - - // *** sort options - headers : {}, // set sorter, string, empty, locked order, sortInitialOrder, filter, etc. - ignoreCase : true, // ignore case while sorting - sortForce : null, // column(s) first sorted; always applied - sortList : [], // Initial sort order; applied initially; updated when manually sorted - sortAppend : null, // column(s) sorted last; always applied - - sortInitialOrder : 'asc', // sort direction on first click - sortLocaleCompare: false, // replace equivalent character (accented characters) - sortReset : false, // third click on the header will reset column to default - unsorted - sortRestart : false, // restart sort to "sortInitialOrder" when clicking on previously unsorted columns - - emptyTo : 'bottom', // sort empty cell to bottom, top, none, zero - stringTo : 'max', // sort strings in numerical column as max, min, top, bottom, zero - textExtraction : 'simple', // text extraction method/function - function(node, table, cellIndex){} - textSorter : null, // use custom text sorter - function(a,b){ return a.sort(b); } // basic sort - - // *** widget options - widgets: [], // method to add widgets, e.g. widgets: ['zebra'] - widgetOptions : { - zebra : [ 'even', 'odd' ] // zebra widget alternating row class names - }, - initWidgets : true, // apply widgets on tablesorter initialization - - // *** callbacks - initialized : null, // function(table){}, - - // *** css class names - tableClass : 'tablesorter', - cssAsc : 'tablesorter-headerAsc', - cssChildRow : 'tablesorter-childRow', // previously "expand-child" - cssDesc : 'tablesorter-headerDesc', - cssHeader : 'tablesorter-header', - cssHeaderRow : 'tablesorter-headerRow', - cssIcon : 'tablesorter-icon', // if this class exists, a will be added to the header automatically - cssInfoBlock : 'tablesorter-infoOnly', // don't sort tbody with this class name - cssProcessing : 'tablesorter-processing', // processing icon applied to header during sort/filter - - // *** selectors - selectorHeaders : '> thead th, > thead td', - selectorSort : 'th, td', // jQuery selector of content within selectorHeaders that is clickable to trigger a sort - selectorRemove : '.remove-me', - - // *** advanced - debug : false, - - // *** Internal variables - headerList: [], - empties: {}, - strings: {}, - parsers: [] - - // deprecated; but retained for backwards compatibility - // widgetZebra: { css: ["even", "odd"] } - - }; - - /* debuging utils */ - function log(s) { - if (typeof console !== "undefined" && typeof console.log !== "undefined") { - console.log(s); - } else { - alert(s); - } - } - - function benchmark(s, d) { - log(s + " (" + (new Date().getTime() - d.getTime()) + "ms)"); - } - - ts.benchmark = benchmark; - - function getElementText(table, node, cellIndex) { - if (!node) { return ""; } - var c = table.config, - t = c.textExtraction, text = ""; - if (t === "simple") { - if (c.supportsTextContent) { - text = node.textContent; // newer browsers support this - } else { - text = $(node).text(); - } - } else { - if (typeof(t) === "function") { - text = t(node, table, cellIndex); - } else if (typeof(t) === "object" && t.hasOwnProperty(cellIndex)) { - text = t[cellIndex](node, table, cellIndex); - } else { - text = c.supportsTextContent ? node.textContent : $(node).text(); - } - } - return $.trim(text); - } - - function detectParserForColumn(table, rows, rowIndex, cellIndex) { - var i, l = ts.parsers.length, - node = false, - nodeValue = '', - keepLooking = true; - while (nodeValue === '' && keepLooking) { - rowIndex++; - if (rows[rowIndex]) { - node = rows[rowIndex].cells[cellIndex]; - nodeValue = getElementText(table, node, cellIndex); - if (table.config.debug) { - log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': ' + nodeValue); - } - } else { - keepLooking = false; - } - } - for (i = 1; i < l; i++) { - if (ts.parsers[i].is && ts.parsers[i].is(nodeValue, table, node)) { - return ts.parsers[i]; - } - } - // 0 is always the generic parser (text) - return ts.parsers[0]; - } - - function buildParserCache(table) { - var c = table.config, - // update table bodies in case we start with an empty table - tb = c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')'), - rows, list, l, i, h, ch, p, parsersDebug = ""; - if ( tb.length === 0) { - return c.debug ? log('*Empty table!* Not building a parser cache') : ''; - } - rows = tb[0].rows; - if (rows[0]) { - list = []; - l = rows[0].cells.length; - for (i = 0; i < l; i++) { - // tons of thanks to AnthonyM1229 for working out the following selector (issue #74) to make this work in IE8! - // More fixes to this selector to work properly in iOS and jQuery 1.8+ (issue #132 & #174) - h = c.$headers.filter(':not([colspan])'); - h = h.add( c.$headers.filter('[colspan="1"]') ) // ie8 fix - .filter('[data-column="' + i + '"]:last'); - ch = c.headers[i]; - // get column parser - p = ts.getParserById( ts.getData(h, ch, 'sorter') ); - // empty cells behaviour - keeping emptyToBottom for backwards compatibility - c.empties[i] = ts.getData(h, ch, 'empty') || c.emptyTo || (c.emptyToBottom ? 'bottom' : 'top' ); - // text strings behaviour in numerical sorts - c.strings[i] = ts.getData(h, ch, 'string') || c.stringTo || 'max'; - if (!p) { - p = detectParserForColumn(table, rows, -1, i); - } - if (c.debug) { - parsersDebug += "column:" + i + "; parser:" + p.id + "; string:" + c.strings[i] + '; empty: ' + c.empties[i] + "\n"; - } - list.push(p); - } - } - if (c.debug) { - log(parsersDebug); - } - return list; - } - - /* utils */ - function buildCache(table) { - var b = table.tBodies, - tc = table.config, - totalRows, - totalCells, - parsers = tc.parsers, - t, v, i, j, k, c, cols, cacheTime, colMax = []; - tc.cache = {}; - // if no parsers found, return - it's an empty table. - if (!parsers) { - return tc.debug ? log('*Empty table!* Not building a cache') : ''; - } - if (tc.debug) { - cacheTime = new Date(); - } - // processing icon - if (tc.showProcessing) { - ts.isProcessing(table, true); - } - for (k = 0; k < b.length; k++) { - tc.cache[k] = { row: [], normalized: [] }; - // ignore tbodies with class name from css.cssInfoBlock - if (!$(b[k]).hasClass(tc.cssInfoBlock)) { - totalRows = (b[k] && b[k].rows.length) || 0; - totalCells = (b[k].rows[0] && b[k].rows[0].cells.length) || 0; - for (i = 0; i < totalRows; ++i) { - /** Add the table data to main data array */ - c = $(b[k].rows[i]); - cols = []; - // if this is a child row, add it to the last row's children and continue to the next row - if (c.hasClass(tc.cssChildRow)) { - tc.cache[k].row[tc.cache[k].row.length - 1] = tc.cache[k].row[tc.cache[k].row.length - 1].add(c); - // go to the next for loop - continue; - } - tc.cache[k].row.push(c); - for (j = 0; j < totalCells; ++j) { - t = getElementText(table, c[0].cells[j], j); - // allow parsing if the string is empty, previously parsing would change it to zero, - // in case the parser needs to extract data from the table cell attributes - v = parsers[j].format(t, table, c[0].cells[j], j); - cols.push(v); - if ((parsers[j].type || '').toLowerCase() === "numeric") { - colMax[j] = Math.max(Math.abs(v), colMax[j] || 0); // determine column max value (ignore sign) - } - } - cols.push(tc.cache[k].normalized.length); // add position for rowCache - tc.cache[k].normalized.push(cols); - } - tc.cache[k].colMax = colMax; - } - } - if (tc.showProcessing) { - ts.isProcessing(table); // remove processing icon - } - if (tc.debug) { - benchmark("Building cache for " + totalRows + " rows", cacheTime); - } - } - - // init flag (true) used by pager plugin to prevent widget application - function appendToTable(table, init) { - var c = table.config, - b = table.tBodies, - rows = [], - c2 = c.cache, - r, n, totalRows, checkCell, $bk, $tb, - i, j, k, l, pos, appendTime; - if (!c2[0]) { return; } // empty table - fixes #206 - if (c.debug) { - appendTime = new Date(); - } - for (k = 0; k < b.length; k++) { - $bk = $(b[k]); - if (!$bk.hasClass(c.cssInfoBlock)) { - // get tbody - $tb = ts.processTbody(table, $bk, true); - r = c2[k].row; - n = c2[k].normalized; - totalRows = n.length; - checkCell = totalRows ? (n[0].length - 1) : 0; - for (i = 0; i < totalRows; i++) { - pos = n[i][checkCell]; - rows.push(r[pos]); - // removeRows used by the pager plugin - if (!c.appender || !c.removeRows) { - l = r[pos].length; - for (j = 0; j < l; j++) { - $tb.append(r[pos][j]); - } - } - } - // restore tbody - ts.processTbody(table, $tb, false); - } - } - if (c.appender) { - c.appender(table, rows); - } - if (c.debug) { - benchmark("Rebuilt table", appendTime); - } - // apply table widgets - if (!init) { ts.applyWidget(table); } - // trigger sortend - $(table).trigger("sortEnd", table); - } - - // computeTableHeaderCellIndexes from: - // http://www.javascripttoolbox.com/lib/table/examples.php - // http://www.javascripttoolbox.com/temp/table_cellindex.html - function computeThIndexes(t) { - var matrix = [], - lookup = {}, - cols = 0, // determine the number of columns - trs = $(t).find('thead:eq(0), tfoot').children('tr'), // children tr in tfoot - see issue #196 - i, j, k, l, c, cells, rowIndex, cellId, rowSpan, colSpan, firstAvailCol, matrixrow; - for (i = 0; i < trs.length; i++) { - cells = trs[i].cells; - for (j = 0; j < cells.length; j++) { - c = cells[j]; - rowIndex = c.parentNode.rowIndex; - cellId = rowIndex + "-" + c.cellIndex; - rowSpan = c.rowSpan || 1; - colSpan = c.colSpan || 1; - if (typeof(matrix[rowIndex]) === "undefined") { - matrix[rowIndex] = []; - } - // Find first available column in the first row - for (k = 0; k < matrix[rowIndex].length + 1; k++) { - if (typeof(matrix[rowIndex][k]) === "undefined") { - firstAvailCol = k; - break; - } - } - lookup[cellId] = firstAvailCol; - cols = Math.max(firstAvailCol, cols); - // add data-column - $(c).attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex - for (k = rowIndex; k < rowIndex + rowSpan; k++) { - if (typeof(matrix[k]) === "undefined") { - matrix[k] = []; - } - matrixrow = matrix[k]; - for (l = firstAvailCol; l < firstAvailCol + colSpan; l++) { - matrixrow[l] = "x"; - } - } - } - } - t.config.columns = cols; // may not be accurate if # header columns !== # tbody columns - return lookup; - } - - function formatSortingOrder(v) { - // look for "d" in "desc" order; return true - return (/^d/i.test(v) || v === 1); - } - - function buildHeaders(table) { - var header_index = computeThIndexes(table), ch, $t, - h, i, t, lock, time, $tableHeaders, c = table.config; - c.headerList = [], c.headerContent = []; - if (c.debug) { - time = new Date(); - } - i = c.cssIcon ? '' : ''; // add icon if cssIcon option exists - $tableHeaders = $(table).find(c.selectorHeaders).each(function(index) { - $t = $(this); - ch = c.headers[index]; - c.headerContent[index] = this.innerHTML; // save original header content - // set up header template - t = c.headerTemplate.replace(/\{content\}/g, this.innerHTML).replace(/\{icon\}/g, i); - if (c.onRenderTemplate) { - h = c.onRenderTemplate.apply($t, [index, t]); - if (h && typeof h === 'string') { t = h; } // only change t if something is returned - } - this.innerHTML = '
' + t + '
'; // faster than wrapInner - - if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index]); } - - this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex]; - this.order = formatSortingOrder( ts.getData($t, ch, 'sortInitialOrder') || c.sortInitialOrder ) ? [1,0,2] : [0,1,2]; - this.count = -1; // set to -1 because clicking on the header automatically adds one - if (ts.getData($t, ch, 'sorter') === 'false') { - this.sortDisabled = true; - $t.addClass('sorter-false'); - } else { - $t.removeClass('sorter-false'); - } - this.lockedOrder = false; - lock = ts.getData($t, ch, 'lockedOrder') || false; - if (typeof(lock) !== 'undefined' && lock !== false) { - this.order = this.lockedOrder = formatSortingOrder(lock) ? [1,1,1] : [0,0,0]; - } - $t.addClass( (this.sortDisabled ? 'sorter-false ' : ' ') + c.cssHeader ); - // add cell to headerList - c.headerList[index] = this; - // add to parent in case there are multiple rows - $t.parent().addClass(c.cssHeaderRow); - }); - if (table.config.debug) { - benchmark("Built headers:", time); - log($tableHeaders); - } - return $tableHeaders; - } - - function setHeadersCss(table) { - var f, i, j, l, - c = table.config, - list = c.sortList, - css = [c.cssAsc, c.cssDesc], - // find the footer - $t = $(table).find('tfoot tr').children().removeClass(css.join(' ')); - // remove all header information - c.$headers.removeClass(css.join(' ')); - l = list.length; - for (i = 0; i < l; i++) { - // direction = 2 means reset! - if (list[i][1] !== 2) { - // multicolumn sorting updating - choose the :last in case there are nested columns - f = c.$headers.not('.sorter-false').filter('[data-column="' + list[i][0] + '"]' + (l === 1 ? ':last' : '') ); - if (f.length) { - for (j = 0; j < f.length; j++) { - if (!f[j].sortDisabled) { - f.eq(j).addClass(css[list[i][1]]); - // add sorted class to footer, if it exists - if ($t.length) { - $t.filter('[data-column="' + list[i][0] + '"]').eq(j).addClass(css[list[i][1]]); - } - } - } - } - } - } - } - - // automatically add col group, and column sizes if set - function fixColumnWidth(table) { - if (table.config.widthFixed && $(table).find('colgroup').length === 0) { - var colgroup = $(''), - overallWidth = $(table).width(); - $(table.tBodies[0]).find("tr:first").children("td").each(function() { - colgroup.append($('').css('width', parseInt(($(this).width()/overallWidth)*1000, 10)/10 + '%')); - }); - $(table).prepend(colgroup); - } - } - - function updateHeaderSortCount(table, list) { - var s, t, o, c = table.config, - sl = list || c.sortList; - c.sortList = []; - $.each(sl, function(i,v){ - // ensure all sortList values are numeric - fixes #127 - s = [ parseInt(v[0], 10), parseInt(v[1], 10) ]; - // make sure header exists - o = c.headerList[s[0]]; - if (o) { // prevents error if sorton array is wrong - c.sortList.push(s); - t = $.inArray(s[1], o.order); // fixes issue #167 - o.count = t >= 0 ? t : s[1] % (c.sortReset ? 3 : 2); - } - }); - } - - function getCachedSortType(parsers, i) { - return (parsers && parsers[i]) ? parsers[i].type || '' : ''; - } - - // sort multiple columns - function multisort(table) { /*jshint loopfunc:true */ - var dynamicExp, sortWrapper, col, mx = 0, dir = 0, tc = table.config, - sortList = tc.sortList, l = sortList.length, bl = table.tBodies.length, - sortTime, i, j, k, c, colMax, cache, lc, s, e, order, orgOrderCol; - if (tc.serverSideSorting || !tc.cache[0]) { // empty table - fixes #206 - return; - } - if (tc.debug) { sortTime = new Date(); } - for (k = 0; k < bl; k++) { - colMax = tc.cache[k].colMax; - cache = tc.cache[k].normalized; - lc = cache.length; - orgOrderCol = (cache && cache[0]) ? cache[0].length - 1 : 0; - cache.sort(function(a, b) { - // cache is undefined here in IE, so don't use it! - for (i = 0; i < l; i++) { - c = sortList[i][0]; - order = sortList[i][1]; - // fallback to natural sort since it is more robust - s = /n/i.test(getCachedSortType(tc.parsers, c)) ? "Numeric" : "Text"; - s += order === 0 ? "" : "Desc"; - if (/Numeric/.test(s) && tc.strings[c]) { - // sort strings in numerical columns - if (typeof (tc.string[tc.strings[c]]) === 'boolean') { - dir = (order === 0 ? 1 : -1) * (tc.string[tc.strings[c]] ? -1 : 1); - } else { - dir = (tc.strings[c]) ? tc.string[tc.strings[c]] || 0 : 0; - } - } - var sort = $.tablesorter["sort" + s](table, a[c], b[c], c, colMax[c], dir); - if (sort) { return sort; } - } - return a[orgOrderCol] - b[orgOrderCol]; - }); - } - if (tc.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time", sortTime); } - } - - function resortComplete($table, callback){ - $table.trigger('updateComplete'); - if (typeof callback === "function") { - callback($table[0]); - } - } - - function checkResort($table, flag, callback) { - if (flag !== false) { - $table.trigger("sorton", [$table[0].config.sortList, function(){ - resortComplete($table, callback); - }]); - } else { - resortComplete($table, callback); - } - } - - /* public methods */ - ts.construct = function(settings) { - return this.each(function() { - // if no thead or tbody, or tablesorter is already present, quit - if (!this.tHead || this.tBodies.length === 0 || this.hasInitialized === true) { - return (this.config && this.config.debug) ? log('stopping initialization! No thead, tbody or tablesorter has already been initialized') : ''; - } - // declare - var $cell, $this = $(this), $t0 = this, - c, i, j, k = '', a, s, o, downTime, - m = $.metadata; - // initialization flag - $t0.hasInitialized = false; - // new blank config object - $t0.config = {}; - // merge and extend - c = $.extend(true, $t0.config, ts.defaults, settings); - // save the settings where they read - $.data($t0, "tablesorter", c); - if (c.debug) { $.data( $t0, 'startoveralltimer', new Date()); } - // constants - c.supportsTextContent = $('x')[0].textContent === 'x'; - c.supportsDataObject = parseFloat($.fn.jquery) >= 1.4; - // digit sort text location; keeping max+/- for backwards compatibility - c.string = { 'max': 1, 'min': -1, 'max+': 1, 'max-': -1, 'zero': 0, 'none': 0, 'null': 0, 'top': true, 'bottom': false }; - // add table theme class only if there isn't already one there - if (!/tablesorter\-/.test($this.attr('class'))) { - k = (c.theme !== '' ? ' tablesorter-' + c.theme : ''); - } - c.$table = $this.addClass(c.tableClass + k); - c.$tbodies = $this.children('tbody:not(.' + c.cssInfoBlock + ')'); - // build headers - c.$headers = buildHeaders($t0); - // fixate columns if the users supplies the fixedWidth option - // do this after theme has been applied - fixColumnWidth($t0); - // try to auto detect column type, and store in tables config - c.parsers = buildParserCache($t0); - // build the cache for the tbody cells - // delayInit will delay building the cache until the user starts a sort - if (!c.delayInit) { buildCache($t0); } - // apply event handling to headers - // this is to big, perhaps break it out? - c.$headers - // http://stackoverflow.com/questions/5312849/jquery-find-self; andSelf() deprecated in jQuery 1.8 - .find('*')[ $.fn.addBack ? 'addBack': 'andSelf' ]().filter(c.selectorSort) - .unbind('mousedown.tablesorter mouseup.tablesorter') - .bind('mousedown.tablesorter mouseup.tablesorter', function(e, external) { - // jQuery v1.2.6 doesn't have closest() - var $cell = this.tagName.match('TH|TD') ? $(this) : $(this).parents('th, td').filter(':last'), cell = $cell[0]; - // only recognize left clicks - if ((e.which || e.button) !== 1) { return false; } - // set timer on mousedown - if (e.type === 'mousedown') { - downTime = new Date().getTime(); - return e.target.tagName === "INPUT" ? '' : !c.cancelSelection; - } - // ignore long clicks (prevents resizable widget from initializing a sort) - if (external !== true && (new Date().getTime() - downTime > 250)) { return false; } - if (c.delayInit && !c.cache) { buildCache($t0); } - if (!cell.sortDisabled) { - // Only call sortStart if sorting is enabled - $this.trigger("sortStart", $t0); - // store exp, for speed - // $cell = $(this); - k = !e[c.sortMultiSortKey]; - // get current column sort order - cell.count = e[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2); - // reset all sorts on non-current column - issue #30 - if (c.sortRestart) { - i = cell; - c.$headers.each(function() { - // only reset counts on columns that weren't just clicked on and if not included in a multisort - if (this !== i && (k || !$(this).is('.' + c.cssDesc + ',.' + c.cssAsc))) { - this.count = -1; - } - }); - } - // get current column index - i = cell.column; - // user only wants to sort on one column - if (k) { - // flush the sort list - c.sortList = []; - if (c.sortForce !== null) { - a = c.sortForce; - for (j = 0; j < a.length; j++) { - if (a[j][0] !== i) { - c.sortList.push(a[j]); - } - } - } - // add column to sort list - o = cell.order[cell.count]; - if (o < 2) { - c.sortList.push([i, o]); - // add other columns if header spans across multiple - if (cell.colSpan > 1) { - for (j = 1; j < cell.colSpan; j++) { - c.sortList.push([i + j, o]); - } - } - } - // multi column sorting - } else { - // get rid of the sortAppend before adding more - fixes issue #115 - if (c.sortAppend && c.sortList.length > 1) { - if (ts.isValueInArray(c.sortAppend[0][0], c.sortList)) { - c.sortList.pop(); - } - } - // the user has clicked on an already sorted column - if (ts.isValueInArray(i, c.sortList)) { - // reverse the sorting direction for all tables - for (j = 0; j < c.sortList.length; j++) { - s = c.sortList[j]; - o = c.headerList[s[0]]; - if (s[0] === i) { - s[1] = o.order[o.count]; - if (s[1] === 2) { - c.sortList.splice(j,1); - o.count = -1; - } - } - } - } else { - // add column to sort list array - o = cell.order[cell.count]; - if (o < 2) { - c.sortList.push([i, o]); - // add other columns if header spans across multiple - if (cell.colSpan > 1) { - for (j = 1; j < cell.colSpan; j++) { - c.sortList.push([i + j, o]); - } - } - } - } - } - if (c.sortAppend !== null) { - a = c.sortAppend; - for (j = 0; j < a.length; j++) { - if (a[j][0] !== i) { - c.sortList.push(a[j]); - } - } - } - // sortBegin event triggered immediately before the sort - $this.trigger("sortBegin", $t0); - // setTimeout needed so the processing icon shows up - setTimeout(function(){ - // set css for headers - setHeadersCss($t0); - multisort($t0); - appendToTable($t0); - }, 1); - } - }); - if (c.cancelSelection) { - // cancel selection - c.$headers.each(function() { - this.onselectstart = function() { - return false; - }; - }); - } - // apply easy methods that trigger boundd events - $this - .unbind('sortReset update updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter ')) - .bind("sortReset.tablesorter", function(){ - c.sortList = []; - setHeadersCss($t0); - multisort($t0); - appendToTable($t0); - }) - .bind("update.tablesorter updateRows.tablesorter", function(e, resort, callback) { - // remove rows/elements before update - $this.find(c.selectorRemove).remove(); - // rebuild parsers - c.parsers = buildParserCache($t0); - // rebuild the cache map - buildCache($t0); - checkResort($this, resort, callback); - }) - .bind("updateCell.tablesorter", function(e, cell, resort, callback) { - $this.find(c.selectorRemove).remove(); - // get position from the dom - var l, row, icell, - $tb = $this.find('tbody'), - // update cache - format: function(s, table, cell, cellIndex) - // no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr'); - tbdy = $tb.index( $(cell).parents('tbody').filter(':last') ), - $row = $(cell).parents('tr').filter(':last'); - cell = $(cell)[0]; // in case cell is a jQuery object - // tbody may not exist if update is initialized while tbody is removed for processing - if ($tb.length && tbdy >= 0) { - row = $tb.eq(tbdy).find('tr').index( $row ); - icell = cell.cellIndex; - l = c.cache[tbdy].normalized[row].length - 1; - c.cache[tbdy].row[$t0.config.cache[tbdy].normalized[row][l]] = $row; - c.cache[tbdy].normalized[row][icell] = c.parsers[icell].format( getElementText($t0, cell, icell), $t0, cell, icell ); - checkResort($this, resort, callback); - } - }) - .bind("addRows.tablesorter", function(e, $row, resort, callback) { - var i, rows = $row.filter('tr').length, - dat = [], l = $row[0].cells.length, - tbdy = $this.find('tbody').index( $row.closest('tbody') ); - // fixes adding rows to an empty table - see issue #179 - if (!c.parsers) { - c.parsers = buildParserCache($t0); - } - // add each row - for (i = 0; i < rows; i++) { - // add each cell - for (j = 0; j < l; j++) { - dat[j] = c.parsers[j].format( getElementText($t0, $row[i].cells[j], j), $t0, $row[i].cells[j], j ); - } - // add the row index to the end - dat.push(c.cache[tbdy].row.length); - // update cache - c.cache[tbdy].row.push([$row[i]]); - c.cache[tbdy].normalized.push(dat); - dat = []; - } - // resort using current settings - checkResort($this, resort, callback); - }) - .bind("sorton.tablesorter", function(e, list, callback, init) { - $this.trigger("sortStart", this); - // update header count index - updateHeaderSortCount($t0, list); - // set css for headers - setHeadersCss($t0); - // sort the table and append it to the dom - multisort($t0); - appendToTable($t0, init); - if (typeof callback === "function") { - callback($t0); - } - }) - .bind("appendCache.tablesorter", function(e, callback, init) { - appendToTable($t0, init); - if (typeof callback === "function") { - callback($t0); - } - }) - .bind("applyWidgetId.tablesorter", function(e, id) { - ts.getWidgetById(id).format($t0, c, c.widgetOptions); - }) - .bind("applyWidgets.tablesorter", function(e, init) { - // apply widgets - ts.applyWidget($t0, init); - }) - .bind("refreshWidgets.tablesorter", function(e, all, dontapply){ - ts.refreshWidgets($t0, all, dontapply); - }) - .bind("destroy.tablesorter", function(e, c, cb){ - ts.destroy($t0, c, cb); - }); - - // get sort list from jQuery data or metadata - // in jQuery < 1.4, an error occurs when calling $this.data() - if (c.supportsDataObject && typeof $this.data().sortlist !== 'undefined') { - c.sortList = $this.data().sortlist; - } else if (m && ($this.metadata() && $this.metadata().sortlist)) { - c.sortList = $this.metadata().sortlist; - } - // apply widget init code - ts.applyWidget($t0, true); - // if user has supplied a sort list to constructor - if (c.sortList.length > 0) { - $this.trigger("sorton", [c.sortList, {}, !c.initWidgets]); - } else if (c.initWidgets) { - // apply widget format - ts.applyWidget($t0); - } - - // show processesing icon - if (c.showProcessing) { - $this - .unbind('sortBegin.tablesorter sortEnd.tablesorter') - .bind('sortBegin.tablesorter sortEnd.tablesorter', function(e) { - ts.isProcessing($t0, e.type === 'sortBegin'); - }); - } - - // initialized - $t0.hasInitialized = true; - if (c.debug) { - ts.benchmark("Overall initialization time", $.data( $t0, 'startoveralltimer')); - } - $this.trigger('tablesorter-initialized', $t0); - if (typeof c.initialized === 'function') { c.initialized($t0); } - }); - }; - - // *** Process table *** - // add processing indicator - ts.isProcessing = function(table, toggle, $ths) { - var c = table.config, - // default to all headers - $h = $ths || $(table).find('.' + c.cssHeader); - if (toggle) { - if (c.sortList.length > 0) { - // get headers from the sortList - $h = $h.filter(function(){ - // get data-column from attr to keep compatibility with jQuery 1.2.6 - return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList); - }); - } - $h.addClass(c.cssProcessing); - } else { - $h.removeClass(c.cssProcessing); - } - }; - - // detach tbody but save the position - // don't use tbody because there are portions that look for a tbody index (updateCell) - ts.processTbody = function(table, $tb, getIt){ - var t, holdr; - if (getIt) { - $tb.before(''); - holdr = ($.fn.detach) ? $tb.detach() : $tb.remove(); - return holdr; - } - holdr = $(table).find('span.tablesorter-savemyplace'); - $tb.insertAfter( holdr ); - holdr.remove(); - }; - - ts.clearTableBody = function(table) { - table.config.$tbodies.empty(); - }; - - ts.destroy = function(table, removeClasses, callback){ - if (!table.hasInitialized) { return; } - // remove all widgets - ts.refreshWidgets(table, true, true); - var $t = $(table), c = table.config, - $h = $t.find('thead:first'), - $r = $h.find('tr.' + c.cssHeaderRow).removeClass(c.cssHeaderRow), - $f = $t.find('tfoot:first > tr').children('th, td'); - // remove widget added rows, just in case - $h.find('tr').not($r).remove(); - // disable tablesorter - $t - .removeData('tablesorter') - .unbind('sortReset update updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave sortBegin sortEnd '.split(' ').join('.tablesorter ')); - c.$headers.add($f) - .removeClass(c.cssHeader + ' ' + c.cssAsc + ' ' + c.cssDesc) - .removeAttr('data-column'); - $r.find(c.selectorSort).unbind('mousedown.tablesorter mouseup.tablesorter'); - // restore headers - $r.children().each(function(i){ - $(this).html( c.headerContent[i] ); - }); - if (removeClasses !== false) { - $t.removeClass(c.tableClass + ' tablesorter-' + c.theme); - } - // clear flag in case the plugin is initialized again - table.hasInitialized = false; - if (typeof callback === 'function') { - callback(table); - } - }; - - // *** sort functions *** - // regex used in natural sort - ts.regex = [ - /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters - /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, //date - /^0x[0-9a-f]+$/i // hex - ]; - - // Natural sort - https://github.com/overset/javascript-natural-sort - ts.sortText = function(table, a, b, col) { - if (a === b) { return 0; } - var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ], - r = ts.regex, xN, xD, yN, yD, xF, yF, i, mx; - if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : -e || -1; } - if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : e || 1; } - if (typeof c.textSorter === 'function') { return c.textSorter(a, b, table, col); } - // chunk/tokenize - xN = a.replace(r[0], '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0'); - yN = b.replace(r[0], '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0'); - // numeric, hex or date detection - xD = parseInt(a.match(r[2]),16) || (xN.length !== 1 && a.match(r[1]) && Date.parse(a)); - yD = parseInt(b.match(r[2]),16) || (xD && b.match(r[1]) && Date.parse(b)) || null; - // first try and sort Hex codes or Dates - if (yD) { - if ( xD < yD ) { return -1; } - if ( xD > yD ) { return 1; } - } - mx = Math.max(xN.length, yN.length); - // natural sorting through split numeric strings and default strings - for (i = 0; i < mx; i++) { - // find floats not starting with '0', string or 0 if not defined - xF = isNaN(xN[i]) ? xN[i] || 0 : parseFloat(xN[i]) || 0; - yF = isNaN(yN[i]) ? yN[i] || 0 : parseFloat(yN[i]) || 0; - // handle numeric vs string comparison - number < string - (Kyle Adams) - if (isNaN(xF) !== isNaN(yF)) { return (isNaN(xF)) ? 1 : -1; } - // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' - if (typeof xF !== typeof yF) { - xF += ''; - yF += ''; - } - if (xF < yF) { return -1; } - if (xF > yF) { return 1; } - } - return 0; - }; - - ts.sortTextDesc = function(table, a, b, col) { - if (a === b) { return 0; } - var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ]; - if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : e || 1; } - if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : -e || -1; } - if (typeof c.textSorter === 'function') { return c.textSorter(b, a, table, col); } - return ts.sortText(table, b, a); - }; - - // return text string value by adding up ascii value - // so the text is somewhat sorted when using a digital sort - // this is NOT an alphanumeric sort - ts.getTextValue = function(a, mx, d) { - if (mx) { - // make sure the text value is greater than the max numerical value (mx) - var i, l = a ? a.length : 0, n = mx + d; - for (i = 0; i < l; i++) { - n += a.charCodeAt(i); - } - return d * n; - } - return 0; - }; - - ts.sortNumeric = function(table, a, b, col, mx, d) { - if (a === b) { return 0; } - var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ]; - if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : -e || -1; } - if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : e || 1; } - if (isNaN(a)) { a = ts.getTextValue(a, mx, d); } - if (isNaN(b)) { b = ts.getTextValue(b, mx, d); } - return a - b; - }; - - ts.sortNumericDesc = function(table, a, b, col, mx, d) { - if (a === b) { return 0; } - var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ]; - if (a === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? -1 : 1) : e || 1; } - if (b === '' && e !== 0) { return (typeof(e) === 'boolean') ? (e ? 1 : -1) : -e || -1; } - if (isNaN(a)) { a = ts.getTextValue(a, mx, d); } - if (isNaN(b)) { b = ts.getTextValue(b, mx, d); } - return b - a; - }; - - // used when replacing accented characters during sorting - ts.characterEquivalents = { - "a" : "\u00e1\u00e0\u00e2\u00e3\u00e4\u0105\u00e5", // áàâãäąå - "A" : "\u00c1\u00c0\u00c2\u00c3\u00c4\u0104\u00c5", // ÁÀÂÃÄĄÅ - "c" : "\u00e7\u0107\u010d", // çćč - "C" : "\u00c7\u0106\u010c", // ÇĆČ - "e" : "\u00e9\u00e8\u00ea\u00eb\u011b\u0119", // éèêëěę - "E" : "\u00c9\u00c8\u00ca\u00cb\u011a\u0118", // ÉÈÊËĚĘ - "i" : "\u00ed\u00ec\u0130\u00ee\u00ef\u0131", // íìİîïı - "I" : "\u00cd\u00cc\u0130\u00ce\u00cf", // ÍÌİÎÏ - "o" : "\u00f3\u00f2\u00f4\u00f5\u00f6", // óòôõö - "O" : "\u00d3\u00d2\u00d4\u00d5\u00d6", // ÓÒÔÕÖ - "ss": "\u00df", // ß (s sharp) - "SS": "\u1e9e", // ẞ (Capital sharp s) - "u" : "\u00fa\u00f9\u00fb\u00fc\u016f", // úùûüů - "U" : "\u00da\u00d9\u00db\u00dc\u016e" // ÚÙÛÜŮ - }; - ts.replaceAccents = function(s) { - var a, acc = '[', eq = ts.characterEquivalents; - if (!ts.characterRegex) { - ts.characterRegexArray = {}; - for (a in eq) { - if (typeof a === 'string') { - acc += eq[a]; - ts.characterRegexArray[a] = new RegExp('[' + eq[a] + ']', 'g'); - } - } - ts.characterRegex = new RegExp(acc + ']'); - } - if (ts.characterRegex.test(s)) { - for (a in eq) { - if (typeof a === 'string') { - s = s.replace( ts.characterRegexArray[a], a ); - } - } - } - return s; - }; - - // *** utilities *** - ts.isValueInArray = function(v, a) { - var i, l = a.length; - for (i = 0; i < l; i++) { - if (a[i][0] === v) { - return true; - } - } - return false; - }; - - ts.addParser = function(parser) { - var i, l = ts.parsers.length, a = true; - for (i = 0; i < l; i++) { - if (ts.parsers[i].id.toLowerCase() === parser.id.toLowerCase()) { - a = false; - } - } - if (a) { - ts.parsers.push(parser); - } - }; - - ts.getParserById = function(name) { - var i, l = ts.parsers.length; - for (i = 0; i < l; i++) { - if (ts.parsers[i].id.toLowerCase() === (name.toString()).toLowerCase()) { - return ts.parsers[i]; - } - } - return false; - }; - - ts.addWidget = function(widget) { - ts.widgets.push(widget); - }; - - ts.getWidgetById = function(name) { - var i, w, l = ts.widgets.length; - for (i = 0; i < l; i++) { - w = ts.widgets[i]; - if (w && w.hasOwnProperty('id') && w.id.toLowerCase() === name.toLowerCase()) { - return w; - } - } - }; - - ts.applyWidget = function(table, init) { - var c = table.config, - wo = c.widgetOptions, - ws = c.widgets.sort().reverse(), // ensure that widgets are always applied in a certain order - time, i, w, l = ws.length; - // make zebra last - i = $.inArray('zebra', c.widgets); - if (i >= 0) { - c.widgets.splice(i,1); - c.widgets.push('zebra'); - } - if (c.debug) { - time = new Date(); - } - // add selected widgets - for (i = 0; i < l; i++) { - w = ts.getWidgetById(ws[i]); - if ( w ) { - if (init === true && w.hasOwnProperty('init')) { - w.init(table, w, c, wo); - } else if (!init && w.hasOwnProperty('format')) { - w.format(table, c, wo); - } - } - } - if (c.debug) { - benchmark("Completed " + (init === true ? "initializing" : "applying") + " widgets", time); - } - }; - - ts.refreshWidgets = function(table, doAll, dontapply) { - var i, c = table.config, - cw = c.widgets, - w = ts.widgets, l = w.length; - // remove previous widgets - for (i = 0; i < l; i++){ - if ( w[i] && w[i].id && (doAll || $.inArray( w[i].id, cw ) < 0) ) { - if (c.debug) { log( 'Refeshing widgets: Removing ' + w[i].id ); } - if (w[i].hasOwnProperty('remove')) { w[i].remove(table, c, c.widgetOptions); } - } - } - if (dontapply !== true) { - ts.applyWidget(table, doAll); - } - }; - - // get sorter, string, empty, etc options for each column from - // jQuery data, metadata, header option or header class name ("sorter-false") - // priority = jQuery data > meta > headers option > header class name - ts.getData = function(h, ch, key) { - var val = '', $h = $(h), m, cl; - if (!$h.length) { return ''; } - m = $.metadata ? $h.metadata() : false; - cl = ' ' + ($h.attr('class') || ''); - if (typeof $h.data(key) !== 'undefined' || typeof $h.data(key.toLowerCase()) !== 'undefined'){ - // "data-lockedOrder" is assigned to "lockedorder"; but "data-locked-order" is assigned to "lockedOrder" - // "data-sort-initial-order" is assigned to "sortInitialOrder" - val += $h.data(key) || $h.data(key.toLowerCase()); - } else if (m && typeof m[key] !== 'undefined') { - val += m[key]; - } else if (ch && typeof ch[key] !== 'undefined') { - val += ch[key]; - } else if (cl !== ' ' && cl.match(' ' + key + '-')) { - // include sorter class name "sorter-text", etc - val = cl.match( new RegExp(' ' + key + '-(\\w+)') )[1] || ''; - } - return $.trim(val); - }; - - ts.formatFloat = function(s, table) { - if (typeof(s) !== 'string' || s === '') { return s; } - // allow using formatFloat without a table; defaults to US number format - var i, - t = table && table.config ? table.config.usNumberFormat !== false : - typeof table !== "undefined" ? table : true; - if (t) { - // US Format - 1,234,567.89 -> 1234567.89 - s = s.replace(/,/g,''); - } else { - // German Format = 1.234.567,89 -> 1234567.89 - // French Format = 1 234 567,89 -> 1234567.89 - s = s.replace(/[\s|\.]/g,'').replace(/,/g,'.'); - } - if(/^\s*\([.\d]+\)/.test(s)) { - // make (#) into a negative number -> (10) = -10 - s = s.replace(/^\s*\(/,'-').replace(/\)/,''); - } - i = parseFloat(s); - // return the text instead of zero - return isNaN(i) ? $.trim(s) : i; - }; - - ts.isDigit = function(s) { - // replace all unwanted chars and match - return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : true; - }; - - }() - }); - - // make shortcut - var ts = $.tablesorter; - - // extend plugin scope - $.fn.extend({ - tablesorter: ts.construct - }); - - // add default parsers - ts.addParser({ - id: "text", - is: function(s, table, node) { - return true; - }, - format: function(s, table, cell, cellIndex) { - var c = table.config; - s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s ); - return c.sortLocaleCompare ? ts.replaceAccents(s) : s; - }, - type: "text" - }); - - ts.addParser({ - id: "currency", - is: function(s) { - return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[,. ]/g,'')); // £$€¤¥¢ - }, - format: function(s, table) { - return ts.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "ipAddress", - is: function(s) { - return (/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/).test(s); - }, - format: function(s, table) { - var i, a = s.split("."), - r = "", - l = a.length; - for (i = 0; i < l; i++) { - r += ("00" + a[i]).slice(-3); - } - return ts.formatFloat(r, table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "url", - is: function(s) { - return (/^(https?|ftp|file):\/\//).test(s); - }, - format: function(s) { - return $.trim(s.replace(/(https?|ftp|file):\/\//, '')); - }, - type: "text" - }); - - ts.addParser({ - id: "isoDate", - is: function(s) { - return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s); - }, - format: function(s, table) { - return ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || "") : "", table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "percent", - is: function(s) { - return (/(\d\s?%|%\s?\d)/).test(s); - }, - format: function(s, table) { - return ts.formatFloat(s.replace(/%/g, ""), table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "usLongDate", - is: function(s) { - // two digit years are not allowed cross-browser - // Jan 01, 2013 12:34:56 PM or 01 Jan 2013 - return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s); - }, - format: function(s, table) { - return ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ''), table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "shortDate", // "mmddyyyy", "ddmmyyyy" or "yyyymmdd" - is: function(s) { - // testing for ####-##-####, so it's not perfect - return (/^(\d{1,2}|\d{4})[\/\-\,\.\s+]\d{1,2}[\/\-\.\,\s+](\d{1,2}|\d{4})$/).test(s); - }, - format: function(s, table, cell, cellIndex) { - var c = table.config, ci = c.headerList[cellIndex], - format = ci.shortDateFormat; - if (typeof format === 'undefined') { - // cache header formatting so it doesn't getData for every cell in the column - format = ci.shortDateFormat = ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat; - } - s = s.replace(/\s+/g," ").replace(/[\-|\.|\,]/g, "/"); - if (format === "mmddyyyy") { - s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2"); - } else if (format === "ddmmyyyy") { - s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1"); - } else if (format === "yyyymmdd") { - s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3"); - } - return ts.formatFloat( (new Date(s).getTime() || ''), table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "time", - is: function(s) { - return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s); - }, - format: function(s, table) { - return ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ""), table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "digit", - is: function(s) { - return ts.isDigit(s); - }, - format: function(s, table) { - return ts.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table); - }, - type: "numeric" - }); - - ts.addParser({ - id: "metadata", - is: function(s) { - return false; - }, - format: function(s, table, cell) { - var c = table.config, - p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; - return $(cell).metadata()[p]; - }, - type: "numeric" - }); - - // add default widgets - ts.addWidget({ - id: "zebra", - format: function(table, c, wo) { - var $tb, $tv, $tr, row, even, time, k, l, - child = new RegExp(c.cssChildRow, 'i'), - b = c.$tbodies; - if (c.debug) { - time = new Date(); - } - for (k = 0; k < b.length; k++ ) { - // loop through the visible rows - $tb = b.eq(k); - l = $tb.children('tr').length; - if (l > 1) { - row = 0; - $tv = $tb.children('tr:visible'); - // revered back to using jQuery each - strangely it's the fastest method - /*jshint loopfunc:true */ - $tv.each(function(){ - $tr = $(this); - // style children rows the same way the parent row was styled - if (!child.test(this.className)) { row++; } - even = (row % 2 === 0); - $tr.removeClass(wo.zebra[even ? 1 : 0]).addClass(wo.zebra[even ? 0 : 1]); - }); - } - } - if (c.debug) { - ts.benchmark("Applying Zebra widget", time); - } - }, - remove: function(table, c, wo){ - var k, $tb, - b = c.$tbodies, - rmv = (c.widgetOptions.zebra || [ "even", "odd" ]).join(' '); - for (k = 0; k < b.length; k++ ){ - $tb = $.tablesorter.processTbody(table, b.eq(k), true); // remove tbody - $tb.children().removeClass(rmv); - $.tablesorter.processTbody(table, $tb, false); // restore tbody - } - } - }); - -})(jQuery); \ No newline at end of file diff --git a/UI/JsLibraries/jquery.tablesorter.pager.js b/UI/JsLibraries/jquery.tablesorter.pager.js deleted file mode 100644 index 99081c8bf..000000000 --- a/UI/JsLibraries/jquery.tablesorter.pager.js +++ /dev/null @@ -1,575 +0,0 @@ -/*! - * tablesorter pager plugin - * updated 2/20/2013 - */ -/*jshint browser:true, jquery:true, unused:false */ -;(function($) { - "use strict"; - /*jshint supernew:true */ - $.extend({ tablesorterPager: new function() { - - this.defaults = { - // target the pager markup - container: null, - - // use this format: "http://mydatabase.com?page={page}&size={size}&{sortList:col}&{filterList:fcol}" - // where {page} is replaced by the page number, {size} is replaced by the number of records to show, - // {sortList:col} adds the sortList to the url into a "col" array, and {filterList:fcol} adds - // the filterList to the url into an "fcol" array. - // So a sortList = [[2,0],[3,0]] becomes "&col[2]=0&col[3]=0" in the url - // and a filterList = [[2,Blue],[3,13]] becomes "&fcol[2]=Blue&fcol[3]=13" in the url - ajaxUrl: null, - - // process ajax so that the following information is returned: - // [ total_rows (number), rows (array of arrays), headers (array; optional) ] - // example: - // [ - // 100, // total rows - // [ - // [ "row1cell1", "row1cell2", ... "row1cellN" ], - // [ "row2cell1", "row2cell2", ... "row2cellN" ], - // ... - // [ "rowNcell1", "rowNcell2", ... "rowNcellN" ] - // ], - // [ "header1", "header2", ... "headerN" ] // optional - // ] - ajaxProcessing: function(ajax){ return [ 0, [], null ]; }, - - // output default: '{page}/{totalPages}' - // possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} - output: '{startRow} to {endRow} of {totalRows} rows', // '{page}/{totalPages}' - - // apply disabled classname to the pager arrows when the rows at either extreme is visible - updateArrows: true, - - // starting page of the pager (zero based index) - page: 0, - - // Number of visible rows - size: 10, - - // if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty - // table row set to a height to compensate; default is false - fixedHeight: false, - - // remove rows from the table to speed up the sort of large tables. - // setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled. - removeRows: false, // removing rows in larger tables speeds up the sort - - // css class names of pager arrows - cssFirst: '.first', // go to first page arrow - cssPrev: '.prev', // previous page arrow - cssNext: '.next', // next page arrow - cssLast: '.last', // go to last page arrow - cssGoto: '.gotoPage', // go to page selector - select dropdown that sets the current page - cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed - cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option - cssErrorRow: 'tablesorter-errorRow', // error information row - - // class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page) - cssDisabled: 'disabled', // Note there is no period "." in front of this class name - - // stuff not set by the user - totalRows: 0, - totalPages: 0, - filteredRows: 0, - filteredPages: 0 - - }; - - var $this = this, - - // hide arrows at extremes - pagerArrows = function(c, disable) { - var a = 'addClass', - r = 'removeClass', - d = c.cssDisabled, - dis = !!disable, - tp = Math.min( c.totalPages, c.filteredPages ); - if ( c.updateArrows ) { - $(c.cssFirst + ',' + c.cssPrev, c.container)[ ( dis || c.page === 0 ) ? a : r ](d); - $(c.cssNext + ',' + c.cssLast, c.container)[ ( dis || c.page === tp - 1 ) ? a : r ](d); - } - }, - - updatePageDisplay = function(table, c) { - var i, p, s, t, out, f = $(table).hasClass('hasFilters') && !c.ajaxUrl; - c.filteredRows = (f) ? table.config.$tbodies.children('tr:not(.filtered,.remove-me)').length : c.totalRows; - c.filteredPages = (f) ? Math.ceil( c.filteredRows / c.size ) : c.totalPages; - if ( Math.min( c.totalPages, c.filteredPages ) > 0 ) { - t = (c.size * c.page > c.filteredRows); - c.startRow = (t) ? 1 : ( c.size * c.page ) + 1; - c.page = (t) ? 0 : c.page; - c.endRow = Math.min( c.filteredRows, c.totalRows, c.size * ( c.page + 1 ) ); - out = $(c.cssPageDisplay, c.container); - // form the output string - s = c.output.replace(/\{(page|filteredRows|filteredPages|totalPages|startRow|endRow|totalRows)\}/gi, function(m){ - return { - '{page}' : c.page + 1, - '{filteredRows}' : c.filteredRows, - '{filteredPages}' : c.filteredPages, - '{totalPages}' : c.totalPages, - '{startRow}' : c.startRow, - '{endRow}' : c.endRow, - '{totalRows}' : c.totalRows - }[m]; - }); - if (out[0]) { - out[ (out[0].tagName === 'INPUT') ? 'val' : 'html' ](s); - if ( $(c.cssGoto, c.container).length ) { - t = ''; - p = Math.min( c.totalPages, c.filteredPages ); - for ( i = 1; i <= p; i++ ) { - t += ''; - } - $(c.cssGoto, c.container).html(t).val(c.page + 1); - } - } - } - pagerArrows(c); - if (c.initialized) { $(table).trigger('pagerComplete', c); } - }, - - fixHeight = function(table, c) { - var d, h, $b = $(table.tBodies[0]); - if (c.fixedHeight) { - $b.find('tr.pagerSavedHeightSpacer').remove(); - h = $.data(table, 'pagerSavedHeight'); - if (h) { - d = h - $b.height(); - if ( d > 5 && $.data(table, 'pagerLastSize') === c.size && $b.children('tr:visible').length < c.size ) { - $b.append(''); - } - } - } - }, - - changeHeight = function(table, c) { - var $b = $(table.tBodies[0]); - $b.find('tr.pagerSavedHeightSpacer').remove(); - $.data(table, 'pagerSavedHeight', $b.height()); - fixHeight(table, c); - $.data(table, 'pagerLastSize', c.size); - }, - - hideRows = function(table, c){ - if (!c.ajaxUrl) { - var i, - rows = $(table.tBodies).children('tr:not(.' + table.config.cssChildRow + ')'), - l = rows.length, - s = ( c.page * c.size ), - e = s + c.size, - j = 0; // size counter - for ( i = 0; i < l; i++ ){ - if (!/filtered/.test(rows[i].className)) { - rows[i].style.display = ( j >= s && j < e ) ? '' : 'none'; - j++; - } - } - } - }, - - hideRowsSetup = function(table, c){ - c.size = parseInt( $(c.cssPageSize, c.container).find('option[selected]').val(), 10 ) || c.size; - $.data(table, 'pagerLastSize', c.size); - pagerArrows(c); - if ( !c.removeRows ) { - hideRows(table, c); - $(table).bind('sortEnd.pager filterEnd.pager', function(){ - hideRows(table, c); - }); - } - }, - - renderAjax = function(data, table, c, exception){ - // process data - if ( typeof(c.ajaxProcessing) === "function" ) { - // ajaxProcessing result: [ total, rows, headers ] - var i, j, hsh, $f, $sh, - $t = $(table), - tc = table.config, - hl = $t.find('thead th').length, tds = '', - err = '' + - (exception ? exception.message + ' (' + exception.name + ')' : 'No rows found') + '', - result = c.ajaxProcessing(data) || [ 0, [] ], - d = result[1] || [], - l = d.length, - th = result[2]; - if ( l > 0 ) { - for ( i = 0; i < l; i++ ) { - tds += ''; - for ( j = 0; j < d[i].length; j++ ) { - // build tbody cells - tds += '' + d[i][j] + ''; - } - tds += ''; - } - } - // only add new header text if the length matches - if ( th && th.length === hl ) { - hsh = $t.hasClass('hasStickyHeaders'); - $sh = $t.find('.' + ((tc.widgetOptions && tc.widgetOptions.stickyHeaders) || 'tablesorter-stickyheader')); - $f = $t.find('tfoot tr:first').children(); - $t.find('th.' + tc.cssHeader).each(function(j){ - var $t = $(this), icn; - // add new test within the first span it finds, or just in the header - if ( $t.find('.' + tc.cssIcon).length ) { - icn = $t.find('.' + tc.cssIcon).clone(true); - $t.find('.tablesorter-header-inner').html( th[j] ).append(icn); - if ( hsh && $sh.length ) { - icn = $sh.find('th').eq(j).find('.' + tc.cssIcon).clone(true); - $sh.find('th').eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icn); - } - } else { - $t.find('.tablesorter-header-inner').html( th[j] ); - $sh.find('th').eq(j).find('.tablesorter-header-inner').html( th[j] ); - } - $f.eq(j).html( th[j] ); - }); - } - - $t.find('thead tr.' + c.cssErrorRow).remove(); // Clean up any previous error. - if ( exception ) { - // add error row to thead instead of tbody, or clicking on the header will result in a parser error - $t.find('thead').append(err); - } else { - $(table.tBodies[0]).html( tds ); // add rows to first tbody - } - if (tc.showProcessing) { - $.tablesorter.isProcessing(table); // remove loading icon - } - $t.trigger('update'); - c.totalRows = result[0] || 0; - c.totalPages = Math.ceil( c.totalRows / c.size ); - updatePageDisplay(table, c); - fixHeight(table, c); - if (c.initialized) { $t.trigger('pagerChange', c); } - } - if (!c.initialized) { - c.initialized = true; - $(table).trigger('pagerInitialized', c); - } - }, - - getAjax = function(table, c){ - var url = getAjaxUrl(table, c), - tc = table.config; - if ( url !== '' ) { - if (tc.showProcessing) { - $.tablesorter.isProcessing(table, true); // show loading icon - } - $(document).bind('ajaxError.pager', function(e, xhr, settings, exception) { - if (settings.url === url) { - renderAjax(null, table, c, exception); - $(document).unbind('ajaxError.pager'); - } - }); - $.getJSON(url, function(data) { - renderAjax(data, table, c); - $(document).unbind('ajaxError.pager'); - }); - } - }, - - getAjaxUrl = function(table, c) { - var url = (c.ajaxUrl) ? c.ajaxUrl.replace(/\{page\}/g, c.page).replace(/\{size\}/g, c.size) : '', - sl = table.config.sortList, - fl = c.currentFilters || [], - sortCol = url.match(/\{sortList[\s+]?:[\s+]?([^}]*)\}/), - filterCol = url.match(/\{filterList[\s+]?:[\s+]?([^}]*)\}/), - arry = []; - if (sortCol) { - sortCol = sortCol[1]; - $.each(sl, function(i,v){ - arry.push(sortCol + '[' + v[0] + ']=' + v[1]); - }); - // if the arry is empty, just add the col parameter... "&{sortList:col}" becomes "&col" - url = url.replace(/\{sortList[\s+]?:[\s+]?([^\}]*)\}/g, arry.length ? arry.join('&') : sortCol ); - } - if (filterCol) { - filterCol = filterCol[1]; - $.each(fl, function(i,v){ - if (v) { - arry.push(filterCol + '[' + i + ']=' + encodeURIComponent(v)); - } - }); - // if the arry is empty, just add the fcol parameter... "&{filterList:fcol}" becomes "&fcol" - url = url.replace(/\{filterList[\s+]?:[\s+]?([^\}]*)\}/g, arry.length ? arry.join('&') : filterCol ); - } - - return url; - }, - - renderTable = function(table, rows, c) { - c.isDisabled = false; // needed because sorting will change the page and re-enable the pager - var i, j, o, - f = document.createDocumentFragment(), - l = rows.length, - s = ( c.page * c.size ), - e = ( s + c.size ); - if ( l < 1 ) { return; } // empty table, abort! - if (c.initialized) { $(table).trigger('pagerChange', c); } - if ( !c.removeRows ) { - hideRows(table, c); - } else { - if ( e > rows.length ) { - e = rows.length; - } - $(table.tBodies[0]).addClass('tablesorter-hidden'); - $.tablesorter.clearTableBody(table); - for ( i = s; i < e; i++ ) { - o = rows[i]; - l = o.length; - for ( j = 0; j < l; j++ ) { - f.appendChild(o[j]); - } - } - table.tBodies[0].appendChild(f); - $(table.tBodies[0]).removeClass('tablesorter-hidden'); - } - if ( c.page >= c.totalPages ) { - moveToLastPage(table, c); - } - updatePageDisplay(table, c); - if ( !c.isDisabled ) { fixHeight(table, c); } - $(table).trigger('applyWidgets'); - }, - - showAllRows = function(table, c){ - if ( c.ajax ) { - pagerArrows(c, true); - } else { - c.isDisabled = true; - $.data(table, 'pagerLastPage', c.page); - $.data(table, 'pagerLastSize', c.size); - c.page = 0; - c.size = c.totalRows; - c.totalPages = 1; - $('tr.pagerSavedHeightSpacer', table.tBodies[0]).remove(); - renderTable(table, table.config.rowsCopy, c); - } - // disable size selector - $(c.container).find(c.cssPageSize + ',' + c.cssGoto).each(function(){ - $(this).addClass(c.cssDisabled)[0].disabled = true; - }); - }, - - moveToPage = function(table, c) { - if ( c.isDisabled ) { return; } - var p = Math.min( c.totalPages, c.filteredPages ); - if ( c.page < 0 ) { c.page = 0; } - if ( c.page > ( p - 1 ) && p !== 0 ) { c.page = p - 1; } - if (c.ajax) { - getAjax(table, c); - } else if (!c.ajax) { - renderTable(table, table.config.rowsCopy, c); - } - $.data(table, 'pagerLastPage', c.page); - $.data(table, 'pagerUpdateTriggered', true); - if (c.initialized) { $(table).trigger('pageMoved', c); } - }, - - setPageSize = function(table, size, c) { - c.size = size; - $.data(table, 'pagerLastPage', c.page); - $.data(table, 'pagerLastSize', c.size); - c.totalPages = Math.ceil( c.totalRows / c.size ); - moveToPage(table, c); - }, - - moveToFirstPage = function(table, c) { - c.page = 0; - moveToPage(table, c); - }, - - moveToLastPage = function(table, c) { - c.page = ( Math.min( c.totalPages, c.filteredPages ) - 1 ); - moveToPage(table, c); - }, - - moveToNextPage = function(table, c) { - c.page++; - if ( c.page >= ( Math.min( c.totalPages, c.filteredPages ) - 1 ) ) { - c.page = ( Math.min( c.totalPages, c.filteredPages ) - 1 ); - } - moveToPage(table, c); - }, - - moveToPrevPage = function(table, c) { - c.page--; - if ( c.page <= 0 ) { - c.page = 0; - } - moveToPage(table, c); - }, - - destroyPager = function(table, c){ - showAllRows(table, c); - $(c.container).hide(); // hide pager - table.config.appender = null; // remove pager appender function - $(table).unbind('destroy.pager sortEnd.pager filterEnd.pager enable.pager disable.pager'); - }, - - enablePager = function(table, c, triggered){ - var p = $(c.cssPageSize, c.container).removeClass(c.cssDisabled).removeAttr('disabled'); - $(c.container).find(c.cssGoto).removeClass(c.cssDisabled).removeAttr('disabled'); - c.isDisabled = false; - c.page = $.data(table, 'pagerLastPage') || c.page || 0; - c.size = $.data(table, 'pagerLastSize') || parseInt(p.find('option[selected]').val(), 10) || c.size; - p.val(c.size); // set page size - c.totalPages = Math.ceil( Math.min( c.totalPages, c.filteredPages ) / c.size); - if ( triggered ) { - $(table).trigger('update'); - setPageSize(table, c.size, c); - hideRowsSetup(table, c); - fixHeight(table, c); - } - }; - - $this.appender = function(table, rows) { - var c = table.config.pager; - if ( !c.ajax ) { - table.config.rowsCopy = rows; - c.totalRows = rows.length; - c.size = $.data(table, 'pagerLastSize') || c.size; - c.totalPages = Math.ceil(c.totalRows / c.size); - renderTable(table, rows, c); - } - }; - - $this.construct = function(settings) { - return this.each(function() { - // check if tablesorter has initialized - if (!(this.config && this.hasInitialized)) { return; } - var t, ctrls, fxn, - config = this.config, - c = config.pager = $.extend( {}, $.tablesorterPager.defaults, settings ), - table = this, - tc = table.config, - $t = $(table), - pager = $(c.container).addClass('tablesorter-pager').show(); // added in case the pager is reinitialized after being destroyed. - config.appender = $this.appender; - - $t - .unbind('filterStart.pager filterEnd.pager sortEnd.pager disable.pager enable.pager destroy.pager update.pager pageSize.pager') - .bind('filterStart.pager', function(e, filters) { - $.data(table, 'pagerUpdateTriggered', false); - c.currentFilters = filters; - }) - // update pager after filter widget completes - .bind('filterEnd.pager sortEnd.pager', function(e) { - //Prevent infinite event loops from occuring by setting this in all moveToPage calls and catching it here. - if ($.data(table, 'pagerUpdateTriggered')) { - $.data(table, 'pagerUpdateTriggered', false); - return; - } - if (e.type === 'filterEnd') { c.page = 0; } - moveToPage(table, c); - updatePageDisplay(table, c); - fixHeight(table, c); - }) - .bind('disable.pager', function(){ - showAllRows(table, c); - }) - .bind('enable.pager', function(){ - enablePager(table, c, true); - }) - .bind('destroy.pager', function(){ - destroyPager(table, c); - }) - .bind('update.pager', function(){ - hideRows(table, c); - }) - .bind('pageSize.pager', function(e,v){ - c.size = parseInt(v, 10) || 10; - hideRows(table, c); - updatePageDisplay(table, c); - }) - .bind('pageSet.pager', function(e,v){ - c.page = (parseInt(v, 10) || 1) - 1; - moveToPage(table, c); - updatePageDisplay(table, c); - }); - - // clicked controls - ctrls = [c.cssFirst, c.cssPrev, c.cssNext, c.cssLast]; - fxn = [ moveToFirstPage, moveToPrevPage, moveToNextPage, moveToLastPage ]; - - pager.find(ctrls.join(',')) - .unbind('click.pager') - .bind('click.pager', function(e){ - var i, $this = $(this), l = ctrls.length; - if ( !$this.hasClass(c.cssDisabled) ) { - for (i = 0; i < l; i++) { - if ($this.is(ctrls[i])) { - fxn[i](table, c); - break; - } - } - } - return false; - }); - - // goto selector - if ( pager.find(c.cssGoto).length ) { - pager.find(c.cssGoto) - .unbind('change') - .bind('change', function(){ - c.page = $(this).val() - 1; - moveToPage(table, c); - }); - updatePageDisplay(table, c); - } - - // page size selector - t = pager.find(c.cssPageSize); - if ( t.length ) { - t.unbind('change.pager').bind('change.pager', function() { - t.val( $(this).val() ); // in case there are more than one pagers - if ( !$(this).hasClass(c.cssDisabled) ) { - setPageSize(table, parseInt( $(this).val(), 10 ), c); - changeHeight(table, c); - } - return false; - }); - } - - // clear initialized flag - c.initialized = false; - // before initialization event - $t.trigger('pagerBeforeInitialized', c); - - enablePager(table, c, false); - - if ( typeof(c.ajaxUrl) === 'string' ) { - // ajax pager; interact with database - c.ajax = true; - //When filtering with ajax, allow only custom filtering function, disable default filtering since it will be done server side. - tc.widgetOptions.filter_serversideFiltering = true; - tc.serverSideSorting = true; - moveToPage(table, c); - } else { - c.ajax = false; - // Regular pager; all rows stored in memory - $(this).trigger("appendCache", true); - hideRowsSetup(table, c); - } - - changeHeight(table, c); - - // pager initialized - if (!c.ajax) { - c.initialized = true; - $(table).trigger('pagerInitialized', c); - } - }); - }; - - }() - }); -// extend plugin scope - $.fn.extend({ - tablesorterPager: $.tablesorterPager.construct - }); - -})(jQuery); \ No newline at end of file diff --git a/UI/Mixins/tablesorter.extensions.js b/UI/Mixins/tablesorter.extensions.js deleted file mode 100644 index 7ecbe5f9d..000000000 --- a/UI/Mixins/tablesorter.extensions.js +++ /dev/null @@ -1,50 +0,0 @@ -$.tablesorter.addParser({ - // set a unique id - id : 'title', - is : function () { - // return false so this parser is not auto detected - return false; - }, - format: function (s) { - // format your data for normalization - return s.match(/title="(.*?)"/)[1].toLowerCase(); - }, - // set type, either numeric or text - type : 'text' -}); - -$.tablesorter.addParser({ - // set a unique id - id : 'date', - is : function () { - // return false so this parser is not auto detected - return false; - }, - format: function (s) { - // format your data for normalization - var match = s.match(/data-date="(.*?)"/)[1]; - - if (match === '') { - return Date.create().addYears(100).format(Date.ISO8601_DATETIME); - } - - return match; - }, - // set type, either numeric or text - type : 'text' -}); - -$.tablesorter.addParser({ - // set a unique id - id : 'innerHtml', - is : function () { - // return false so this parser is not auto detected - return false; - }, - format: function (s) { - // format your data for normalization - return $(s).get(0).innerHTML; - }, - // set type, either numeric or text - type : 'text' -});