diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/filter.formatter.css b/ajax/libs/jquery.tablesorter/2.15.14/css/filter.formatter.css new file mode 100644 index 000000000..cb5dde1f0 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/filter.formatter.css @@ -0,0 +1,183 @@ +/**** Filter Formatter Elements ****/ +.tablesorter .tablesorter-filter-row td { + text-align: center; + font-size: 0.9em; + font-weight: normal; +} + +/**** Sliders ****/ +/* shrink the sliders to look nicer inside of a table cell */ +.tablesorter .ui-slider, .tablesorter input.range { + width: 90%; + margin: 2px auto 2px auto; /* add enough top margin so the tooltips will fit */ + font-size: 0.8em; +} +.tablesorter .ui-slider { + top: 12px; +} +.tablesorter .ui-slider .ui-slider-handle { + width: 0.9em; + height: 0.9em; +} +.tablesorter .ui-datepicker { + font-size: 0.8em; +} +.tablesorter .ui-slider-horizontal { + height: 0.5em; +} +/* Add tooltips to slider handles */ +.tablesorter .value-popup:after { + content : attr(data-value); + position: absolute; + bottom: 14px; + left: -7px; + min-width: 18px; + height: 12px; + background-color: #444; + background-image: -webkit-gradient(linear, left top, left bottom, from(#444444), to(#999999)); + background-image: -webkit-linear-gradient(top, #444, #999); + background-image: -moz-linear-gradient(top, #444, #999); + background-image: -o-linear-gradient(top, #444, #999); + background-image: linear-gradient(to bottom, #444, #999); + -webkit-border-radius: 3px; + border-radius: 3px; + -webkit-background-clip: padding-box; background-clip: padding-box; + -webkit-box-shadow: 0px 0px 4px 0px #777; + box-shadow: 0px 0px 4px 0px #777; + border: #444 1px solid; + color: #fff; + font: 1em/1.1em Arial, Sans-Serif; + padding: 1px; + text-align: center; +} +.tablesorter .value-popup:before { + content: ""; + position: absolute; + width: 0; + height: 0; + border-top: 8px solid #777; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + top: -8px; + left: 50%; + margin-left: -8px; + margin-top: -1px; +} + +/**** Date Picker ****/ +.tablesorter .dateFrom, .tablesorter .dateTo { + width: 80px; + margin: 2px 5px; +} + +/**** Color Picker/HTML5Number Toggle button ****/ +.tablesorter .button { + width: 14px; + height: 14px; + background: #fcfff4; + background: -webkit-linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); + background: -moz-linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); + background: -o-linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); + background: -ms-linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); + background: linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfff4', endColorstr='#b3bead', GradientType=0 ); + margin: 1px 5px 1px 1px; + -webkit-border-radius: 25px; + -moz-border-radius: 25px; + border-radius: 25px; + -webkit-box-shadow: inset 0px 1px 1px white, 0px 1px 3px rgba(0,0,0,0.5); + -moz-box-shadow: inset 0px 1px 1px white, 0px 1px 3px rgba(0,0,0,0.5); + box-shadow: inset 0px 1px 1px white, 0px 1px 3px rgba(0,0,0,0.5); + position: relative; + top: 3px; + display: inline-block; +} + +.tablesorter .button label { + cursor: pointer; + position: absolute; + width: 10px; + height: 10px; + -webkit-border-radius: 25px; + -moz-border-radius: 25px; + border-radius: 25px; + left: 2px; + top: 2px; + -webkit-box-shadow: inset 0px 1px 1px rgba(0,0,0,0.5), 0px 1px 0px rgba(255,255,255,1); + -moz-box-shadow: inset 0px 1px 1px rgba(0,0,0,0.5), 0px 1px 0px rgba(255,255,255,1); + box-shadow: inset 0px 1px 1px rgba(0,0,0,0.5), 0px 1px 0px rgba(255,255,255,1); + background: #45484d; + background: -webkit-linear-gradient(top, #222 0%, #45484d 100%); + background: -moz-linear-gradient(top, #222 0%, #45484d 100%); + background: -o-linear-gradient(top, #222 0%, #45484d 100%); + background: -ms-linear-gradient(top, #222 0%, #45484d 100%); + background: linear-gradient(top, #222 0%, #45484d 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#222', endColorstr='#45484d', GradientType=0 ); +} + +.tablesorter .button label:after { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + opacity: 0; + content: ''; + position: absolute; + width: 8px; + height: 8px; + background: #55f; + background: -webkit-linear-gradient(top, #aaf 0%, #55f 100%); + background: -moz-linear-gradient(top, #aaf 0%, #55f 100%); + background: -o-linear-gradient(top, #aaf 0%, #55f 100%); + background: -ms-linear-gradient(top, #aaf 0%, #55f 100%); + background: linear-gradient(top, #aaf 0%, #55f 100%); + -webkit-border-radius: 25px; + -moz-border-radius: 25px; + border-radius: 25px; + top: 1px; + left: 1px; + -webkit-box-shadow: inset 0px 1px 1px #fff, 0px 1px 3px rgba(0,0,0,0.5); + -moz-box-shadow: inset 0px 1px 1px #fff, 0px 1px 3px rgba(0,0,0,0.5); + box-shadow: inset 0px 1px 1px #fff, 0px 1px 3px rgba(0,0,0,0.5); +} + +.tablesorter .button label:hover::after { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; + filter: alpha(opacity=30); + opacity: 0.3; +} + +.tablesorter .button input[type=checkbox] { + visibility: hidden; +} + +.tablesorter .button input[type=checkbox]:checked + label:after { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); + opacity: 1; +} + +.tablesorter .colorpicker { + width: 30px; + height: 18px; +} +.tablesorter .ui-spinner-input { + width: 100px; + height: 18px; +} +.tablesorter .currentColor, .tablesorter .ui-spinner { + position: relative; +} +.tablesorter input.number { + position: relative; +} + +/* hide filter row */ +.tablesorter .tablesorter-filter-row.hideme td * { + 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); +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-asc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-asc.gif new file mode 100644 index 000000000..730533fa3 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-asc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-desc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-desc.gif new file mode 100644 index 000000000..4c3b61020 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-desc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-unsorted.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-unsorted.gif new file mode 100644 index 000000000..5647f6583 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/black-unsorted.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-asc-hovered.png b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-asc-hovered.png new file mode 100644 index 000000000..bc45223f1 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-asc-hovered.png differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-asc.png b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-asc.png new file mode 100644 index 000000000..0d6ee1505 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-asc.png differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-desc-hovered.png b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-desc-hovered.png new file mode 100644 index 000000000..493094204 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-desc-hovered.png differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-desc.png b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-desc.png new file mode 100644 index 000000000..0bce65a07 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/dropbox-desc.png differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-asc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-asc.gif new file mode 100644 index 000000000..4cfba0950 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-asc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-desc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-desc.gif new file mode 100644 index 000000000..4f8817650 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-desc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-header.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-header.gif new file mode 100644 index 000000000..cc746b70a Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-header.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-unsorted.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-unsorted.gif new file mode 100644 index 000000000..0afe2c021 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/green-unsorted.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-asc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-asc.gif new file mode 100644 index 000000000..0961d9aaf Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-asc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-desc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-desc.gif new file mode 100644 index 000000000..0330fccaa Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-desc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-unsorted.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-unsorted.gif new file mode 100644 index 000000000..c1afde558 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/ice-unsorted.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-asc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-asc.gif new file mode 100644 index 000000000..2173b0a05 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-asc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-desc.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-desc.gif new file mode 100644 index 000000000..7109c3ea1 Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-desc.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-unsorted.gif b/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-unsorted.gif new file mode 100644 index 000000000..9bfc3459c Binary files /dev/null and b/ajax/libs/jquery.tablesorter/2.15.14/css/images/white-unsorted.gif differ diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.black-ice.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.black-ice.css new file mode 100644 index 000000000..a5911aaeb --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.black-ice.css @@ -0,0 +1,186 @@ +/************* + Black Ice Theme (by thezoggy) + *************/ +/* overall */ +.tablesorter-blackice { + width: 100%; + margin-right: auto; + margin-left: auto; + font: 11px/18px Arial, Sans-serif; + text-align: left; + background-color: #000; + border-collapse: collapse; + border-spacing: 0; +} + +/* header */ +.tablesorter-blackice th, +.tablesorter-blackice thead td { + padding: 4px; + font: bold 13px/20px Arial, Sans-serif; + color: #e5e5e5; + text-align: left; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.7); + background-color: #111; + border: 1px solid #232323; +} +.tablesorter-blackice .header, +.tablesorter-blackice .tablesorter-header { + padding: 4px 20px 4px 4px; + cursor: pointer; + background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); + background-position: center right; + background-repeat: no-repeat; +} +.tablesorter-blackice .headerSortUp, +.tablesorter-blackice .tablesorter-headerSortUp, +.tablesorter-blackice .tablesorter-headerAsc { + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); + color: #fff; +} +.tablesorter-blackice .headerSortDown, +.tablesorter-blackice .tablesorter-headerSortDown, +.tablesorter-blackice .tablesorter-headerDesc { + color: #fff; + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); +} +.tablesorter-blackice thead .sorter-false { + background-image: none; + cursor: default; + padding: 4px; +} + +/* tfoot */ +.tablesorter-blackice tfoot .tablesorter-headerSortUp, +.tablesorter-blackice tfoot .tablesorter-headerSortDown, +.tablesorter-blackice tfoot .tablesorter-headerAsc, +.tablesorter-blackice tfoot .tablesorter-headerDesc { + /* remove sort arrows from footer */ + background-image: none; +} + +/* tbody */ +.tablesorter-blackice td { + padding: 4px; + color: #ccc; + vertical-align: top; + background-color: #333; + border: 1px solid #232323; +} + +/* hovered row colors */ +.tablesorter-blackice tbody > tr:hover > td, +.tablesorter-blackice tbody > tr.even:hover > td, +.tablesorter-blackice tbody > tr.odd:hover > td { + background: #000; +} + +/* table processing indicator */ +.tablesorter-blackice .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-blackice tr.odd td { + background-color: #333; +} +.tablesorter-blackice tr.even td { + background-color: #393939; +} + +/* Column Widget - column sort colors */ +.tablesorter-blackice td.primary, +.tablesorter-blackice tr.odd td.primary { + background-color: #2f3a40; +} +.tablesorter-blackice tr.even td.primary { + background-color: #3f4a50; +} +.tablesorter-blackice td.secondary, +.tablesorter-blackice tr.odd td.secondary { + background-color: #3f4a50; +} +.tablesorter-blackice tr.even td.secondary { + background-color: #4f5a60; +} +.tablesorter-blackice td.tertiary, +.tablesorter-blackice tr.odd td.tertiary { + background-color: #4f5a60; +} +.tablesorter-blackice tr.even td.tertiary { + background-color: #5a646b; +} + +/* caption */ +caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-blackice .tablesorter-filter-row td { + background: #222; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-blackice .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} +/* hidden filter row */ +.tablesorter-blackice .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-blackice .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); +} +/* filters */ +.tablesorter-blackice .tablesorter-filter { + width: 98%; + height: auto; + margin: 0; + padding: 4px; + background-color: #fff; + border: 1px solid #bbb; + color: #333; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.blue.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.blue.css new file mode 100644 index 000000000..74e9ef202 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.blue.css @@ -0,0 +1,221 @@ +/************* + Blue Theme + *************/ +/* overall */ +.tablesorter-blue { + width: 100%; + background-color: #fff; + margin: 10px 0 15px; + text-align: left; + border-spacing: 0; + border: #cdcdcd 1px solid; + border-width: 1px 0 0 1px; +} +.tablesorter-blue th, +.tablesorter-blue td { + border: #cdcdcd 1px solid; + border-width: 0 1px 1px 0; +} + +/* header */ +.tablesorter-blue th, +.tablesorter-blue thead td { + font: bold 12px/18px Arial, Sans-serif; + color: #000; + background-color: #99bfe6; + border-collapse: collapse; + padding: 4px; + text-shadow: 0 1px 0 rgba(204, 204, 204, 0.7); +} +.tablesorter-blue tbody td, +.tablesorter-blue tfoot th, +.tablesorter-blue tfoot td { + padding: 4px; + vertical-align: top; +} +.tablesorter-blue .header, +.tablesorter-blue .tablesorter-header { + /* black (unsorted) double arrow */ + background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); + /* white (unsorted) double arrow */ + /* background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); */ + /* image */ + /* background-image: url(images/black-unsorted.gif); */ + background-repeat: no-repeat; + background-position: center right; + padding: 4px 18px 4px 4px; + white-space: normal; + cursor: pointer; +} +.tablesorter-blue .headerSortUp, +.tablesorter-blue .tablesorter-headerSortUp, +.tablesorter-blue .tablesorter-headerAsc { + background-color: #9fbfdf; + /* black asc arrow */ + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); + /* white asc arrow */ + /* background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); */ + /* image */ + /* background-image: url(images/black-asc.gif); */ +} +.tablesorter-blue .headerSortDown, +.tablesorter-blue .tablesorter-headerSortDown, +.tablesorter-blue .tablesorter-headerDesc { + background-color: #8cb3d9; + /* black desc arrow */ + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); + /* white desc arrow */ + /* background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); */ + /* image */ + /* background-image: url(images/black-desc.gif); */ +} +.tablesorter-blue thead .sorter-false { + background-image: none; + cursor: default; + padding: 4px; +} + +/* tfoot */ +.tablesorter-blue tfoot .tablesorter-headerSortUp, +.tablesorter-blue tfoot .tablesorter-headerSortDown, +.tablesorter-blue tfoot .tablesorter-headerAsc, +.tablesorter-blue tfoot .tablesorter-headerDesc { + /* remove sort arrows from footer */ + background-image: none; +} + +/* tbody */ +.tablesorter-blue td { + color: #3d3d3d; + background-color: #fff; + padding: 4px; + vertical-align: top; +} + +/* hovered row colors + you'll need to add additional lines for + rows with more than 2 child rows + */ +.tablesorter-blue tbody > tr:hover > td, +.tablesorter-blue tbody > tr:hover + tr.tablesorter-childRow > td, +.tablesorter-blue tbody > tr:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td, +.tablesorter-blue tbody > tr.even:hover > td, +.tablesorter-blue tbody > tr.even:hover + tr.tablesorter-childRow > td, +.tablesorter-blue tbody > tr.even:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + background: #d9d9d9; +} +.tablesorter-blue tbody > tr.odd:hover > td, +.tablesorter-blue tbody > tr.odd:hover + tr.tablesorter-childRow > td, +.tablesorter-blue tbody > tr.odd:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + background: #bfbfbf; +} + +/* table processing indicator */ +.tablesorter-blue .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-blue tbody tr.odd td { + background-color: #ebf2fa; +} +.tablesorter-blue tbody tr.even td { + background-color: #fff; +} + +/* Column Widget - column sort colors */ +.tablesorter-blue td.primary, +.tablesorter-blue tr.odd td.primary { + background-color: #99b3e6; +} +.tablesorter-blue tr.even td.primary { + background-color: #c2d1f0; +} +.tablesorter-blue td.secondary, +.tablesorter-blue tr.odd td.secondary { + background-color: #c2d1f0; +} +.tablesorter-blue tr.even td.secondary { + background-color: #d6e0f5; +} +.tablesorter-blue td.tertiary, +.tablesorter-blue tr.odd td.tertiary { + background-color: #d6e0f5; +} +.tablesorter-blue tr.even td.tertiary { + background-color: #ebf0fa; +} + +/* caption */ +caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-blue .tablesorter-filter-row td { + background: #eee; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-blue .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} +/* hidden filter row */ +.tablesorter-blue .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-blue .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); +} +/* filters */ +.tablesorter-blue .tablesorter-filter { + width: 98%; + height: auto; + margin: 0; + padding: 4px; + background-color: #fff; + border: 1px solid #bbb; + color: #333; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.bootstrap.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.bootstrap.css new file mode 100644 index 000000000..cab2b0d11 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.bootstrap.css @@ -0,0 +1,148 @@ +/************* + Bootstrap theme + *************/ +/* jQuery Bootstrap Theme */ +.tablesorter-bootstrap { + width: 100%; +} +.tablesorter-bootstrap thead th, +.tablesorter-bootstrap thead td, +.tablesorter-bootstrap tfoot th, +.tablesorter-bootstrap tfoot td { + font: bold 14px/20px Arial, Sans-serif; + padding: 4px; + margin: 0 0 18px; + background-color: #eee; +} + +.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 { + font-size: 11px; + 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 > tbody > tr.odd > td, +.tablesorter-bootstrap > tbody > tr.tablesorter-hasChildRow.odd:hover ~ tr.tablesorter-hasChildRow.odd ~ .tablesorter-childRow.odd > td { + background-color: #f9f9f9; +} +.tablesorter-bootstrap > tbody > tr.odd:hover > td, +.tablesorter-bootstrap > tbody > tr.even:hover > td, +.tablesorter-bootstrap > tbody > tr.tablesorter-hasChildRow.odd:hover ~ .tablesorter-childRow.odd > td, +.tablesorter-bootstrap > tbody > tr.tablesorter-hasChildRow.even:hover ~ .tablesorter-childRow.even > td { + background-color: #f5f5f5; +} +.tablesorter-bootstrap > tbody > tr.even > td, +.tablesorter-bootstrap > tbody > tr.tablesorter-hasChildRow.even:hover ~ tr.tablesorter-hasChildRow.even ~ .tablesorter-childRow.even > td { + background-color: #fff; +} + +/* processing icon */ +.tablesorter-bootstrap .tablesorter-processing { + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs='); + background-position: center center !important; + background-repeat: no-repeat !important; + position: absolute; + z-index: 1000; +} + +/* caption */ +.caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-bootstrap .tablesorter-filter-row .tablesorter-filter { + width: 98%; + height: auto; + margin: 0 auto; + padding: 4px 6px; + color: #333; + -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 .tablesorter-filter.disabled { + background-color: #eee; + color: #555; + cursor: not-allowed; + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset; + box-sizing: border-box; + transition: height 0.1s ease; +} +.tablesorter-bootstrap .tablesorter-filter-row td { + background: #efefef; + 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); +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* pager plugin */ +.tablesorter-bootstrap .tablesorter-pager select { + padding: 4px 6px; +} +.tablesorter-bootstrap .tablesorter-pager .pagedisplay { + border: 0; +} +/* tfoot i for pager controls */ +.tablesorter-bootstrap tfoot i { + font-size: 11px; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.bootstrap_2.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.bootstrap_2.css new file mode 100644 index 000000000..1ecd8d101 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.bootstrap_2.css @@ -0,0 +1,144 @@ +/************* + Bootstrap 2 Theme + *************/ +/* jQuery Bootstrap 2 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: #fff; +} + +/* 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; +} + +/* caption */ +caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-bootstrap .tablesorter-filter-row .tablesorter-filter { + width: 98%; + height: auto; + margin: 0 auto; + padding: 4px 6px; + background-color: #fff; + color: #333; + -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 .tablesorter-filter.disabled { + background: #eee; + cursor: not-allowed; +} +.tablesorter-bootstrap .tablesorter-filter-row td { + background: #eee; + 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); +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* pager plugin */ +.tablesorter-bootstrap .tablesorter-pager select { + padding: 4px 6px; +} +.tablesorter-bootstrap .tablesorter-pager .pagedisplay { + border: 0; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.dark.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.dark.css new file mode 100644 index 000000000..091d7f78f --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.dark.css @@ -0,0 +1,187 @@ +/************* + Dark Theme (by thezoggy) + *************/ +/* overall */ +.tablesorter-dark { + width: 100%; + font: 11px/18px Arial, Sans-serif; + color: #ccc; + text-align: left; + background-color: #000; + border-spacing: 0; +} + +/* header */ +.tablesorter-dark th, +.tablesorter-dark thead td { + padding: 4px; + font: bold 12px/20px Arial, Sans-serif; + color: #fff; + background-color: #000; + border-collapse: collapse; +} +.tablesorter-dark thead th { + border-bottom: #333 2px solid; +} +.tablesorter-dark .header, +.tablesorter-dark .tablesorter-header { + padding: 4px 20px 4px 4px; + cursor: pointer; + background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); + background-position: center right; + background-repeat: no-repeat; +} +.tablesorter-dark thead .headerSortUp, +.tablesorter-dark thead .tablesorter-headerSortUp, +.tablesorter-dark thead .tablesorter-headerAsc { + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); + border-bottom: #888 1px solid; +} +.tablesorter-dark thead .headerSortDown, +.tablesorter-dark thead .tablesorter-headerSortDown, +.tablesorter-dark thead .tablesorter-headerDesc { + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); + border-bottom: #888 1px solid; +} +.tablesorter-dark thead .sorter-false { + background-image: none; + cursor: default; + padding: 4px; +} + +/* tfoot */ +.tablesorter-dark tfoot .tablesorter-headerSortUp, +.tablesorter-dark tfoot .tablesorter-headerSortDown, +.tablesorter-dark tfoot .tablesorter-headerAsc, +.tablesorter-dark tfoot .tablesorter-headerDesc { + border-top: #888 1px solid; + /* remove sort arrows from footer */ + background-image: none; +} + +/* tbody */ +.tablesorter-dark td { + padding: 4px; + background-color: #000; + border-bottom: #333 1px solid; + color: #ccc; +} + +/* hovered row colors */ +.tablesorter-dark tbody > tr:hover > td, +.tablesorter-dark tbody > tr.even:hover > td, +.tablesorter-dark tbody > tr.odd:hover > td { + background: #000; +} + +/* table processing indicator */ +.tablesorter-dark .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-dark tr.odd td { + background-color: #202020; +} +.tablesorter-dark tr.even td { + background-color: #101010; +} + +/* Column Widget - column sort colors */ +.tablesorter-dark td.primary, +.tablesorter-dark tr.odd td.primary { + background-color: #0a0a0a; +} +.tablesorter-dark tr.even td.primary { + background-color: #050505; +} +.tablesorter-dark td.secondary, +.tablesorter-dark tr.odd td.secondary { + background-color: #0f0f0f; +} +.tablesorter-dark tr.even td.secondary { + background-color: #0a0a0a; +} +.tablesorter-dark td.tertiary, +.tablesorter-dark tr.odd td.tertiary { + background-color: #191919; +} +.tablesorter-dark tr.even td.tertiary { + background-color: #0f0f0f; +} + +/* caption */ +caption { + background: #202020; +} + +/* filter widget */ +.tablesorter-dark .tablesorter-filter-row td { + background: #202020; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-dark .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} + +/* hidden filter row */ +.tablesorter-dark .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-dark .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); +} + +/* filters */ +.tablesorter-dark .tablesorter-filter { + width: 98%; + height: auto; + margin: 4px; + padding: 4px; + background-color: #111; + border: 1px solid #222; + color: #ddd; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.default.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.default.css new file mode 100644 index 000000000..468df0a32 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.default.css @@ -0,0 +1,189 @@ +/************* +Default Theme +*************/ +/* overall */ +.tablesorter-default { + width: 100%; + font: 12px/18px Arial, Sans-serif; + color: #333; + background-color: #fff; + border-spacing: 0; + margin: 10px 0 15px; + text-align: left; +} + +/* header */ +.tablesorter-default th, +.tablesorter-default thead td { + font: bold 12px/18px Arial, Sans-serif; + color: #000; + background-color: #fff; + border-collapse: collapse; + border-bottom: #ccc 2px solid; + padding: 0; +} +.tablesorter-default tfoot th, +.tablesorter-default tfoot td { + border: 0; +} +.tablesorter-default .header, +.tablesorter-default .tablesorter-header { + background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); + background-position: center right; + background-repeat: no-repeat; + cursor: pointer; + white-space: normal; + padding: 4px 20px 4px 4px; +} +.tablesorter-default thead .headerSortUp, +.tablesorter-default thead .tablesorter-headerSortUp, +.tablesorter-default thead .tablesorter-headerAsc { + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); + border-bottom: #000 2px solid; +} +.tablesorter-default thead .headerSortDown, +.tablesorter-default thead .tablesorter-headerSortDown, +.tablesorter-default thead .tablesorter-headerDesc { + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); + border-bottom: #000 2px solid; +} +.tablesorter-default thead .sorter-false { + background-image: none; + cursor: default; + padding: 4px; +} + +/* tfoot */ +.tablesorter-default tfoot .tablesorter-headerSortUp, +.tablesorter-default tfoot .tablesorter-headerSortDown, +.tablesorter-default tfoot .tablesorter-headerAsc, +.tablesorter-default tfoot .tablesorter-headerDesc { + border-top: #000 2px solid; +} + +/* tbody */ +.tablesorter-default td { + background-color: #fff; + border-bottom: #ccc 1px solid; + padding: 4px; + vertical-align: top; +} + +/* hovered row colors */ +.tablesorter-default tbody > tr:hover > td, +.tablesorter-default tbody > tr.even:hover > td, +.tablesorter-default tbody > tr.odd:hover > td { + background: #fff; + color: #000; +} + +/* table processing indicator */ +.tablesorter-default .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-default tr.odd td { + background-color: #dfdfdf; +} +.tablesorter-default tr.even td { + background-color: #efefef; +} + +/* Column Widget - column sort colors */ +.tablesorter-default tr.odd td.primary { + background-color: #bfbfbf; +} +.tablesorter-default td.primary, +.tablesorter-default tr.even td.primary { + background-color: #d9d9d9; +} +.tablesorter-default tr.odd td.secondary { + background-color: #d9d9d9; +} +.tablesorter-default td.secondary, +.tablesorter-default tr.even td.secondary { + background-color: #e6e6e6; +} +.tablesorter-default tr.odd td.tertiary { + background-color: #e6e6e6; +} +.tablesorter-default td.tertiary, +.tablesorter-default tr.even td.tertiary { + background-color: #f2f2f2; +} + +/* caption */ +caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-default .tablesorter-filter-row td { + background: #eee; + border-bottom: #ccc 1px solid; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-default .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} +/* hidden filter row */ +.tablesorter-default .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-default .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); +} +/* filters */ +.tablesorter-default .tablesorter-filter { + width: 95%; + height: auto; + margin: 4px; + padding: 4px; + background-color: #fff; + border: 1px solid #bbb; + color: #333; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.dropbox.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.dropbox.css new file mode 100644 index 000000000..e844e963d --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.dropbox.css @@ -0,0 +1,212 @@ +/************* + Dropbox Theme (by thezoggy) + *************/ +/* overall */ +.tablesorter-dropbox { + width: 100%; + font: 13px/32px "Open Sans","lucida grande","Segoe UI",arial,verdana,"lucida sans unicode",tahoma,sans-serif; + color: #555; + text-align: left; + background-color: #fff; + border-collapse: collapse; + border-top: 1px solid #82cffa; + border-spacing: 0; +} + +/* header */ +.tablesorter-dropbox th, +.tablesorter-dropbox thead td, +.tablesorter-dropbox tfoot th, +.tablesorter-dropbox tfoot td { + background-color: #f0f9ff; + border-color: #82cffa #e7f2fb #96c4ea; + border-style: solid; + border-width: 1px; + padding: 3px 6px; + font-size: 13px; + font-weight: normal; + line-height: 29px; + color: #2281CF; + text-align: left; +} +.tablesorter-dropbox .header, +.tablesorter-dropbox thead tr, +.tablesorter-dropbox .tablesorter-headerRow { + background-color: #f0f9ff; + border-bottom: 1px solid #96c4ea; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.12), 0 0 0 #000000 inset; + white-space: normal; +} +.tablesorter-dropbox .tablesorter-headerSortUp, +.tablesorter-dropbox .tablesorter-headerSortDown, +.tablesorter-dropbox .tablesorter-headerAsc, +.tablesorter-dropbox .tablesorter-headerDesc { + font-weight: 600; +} +.tablesorter-dropbox .tablesorter-header { + cursor: pointer; +} +.tablesorter-dropbox .tablesorter-header i { + width: 9px; + height: 9px; + padding: 0 10px 0 4px; + display: inline-block; + background-position: center right; + background-repeat: no-repeat; + content: ""; +} +.tablesorter-dropbox .tablesorter-headerSortUp i, +.tablesorter-dropbox .tablesorter-headerAsc i { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALhJREFUeNpi/P//PwMhwILMiexYx8bIxNTy/9+/muUVQb9g4kzIitg4edI4+YRLQTSyOCPMupjerUI8whK3OXgEhH58+fDuy9sXqkuKvd+hmMTOxdvCxS8sxMUvxACiQXwU6+Im7DDg5BNKY+fiY2BmYWMA0SA+SByuiJ2bbzIHrwAzMxsb0AGMDCAaxAeJg+SZ7wtaqfAISfQAdTIwMUM8ywhUyMTEzPD/71+5FXvPLWUkJpwAAgwAZqYvvHStbD4AAAAASUVORK5CYII='); + /* background-image: url(images/dropbox-asc.png); */ +} +.tablesorter-dropbox .tablesorter-headerSortUp:hover i, +.tablesorter-dropbox .tablesorter-headerAsc:hover i { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALVJREFUeNpi/P//PwMhwILMCc+qZGNkYmr5/+9fzcpp7b9g4kzIitjYOdM4uXlLQTSyOCPMuqi8OiEefsHbHFzcQj++fX335eN71WWTmt6hmMTOwdXCycMnBDSJAUSD+CjWxRQ0GHBw86Sxc3AyMDOzMIBoEB8kDlfEzsk1mYOLByjPCnQAIwOIBvFB4iB55rsfmVS4+QV7QNYwMTNDHApUyMTExPDv/z+5Feu3L2UkJpwAAgwA244u+I9CleAAAAAASUVORK5CYII='); + /* background-image: url(images/dropbox-asc-hovered.png); */ +} +.tablesorter-dropbox .tablesorter-headerSortDown i, +.tablesorter-dropbox .tablesorter-headerDesc i { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNpi/P//PwMhwBLdtVGFhZ3zNhMzC4bkv79/GP78/K7KCDIpZ9mVw+xcfDaMTExwBf///WP4+e3TkSlROrZg7UxMLLns3HxnmFnZmGGK/v7+9ff3j2+5YHkQMSlC48Kv719m/f//D2IKkAbxQeJwRSDw4/OHmr+/fr0DqmAA0SA+TA6uaEq0zjugG+r//vkFcks9iA/3HbJvvn18O+vf379yP758mMXAoAAXZyQmnAACDADX316BiTFbMQAAAABJRU5ErkJggg=='); + /* background-image: url(images/dropbox-desc.png); */ +} +.tablesorter-dropbox .tablesorter-headerSortDown:hover i, +.tablesorter-dropbox .tablesorter-headerDesc:hover i { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALNJREFUeNpi/P//PwMhwBJf3uP879e3PUzMzBiS//7+ZWBi43JhBJmU2z7nIzMzEx8jIyNcAUj8799/nyZXpvCzgARYuXjTWBkZVjCzIEz7++cvw+//DGkgNiPMTWVT1l5hZvynDTINbMp/pqtdOcE6IDkmmM5fv3/5//v37z9QBQOIBvFhcnBFEwoj7/5jZFnz9+8fBhAN4sN9h+ybH9++JrGxscr/+vE1CVmckZhwAggwANvlUyq5Dd1wAAAAAElFTkSuQmCC'); + /* background-image: url(images/dropbox-desc-hovered.png); */ +} +.tablesorter-dropbox thead .sorter-false { + cursor: default; +} + +.tablesorter-dropbox thead .sorter-false i, +.tablesorter-dropbox thead .sorter-false:hover i { + background-image: none; + padding: 4px; +} + +/* tbody */ +.tablesorter-dropbox td { + padding: 5px 6px; + line-height: 32px; + color: #555; + text-align: left; + border-top: 1px solid #edf1f5; + border-bottom: 1px solid #edf1f5; +} + +/* hovered row colors */ +.tablesorter-dropbox tbody > tr:hover > td, +.tablesorter-dropbox tbody > tr.even:hover > td, +.tablesorter-dropbox tbody > tr.odd:hover > td { + background-color: rgba(230, 245, 255, 0.3); + border-right: 0; + border-left: 0; + border-color: #c6d8e4; + /* trick to do border-top and bottom colors */ + border-style: double; +} + +/* table processing indicator */ +.tablesorter-dropbox .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-dropbox tr.odd td { +} +.tablesorter-dropbox tr.even td { +} + +/* Column Widget - column sort colors */ +.tablesorter-dropbox td.primary, +.tablesorter-dropbox tr.odd td.primary { +} +.tablesorter-dropbox tr.even td.primary { +} +.tablesorter-dropbox td.secondary, +.tablesorter-dropbox tr.odd td.secondary { +} +.tablesorter-dropbox tr.even td.secondary { +} +.tablesorter-dropbox td.tertiary, +.tablesorter-dropbox tr.odd td.tertiary { +} +.tablesorter-dropbox tr.even td.tertiary { +} + +/* caption */ +caption { + background: #fff; +} + +/* Filter Widget */ +.tablesorter-dropbox .tablesorter-filter-row td { + background: #fff; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-dropbox .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} + +/* hidden filter row */ +.tablesorter-dropbox .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-dropbox .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); +} + +/* filters */ +.tablesorter-dropbox .tablesorter-filter { + width: 98%; + height: auto; + margin: 4px; + + background-color: #fff; + border: 1px solid #bbb; + color: #333; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.green.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.green.css new file mode 100644 index 000000000..85f5cde3e --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.green.css @@ -0,0 +1,203 @@ +/************* + Green Theme + *************/ +/* overall */ +.tablesorter-green { + width: 100%; + text-align: left; + border-spacing: 0; + border: #cdcdcd 1px solid; + border-width: 1px 0 0 1px; +} +.tablesorter-green th, +.tablesorter-green td { + font: 12px/18px Arial, Sans-serif; + border: #cdcdcd 1px solid; + border-width: 0 1px 1px 0; +} + +/* header */ +.tablesorter-green thead tr, +.tablesorter-green tfoot tr { + background: center center repeat-x; + background-image: url(data:image/gif;base64,R0lGODlhAQBkAOYAAN/e39XU1fX19tTU1eXm5uTl5ePk5OLj4+Hi4vX29fT19PP08/Lz8vHy8fDx8O/w7+7v7uzt7Orr6ufo5/T08/Pz8ufn5uLi4eDg39/f3t3d3Nzc29HR0NDQz8/Pzuvq6urp6eno6Ojn5+fm5tfW1tbV1dTT09PS0tLR0dHQ0NDPz/f39/b29vX19fT09PPz8/Ly8vHx8e/v7+7u7u3t7ezs7Ovr6+rq6unp6ejo6Ofn5+bm5uXl5eTk5OPj4+Li4uHh4eDg4N/f397e3t3d3dzc3Nvb29ra2tnZ2djY2NfX19XV1dPT09LS0tHR0dDQ0M/Pz8rKysXFxf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAFMALAAAAAABAGQAAAdegCsrLC0tLi+ILi6FCSwsCS0KkhQVDA0OMjM0NTYfICEiIzw9P0AYGUQaG0ZHSEoDTU9Qs08pTk1MSyRJR0VDQT8+PTw7Ojg3NTMyMTAvi4WOhC0vMTI1OT9GTlFSgQA7); + /* background-image: url(images/green-header.gif); */ +} +.tablesorter-green th, +.tablesorter-green thead td { + font-weight: bold; + border-right: #cdcdcd 1px solid; + border-collapse: collapse; + padding: 6px; +} +.tablesorter-green .header, +.tablesorter-green .tablesorter-header { + background: no-repeat 5px center; + background-image: url(data:image/gif;base64,R0lGODlhEAAQAOYAAA5NDBBYDlWWUzRUM5DVjp7inJ/fnQ1ECiCsGhyYFxqKFRFdDhBXDQxCCiO8HSK2HCCqGh2aGByUFxuPFhqNFhmHFRZ2EhVvERRpEBBVDSS8HiGyHB+mGh6fGRuTFxiAFBd5Eww/Cgs5CRp7Fiu+JRx8GCy/JjHAKyynKCuhJzXCMDbCMDnDMyNuHz3EODy9N0LFPSl7JkvIRjycOFDKS1LKTVPLT1XLUFTCT17OWTBkLmbQYnDTbHXVcXnWdoXago/djGmUZ112XCJEIEdjRf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAEUALAAAAAAQABAAAAdlgEWCg4SFhoIvh4cVLECKhCMeJjwFj0UlEwgaMD4Gii0WFAkRHQ47BIY6IQAZDAwBCyAPOJa1toRBGBAwNTY3OT0/AoZCDQoOKi4yNDOKRCIfGycrKZYDBxIkKLZDFxy3RTHgloEAOw==); + /* background-image: url(images/green-unsorted.gif); */ + border-collapse: collapse; + white-space: normal; + cursor: pointer; +} +.tablesorter-green thead .headerSortUp, +.tablesorter-green thead .tablesorter-headerSortUp, +.tablesorter-green thead .tablesorter-headerAsc { + background-image: url(data:image/gif;base64,R0lGODlhEAAQANUAAA5NDBBYDpDVjp7inJ/fnSCsGhyYFxFdDhBXDSO8HSK2HB2aGBuPFhqNFhmHFRZ2EhBVDSS8Hh6fGRuTFxd5Eww/Chp7Fhx8GCy/JjnDMyNuHzy9N0LFPVTCTzBkLmbQYnDTbHnWdo/djP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACMALAAAAAAQABAAAAY4wJFwSCwaj8ikcslMbpojR0bEtEwwoIHywihEOCECUvNoGBaSxEdg9FQAEAQicKAoOtC8fs8fBgEAOw==) + /* background-image: url(images/green-asc.gif); */ +} +.tablesorter-green thead .headerSortDown, +.tablesorter-green thead .tablesorter-headerSortDown, +.tablesorter-green thead .tablesorter-headerDesc { + background-image: url(data:image/gif;base64,R0lGODlhEAAQANUAAFWWUzRUMw1EChqKFQxCCiO8HSCqGhyUFxVvERRpECGyHB+mGhiAFAs5CSu+JTHAKyynKCuhJzXCMDbCMD3EOELFPSl7JkvIRjycOFDKS1LKTVPLT1XLUF7OWXXVcYXagmmUZ112XCJEIEdjRf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACQALAAAAAAQABAAAAY4QJJwSCwaj8ikcskkghKGimbD6Xg+AGOIMChIKJcMBjlqMBSPSUQZEBwcEKYIsWiSLPa8fs9HBgEAOw==) + /* background-image: url(images/green-desc.gif); */ +} +.tablesorter-green th.tablesorter-header .tablesorter-header-inner, +.tablesorter-green td.tablesorter-header .tablesorter-header-inner { + padding-left: 23px; +} +.tablesorter-green thead .tablesorter-header.sorter-false { + background-image: none; + cursor: default; + padding: 4px; +} + +/* tfoot */ +.tablesorter-green tbody td, +.tablesorter-green tfoot th { + padding: 6px; + vertical-align: top; +} + +/* tbody */ +.tablesorter-green td { + color: #3d3d3d; + padding: 6px; +} + +/* hovered row colors + you'll need to add additional lines for + rows with more than 2 child rows + */ +.tablesorter-green tbody > tr:hover > td, +.tablesorter-green tbody > tr:hover + tr.tablesorter-childRow > td, +.tablesorter-green tbody > tr:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td, +.tablesorter-green tbody > tr.even:hover > td, +.tablesorter-green tbody > tr.even:hover + tr.tablesorter-childRow > td, +.tablesorter-green tbody > tr.even:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + background: #d9d9d9; +} +.tablesorter-green tbody > tr.odd:hover > td, +.tablesorter-green tbody > tr.odd:hover + tr.tablesorter-childRow > td, +.tablesorter-green tbody > tr.odd:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + background: #bfbfbf; +} + +/* table processing indicator */ +.tablesorter-green .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-green tr.odd td { + background-color: #ebfaeb; +} +.tablesorter-green tr.even td { + background-color: #fff; +} + +/* Column Widget - column sort colors */ +.tablesorter-green td.primary, +.tablesorter-green tr.odd td.primary { + background-color: #99e6a6; +} +.tablesorter-green tr.even td.primary { + background-color: #c2f0c9; +} +.tablesorter-green td.secondary, +.tablesorter-green tr.odd td.secondary { + background-color: #c2f0c9; +} +.tablesorter-green tr.even td.secondary { + background-color: #d6f5db; +} +.tablesorter-green td.tertiary, +.tablesorter-green tr.odd td.tertiary { + background-color: #d6f5db; +} +.tablesorter-green tr.even td.tertiary { + background-color: #ebfaed; +} + +/* caption */ +caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-green .tablesorter-filter-row td { + background: #eee; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-green .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} +/* hidden filter row */ +.tablesorter-green .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-green .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); +} +/* filters */ +.tablesorter-green .tablesorter-filter { + width: 98%; + height: auto; + margin: 4px; + padding: 4px; + background-color: #fff; + border: 1px solid #bbb; + color: #333; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.grey.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.grey.css new file mode 100644 index 000000000..ae62ee733 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.grey.css @@ -0,0 +1,245 @@ +/************* + Grey Theme + *************/ +/* overall */ +.tablesorter-grey { + width: 100%; + margin: 10px 0 15px; + text-align: left; + border-spacing: 0; + border-left: #555 1px solid; +} + +/* header */ +.tablesorter-grey th, +.tablesorter-grey thead td { + font: bold 12px/18px Arial, Sans-serif; + color: #c8c8c8; + background-color: #3c3c3c; + background-image: -moz-linear-gradient(top, #555, #3c3c3c); + background-image: -ms-linear-gradient(top, #555, #3c3c3c); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555), to(#3c3c3c)); + background-image: -webkit-linear-gradient(top, #555, #3c3c3c); + background-image: -o-linear-gradient(top, #555, #3c3c3c); + background-image: linear-gradient(to bottom, #555,#3c3c3c); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#555555', endColorstr='#3c3c3c',GradientType=0 ); + background-repeat: repeat-x; + border-right: #555 1px solid; + text-shadow: 0 1px 0 rgba(128, 128, 128, 0.7); + -webkit-box-shadow: inset 0 1px 0 #222; + -moz-box-shadow: inset 0 1px 0 #222; + box-shadow: inset 0 1px 0 #222; + padding: 4px; +} +.tablesorter-grey .tablesorter-header-inner, +.tablesorter-grey .tablesorter-header-inner { + position: relative; + padding: 4px 15px 4px 4px; +} +.tablesorter-grey .header, +.tablesorter-grey .tablesorter-header { + cursor: pointer; +} +.tablesorter-grey .header i, +.tablesorter-grey .tablesorter-header i { + width: 18px; + height: 10px; + position: absolute; + right: 2px; + top: 50%; + margin-top: -10px; + /* white (unsorted) double arrow */ + background-image: url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); + background-repeat: no-repeat; + background-position: center right; + padding: 4px; + white-space: normal; +} +.tablesorter-grey th.headerSortUp, +.tablesorter-grey th.tablesorter-headerSortUp, +.tablesorter-grey th.headerSortDown, +.tablesorter-grey th.tablesorter-headerSortDown { + color: #ddd; + background-color: #135185; + background-image: -moz-linear-gradient(top, #195c93, #0e4776); + background-image: -ms-linear-gradient(top, #195c93, #0e4776); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#195c93), to(#0e4776)); + background-image: -webkit-linear-gradient(top, #195c93, #0e4776); + background-image: -o-linear-gradient(top, #195c93, #0e4776); + background-image: linear-gradient(to bottom, #195c93, #0e4776); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#195c93', endColorstr='#0e4776',GradientType=0 ); +} +.tablesorter-grey .headerSortUp i, +.tablesorter-grey .tablesorter-headerSortUp i, +.tablesorter-grey .tablesorter-headerAsc i { + /* white asc arrow */ + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); +} +.tablesorter-grey .headerSortDown i, +.tablesorter-grey .tablesorter-headerSortDown i, +.tablesorter-grey .tablesorter-headerDesc i { + /* white desc arrow */ + background-image: url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); +} +.tablesorter-grey thead .sorter-false { + cursor: default; +} +.tablesorter-grey thead .sorter-false i { + background-image: none; + padding: 4px; +} + +/* tfoot */ +.tablesorter-grey tbody td, +.tablesorter-grey tfoot th, +.tablesorter-grey tfoot td { + padding: 4px; + vertical-align: top; + border-right: #555 1px solid; +} +.tablesorter-grey tfoot th, +.tablesorter-grey tfoot td { + padding: 8px; +} + +/* tbody */ +.tablesorter-grey td { + color: #eee; + background-color: #6d6d6d; + padding: 4px; + vertical-align: top; +} + +/* hovered row colors + you'll need to add additional lines for + rows with more than 2 child rows + */ +.tablesorter-grey tbody > tr:hover > td, +.tablesorter-grey tbody > tr:hover + tr.tablesorter-childRow > td, +.tablesorter-grey tbody > tr:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td, +.tablesorter-grey tbody > tr.even:hover > td, +.tablesorter-grey tbody > tr.even:hover + tr.tablesorter-childRow > td, +.tablesorter-grey tbody > tr.even:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + background: #134b78; +} +.tablesorter-grey tbody > tr.odd:hover > td, +.tablesorter-grey tbody > tr.odd:hover + tr.tablesorter-childRow > td, +.tablesorter-grey tbody > tr.odd:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + background: #134b78; +} + +/* table processing indicator */ +.tablesorter-grey .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-grey tbody tr.odd td { + background-color: #5e5e5e; +} +.tablesorter-grey tbody tr.even td { + background-color: #6d6d6d; +} + +/* Column Widget - column sort colors */ +.tablesorter-grey td.primary, +.tablesorter-grey tr.odd td.primary { + color: #ddd; + background-color: #165388; +} +.tablesorter-grey tr.even td.primary { + color: #ddd; + background-color: #195c93; +} +.tablesorter-grey td.secondary, +.tablesorter-grey tr.odd td.secondary { + color: #ddd; + background-color: #185C9A; +} +.tablesorter-grey tr.even td.secondary { + color: #ddd; + background-color: #1D67A5; +} +.tablesorter-grey td.tertiary, +.tablesorter-grey tr.odd td.tertiary { + color: #ddd; + background-color: #1B67AD; +} +.tablesorter-grey tr.even td.tertiary { + color: #ddd; + background-color: #2073B7; +} + +/* caption */ +caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-grey .tablesorter-filter-row td { + background: #3c3c3c; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-grey .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} +/* hidden filter row */ +.tablesorter-grey .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-grey .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); +} +/* filters */ +.tablesorter-grey .tablesorter-filter { + width: 98%; + height: auto; + margin: 0; + padding: 4px; + background-color: #6d6d6d; + border: 1px solid #555; + color: #ddd; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.ice.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.ice.css new file mode 100644 index 000000000..45080ff56 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.ice.css @@ -0,0 +1,201 @@ +/************* + Ice Theme (by thezoggy) + *************/ +/* overall */ +.tablesorter-ice { + width: 100%; + background-color: #fff; + margin: 10px 0 15px; + text-align: left; + border-spacing: 0; + border: #ccc 1px solid; + border-width: 1px 0 0 1px; +} +.tablesorter-ice th, +.tablesorter-ice td { + border: #ccc 1px solid; + border-width: 0 1px 1px 0; +} + +/* header */ +.tablesorter-ice th, +.tablesorter-ice thead td { + font: 12px/18px Arial, Sans-serif; + color: #555; + background-color: #f6f8f9; + border-collapse: collapse; + padding: 4px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); +} +.tablesorter-ice tbody td, +.tablesorter-ice tfoot th, +.tablesorter-ice tfoot td { + padding: 4px; + vertical-align: top; +} +.tablesorter-ice .header, +.tablesorter-ice .tablesorter-header { + background: #f6f8f9 no-repeat center right; + background-image: url(data:image/gif;base64,R0lGODlhDAAMAMQAAAJEjAJCiwJBigJAiANFjgNGjgNEjQRIkQRHkANIkAVMlAVQmAZWnQZUnAdYoAhdpAhZoAlhqQlepQliqQppsApmrQxutgtutQtutAxwtwxwtg1yug1zugxtsw1yuP8A/yH5BAEAAB8ALAAAAAAMAAwAAAUx4Cd+3GiOW4ado2d9VMVm1xg9ptadTsP+QNZEcjoQTBDGCAFgLRSfQgCYMAiCn8EvBAA7); + /* background-image: url(images/ice-unsorted.gif) */ + padding: 4px 20px 4px 4px; + white-space: normal; + cursor: pointer; +} +.tablesorter-ice .headerSortUp, +.tablesorter-ice .tablesorter-headerSortUp, +.tablesorter-ice .tablesorter-headerAsc { + color: #333; + background: #ebedee no-repeat center right; + background-image: url(data:image/gif;base64,R0lGODlhDAAMANUAAAJCiwNHkANFjgNEjQRIkQNJkQRMlARKkwRKkgVPlwZSmgdaogdYnwhfpghcowlhqgliqglgqAlgpwljqwporwpmrQplrAtsswtqsgtrsgtqsQxttAtvtQtttAxyuQxwtwxxtwxvtg10uw1zuQ1xuP8A/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACUALAAAAAAMAAwAAAY6wJKwJBoahyNQ6Dj0fDoZCpPEuWgqk4jxs8FQLI+Gg8Esm5kQydFQMC7IwkOAqUiUCAIzIjA4lwBlQQA7); + /* background-image: url(images/ice-desc.gif) */ +} +.tablesorter-ice .headerSortDown, +.tablesorter-ice .tablesorter-headerSortDown, +.tablesorter-ice .tablesorter-headerDesc { + color: #333; + background: #ebedee no-repeat center right; + background-image: url(data:image/gif;base64,R0lGODlhDAAMANUAAAE/iAJBigNFjgNEjQNFjQNDiwRHkQRHjwNHjwROlgRMlQRMlARJkgRKkgZQmAVPlgZWnQZSmgZRmAdXoAdXnwdUnAdbogdZoQhbowlhqAlepglkrAliqQtstAtqsQxyugxyuQxwuAxxuAxxtwxwtgxvtQ10vA12vA10u/8A/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACkALAAAAAAMAAwAAAY6wJQwdRoah6bP6DhEiVIdDxNEGm4yxlDpiJkwv2AmR2OhVCSJBsJ4gUQeCwOB6VAwBAXwYRAIpwBfQQA7); + /* background-image: url(images/ice-asc.gif); */ +} +.tablesorter-ice thead .sorter-false { + background-image: none; + cursor: default; + padding: 4px; +} + +/* tfoot */ +.tablesorter-ice tfoot .tablesorter-headerSortUp, +.tablesorter-ice tfoot .tablesorter-headerSortDown, +.tablesorter-ice tfoot .tablesorter-headerAsc, +.tablesorter-ice tfoot .tablesorter-headerDesc { + background: #ebedee; +} + +/* tbody */ +.tablesorter-ice td { + color: #333; +} + +/* hovered row colors */ +.tablesorter-ice tbody > tr:hover > td, +.tablesorter-ice tbody > tr.even:hover > td, +.tablesorter-ice tbody > tr.odd:hover > td { + background: #ebf2fa; +} + +/* table processing indicator */ +.tablesorter-ice .tablesorter-processing { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra Widget - row alternating colors */ +.tablesorter-ice tr.odd td { + background-color: #dfdfdf; +} +.tablesorter-ice tr.even td { + background-color: #efefef; +} + +/* Column Widget - column sort colors */ +.tablesorter-ice td.primary, +.tablesorter-ice tr.odd td.primary { + background-color: #9ae5e5; +} +.tablesorter-ice tr.even td.primary { + background-color: #c2f0f0; +} +.tablesorter-ice td.secondary, +.tablesorter-ice tr.odd td.secondary { + background-color: #c2f0f0; +} +.tablesorter-ice tr.even td.secondary { + background-color: #d5f5f5; +} +.tablesorter-ice td.tertiary, +.tablesorter-ice tr.odd td.tertiary { + background-color: #d5f5f5; +} +.tablesorter-ice tr.even td.tertiary { + background-color: #ebfafa; +} + +/* sticky headers */ +.tablesorter-ice.containsStickyHeaders thead tr:nth-child(1) th, +.tablesorter-ice.containsStickyHeaders thead tr:nth-child(1) td { + border-top: #ccc 1px solid; +} + +/* caption */ +caption { + background: #fff; +} + +/* filter widget */ +.tablesorter-ice .tablesorter-filter-row td { + background: #eee; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-ice .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} +/* hidden filter row */ +.tablesorter-ice .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-ice .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); +} +/* filters */ +.tablesorter-ice .tablesorter-filter { + width: 98%; + height: auto; + margin: 4px; + padding: 4px; + background-color: #fff; + border: 1px solid #bbb; + color: #333; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.jui.css b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.jui.css new file mode 100644 index 000000000..ea33277df --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.jui.css @@ -0,0 +1,156 @@ +/************* + jQuery UI Theme + *************/ + /* overall */ +.tablesorter-jui { + width: 100%; + border-collapse: separate; + border-spacing: 2px; /* adjust spacing between table cells */ + margin: 10px 0 15px; + padding: 5px; + font-size: 0.8em; +} + +/* header */ +.tablesorter-jui thead th, +.tablesorter-jui thead td, +.tablesorter-jui tfoot th, +.tablesorter-jui tfoot td { + position: relative; + background-repeat: no-repeat; + background-position: right center; + /* UI hover and active states make the font normal and the table resizes, this fixes it */ + font-weight: bold !important; + border-width: 1px !important; + text-align: left; + padding: 8px; /* wider than the icon */ +} +.tablesorter-jui .header, +.tablesorter-jui .tablesorter-header { + cursor: pointer; + white-space: normal; +} +.tablesorter-jui .tablesorter-header-inner { + padding-right: 20px; +} +.tablesorter-jui thead tr th .ui-icon { + position: absolute; + right: 3px; + top: 50%; + margin-top: -8px; /* half the icon height; older IE doesn't like this */ +} + +.tablesorter-jui thead .sorter-false { + cursor: default; +} + +/* tfoot */ +.tablesorter-jui tfoot th, +.tablesorter-jui tfoot td { + font-weight: normal !important; + font-size: .9em; + padding: 2px; +} + +/* tbody */ +.tablesorter-jui td { + padding: 4px; + vertical-align: top; +} + +/* hovered row colors */ +.tablesorter-jui tbody > tr:hover td { + opacity: 0.7; + filter: alpha(opacity=70); +} + +/* table processing indicator */ +.tablesorter-jui .tablesorter-processing .tablesorter-header-inner { + background-position: center center !important; + background-repeat: no-repeat !important; + /* background-image: url(../addons/pager/icons/loading.gif) !important; */ + background-image: url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs=') !important; +} + +/* Zebra widget - This allows you to use ui-state-default as the zebra stripe color */ +.tablesorter-jui tr.ui-state-default { + background-image: none; + font-weight: normal; +} + +/* processing background color */ +.tablesorter-jui .tablesorter-processing { + background-color: #ddd; /* older browsers that don't support rgba */ + background-color: rgba(255,255,255,0.8); +} + +/* caption */ +.tablesorter-jui caption { + border: 0; +} + +/* filter widget */ +.tablesorter-jui .tablesorter-filter-row td { + background: transparent; + line-height: normal; + text-align: center; /* center the input */ + -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; +} +/* optional disabled input styling */ +.tablesorter-jui .tablesorter-filter-row .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; +} +/* hidden filter row */ +.tablesorter-jui .tablesorter-filter-row.hideme td { + /*** *********************************************** ***/ + /*** change this padding to modify the thickness ***/ + /*** of the closed filter row (height = padding x 2) ***/ + padding: 2px; + /*** *********************************************** ***/ + margin: 0; + line-height: 0; + cursor: pointer; +} +.tablesorter-jui .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); +} +/* filters */ +.tablesorter-jui .tablesorter-filter { + width: 98%; + height: auto; + margin: 0; + padding: 4px; + background-color: #fff; + border: 1px solid #bbb; + color: #333; + -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; +} +/* rows hidden by filtering (needed for child rows) */ +.tablesorter .filtered { + display: none; +} + +/* ajax error row */ +.tablesorter .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: #e6bf99; +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/css/theme.less b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.less new file mode 100644 index 000000000..e4c2a1640 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/css/theme.less @@ -0,0 +1,332 @@ +/* LESS Theme by Rob Garrison + + To create your own theme, modify the code below and run it through + a LESS compiler, like this one: http://leafo.net/lessphp/editor.html + or download less.js from http://lesscss.org/ + + Test out this less file live at http://codepen.io/Mottie/pen/eqBbn + + */ + +/*** theme ***/ +@theme : tablesorter-custom; + +/*** fonts ***/ +@tableHeaderFont : 11px 'trebuchet ms', verdana, arial; +@tableBodyFont : 11px 'trebuchet ms', verdana, arial; + +/*** color definitions ***/ +/* for best results, only change the hue (120), + leave the saturation (60%) and luminosity (75%) alone + pick the color from here: http://hslpicker.com/#99E699 */ +@headerBackground : hsl(120, 60%, 75%); +@borderAndBackground : #cdcdcd; +@overallBorder : @borderAndBackground 1px solid; +@headerTextColor : #000; + +@bodyBackground : #fff; +@bodyTextColor : #000; + +@headerAsc : darken(spin(@headerBackground, 5), 10%); /* darken(@headerBackground, 10%); */ +@headerDesc : lighten(spin(@headerBackground, -5), 10%); /* desaturate(@headerAsc, 5%); */ + +@captionBackground : #fff; /* it might be best to match the document body background color here */ +@errorBackground : #e6bf99; /* ajax error message (added to thead) */ + +@filterCellBackground : #eee; +@filterElementTextColor: #333; +@filterElementBkgd : #fff; +@filterElementBorder : 1px solid #bbb; +@filterTransitionTime : 0.1s; +@filterRowHiddenHeight : 4px; /* becomes height using padding (so it's divided by 2) */ + +@overallPadding : 4px; +/* 20px should be slightly wider than the icon width to avoid overlap */ +@headerPadding : 4px 20px 4px 4px; + +/* url(icons/loading.gif); */ +@processingIcon : url('data:image/gif;base64,R0lGODlhFAAUAKEAAO7u7lpaWgAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCgACACwAAAAAFAAUAAACQZRvoIDtu1wLQUAlqKTVxqwhXIiBnDg6Y4eyx4lKW5XK7wrLeK3vbq8J2W4T4e1nMhpWrZCTt3xKZ8kgsggdJmUFACH5BAEKAAIALAcAAAALAAcAAAIUVB6ii7jajgCAuUmtovxtXnmdUAAAIfkEAQoAAgAsDQACAAcACwAAAhRUIpmHy/3gUVQAQO9NetuugCFWAAAh+QQBCgACACwNAAcABwALAAACE5QVcZjKbVo6ck2AF95m5/6BSwEAIfkEAQoAAgAsBwANAAsABwAAAhOUH3kr6QaAcSrGWe1VQl+mMUIBACH5BAEKAAIALAIADQALAAcAAAIUlICmh7ncTAgqijkruDiv7n2YUAAAIfkEAQoAAgAsAAAHAAcACwAAAhQUIGmHyedehIoqFXLKfPOAaZdWAAAh+QQFCgACACwAAAIABwALAAACFJQFcJiXb15zLYRl7cla8OtlGGgUADs='); + +/* zebra striping */ +.allRows { + background: @bodyBackground; + color: @bodyTextColor; +} +.evenRows { + background: lighten(@headerBackground, 40%); + color: @bodyTextColor; +} +.oddRows { + background: lighten(@headerBackground, 20%); +} + +/* hovered rows */ +.oddHovered { + background: desaturate(@headerBackground, 60%); + color: @bodyTextColor; +} +.evenHovered { + background: lighten( desaturate(@headerBackground, 60%), 10% ); + color: @bodyTextColor; +} + +/* Columns widget */ +@primaryOdd : spin(@headerBackground, 10); /* saturate( darken( desaturate(@headerBackground, 10%), 10% ), 30%); */ +@primaryEven : lighten( @primaryOdd, 10% ); +@secondaryOdd : @primaryEven; +@secondaryEven : lighten( @primaryEven, 5% ); +@tertiaryOdd : @secondaryEven; +@tertiaryEven : lighten( @secondaryEven, 5% ); + +/* Filter widget transition */ +.filterWidgetTransition { + -webkit-transition: line-height @filterTransitionTime ease; + -moz-transition: line-height @filterTransitionTime ease; + -o-transition: line-height @filterTransitionTime ease; + transition: line-height @filterTransitionTime ease; +} + +/*** Arrows ***/ +@arrowPosition : center right; + +/* black */ +@unsortedBlack : url(data:image/gif;base64,R0lGODlhFQAJAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); +@sortAscBlack : url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); +@sortDescBlack : url(data:image/gif;base64,R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); + +@filterIconBlack : url(data:image/gif;base64,R0lGODlhCgAMALMAAEpKSklJSUNDQ0FBQUBAQDk5OTc3NzY2NiQkJP///wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAAAKAAwAAAQnEMlJk72YamQE+KBgJEcAAsFxFWeBJcRHvInxjfRHW/oODLsEEBMBADs=); + +/* white */ +@unsortedWhite : url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==); +@sortAscWhite : url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7); +@sortDescWhite : url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7); + +@filterIconWhite : url(data:image/gif;base64,R0lGODlhCgANALMAAP////r6+u7u7ufn5+Hh4d3d3cXFxb+/v76+vru7u7m5uf///wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAA0AAAQpUMhJl72YanEG+OBwLEkAAkFyGaeBLcVXvAvyIfTy5TrAAwQeQcEjYiIAOw==); + +/* automatically choose the correct arrow/text color */ +.unsorted (@a) when (lightness(@a) >= 50%) { + background-image: @unsortedBlack; + color: @headerTextColor; +} +.unsorted (@a) when (lightness(@a) < 50%) { + background-image: @unsortedWhite; + color: lighten(@headerTextColor, 90%); +} +.sortAsc (@a) when (lightness(@a) >= 50%) { + background-image: @sortAscBlack; + color: @headerTextColor; +} +.sortAsc (@a) when (lightness(@a) < 50%) { + background-image: @sortAscWhite; + color: lighten(@headerTextColor, 90%); +} +.sortDesc (@a) when (lightness(@a) >= 50%) { + background-image: @sortDescBlack; + color: @headerTextColor; +} +.sortDesc (@a) when (lightness(@a) < 50%) { + background-image: @sortDescWhite; + color: lighten(@headerTextColor, 90%); +} +.filterIcon (@a) when (lightness(@a) >= 50%) { + background-image: @filterIconBlack; +} +.filterIcon (@a) when (lightness(@a) < 50%) { + background-image: @filterIconWhite; +} + +/* variable theme name - requires less.js 1.3+; + or just replace (!".@{theme}") with the contents of @theme + */ +.@{theme} { + font: @tableBodyFont; + background-color: @borderAndBackground; + margin: 10px 0 15px; + width: 100%; + text-align: left; + border-spacing: 0; + border: @overallBorder; + border-width: 1px 0 0 1px; + + th, td { + border: @overallBorder; + border-width: 0 1px 1px 0; + } + + /* style th's outside of the thead */ + th, thead td { + font: @tableHeaderFont; + font-weight: bold; + color: @headerTextColor; + background-color: @headerBackground; + border-collapse: collapse; + padding: @overallPadding; + } + + tbody td, tfoot th, tfoot td { + padding: @overallPadding; + vertical-align: top; + } + + /* style header */ + .tablesorter-header { + .unsorted(@headerBackground); + background-repeat: no-repeat; + background-position: @arrowPosition; + padding: @headerPadding; + cursor: pointer; + } + + .tablesorter-header.sorter-false { + background-image: none; + cursor: default; + padding: @overallPadding; + } + + .tablesorter-headerAsc { + background-color: @headerAsc; + .sortAsc(@headerBackground); + } + + .tablesorter-headerDesc { + background-color: @headerDesc; + .sortDesc(@headerBackground); + } + + /* tfoot */ + tfoot .tablesorter-headerAsc, + tfoot .tablesorter-headerDesc { + /* remove sort arrows from footer */ + background-image: none; + } + + /* optional disabled input styling */ + .disabled { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: not-allowed; + } + + /* body */ + tbody { + + td { + .allRows; + padding: @overallPadding; + vertical-align: top; + } + + /* Zebra Widget - row alternating colors */ + tr.odd td { + .oddRows; + } + tr.even td { + .evenRows; + } + + } + + /* hovered row colors + you'll need to add additional lines for + rows with more than 2 child rows + */ + tbody > tr:hover td, + tbody > tr:hover + tr.tablesorter-childRow > td, + tbody > tr:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td, + tbody > tr.even:hover > td, + tbody > tr.even:hover + tr.tablesorter-childRow > td, + tbody > tr.even:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + .evenHovered; + } + tbody > tr.odd:hover > td, + tbody > tr.odd:hover + tr.tablesorter-childRow > td, + tbody > tr.odd:hover + tr.tablesorter-childRow + tr.tablesorter-childRow > td { + .oddHovered; + } + + /* table processing indicator - indeterminate spinner */ + .tablesorter-processing { + background-image: @processingIcon; + background-position: center center; + background-repeat: no-repeat; + position: absolute; + z-index: 1000; + } + + /* Column Widget - column sort colors */ + tr.odd td.primary { + background-color: @primaryOdd; + } + td.primary, tr.even td.primary { + background-color: @primaryEven; + } + tr.odd td.secondary { + background-color: @secondaryOdd; + } + td.secondary, tr.even td.secondary { + background-color: @secondaryEven; + } + tr.odd td.tertiary { + background-color: @tertiaryOdd; + } + td.tertiary, tr.even td.tertiary { + background-color: @tertiaryEven; + } + + /* caption (non-theme matching) */ + caption { + background: @captionBackground ; + } + + /* filter widget */ + .tablesorter-filter-row input, + .tablesorter-filter-row select{ + width: 98%; + height: auto; + margin: 0; + padding: @overallPadding; + color: @filterElementTextColor; + background: @filterElementBkgd; + border: @filterElementBorder; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + .filterWidgetTransition; + } + .tablesorter-filter-row td { + text-align: center; + background: @filterCellBackground; + line-height: normal; + text-align: center; /* center the input */ + .filterWidgetTransition; + } + /* hidden filter row */ + .tablesorter-filter-row.hideme td { + padding: @filterRowHiddenHeight / 2; + margin: 0; + line-height: 0; + cursor: pointer; + } + .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); + } + /* rows hidden by filtering (needed for child rows) */ + .filtered { + display: none; + } + + /* ajax error row */ + .tablesorter-errorRow td { + text-align: center; + cursor: pointer; + background-color: @errorBackground; + } + +} diff --git a/ajax/libs/jquery.tablesorter/2.15.14/extras/jquery.quicksearch.js b/ajax/libs/jquery.tablesorter/2.15.14/extras/jquery.quicksearch.js new file mode 100644 index 000000000..ee783acea --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/extras/jquery.quicksearch.js @@ -0,0 +1,191 @@ +/* jQuery Quicksearch plugin + by riklomas https://github.com/riklomas/quicksearch + Modified to include childRows (for tablesorter) + + See http://stackoverflow.com/q/20342203/145346 for + more details +*/ +(function($, window, document, undefined) { + $.fn.quicksearch = function (target, opt) { + + var timeout, cache, rowcache, jq_results, val = '', e = this, options = $.extend({ + delay: 100, + selector: null, + stripeRows: null, + loader: null, + noResults: '', + childRow: 'tablesorter-childRow', // include child row with search results + matchedResultsCount: 0, + bind: 'keyup', + onBefore: function () { + return; + }, + onAfter: function () { + return; + }, + show: function () { + this.style.display = ""; + }, + hide: function () { + this.style.display = "none"; + }, + prepareQuery: function (val) { + return val.toLowerCase().split(' '); + }, + testQuery: function (query, txt, _row) { + for (var i = 0; i < query.length; i += 1) { + if (txt.indexOf(query[i]) === -1) { + return false; + } + } + return true; + } + }, opt); + + this.go = function () { + + var i = 0, + numMatchedRows = 0, + noresults = true, + query = options.prepareQuery(val), + val_empty = (val.replace(' ', '').length === 0); + + for (var i = 0, len = rowcache.length; i < len; i++) { + if (val_empty || options.testQuery(query, cache[i], rowcache[i]) || + ($(rowcache[i]).hasClass(options.childRow) && $(rowcache[i > 1 ? i - 1 : 0]).is(':visible'))) { + options.show.apply(rowcache[i]); + noresults = false; + numMatchedRows++; + } else { + options.hide.apply(rowcache[i]); + } + } + + if (noresults) { + this.results(false); + } else { + this.results(true); + this.stripe(); + } + + this.matchedResultsCount = numMatchedRows; + this.loader(false); + options.onAfter(); + + return this; + }; + + /* + * External API so that users can perform search programatically. + * */ + this.search = function (submittedVal) { + val = submittedVal; + e.trigger(); + }; + + /* + * External API to get the number of matched results as seen in + * https://github.com/ruiz107/quicksearch/commit/f78dc440b42d95ce9caed1d087174dd4359982d6 + * */ + this.currentMatchedResults = function() { + return this.matchedResultsCount; + }; + + this.stripe = function () { + + if (typeof options.stripeRows === "object" && options.stripeRows !== null) + { + var joined = options.stripeRows.join(' '); + var stripeRows_length = options.stripeRows.length; + + jq_results.not(':hidden').each(function (i) { + $(this).removeClass(joined).addClass(options.stripeRows[i % stripeRows_length]); + }); + } + + return this; + }; + + this.strip_html = function (input) { + var output = input.replace(new RegExp('<[^<]+\>', 'g'), ""); + output = $.trim(output.toLowerCase()); + return output; + }; + + this.results = function (bool) { + if (typeof options.noResults === "string" && options.noResults !== "") { + if (bool) { + $(options.noResults).hide(); + } else { + $(options.noResults).show(); + } + } + return this; + }; + + this.loader = function (bool) { + if (typeof options.loader === "string" && options.loader !== "") { + (bool) ? $(options.loader).show() : $(options.loader).hide(); + } + return this; + }; + + this.cache = function () { + + jq_results = $(target); + + if (typeof options.noResults === "string" && options.noResults !== "") { + jq_results = jq_results.not(options.noResults); + } + + var t = (typeof options.selector === "string") ? + jq_results.find(options.selector) : $(target).not(options.noResults); + cache = t.map(function () { + return e.strip_html(this.innerHTML); + }); + + rowcache = jq_results.map(function () { + return this; + }); + + /* + * Modified fix for sync-ing "val". + * Original fix https://github.com/michaellwest/quicksearch/commit/4ace4008d079298a01f97f885ba8fa956a9703d1 + * */ + val = val || this.val() || ""; + + return this.go(); + }; + + this.trigger = function () { + this.loader(true); + options.onBefore(); + + window.clearTimeout(timeout); + timeout = window.setTimeout(function () { + e.go(); + }, options.delay); + + return this; + }; + + this.cache(); + this.results(true); + this.stripe(); + this.loader(false); + + return this.each(function () { + + /* + * Changed from .bind to .on. + * */ + $(this).on(options.bind, function () { + + val = $(this).val(); + e.trigger(); + }); + }); + + }; + +}(jQuery, this, document)); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/extras/semver-mod.js b/ajax/libs/jquery.tablesorter/2.15.14/extras/semver-mod.js new file mode 100644 index 000000000..ac643039b --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/extras/semver-mod.js @@ -0,0 +1,1026 @@ +/** + Modified semver.js for node.js by R.Garrison (@Mottie) + Original by @isaacs: https://github.com/isaacs/node-semver + ( all modifications have been labeled ) + */ +// ***** MODIFIED LINE BELOW ***** +(function(){ +// ***** MODIFIED LINE BELOW ***** +var module = { exports : {} }; + +// export the class if we are in a Node-like system. +// ***** MODIFIED LINE BELOW ***** +// if (typeof module === 'object' && module.exports === exports) +// ***** MODIFIED LINE BELOW ***** + var exports = module.exports = SemVer; + +// The debug function is excluded entirely from the minified version. +/* nomin */ var debug; +/* nomin */ if (typeof process === 'object' && + /* nomin */ process.env && + /* nomin */ process.env.NODE_DEBUG && + /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) + /* nomin */ debug = function() { + /* nomin */ var args = Array.prototype.slice.call(arguments, 0); + /* nomin */ args.unshift('SEMVER'); + /* nomin */ console.log.apply(console, args); + /* nomin */ }; +/* nomin */ else + /* nomin */ debug = function() {}; + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0'; + +// The actual regexps go on exports.re +var re = exports.re = []; +var src = exports.src = []; +var R = 0; + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++; +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; +var NUMERICIDENTIFIERLOOSE = R++; +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; + + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++; +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; + + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++; +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')'; + +var MAINVERSIONLOOSE = R++; +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++; +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + +var PRERELEASEIDENTIFIERLOOSE = R++; +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++; +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; + +var PRERELEASELOOSE = R++; +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++; +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++; +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; + + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++; +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?'; + +src[FULL] = '^' + FULLPLAIN + '$'; + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?'; + +var LOOSE = R++; +src[LOOSE] = '^' + LOOSEPLAIN + '$'; + +var GTLT = R++; +src[GTLT] = '((?:<|>)?=?)'; + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++; +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; +var XRANGEIDENTIFIER = R++; +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; + +var XRANGEPLAIN = R++; +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:(' + src[PRERELEASE] + ')' + + ')?)?)?'; + +var XRANGEPLAINLOOSE = R++; +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:(' + src[PRERELEASELOOSE] + ')' + + ')?)?)?'; + +// >=2.x, for example, means >=2.0.0-0 +// <1.x would be the same as "<1.0.0-0", though. +var XRANGE = R++; +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; +var XRANGELOOSE = R++; +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++; +src[LONETILDE] = '(?:~>?)'; + +var TILDETRIM = R++; +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); +var tildeTrimReplace = '$1~'; + +var TILDE = R++; +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; +var TILDELOOSE = R++; +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++; +src[LONECARET] = '(?:\\^)'; + +var CARETTRIM = R++; +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); +var caretTrimReplace = '$1^'; + +var CARET = R++; +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; +var CARETLOOSE = R++; +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++; +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; +var COMPARATOR = R++; +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++; +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); +var comparatorTrimReplace = '$1$2$3'; + + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++; +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$'; + +var HYPHENRANGELOOSE = R++; +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$'; + +// Star ranges basically just allow anything at all. +var STAR = R++; +src[STAR] = '(<|>)?=?\\s*\\*'; + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]); + if (!re[i]) + re[i] = new RegExp(src[i]); +} + +exports.parse = parse; +function parse(version, loose) { + var r = loose ? re[LOOSE] : re[FULL]; + return (r.test(version)) ? new SemVer(version, loose) : null; +} + +exports.valid = valid; +function valid(version, loose) { + var v = parse(version, loose); + return v ? v.version : null; +} + + +exports.clean = clean; +function clean(version, loose) { + var s = parse(version, loose); + return s ? s.version : null; +} + +// ***** MODIFIED LINE BELOW ***** +window.semver = exports.SemVer = SemVer; + +function SemVer(version, loose) { + if (version instanceof SemVer) { + if (version.loose === loose) + return version; + else + version = version.version; + } + + if (!(this instanceof SemVer)) + return new SemVer(version, loose); + + debug('SemVer', version, loose); + this.loose = loose; + var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + + if (!m) + throw new TypeError('Invalid Version: ' + version); + + this.raw = version; + + // these are actually numbers + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + + // numberify any prerelease numeric ids + if (!m[4]) + this.prerelease = []; + else + this.prerelease = m[4].split('.').map(function(id) { + return (/^[0-9]+$/.test(id)) ? +id : id; + }); + + this.build = m[5] ? m[5].split('.') : []; + this.format(); +} + +SemVer.prototype.format = function() { + this.version = this.major + '.' + this.minor + '.' + this.patch; + if (this.prerelease.length) + this.version += '-' + this.prerelease.join('.'); + return this.version; +}; + +SemVer.prototype.inspect = function() { + return ''; +}; + +SemVer.prototype.toString = function() { + return this.version; +}; + +SemVer.prototype.compare = function(other) { + debug('SemVer.compare', this.version, this.loose, other); + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return this.compareMain(other) || this.comparePre(other); +}; + +SemVer.prototype.compareMain = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch); +}; + +SemVer.prototype.comparePre = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) + return -1; + else if (!this.prerelease.length && other.prerelease.length) + return 1; + else if (!this.prerelease.lenth && !other.prerelease.length) + return 0; + + var i = 0; + do { + var a = this.prerelease[i]; + var b = other.prerelease[i]; + debug('prerelease compare', i, a, b); + if (a === undefined && b === undefined) + return 0; + else if (b === undefined) + return 1; + else if (a === undefined) + return -1; + else if (a === b) + continue; + else + return compareIdentifiers(a, b); + } while (++i); +}; + +SemVer.prototype.inc = function(release) { + switch (release) { + case 'major': + this.major++; + this.minor = -1; + case 'minor': + this.minor++; + this.patch = -1; + case 'patch': + this.patch++; + this.prerelease = []; + break; + case 'prerelease': + if (this.prerelease.length === 0) + this.prerelease = [0]; + else { + var i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) // didn't increment anything + this.prerelease.push(0); + } + break; + + default: + throw new Error('invalid increment argument: ' + release); + } + this.format(); + return this; +}; + +exports.inc = inc; +function inc(version, release, loose) { + try { + return new SemVer(version, loose).inc(release).version; + } catch (er) { + return null; + } +} + +exports.compareIdentifiers = compareIdentifiers; + +var numeric = /^[0-9]+$/; +function compareIdentifiers(a, b) { + var anum = numeric.test(a); + var bnum = numeric.test(b); + + if (anum && bnum) { + a = +a; + b = +b; + } + + return (anum && !bnum) ? -1 : + (bnum && !anum) ? 1 : + a < b ? -1 : + a > b ? 1 : + 0; +} + +exports.rcompareIdentifiers = rcompareIdentifiers; +function rcompareIdentifiers(a, b) { + return compareIdentifiers(b, a); +} + +exports.compare = compare; +function compare(a, b, loose) { + return new SemVer(a, loose).compare(b); +} + +exports.compareLoose = compareLoose; +function compareLoose(a, b) { + return compare(a, b, true); +} + +exports.rcompare = rcompare; +function rcompare(a, b, loose) { + return compare(b, a, loose); +} + +exports.sort = sort; +function sort(list, loose) { + return list.sort(function(a, b) { + return exports.compare(a, b, loose); + }); +} + +exports.rsort = rsort; +function rsort(list, loose) { + return list.sort(function(a, b) { + return exports.rcompare(a, b, loose); + }); +} + +exports.gt = gt; +function gt(a, b, loose) { + return compare(a, b, loose) > 0; +} + +exports.lt = lt; +function lt(a, b, loose) { + return compare(a, b, loose) < 0; +} + +exports.eq = eq; +function eq(a, b, loose) { + return compare(a, b, loose) === 0; +} + +exports.neq = neq; +function neq(a, b, loose) { + return compare(a, b, loose) !== 0; +} + +exports.gte = gte; +function gte(a, b, loose) { + return compare(a, b, loose) >= 0; +} + +exports.lte = lte; +function lte(a, b, loose) { + return compare(a, b, loose) <= 0; +} + +exports.cmp = cmp; +function cmp(a, op, b, loose) { + var ret; + switch (op) { + case '===': ret = a === b; break; + case '!==': ret = a !== b; break; + case '': case '=': case '==': ret = eq(a, b, loose); break; + case '!=': ret = neq(a, b, loose); break; + case '>': ret = gt(a, b, loose); break; + case '>=': ret = gte(a, b, loose); break; + case '<': ret = lt(a, b, loose); break; + case '<=': ret = lte(a, b, loose); break; + default: throw new TypeError('Invalid operator: ' + op); + } + return ret; +} + +exports.Comparator = Comparator; +function Comparator(comp, loose) { + if (comp instanceof Comparator) { + if (comp.loose === loose) + return comp; + else + comp = comp.value; + } + + if (!(this instanceof Comparator)) + return new Comparator(comp, loose); + + debug('comparator', comp, loose); + this.loose = loose; + this.parse(comp); + + if (this.semver === ANY) + this.value = ''; + else + this.value = this.operator + this.semver.version; +} + +var ANY = {}; +Comparator.prototype.parse = function(comp) { + var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var m = comp.match(r); + + if (!m) + throw new TypeError('Invalid comparator: ' + comp); + + this.operator = m[1]; + // if it literally is just '>' or '' then allow anything. + if (!m[2]) + this.semver = ANY; + else { + this.semver = new SemVer(m[2], this.loose); + + // <1.2.3-rc DOES allow 1.2.3-beta (has prerelease) + // >=1.2.3 DOES NOT allow 1.2.3-beta + // <=1.2.3 DOES allow 1.2.3-beta + // However, <1.2.3 does NOT allow 1.2.3-beta, + // even though `1.2.3-beta < 1.2.3` + // The assumption is that the 1.2.3 version has something you + // *don't* want, so we push the prerelease down to the minimum. + if (this.operator === '<' && !this.semver.prerelease.length) { + this.semver.prerelease = ['0']; + this.semver.format(); + } + } +}; + +Comparator.prototype.inspect = function() { + return ''; +}; + +Comparator.prototype.toString = function() { + return this.value; +}; + +Comparator.prototype.test = function(version) { + debug('Comparator.test', version, this.loose); + return (this.semver === ANY) ? true : + cmp(version, this.operator, this.semver, this.loose); +}; + + +exports.Range = Range; +function Range(range, loose) { + if ((range instanceof Range) && range.loose === loose) + return range; + + if (!(this instanceof Range)) + return new Range(range, loose); + + this.loose = loose; + + // First, split based on boolean or || + this.raw = range; + this.set = range.split(/\s*\|\|\s*/).map(function(range) { + return this.parseRange(range.trim()); + }, this).filter(function(c) { + // throw out any that are not relevant for whatever reason + return c.length; + }); + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range); + } + + this.format(); +} + +Range.prototype.inspect = function() { + return ''; +}; + +Range.prototype.format = function() { + this.range = this.set.map(function(comps) { + return comps.join(' ').trim(); + }).join('||').trim(); + return this.range; +}; + +Range.prototype.toString = function() { + return this.range; +}; + +Range.prototype.parseRange = function(range) { + var loose = this.loose; + range = range.trim(); + debug('range', range, loose); + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; + range = range.replace(hr, hyphenReplace); + debug('hyphen replace', range); + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); + debug('comparator trim', range, re[COMPARATORTRIM]); + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace); + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace); + + // normalize spaces + range = range.split(/\s+/).join(' '); + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var set = range.split(' ').map(function(comp) { + return parseComparator(comp, loose); + }).join(' ').split(/\s+/); + if (this.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function(comp) { + return !!comp.match(compRe); + }); + } + set = set.map(function(comp) { + return new Comparator(comp, loose); + }); + + return set; +}; + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators; +function toComparators(range, loose) { + return new Range(range, loose).set.map(function(comp) { + return comp.map(function(c) { + return c.value; + }).join(' ').trim().split(' '); + }); +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator(comp, loose) { + debug('comp', comp); + comp = replaceCarets(comp, loose); + debug('caret', comp); + comp = replaceTildes(comp, loose); + debug('tildes', comp); + comp = replaceXRanges(comp, loose); + debug('xrange', comp); + comp = replaceStars(comp, loose); + debug('stars', comp); + return comp; +} + +function isX(id) { + return !id || id.toLowerCase() === 'x' || id === '*'; +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceTilde(comp, loose); + }).join(' '); +} + +function replaceTilde(comp, loose) { + var r = loose ? re[TILDELOOSE] : re[TILDE]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0'; + else if (isX(p)) + // ~1.2 == >=1.2.0- <1.3.0- + ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0'; + else if (pr) { + debug('replaceTilde pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0-0'; + } else + // ~1.2.3 == >=1.2.3-0 <1.3.0-0 + ret = '>=' + M + '.' + m + '.' + p + '-0' + + ' <' + M + '.' + (+m + 1) + '.0-0'; + + debug('tilde return', ret); + return ret; + }); +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceCaret(comp, loose); + }).join(' '); +} + +function replaceCaret(comp, loose) { + var r = loose ? re[CARETLOOSE] : re[CARET]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0'; + else if (isX(p)) { + if (M === '0') + ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0'; + else + ret = '>=' + M + '.' + m + '.0-0 <' + (+M + 1) + '.0.0-0'; + } else if (pr) { + debug('replaceCaret pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + if (M === '0') { + if (m === '0') + ret = '=' + M + '.' + m + '.' + p + pr; + else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0-0'; + } else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + (+M + 1) + '.0.0-0'; + } else { + if (M === '0') { + if (m === '0') + ret = '=' + M + '.' + m + '.' + p; + else + ret = '>=' + M + '.' + m + '.' + p + '-0' + + ' <' + M + '.' + (+m + 1) + '.0-0'; + } else + ret = '>=' + M + '.' + m + '.' + p + '-0' + + ' <' + (+M + 1) + '.0.0-0'; + } + + debug('caret return', ret); + return ret; + }); +} + +function replaceXRanges(comp, loose) { + debug('replaceXRanges', comp, loose); + return comp.split(/\s+/).map(function(comp) { + return replaceXRange(comp, loose); + }).join(' '); +} + +function replaceXRange(comp, loose) { + comp = comp.trim(); + var r = loose ? re[XRANGELOOSE] : re[XRANGE]; + return comp.replace(r, function(ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr); + var xM = isX(M); + var xm = xM || isX(m); + var xp = xm || isX(p); + var anyX = xp; + + if (gtlt === '=' && anyX) + gtlt = ''; + + if (gtlt && anyX) { + // replace X with 0, and then append the -0 min-prerelease + if (xM) + M = 0; + if (xm) + m = 0; + if (xp) + p = 0; + + if (gtlt === '>') { + // >1 => >=2.0.0-0 + // >1.2 => >=1.3.0-0 + // >1.2.3 => >= 1.2.4-0 + gtlt = '>='; + if (xM) { + // no change + } else if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else if (xp) { + m = +m + 1; + p = 0; + } + } + + + ret = gtlt + M + '.' + m + '.' + p + '-0'; + } else if (xM) { + // allow any + ret = '*'; + } else if (xm) { + // append '-0' onto the version, otherwise + // '1.x.x' matches '2.0.0-beta', since the tag + // *lowers* the version value + ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0'; + } else if (xp) { + ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0'; + } + + debug('xRange return', ret); + + return ret; + }); +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars(comp, loose) { + debug('replaceStars', comp, loose); + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], ''); +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0 +function hyphenReplace($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + + if (isX(fM)) + from = ''; + else if (isX(fm)) + from = '>=' + fM + '.0.0-0'; + else if (isX(fp)) + from = '>=' + fM + '.' + fm + '.0-0'; + else + from = '>=' + from; + + if (isX(tM)) + to = ''; + else if (isX(tm)) + to = '<' + (+tM + 1) + '.0.0-0'; + else if (isX(tp)) + to = '<' + tM + '.' + (+tm + 1) + '.0-0'; + else if (tpr) + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; + else + to = '<=' + to; + + return (from + ' ' + to).trim(); +} + + +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function(version) { + if (!version) + return false; + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version)) + return true; + } + return false; +}; + +function testSet(set, version) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) + return false; + } + return true; +} + +exports.satisfies = satisfies; +function satisfies(version, range, loose) { + try { + range = new Range(range, loose); + } catch (er) { + return false; + } + return range.test(version); +} + +exports.maxSatisfying = maxSatisfying; +function maxSatisfying(versions, range, loose) { + return versions.filter(function(version) { + return satisfies(version, range, loose); + }).sort(function(a, b) { + return rcompare(a, b, loose); + })[0] || null; +} + +exports.validRange = validRange; +function validRange(range, loose) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, loose).range || '*'; + } catch (er) { + return null; + } +} + +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr; +function ltr(version, range, loose) { + return outside(version, range, '<', loose); +} + +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr; +function gtr(version, range, loose) { + return outside(version, range, '>', loose); +} + +exports.outside = outside; +function outside(version, range, hilo, loose) { + version = new SemVer(version, loose); + range = new Range(range, loose); + + var gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case '>': + gtfn = gt; + ltefn = lte; + ltfn = lt; + comp = '>'; + ecomp = '>='; + break; + case '<': + gtfn = lt; + ltefn = gte; + ltfn = gt; + comp = '<'; + ecomp = '<='; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, loose)) { + return false; + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i]; + + var high = null; + var low = null; + + comparators.forEach(function(comparator) { + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, loose)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, loose)) { + low = comparator; + } + }); + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false; + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; +} + +// Use the define() function if we're in AMD land +if (typeof define === 'function' && define.amd) + define(exports); +// ***** MODIFIED LINE BELOW ***** +})(); \ No newline at end of file diff --git a/ajax/libs/jquery.tablesorter/2.15.14/extras/semver.js b/ajax/libs/jquery.tablesorter/2.15.14/extras/semver.js new file mode 100644 index 000000000..9e9470d86 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/extras/semver.js @@ -0,0 +1,1011 @@ +// export the class if we are in a Node-like system. +if (typeof module === 'object' && module.exports === exports) + exports = module.exports = SemVer; + +// The debug function is excluded entirely from the minified version. +/* nomin */ var debug; +/* nomin */ if (typeof process === 'object' && + /* nomin */ process.env && + /* nomin */ process.env.NODE_DEBUG && + /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) + /* nomin */ debug = function() { + /* nomin */ var args = Array.prototype.slice.call(arguments, 0); + /* nomin */ args.unshift('SEMVER'); + /* nomin */ console.log.apply(console, args); + /* nomin */ }; +/* nomin */ else + /* nomin */ debug = function() {}; + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0'; + +// The actual regexps go on exports.re +var re = exports.re = []; +var src = exports.src = []; +var R = 0; + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++; +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; +var NUMERICIDENTIFIERLOOSE = R++; +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; + + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++; +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; + + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++; +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')'; + +var MAINVERSIONLOOSE = R++; +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++; +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + +var PRERELEASEIDENTIFIERLOOSE = R++; +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++; +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; + +var PRERELEASELOOSE = R++; +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++; +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++; +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; + + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++; +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?'; + +src[FULL] = '^' + FULLPLAIN + '$'; + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?'; + +var LOOSE = R++; +src[LOOSE] = '^' + LOOSEPLAIN + '$'; + +var GTLT = R++; +src[GTLT] = '((?:<|>)?=?)'; + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++; +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; +var XRANGEIDENTIFIER = R++; +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; + +var XRANGEPLAIN = R++; +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:(' + src[PRERELEASE] + ')' + + ')?)?)?'; + +var XRANGEPLAINLOOSE = R++; +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:(' + src[PRERELEASELOOSE] + ')' + + ')?)?)?'; + +// >=2.x, for example, means >=2.0.0-0 +// <1.x would be the same as "<1.0.0-0", though. +var XRANGE = R++; +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; +var XRANGELOOSE = R++; +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++; +src[LONETILDE] = '(?:~>?)'; + +var TILDETRIM = R++; +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); +var tildeTrimReplace = '$1~'; + +var TILDE = R++; +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; +var TILDELOOSE = R++; +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++; +src[LONECARET] = '(?:\\^)'; + +var CARETTRIM = R++; +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); +var caretTrimReplace = '$1^'; + +var CARET = R++; +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; +var CARETLOOSE = R++; +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++; +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; +var COMPARATOR = R++; +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++; +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); +var comparatorTrimReplace = '$1$2$3'; + + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++; +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$'; + +var HYPHENRANGELOOSE = R++; +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$'; + +// Star ranges basically just allow anything at all. +var STAR = R++; +src[STAR] = '(<|>)?=?\\s*\\*'; + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]); + if (!re[i]) + re[i] = new RegExp(src[i]); +} + +exports.parse = parse; +function parse(version, loose) { + var r = loose ? re[LOOSE] : re[FULL]; + return (r.test(version)) ? new SemVer(version, loose) : null; +} + +exports.valid = valid; +function valid(version, loose) { + var v = parse(version, loose); + return v ? v.version : null; +} + + +exports.clean = clean; +function clean(version, loose) { + var s = parse(version, loose); + return s ? s.version : null; +} + +exports.SemVer = SemVer; + +function SemVer(version, loose) { + if (version instanceof SemVer) { + if (version.loose === loose) + return version; + else + version = version.version; + } + + if (!(this instanceof SemVer)) + return new SemVer(version, loose); + + debug('SemVer', version, loose); + this.loose = loose; + var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + + if (!m) + throw new TypeError('Invalid Version: ' + version); + + this.raw = version; + + // these are actually numbers + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + + // numberify any prerelease numeric ids + if (!m[4]) + this.prerelease = []; + else + this.prerelease = m[4].split('.').map(function(id) { + return (/^[0-9]+$/.test(id)) ? +id : id; + }); + + this.build = m[5] ? m[5].split('.') : []; + this.format(); +} + +SemVer.prototype.format = function() { + this.version = this.major + '.' + this.minor + '.' + this.patch; + if (this.prerelease.length) + this.version += '-' + this.prerelease.join('.'); + return this.version; +}; + +SemVer.prototype.inspect = function() { + return ''; +}; + +SemVer.prototype.toString = function() { + return this.version; +}; + +SemVer.prototype.compare = function(other) { + debug('SemVer.compare', this.version, this.loose, other); + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return this.compareMain(other) || this.comparePre(other); +}; + +SemVer.prototype.compareMain = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch); +}; + +SemVer.prototype.comparePre = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) + return -1; + else if (!this.prerelease.length && other.prerelease.length) + return 1; + else if (!this.prerelease.lenth && !other.prerelease.length) + return 0; + + var i = 0; + do { + var a = this.prerelease[i]; + var b = other.prerelease[i]; + debug('prerelease compare', i, a, b); + if (a === undefined && b === undefined) + return 0; + else if (b === undefined) + return 1; + else if (a === undefined) + return -1; + else if (a === b) + continue; + else + return compareIdentifiers(a, b); + } while (++i); +}; + +SemVer.prototype.inc = function(release) { + switch (release) { + case 'major': + this.major++; + this.minor = -1; + case 'minor': + this.minor++; + this.patch = -1; + case 'patch': + this.patch++; + this.prerelease = []; + break; + case 'prerelease': + if (this.prerelease.length === 0) + this.prerelease = [0]; + else { + var i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) // didn't increment anything + this.prerelease.push(0); + } + break; + + default: + throw new Error('invalid increment argument: ' + release); + } + this.format(); + return this; +}; + +exports.inc = inc; +function inc(version, release, loose) { + try { + return new SemVer(version, loose).inc(release).version; + } catch (er) { + return null; + } +} + +exports.compareIdentifiers = compareIdentifiers; + +var numeric = /^[0-9]+$/; +function compareIdentifiers(a, b) { + var anum = numeric.test(a); + var bnum = numeric.test(b); + + if (anum && bnum) { + a = +a; + b = +b; + } + + return (anum && !bnum) ? -1 : + (bnum && !anum) ? 1 : + a < b ? -1 : + a > b ? 1 : + 0; +} + +exports.rcompareIdentifiers = rcompareIdentifiers; +function rcompareIdentifiers(a, b) { + return compareIdentifiers(b, a); +} + +exports.compare = compare; +function compare(a, b, loose) { + return new SemVer(a, loose).compare(b); +} + +exports.compareLoose = compareLoose; +function compareLoose(a, b) { + return compare(a, b, true); +} + +exports.rcompare = rcompare; +function rcompare(a, b, loose) { + return compare(b, a, loose); +} + +exports.sort = sort; +function sort(list, loose) { + return list.sort(function(a, b) { + return exports.compare(a, b, loose); + }); +} + +exports.rsort = rsort; +function rsort(list, loose) { + return list.sort(function(a, b) { + return exports.rcompare(a, b, loose); + }); +} + +exports.gt = gt; +function gt(a, b, loose) { + return compare(a, b, loose) > 0; +} + +exports.lt = lt; +function lt(a, b, loose) { + return compare(a, b, loose) < 0; +} + +exports.eq = eq; +function eq(a, b, loose) { + return compare(a, b, loose) === 0; +} + +exports.neq = neq; +function neq(a, b, loose) { + return compare(a, b, loose) !== 0; +} + +exports.gte = gte; +function gte(a, b, loose) { + return compare(a, b, loose) >= 0; +} + +exports.lte = lte; +function lte(a, b, loose) { + return compare(a, b, loose) <= 0; +} + +exports.cmp = cmp; +function cmp(a, op, b, loose) { + var ret; + switch (op) { + case '===': ret = a === b; break; + case '!==': ret = a !== b; break; + case '': case '=': case '==': ret = eq(a, b, loose); break; + case '!=': ret = neq(a, b, loose); break; + case '>': ret = gt(a, b, loose); break; + case '>=': ret = gte(a, b, loose); break; + case '<': ret = lt(a, b, loose); break; + case '<=': ret = lte(a, b, loose); break; + default: throw new TypeError('Invalid operator: ' + op); + } + return ret; +} + +exports.Comparator = Comparator; +function Comparator(comp, loose) { + if (comp instanceof Comparator) { + if (comp.loose === loose) + return comp; + else + comp = comp.value; + } + + if (!(this instanceof Comparator)) + return new Comparator(comp, loose); + + debug('comparator', comp, loose); + this.loose = loose; + this.parse(comp); + + if (this.semver === ANY) + this.value = ''; + else + this.value = this.operator + this.semver.version; +} + +var ANY = {}; +Comparator.prototype.parse = function(comp) { + var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var m = comp.match(r); + + if (!m) + throw new TypeError('Invalid comparator: ' + comp); + + this.operator = m[1]; + // if it literally is just '>' or '' then allow anything. + if (!m[2]) + this.semver = ANY; + else { + this.semver = new SemVer(m[2], this.loose); + + // <1.2.3-rc DOES allow 1.2.3-beta (has prerelease) + // >=1.2.3 DOES NOT allow 1.2.3-beta + // <=1.2.3 DOES allow 1.2.3-beta + // However, <1.2.3 does NOT allow 1.2.3-beta, + // even though `1.2.3-beta < 1.2.3` + // The assumption is that the 1.2.3 version has something you + // *don't* want, so we push the prerelease down to the minimum. + if (this.operator === '<' && !this.semver.prerelease.length) { + this.semver.prerelease = ['0']; + this.semver.format(); + } + } +}; + +Comparator.prototype.inspect = function() { + return ''; +}; + +Comparator.prototype.toString = function() { + return this.value; +}; + +Comparator.prototype.test = function(version) { + debug('Comparator.test', version, this.loose); + return (this.semver === ANY) ? true : + cmp(version, this.operator, this.semver, this.loose); +}; + + +exports.Range = Range; +function Range(range, loose) { + if ((range instanceof Range) && range.loose === loose) + return range; + + if (!(this instanceof Range)) + return new Range(range, loose); + + this.loose = loose; + + // First, split based on boolean or || + this.raw = range; + this.set = range.split(/\s*\|\|\s*/).map(function(range) { + return this.parseRange(range.trim()); + }, this).filter(function(c) { + // throw out any that are not relevant for whatever reason + return c.length; + }); + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range); + } + + this.format(); +} + +Range.prototype.inspect = function() { + return ''; +}; + +Range.prototype.format = function() { + this.range = this.set.map(function(comps) { + return comps.join(' ').trim(); + }).join('||').trim(); + return this.range; +}; + +Range.prototype.toString = function() { + return this.range; +}; + +Range.prototype.parseRange = function(range) { + var loose = this.loose; + range = range.trim(); + debug('range', range, loose); + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; + range = range.replace(hr, hyphenReplace); + debug('hyphen replace', range); + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); + debug('comparator trim', range, re[COMPARATORTRIM]); + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace); + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace); + + // normalize spaces + range = range.split(/\s+/).join(' '); + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var set = range.split(' ').map(function(comp) { + return parseComparator(comp, loose); + }).join(' ').split(/\s+/); + if (this.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function(comp) { + return !!comp.match(compRe); + }); + } + set = set.map(function(comp) { + return new Comparator(comp, loose); + }); + + return set; +}; + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators; +function toComparators(range, loose) { + return new Range(range, loose).set.map(function(comp) { + return comp.map(function(c) { + return c.value; + }).join(' ').trim().split(' '); + }); +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator(comp, loose) { + debug('comp', comp); + comp = replaceCarets(comp, loose); + debug('caret', comp); + comp = replaceTildes(comp, loose); + debug('tildes', comp); + comp = replaceXRanges(comp, loose); + debug('xrange', comp); + comp = replaceStars(comp, loose); + debug('stars', comp); + return comp; +} + +function isX(id) { + return !id || id.toLowerCase() === 'x' || id === '*'; +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceTilde(comp, loose); + }).join(' '); +} + +function replaceTilde(comp, loose) { + var r = loose ? re[TILDELOOSE] : re[TILDE]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0'; + else if (isX(p)) + // ~1.2 == >=1.2.0- <1.3.0- + ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0'; + else if (pr) { + debug('replaceTilde pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0-0'; + } else + // ~1.2.3 == >=1.2.3-0 <1.3.0-0 + ret = '>=' + M + '.' + m + '.' + p + '-0' + + ' <' + M + '.' + (+m + 1) + '.0-0'; + + debug('tilde return', ret); + return ret; + }); +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceCaret(comp, loose); + }).join(' '); +} + +function replaceCaret(comp, loose) { + var r = loose ? re[CARETLOOSE] : re[CARET]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0'; + else if (isX(p)) { + if (M === '0') + ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0'; + else + ret = '>=' + M + '.' + m + '.0-0 <' + (+M + 1) + '.0.0-0'; + } else if (pr) { + debug('replaceCaret pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + if (M === '0') { + if (m === '0') + ret = '=' + M + '.' + m + '.' + p + pr; + else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0-0'; + } else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + (+M + 1) + '.0.0-0'; + } else { + if (M === '0') { + if (m === '0') + ret = '=' + M + '.' + m + '.' + p; + else + ret = '>=' + M + '.' + m + '.' + p + '-0' + + ' <' + M + '.' + (+m + 1) + '.0-0'; + } else + ret = '>=' + M + '.' + m + '.' + p + '-0' + + ' <' + (+M + 1) + '.0.0-0'; + } + + debug('caret return', ret); + return ret; + }); +} + +function replaceXRanges(comp, loose) { + debug('replaceXRanges', comp, loose); + return comp.split(/\s+/).map(function(comp) { + return replaceXRange(comp, loose); + }).join(' '); +} + +function replaceXRange(comp, loose) { + comp = comp.trim(); + var r = loose ? re[XRANGELOOSE] : re[XRANGE]; + return comp.replace(r, function(ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr); + var xM = isX(M); + var xm = xM || isX(m); + var xp = xm || isX(p); + var anyX = xp; + + if (gtlt === '=' && anyX) + gtlt = ''; + + if (gtlt && anyX) { + // replace X with 0, and then append the -0 min-prerelease + if (xM) + M = 0; + if (xm) + m = 0; + if (xp) + p = 0; + + if (gtlt === '>') { + // >1 => >=2.0.0-0 + // >1.2 => >=1.3.0-0 + // >1.2.3 => >= 1.2.4-0 + gtlt = '>='; + if (xM) { + // no change + } else if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else if (xp) { + m = +m + 1; + p = 0; + } + } + + + ret = gtlt + M + '.' + m + '.' + p + '-0'; + } else if (xM) { + // allow any + ret = '*'; + } else if (xm) { + // append '-0' onto the version, otherwise + // '1.x.x' matches '2.0.0-beta', since the tag + // *lowers* the version value + ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0'; + } else if (xp) { + ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0'; + } + + debug('xRange return', ret); + + return ret; + }); +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars(comp, loose) { + debug('replaceStars', comp, loose); + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], ''); +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0 +function hyphenReplace($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + + if (isX(fM)) + from = ''; + else if (isX(fm)) + from = '>=' + fM + '.0.0-0'; + else if (isX(fp)) + from = '>=' + fM + '.' + fm + '.0-0'; + else + from = '>=' + from; + + if (isX(tM)) + to = ''; + else if (isX(tm)) + to = '<' + (+tM + 1) + '.0.0-0'; + else if (isX(tp)) + to = '<' + tM + '.' + (+tm + 1) + '.0-0'; + else if (tpr) + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; + else + to = '<=' + to; + + return (from + ' ' + to).trim(); +} + + +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function(version) { + if (!version) + return false; + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version)) + return true; + } + return false; +}; + +function testSet(set, version) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) + return false; + } + return true; +} + +exports.satisfies = satisfies; +function satisfies(version, range, loose) { + try { + range = new Range(range, loose); + } catch (er) { + return false; + } + return range.test(version); +} + +exports.maxSatisfying = maxSatisfying; +function maxSatisfying(versions, range, loose) { + return versions.filter(function(version) { + return satisfies(version, range, loose); + }).sort(function(a, b) { + return rcompare(a, b, loose); + })[0] || null; +} + +exports.validRange = validRange; +function validRange(range, loose) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, loose).range || '*'; + } catch (er) { + return null; + } +} + +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr; +function ltr(version, range, loose) { + return outside(version, range, '<', loose); +} + +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr; +function gtr(version, range, loose) { + return outside(version, range, '>', loose); +} + +exports.outside = outside; +function outside(version, range, hilo, loose) { + version = new SemVer(version, loose); + range = new Range(range, loose); + + var gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case '>': + gtfn = gt; + ltefn = lte; + ltfn = lt; + comp = '>'; + ecomp = '>='; + break; + case '<': + gtfn = lt; + ltefn = gte; + ltfn = gt; + comp = '<'; + ecomp = '<='; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, loose)) { + return false; + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i]; + + var high = null; + var low = null; + + comparators.forEach(function(comparator) { + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, loose)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, loose)) { + low = comparator; + } + }); + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false; + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; +} + +// Use the define() function if we're in AMD land +if (typeof define === 'function' && define.amd) + define(exports); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/jquery.metadata.js b/ajax/libs/jquery.tablesorter/2.15.14/jquery.metadata.js new file mode 100644 index 000000000..07b10bae8 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/jquery.metadata.js @@ -0,0 +1,116 @@ +/* + * Metadata - jQuery plugin for parsing metadata from elements + * + * Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer, Paul McLanahan + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +/** + * Sets the type of metadata to use. Metadata is encoded in JSON, and each property + * in the JSON will become a property of the element itself. + * + * There are three supported types of metadata storage: + * + * attr: Inside an attribute. The name parameter indicates *which* attribute. + * + * class: Inside the class attribute, wrapped in curly braces: { } + * + * elem: Inside a child element (e.g. a script tag). The + * name parameter indicates *which* element. + * + * The metadata for an element is loaded the first time the element is accessed via jQuery. + * + * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements + * matched by expr, then redefine the metadata type and run another $(expr) for other elements. + * + * @name $.metadata.setType + * + * @example

This is a p

+ * @before $.metadata.setType("class") + * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" + * @desc Reads metadata from the class attribute + * + * @example

This is a p

+ * @before $.metadata.setType("attr", "data") + * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" + * @desc Reads metadata from a "data" attribute + * + * @example

This is a p

+ * @before $.metadata.setType("elem", "script") + * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" + * @desc Reads metadata from a nested script element + * + * @param String type The encoding type + * @param String name The name of the attribute to be used to get metadata (optional) + * @cat Plugins/Metadata + * @descr Sets the type of encoding to be used when loading metadata for the first time + * @type undefined + * @see metadata() + */ + +(function($) { + +$.extend({ + metadata : { + defaults : { + type: 'class', + name: 'metadata', + cre: /(\{.*\})/, + single: 'metadata' + }, + setType: function( type, name ){ + this.defaults.type = type; + this.defaults.name = name; + }, + get: function( elem, opts ){ + var data, m, e, attr, + settings = $.extend({},this.defaults,opts); + // check for empty string in single property + if ( !settings.single.length ) { settings.single = 'metadata'; } + + data = $.data(elem, settings.single); + // returned cached data if it already exists + if ( data ) { return data; } + + data = "{}"; + + if ( settings.type === "class" ) { + m = settings.cre.exec( elem.className ); + if ( m ) { data = m[1]; } + } else if ( settings.type === "elem" ) { + if( !elem.getElementsByTagName ) { return undefined; } + e = elem.getElementsByTagName(settings.name); + if ( e.length ) { data = $.trim(e[0].innerHTML); } + } else if ( elem.getAttribute !== undefined ) { + attr = elem.getAttribute( settings.name ); + if ( attr ) { data = attr; } + } + + if ( data.indexOf( '{' ) <0 ) { data = "{" + data + "}"; } + + data = eval("(" + data + ")"); + + $.data( elem, settings.single, data ); + return data; + } + } +}); + +/** + * Returns the metadata object for the first member of the jQuery object. + * + * @name metadata + * @descr Returns element's metadata object + * @param Object opts An object contianing settings to override the defaults + * @type jQuery + * @cat Plugins/Metadata + */ +$.fn.metadata = function( opts ){ + return $.metadata.get( this[0], opts ); +}; + +})(jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.js b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.js new file mode 100644 index 000000000..aa788ca35 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.js @@ -0,0 +1,1714 @@ +/**! +* TableSorter 2.15.14 - 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.15.14"; + + 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 + tabIndex : true, // add tabindex to header for keyboard accessibility + 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 + sortStable : false, // when sorting two rows with exactly the same content, the original sort order is maintained + + 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, // choose overall or specific column sorter function(a, b, direction, table, columnIndex) [alt: ts.sortText] + numberSorter : null, // choose overall numeric sorter function(a, b, direction, maxColumnValue) + + // *** 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){}, + + // *** extra css class names + tableClass : '', + cssAsc : '', + cssDesc : '', + cssNone : '', + cssHeader : '', + cssHeaderRow : '', + cssProcessing : '', // processing icon applied to header during sort/filter + + cssChildRow : 'tablesorter-childRow', // class name indiciating that a row is to be attached to the its parent + 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 (only one class name allowed here!) + + // *** 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"] } + + }; + + // internal css classes - these will ALWAYS be added to + // the table and MUST only contain one class name - fixes #381 + ts.css = { + table : 'tablesorter', + cssHasChild: 'tablesorter-hasChildRow', + childRow : 'tablesorter-childRow', + header : 'tablesorter-header', + headerRow : 'tablesorter-headerRow', + headerIn : 'tablesorter-header-inner', + icon : 'tablesorter-icon', + info : 'tablesorter-infoOnly', + processing : 'tablesorter-processing', + sortAsc : 'tablesorter-headerAsc', + sortDesc : 'tablesorter-headerDesc', + sortNone : 'tablesorter-headerUnSorted' + }; + + // labels applied to sortable headers for accessibility (aria) support + ts.language = { + sortAsc : 'Ascending sort applied, ', + sortDesc : 'Descending sort applied, ', + sortNone : 'No sort applied, ', + nextAsc : 'activate to apply an ascending sort', + nextDesc : 'activate to apply a descending sort', + nextNone : 'activate to remove the sort' + }; + + /* debuging utils */ + function log() { + var a = arguments[0], + s = arguments.length > 1 ? Array.prototype.slice.call(arguments) : a; + if (typeof console !== "undefined" && typeof console.log !== "undefined") { + console[ /error/i.test(a) ? 'error' : /warn/i.test(a) ? 'warn' : 'log' ](s); + } else { + alert(s); + } + } + + function benchmark(s, d) { + log(s + " (" + (new Date().getTime() - d.getTime()) + "ms)"); + } + + ts.log = log; + ts.benchmark = benchmark; + + // $.isEmptyObject from jQuery v1.4 + function isEmptyObject(obj) { + /*jshint forin: false */ + for (var name in obj) { + return false; + } + return true; + } + + 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 cur, + i = 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; + } + } + while (--i >= 0) { + cur = ts.parsers[i]; + // ignore the default text parser because it will always be true + if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, table, node)) { + return cur; + } + } + // nothing found, return the generic parser (text) + return ts.getParserById('text'); + } + + 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, time, parsersDebug = ""; + if ( tb.length === 0) { + return c.debug ? log('Warning: *Empty table!* Not building a parser cache') : ''; + } else if (c.debug) { + time = new Date(); + log('Detecting parsers for each column'); + } + 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); + benchmark("Completed detecting parsers", time); + } + c.parsers = 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('Warning: *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 c.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 + // ignore child row class, if it is the first row + if (c.hasClass(tc.cssChildRow) && i !== 0) { + tc.cache[k].row[tc.cache[k].row.length - 1] = tc.cache[k].row[tc.cache[k].row.length - 1].add(c); + // add "hasChild" class name to parent row + if (!c.prev().hasClass(tc.cssChildRow)) { + c.prev().addClass(ts.css.cssHasChild); + } + // go to the next for loop + continue; + } + tc.cache[k].row.push(c); + for (j = 0; j < totalCells; ++j) { + if (typeof parsers[j] === 'undefined') { + if (tc.debug) { + log('No parser found for cell:', c[0].cells[j], 'does it have a header?'); + } + continue; + } + 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) || 0, 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, + wo = c.widgetOptions, + b = table.tBodies, + rows = [], + c2 = c.cache, + r, n, totalRows, checkCell, $bk, $tb, + i, j, k, l, pos, appendTime; + // empty table - fixes #206/#346 + if (isEmptyObject(c2)) { + // run pager appender in case the table was just emptied + return c.appender ? c.appender(table, rows) : + table.isUpdating ? c.$table.trigger("updateComplete", table) : ''; // Fixes #532 + } + if (c.debug) { + appendTime = new Date(); + } + for (k = 0; k < b.length; k++) { + $bk = $(b[k]); + if ($bk.length && !$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; don't render if using ajax - fixes #411 + if (!c.appender || (c.pager && (!c.pager.removeRows || !wo.pager_removeRows) && !c.pager.ajax)) { + 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; but not before ajax completes + if (!init && !c.appender) { ts.applyWidget(table); } + if (table.isUpdating) { + c.$table.trigger("updateComplete", 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).children('thead, tfoot').children('tr'), // children tr in tfoot - see issue #196 & #547 + 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).index(); + 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"; + } + } + } + } + // may not be accurate if # header columns !== # tbody columns + t.config.columns = cols + 1; // add one because it's a zero-based index + } + + function formatSortingOrder(v) { + // look for "d" in "desc" order; return true + return (/^d/i.test(v) || v === 1); + } + + function buildHeaders(table) { + var ch, $t, + h, i, t, lock, time, + c = table.config; + c.headerList = []; + c.headerContent = []; + if (c.debug) { + time = new Date(); + } + computeThIndexes(table); + // add icon if cssIcon option exists + i = c.cssIcon ? '' : ''; + c.$headers = $(table).find(c.selectorHeaders).each(function(index) { + $t = $(this); + ch = c.headers[index]; + c.headerContent[index] = $(this).html(); // save original header content + // set up header template + t = c.headerTemplate.replace(/\{content\}/g, $(this).html()).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).html('
' + t + '
'); // faster than wrapInner + + if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index]); } + this.column = parseInt( $(this).attr('data-column'), 10); + 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 + 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(ts.css.header + ' ' + c.cssHeader); + // add cell to headerList + c.headerList[index] = this; + // add to parent in case there are multiple rows + $t.parent().addClass(ts.css.headerRow + ' ' + c.cssHeaderRow).attr('role', 'row'); + // allow keyboard cursor to focus on element + if (c.tabIndex) { $t.attr("tabindex", 0); } + }).attr({ + scope: 'col', + role : 'columnheader' + }); + // enable/disable sorting + updateHeader(table); + if (c.debug) { + benchmark("Built headers:", time); + log(c.$headers); + } + } + + function commonUpdate(table, resort, callback) { + var c = table.config; + // remove rows/elements before update + c.$table.find(c.selectorRemove).remove(); + // rebuild parsers + buildParserCache(table); + // rebuild the cache map + buildCache(table); + checkResort(c.$table, resort, callback); + } + + function updateHeader(table) { + var s, $th, c = table.config; + c.$headers.each(function(index, th){ + $th = $(th); + s = ts.getData( th, c.headers[index], 'sorter' ) === 'false'; + th.sortDisabled = s; + $th[ s ? 'addClass' : 'removeClass' ]('sorter-false').attr('aria-disabled', '' + s); + // aria-controls - requires table ID + if (table.id) { + if (s) { + $th.removeAttr('aria-controls'); + } else { + $th.attr('aria-controls', table.id); + } + } + }); + } + + function setHeadersCss(table) { + var f, i, j, l, + c = table.config, + list = c.sortList, + none = ts.css.sortNone + ' ' + c.cssNone, + css = [ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc], + aria = ['ascending', 'descending'], + // find the footer + $t = $(table).find('tfoot tr').children().removeClass(css.join(' ')); + // remove all header information + c.$headers + .removeClass(css.join(' ')) + .addClass(none).attr('aria-sort', 'none'); + 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).removeClass(none).addClass(css[list[i][1]]).attr('aria-sort', aria[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]]); + } + } + } + } + } + } + // add verbose aria labels + c.$headers.not('.sorter-false').each(function(){ + var $this = $(this), + nextSort = this.order[(this.count + 1) % (c.sortReset ? 3 : 2)], + txt = $this.text() + ': ' + + ts.language[ $this.hasClass(ts.css.sortAsc) ? 'sortAsc' : $this.hasClass(ts.css.sortDesc) ? 'sortDesc' : 'sortNone' ] + + ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ]; + $this.attr('aria-label', txt ); + }); + } + + // 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(); + // only add col for visible columns - fixes #371 + $(table.tBodies[0]).find("tr:first").children("td:visible").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.$headers[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 || '' : ''; + } + + function initSort(table, cell, event){ + var arry, indx, col, order, s, + c = table.config, + key = !event[c.sortMultiSortKey], + $table = c.$table; + // Only call sortStart if sorting is enabled + $table.trigger("sortStart", table); + // get current column sort order + cell.count = event[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2); + // reset all sorts on non-current column - issue #30 + if (c.sortRestart) { + indx = 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 !== indx && (key || !$(this).is('.' + ts.css.sortDesc + ',.' + ts.css.sortAsc))) { + this.count = -1; + } + }); + } + // get current column index + indx = cell.column; + // user only wants to sort on one column + if (key) { + // flush the sort list + c.sortList = []; + if (c.sortForce !== null) { + arry = c.sortForce; + for (col = 0; col < arry.length; col++) { + if (arry[col][0] !== indx) { + c.sortList.push(arry[col]); + } + } + } + // add column to sort list + order = cell.order[cell.count]; + if (order < 2) { + c.sortList.push([indx, order]); + // add other columns if header spans across multiple + if (cell.colSpan > 1) { + for (col = 1; col < cell.colSpan; col++) { + c.sortList.push([indx + col, order]); + } + } + } + // multi column sorting + } else { + // get rid of the sortAppend before adding more - fixes issue #115 & #523 + if (c.sortAppend && c.sortList.length > 1) { + for (col = 0; col < c.sortAppend.length; col++) { + s = ts.isValueInArray(c.sortAppend[col][0], c.sortList); + if (s >= 0) { + c.sortList.splice(s,1); + } + } + } + // the user has clicked on an already sorted column + if (ts.isValueInArray(indx, c.sortList) >= 0) { + // reverse the sorting direction + for (col = 0; col < c.sortList.length; col++) { + s = c.sortList[col]; + order = c.$headers[s[0]]; + if (s[0] === indx) { + // order.count seems to be incorrect when compared to cell.count + s[1] = order.order[cell.count]; + if (s[1] === 2) { + c.sortList.splice(col,1); + order.count = -1; + } + } + } + } else { + // add column to sort list array + order = cell.order[cell.count]; + if (order < 2) { + c.sortList.push([indx, order]); + // add other columns if header spans across multiple + if (cell.colSpan > 1) { + for (col = 1; col < cell.colSpan; col++) { + c.sortList.push([indx + col, order]); + } + } + } + } + } + if (c.sortAppend !== null) { + arry = c.sortAppend; + for (col = 0; col < arry.length; col++) { + if (arry[col][0] !== indx) { + c.sortList.push(arry[col]); + } + } + } + // sortBegin event triggered immediately before the sort + $table.trigger("sortBegin", table); + // setTimeout needed so the processing icon shows up + setTimeout(function(){ + // set css for headers + setHeadersCss(table); + multisort(table); + appendToTable(table); + $table.trigger("sortEnd", table); + }, 1); + } + + // sort multiple columns + function multisort(table) { /*jshint loopfunc:true */ + var i, k, num, col, colMax, cache, lc, + order, orgOrderCol, sortTime, sort, x, y, + dir = 0, + c = table.config, + cts = c.textSorter || '', + sortList = c.sortList, + l = sortList.length, + bl = table.tBodies.length; + if (c.serverSideSorting || isEmptyObject(c.cache)) { // empty table - fixes #206/#346 + return; + } + if (c.debug) { sortTime = new Date(); } + for (k = 0; k < bl; k++) { + colMax = c.cache[k].colMax; + cache = c.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++) { + col = sortList[i][0]; + order = sortList[i][1]; + // sort direction, true = asc, false = desc + dir = order === 0; + + if (c.sortStable && a[col] === b[col] && l === 1) { + return a[orgOrderCol] - b[orgOrderCol]; + } + + // fallback to natural sort since it is more robust + num = /n/i.test(getCachedSortType(c.parsers, col)); + if (num && c.strings[col]) { + // sort strings in numerical columns + if (typeof (c.string[c.strings[col]]) === 'boolean') { + num = (dir ? 1 : -1) * (c.string[c.strings[col]] ? -1 : 1); + } else { + num = (c.strings[col]) ? c.string[c.strings[col]] || 0 : 0; + } + // fall back to built-in numeric sort + // var sort = $.tablesorter["sort" + s](table, a[c], b[c], c, colMax[c], dir); + sort = c.numberSorter ? c.numberSorter(a[col], b[col], dir, colMax[col], table) : + ts[ 'sortNumeric' + (dir ? 'Asc' : 'Desc') ](a[col], b[col], num, colMax[col], col, table); + } else { + // set a & b depending on sort direction + x = dir ? a : b; + y = dir ? b : a; + // text sort function + if (typeof(cts) === 'function') { + // custom OVERALL text sorter + sort = cts(x[col], y[col], dir, col, table); + } else if (typeof(cts) === 'object' && cts.hasOwnProperty(col)) { + // custom text sorter for a SPECIFIC COLUMN + sort = cts[col](x[col], y[col], dir, col, table); + } else { + // fall back to natural sort + sort = ts[ 'sortNatural' + (dir ? 'Asc' : 'Desc') ](a[col], b[col], col, table, c); + } + } + if (sort) { return sort; } + } + return a[orgOrderCol] - b[orgOrderCol]; + }); + } + if (c.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time", sortTime); } + } + + function resortComplete($table, callback){ + var table = $table[0]; + if (table.isUpdating) { + $table.trigger('updateComplete'); + } + if (typeof callback === "function") { + callback($table[0]); + } + } + + function checkResort($table, flag, callback) { + var sl = $table[0].config.sortList; + // don't try to resort if the table is still processing + // this will catch spamming of the updateCell method + if (flag !== false && !$table[0].isProcessing && sl.length) { + $table.trigger("sorton", [sl, function(){ + resortComplete($table, callback); + }, true]); + } else { + $table.trigger('applyWidgets'); + resortComplete($table, callback); + } + } + + function bindMethods(table){ + var c = table.config, + $table = c.$table; + // apply easy methods that trigger bound events + $table + .unbind('sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join(c.namespace + ' ')) + .bind("sortReset" + c.namespace, function(e){ + e.stopPropagation(); + c.sortList = []; + setHeadersCss(table); + multisort(table); + appendToTable(table); + }) + .bind("updateAll" + c.namespace, function(e, resort, callback){ + e.stopPropagation(); + table.isUpdating = true; + ts.refreshWidgets(table, true, true); + ts.restoreHeaders(table); + buildHeaders(table); + ts.bindEvents(table, c.$headers); + bindMethods(table); + commonUpdate(table, resort, callback); + }) + .bind("update" + c.namespace + " updateRows" + c.namespace, function(e, resort, callback) { + e.stopPropagation(); + table.isUpdating = true; + // update sorting (if enabled/disabled) + updateHeader(table); + commonUpdate(table, resort, callback); + }) + .bind("updateCell" + c.namespace, function(e, cell, resort, callback) { + e.stopPropagation(); + table.isUpdating = true; + $table.find(c.selectorRemove).remove(); + // get position from the dom + var l, row, icell, + $tb = $table.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(':first') ), + $row = $(cell).parents('tr').filter(':first'); + 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).index(); + l = c.cache[tbdy].normalized[row].length - 1; + c.cache[tbdy].row[ c.cache[tbdy].normalized[row][l] ] = $row; + c.cache[tbdy].normalized[row][icell] = c.parsers[icell].format( getElementText(table, cell, icell), table, cell, icell ); + checkResort($table, resort, callback); + } + }) + .bind("addRows" + c.namespace, function(e, $row, resort, callback) { + e.stopPropagation(); + table.isUpdating = true; + if (isEmptyObject(c.cache)) { + // empty table, do an update instead - fixes #450 + updateHeader(table); + commonUpdate(table, resort, callback); + } else { + var i, j, + rows = $row.filter('tr').length, + dat = [], l = $row[0].cells.length, + tbdy = $table.find('tbody').index( $row.parents('tbody').filter(':first') ); + // fixes adding rows to an empty table - see issue #179 + if (!c.parsers) { + buildParserCache(table); + } + // 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(table, $row[i].cells[j], j), table, $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($table, resort, callback); + } + }) + .bind("updateComplete" + c.namespace, function(){ + table.isUpdating = false; + }) + .bind("sorton" + c.namespace, function(e, list, callback, init) { + var c = table.config; + e.stopPropagation(); + $table.trigger("sortStart", this); + // update header count index + updateHeaderSortCount(table, list); + // set css for headers + setHeadersCss(table); + // fixes #346 + if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); } + $table.trigger("sortBegin", this); + // sort the table and append it to the dom + multisort(table); + appendToTable(table, init); + $table + .trigger("sortEnd", this) + .trigger('applyWidgets'); + if (typeof callback === "function") { + callback(table); + } + }) + .bind("appendCache" + c.namespace, function(e, callback, init) { + e.stopPropagation(); + appendToTable(table, init); + if (typeof callback === "function") { + callback(table); + } + }) + .bind("updateCache" + c.namespace, function(e, callback){ + // rebuild parsers + if (!c.parsers) { + buildParserCache(table); + } + // rebuild the cache map + buildCache(table); + if (typeof callback === "function") { + callback(table); + } + }) + .bind("applyWidgetId" + c.namespace, function(e, id) { + e.stopPropagation(); + ts.getWidgetById(id).format(table, c, c.widgetOptions); + }) + .bind("applyWidgets" + c.namespace, function(e, init) { + e.stopPropagation(); + // apply widgets + ts.applyWidget(table, init); + }) + .bind("refreshWidgets" + c.namespace, function(e, all, dontapply){ + e.stopPropagation(); + ts.refreshWidgets(table, all, dontapply); + }) + .bind("destroy" + c.namespace, function(e, c, cb){ + e.stopPropagation(); + ts.destroy(table, c, cb); + }); + } + + /* public methods */ + ts.construct = function(settings) { + return this.each(function() { + var table = this, + // merge & extend config options + c = $.extend(true, {}, ts.defaults, settings); + // create a table from data (build table widget) + if (!table.hasInitialized && ts.buildTable && this.tagName !== 'TABLE') { + // return the table (in case the original target is the table's container) + ts.buildTable(table, c); + } else { + ts.setup(table, c); + } + }); + }; + + ts.setup = function(table, c) { + // if no thead or tbody, or tablesorter is already present, quit + if (!table || !table.tHead || table.tBodies.length === 0 || table.hasInitialized === true) { + return c.debug ? log('ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized') : ''; + } + + var k = '', + $table = $(table), + m = $.metadata; + // initialization flag + table.hasInitialized = false; + // table is being processed flag + table.isProcessing = true; + // make sure to store the config object + table.config = c; + // save the settings where they read + $.data(table, "tablesorter", c); + if (c.debug) { $.data( table, 'startoveralltimer', new Date()); } + + // constants + c.supportsTextContent = $('x')[0].textContent === 'x'; + // removing this in version 3 (only supports jQuery 1.7+) + c.supportsDataObject = (function(version) { + version[0] = parseInt(version[0], 10); + return (version[0] > 1) || (version[0] === 1 && parseInt(version[1], 10) >= 4); + })($.fn.jquery.split(".")); + // 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($table.attr('class'))) { + k = (c.theme !== '' ? ' tablesorter-' + c.theme : ''); + } + c.$table = $table + .addClass(ts.css.table + ' ' + c.tableClass + k) + .attr({ role : 'grid'}); + + // give the table a unique id, which will be used in namespace binding + if (!c.namespace) { + c.namespace = '.tablesorter' + Math.random().toString(16).slice(2); + } else { + // make sure namespace starts with a period & doesn't have weird characters + c.namespace = '.' + c.namespace.replace(/\W/g,''); + } + + c.$tbodies = $table.children('tbody:not(.' + c.cssInfoBlock + ')').attr({ + 'aria-live' : 'polite', + 'aria-relevant' : 'all' + }); + if (c.$table.find('caption').length) { + c.$table.attr('aria-labelledby', 'theCaption'); + } + c.widgetInit = {}; // keep a list of initialized widgets + // build headers + buildHeaders(table); + // fixate columns if the users supplies the fixedWidth option + // do this after theme has been applied + fixColumnWidth(table); + // try to auto detect column type, and store in tables config + buildParserCache(table); + // build the cache for the tbody cells + // delayInit will delay building the cache until the user starts a sort + if (!c.delayInit) { buildCache(table); } + // bind all header events and methods + ts.bindEvents(table, c.$headers); + bindMethods(table); + // get sort list from jQuery data or metadata + // in jQuery < 1.4, an error occurs when calling $table.data() + if (c.supportsDataObject && typeof $table.data().sortlist !== 'undefined') { + c.sortList = $table.data().sortlist; + } else if (m && ($table.metadata() && $table.metadata().sortlist)) { + c.sortList = $table.metadata().sortlist; + } + // apply widget init code + ts.applyWidget(table, true); + // if user has supplied a sort list to constructor + if (c.sortList.length > 0) { + $table.trigger("sorton", [c.sortList, {}, !c.initWidgets, true]); + } else { + setHeadersCss(table); + if (c.initWidgets) { + // apply widget format + ts.applyWidget(table); + } + } + + // show processesing icon + if (c.showProcessing) { + $table + .unbind('sortBegin' + c.namespace + ' sortEnd' + c.namespace) + .bind('sortBegin' + c.namespace + ' sortEnd' + c.namespace, function(e) { + ts.isProcessing(table, e.type === 'sortBegin'); + }); + } + + // initialized + table.hasInitialized = true; + table.isProcessing = false; + if (c.debug) { + ts.benchmark("Overall initialization time", $.data( table, 'startoveralltimer')); + } + $table.trigger('tablesorter-initialized', table); + if (typeof c.initialized === 'function') { c.initialized(table); } + }; + + // *** Process table *** + // add processing indicator + ts.isProcessing = function(table, toggle, $ths) { + table = $(table); + var c = table[0].config, + // default to all headers + $h = $ths || table.find('.' + ts.css.header); + if (toggle) { + // don't use sortList if custom $ths used + if (typeof $ths !== 'undefined' && 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) >= 0; + }); + } + $h.addClass(ts.css.processing + ' ' + c.cssProcessing); + } else { + $h.removeClass(ts.css.processing + ' ' + 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){ + table = $(table)[0]; + var holdr; + if (getIt) { + table.isProcessing = true; + $tb.before(''); + holdr = ($.fn.detach) ? $tb.detach() : $tb.remove(); + return holdr; + } + holdr = $(table).find('span.tablesorter-savemyplace'); + $tb.insertAfter( holdr ); + holdr.remove(); + table.isProcessing = false; + }; + + ts.clearTableBody = function(table) { + $(table)[0].config.$tbodies.empty(); + }; + + ts.bindEvents = function(table, $headers){ + table = $(table)[0]; + var downTime, + c = table.config; + // apply event handling to headers and/or additional headers (stickyheaders, scroller, etc) + $headers + // http://stackoverflow.com/questions/5312849/jquery-find-self; + .find(c.selectorSort).add( $headers.filter(c.selectorSort) ) + .unbind('mousedown mouseup sort keyup '.split(' ').join(c.namespace + ' ')) + .bind('mousedown mouseup sort keyup '.split(' ').join(c.namespace + ' '), function(e, external) { + var cell, type = e.type; + // only recognize left clicks or enter + if ( ((e.which || e.button) !== 1 && !/sort|keyup/.test(type)) || (type === 'keyup' && e.which !== 13) ) { + return; + } + // ignore long clicks (prevents resizable widget from initializing a sort) + if (type === 'mouseup' && external !== true && (new Date().getTime() - downTime > 250)) { return; } + // set timer on mousedown + if (type === 'mousedown') { + downTime = new Date().getTime(); + return e.target.tagName === "INPUT" ? '' : !c.cancelSelection; + } + if (c.delayInit && isEmptyObject(c.cache)) { buildCache(table); } + // jQuery v1.2.6 doesn't have closest() + cell = /TH|TD/.test(this.tagName) ? this : $(this).parents('th, td')[0]; + // reference original table headers and find the same cell + cell = c.$headers[ $headers.index( cell ) ]; + if (!cell.sortDisabled) { + initSort(table, cell, e); + } + }); + if (c.cancelSelection) { + // cancel selection + $headers + .attr('unselectable', 'on') + .bind('selectstart', false) + .css({ + 'user-select': 'none', + 'MozUserSelect': 'none' // not needed for jQuery 1.8+ + }); + } + }; + + // restore headers + ts.restoreHeaders = function(table){ + var c = $(table)[0].config; + // don't use c.$headers here in case header cells were swapped + c.$table.find(c.selectorHeaders).each(function(i){ + // only restore header cells if it is wrapped + // because this is also used by the updateAll method + if ($(this).find('.' + ts.css.headerIn).length){ + $(this).html( c.headerContent[i] ); + } + }); + }; + + ts.destroy = function(table, removeClasses, callback){ + table = $(table)[0]; + 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.' + ts.css.headerRow).removeClass(ts.css.headerRow + ' ' + c.cssHeaderRow), + $f = $t.find('tfoot:first > tr').children('th, td'); + if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) { + // reapply uitheme classes, in case we want to maintain appearance + $t.trigger('applyWidgetId', ['uitheme']); + $t.trigger('applyWidgetId', ['zebra']); + } + // remove widget added rows, just in case + $h.find('tr').not($r).remove(); + // disable tablesorter + $t + .removeData('tablesorter') + .unbind('sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd '.split(' ').join(c.namespace + ' ')); + c.$headers.add($f) + .removeClass( [ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone].join(' ') ) + .removeAttr('data-column') + .removeAttr('aria-label') + .attr('aria-disabled', 'true'); + $r.find(c.selectorSort).unbind('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')); + ts.restoreHeaders(table); + $t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false); + // 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 = { + chunk : /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters + chunks: /(^\\0|\\0$)/, // replace chunks @ ends + hex: /^0x[0-9a-f]+$/i // hex + }; + + // Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed) + ts.sortNatural = function(a, b) { + if (a === b) { return 0; } + var xN, xD, yN, yD, xF, yF, i, mx, + r = ts.regex; + // first try and sort Hex codes + if (r.hex.test(b)) { + xD = parseInt(a.match(r.hex), 16); + yD = parseInt(b.match(r.hex), 16); + if ( xD < yD ) { return -1; } + if ( xD > yD ) { return 1; } + } + // chunk/tokenize + xN = a.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0'); + yN = b.replace(r.chunk, '\\0$1\\0').replace(r.chunks, '').split('\\0'); + 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.sortNaturalAsc = function(a, b, col, table, c) { + if (a === b) { return 0; } + var 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; } + return ts.sortNatural(a, b); + }; + + ts.sortNaturalDesc = function(a, b, col, table, c) { + if (a === b) { return 0; } + var 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; } + return ts.sortNatural(b, a); + }; + + // basic alphabetical sort + ts.sortText = function(a, b) { + return a > b ? 1 : (a < b ? -1 : 0); + }; + + // 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, num, mx) { + if (mx) { + // make sure the text value is greater than the max numerical value (mx) + var i, l = a ? a.length : 0, n = mx + num; + for (i = 0; i < l; i++) { + n += a.charCodeAt(i); + } + return num * n; + } + return 0; + }; + + ts.sortNumericAsc = function(a, b, num, mx, col, table) { + 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, num, mx); } + if (isNaN(b)) { b = ts.getTextValue(b, num, mx); } + return a - b; + }; + + ts.sortNumericDesc = function(a, b, num, mx, col, table) { + 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, num, mx); } + if (isNaN(b)) { b = ts.getTextValue(b, num, mx); } + return b - a; + }; + + ts.sortNumeric = function(a, b) { + return a - b; + }; + + // 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(column, arry) { + var indx, len = arry.length; + for (indx = 0; indx < len; indx++) { + if (arry[indx][0] === column) { + return indx; + } + } + return -1; + }; + + 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) { + table = $(table)[0]; // in case this is called externally + var c = table.config, + wo = c.widgetOptions, + widgets = [], + time, w, wd; + if (c.debug) { time = new Date(); } + if (c.widgets.length) { + // ensure unique widget ids + c.widgets = $.grep(c.widgets, function(v, k){ + return $.inArray(v, c.widgets) === k; + }); + // build widget array & add priority as needed + $.each(c.widgets || [], function(i,n){ + wd = ts.getWidgetById(n); + if (wd && wd.id) { + // set priority to 10 if not defined + if (!wd.priority) { wd.priority = 10; } + widgets[i] = wd; + } + }); + // sort widgets by priority + widgets.sort(function(a, b){ + return a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1; + }); + // add/update selected widgets + $.each(widgets, function(i,w){ + if (w) { + if (init || !(c.widgetInit[w.id])) { + if (w.hasOwnProperty('options')) { + wo = table.config.widgetOptions = $.extend( true, {}, w.options, wo ); + } + if (w.hasOwnProperty('init')) { + w.init(table, w, c, wo); + } + c.widgetInit[w.id] = true; + } + if (!init && w.hasOwnProperty('format')) { + w.format(table, c, wo, false); + } + } + }); + } + if (c.debug) { + w = c.widgets.length; + benchmark("Completed " + (init === true ? "initializing " : "applying ") + w + " widget" + (w !== 1 ? "s" : ""), time); + } + }; + + ts.refreshWidgets = function(table, doAll, dontapply) { + table = $(table)[0]; // see issue #243 + 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 + '"' ); } + // only remove widgets that have been initialized - fixes #442 + if (w[i].hasOwnProperty('remove') && c.widgetInit[w[i].id]) { + w[i].remove(table, c, c.widgetOptions); + c.widgetInit[w[i].id] = false; + } + } + } + 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; now works with "sorter-my-custom-parser" + val = cl.match( new RegExp('\\s' + 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*\(([.\d]+)\)/, '-$1'); + } + 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() { + return true; + }, + format: function(s, table) { + var c = table.config; + if (s) { + s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s ); + s = c.sortLocaleCompare ? ts.replaceAccents(s) : s; + } + return s; + }, + type: "text" + }); + + ts.addParser({ + id: "digit", + is: function(s) { + return ts.isDigit(s); + }, + format: function(s, table) { + var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ""), table); + return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s; + }, + type: "numeric" + }); + + 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) { + var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ""), table); + return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s; + }, + 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 ? s.split(".") : '', + r = "", + l = a.length; + for (i = 0; i < l; i++) { + r += ("00" + a[i]).slice(-3); + } + return s ? ts.formatFloat(r, table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "url", + is: function(s) { + return (/^(https?|ftp|file):\/\//).test(s); + }, + format: function(s) { + return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s; + }, + 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 s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || s) : "", table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "percent", + is: function(s) { + return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15; + }, + format: function(s, table) { + return s ? ts.formatFloat(s.replace(/%/g, ""), table) : s; + }, + 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 s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "shortDate", // "mmddyyyy", "ddmmyyyy" or "yyyymmdd" + is: function(s) { + // testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included + return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test((s || '').replace(/\s+/g," ").replace(/[\-.,]/g, "/")); + }, + format: function(s, table, cell, cellIndex) { + if (s) { + var c = table.config, + ci = c.$headers.filter('[data-column=' + cellIndex + ']:last'), + format = ci.length && ci[0].dateFormat || ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat; + s = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error + 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 s ? ts.formatFloat( (new Date(s).getTime() || s), table) : s; + }, + 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 s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s; + }, + type: "numeric" + }); + + ts.addParser({ + id: "metadata", + is: function() { + 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", + priority: 90, + 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').not(c.selectorRemove); + // 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 = (wo.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); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.min.js b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.min.js new file mode 100644 index 000000000..2a55180c5 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.min.js @@ -0,0 +1,5 @@ +/*! +* TableSorter 2.15.14 min - Client-side table sorting with ease! +* Copyright (c) 2007 Christian Bach +*/ +!function(g){g.extend({tablesorter:new function(){function d(){var a=arguments[0],b=1
':"";l.$headers=g(a).find(l.selectorHeaders).each(function(a){c=g(this);b=l.headers[a];l.headerContent[a]=g(this).html();u=l.headerTemplate.replace(/\{content\}/g,g(this).html()).replace(/\{icon\}/g,e);l.onRenderTemplate&&(k= l.onRenderTemplate.apply(c,[a,u]))&&"string"===typeof k&&(u=k);g(this).html('
'+u+"
");l.onRenderHeader&&l.onRenderHeader.apply(c,[a]);this.column=parseInt(g(this).attr("data-column"),10);this.order=C(f.getData(c,b,"sortInitialOrder")||l.sortInitialOrder)?[1,0,2]:[0,1,2];this.count=-1;this.lockedOrder=!1;h=f.getData(c,b,"lockedOrder")||!1;"undefined"!==typeof h&&!1!==h&&(this.order=this.lockedOrder=C(h)?[1,1,1]:[0,0,0]);c.addClass(f.css.header+" "+l.cssHeader); l.headerList[a]=this;c.parent().addClass(f.css.headerRow+" "+l.cssHeaderRow).attr("role","row");l.tabIndex&&c.attr("tabindex",0)}).attr({scope:"col",role:"columnheader"});G(a);l.debug&&(v("Built headers:",p),d(l.$headers))}function B(a,b,c){var k=a.config;k.$table.find(k.selectorRemove).remove();r(a);w(a);H(k.$table,b,c)}function G(a){var b,c,k=a.config;k.$headers.each(function(e,d){c=g(d);b="false"===f.getData(d,k.headers[e],"sorter");d.sortDisabled=b;c[b?"addClass":"removeClass"]("sorter-false").attr("aria-disabled", ""+b);a.id&&(b?c.removeAttr("aria-controls"):c.attr("aria-controls",a.id))})}function F(a){var b,c,k,e=a.config,d=e.sortList,h=f.css.sortNone+" "+e.cssNone,p=[f.css.sortAsc+" "+e.cssAsc,f.css.sortDesc+" "+e.cssDesc],l=["ascending","descending"],q=g(a).find("tfoot tr").children().removeClass(p.join(" "));e.$headers.removeClass(p.join(" ")).addClass(h).attr("aria-sort","none");k=d.length;for(b=0;b"),c=g(a).width();g(a.tBodies[0]).find("tr:first").children("td:visible").each(function(){b.append(g("").css("width",parseInt(g(this).width()/c*1E3,10)/10+"%"))});g(a).prepend(b)}}function M(a,b){var c,k,e,d=a.config,f=b||d.sortList;d.sortList=[];g.each(f,function(a,b){c=[parseInt(b[0],10),parseInt(b[1],10)];if(e=d.$headers[c[0]])d.sortList.push(c),k=g.inArray(c[1],e.order),e.count=0<=k?k:c[1]%(d.sortReset? 3:2)})}function N(a,b){return a&&a[b]?a[b].type||"":""}function O(a,b,c){var k,e,d,h=a.config,p=!c[h.sortMultiSortKey],l=h.$table;l.trigger("sortStart",a);b.count=c[h.sortResetKey]?2:(b.count+1)%(h.sortReset?3:2);h.sortRestart&&(e=b,h.$headers.each(function(){this===e||!p&&g(this).is("."+f.css.sortDesc+",."+f.css.sortAsc)||(this.count=-1)}));e=b.column;if(p){h.sortList=[];if(null!==h.sortForce)for(k=h.sortForce,c=0;ck&&(h.sortList.push([e, k]),1k&&(h.sortList.push([e,k]),1 thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]};f.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",info:"tablesorter-infoOnly",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc", sortNone:"tablesorter-headerUnSorted"};f.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"};f.log=d;f.benchmark=v;f.construct=function(a){return this.each(function(){var b=g.extend(!0,{},f.defaults,a);!this.hasInitialized&&f.buildTable&&"TABLE"!==this.tagName?f.buildTable(this,b):f.setup(this,b)})};f.setup= function(a,b){if(!a||!a.tHead||0===a.tBodies.length||!0===a.hasInitialized)return b.debug?d("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"):"";var c="",k=g(a),e=g.metadata;a.hasInitialized=!1;a.isProcessing=!0;a.config=b;g.data(a,"tablesorter",b);b.debug&&g.data(a,"startoveralltimer",new Date);b.supportsTextContent="x"===g("x")[0].textContent;b.supportsDataObject=function(a){a[0]=parseInt(a[0],10);return 1'),c=g.fn.detach?b.detach():b.remove();c=g(a).find("span.tablesorter-savemyplace");b.insertAfter(c);c.remove();a.isProcessing=!1};f.clearTableBody=function(a){g(a)[0].config.$tbodies.empty()};f.bindEvents=function(a,b){a=g(a)[0];var c,d=a.config;b.find(d.selectorSort).add(b.filter(d.selectorSort)).unbind(["mousedown", "mouseup","sort","keyup",""].join(d.namespace+" ")).bind(["mousedown","mouseup","sort","keyup",""].join(d.namespace+" "),function(e,f){var h;h=e.type;if(!(1!==(e.which||e.button)&&!/sort|keyup/.test(h)||"keyup"===h&&13!==e.which||"mouseup"===h&&!0!==f&&250<(new Date).getTime()-c)){if("mousedown"===h)return c=(new Date).getTime(),"INPUT"===e.target.tagName?"":!d.cancelSelection;d.delayInit&&m(d.cache)&&w(a);h=/TH|TD/.test(this.tagName)?this:g(this).parents("th, td")[0];h=d.$headers[b.index(h)];h.sortDisabled|| O(a,h,e)}});d.cancelSelection&&b.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})};f.restoreHeaders=function(a){var b=g(a)[0].config;b.$table.find(b.selectorHeaders).each(function(a){g(this).find("."+f.css.headerIn).length&&g(this).html(b.headerContent[a])})};f.destroy=function(a,b,c){a=g(a)[0];if(a.hasInitialized){f.refreshWidgets(a,!0,!0);var d=g(a),e=a.config,u=d.find("thead:first"),h=u.find("tr."+f.css.headerRow).removeClass(f.css.headerRow+" "+ e.cssHeaderRow),m=d.find("tfoot:first > tr").children("th, td");!1===b&&0<=g.inArray("uitheme",e.widgets)&&(d.trigger("applyWidgetId",["uitheme"]),d.trigger("applyWidgetId",["zebra"]));u.find("tr").not(h).remove();d.removeData("tablesorter").unbind("sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd ".split(" ").join(e.namespace+" "));e.$headers.add(m).removeClass([f.css.header, e.cssHeader,e.cssAsc,e.cssDesc,f.css.sortAsc,f.css.sortDesc,f.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true");h.find(e.selectorSort).unbind(["mousedown","mouseup","keypress",""].join(e.namespace+" "));f.restoreHeaders(a);d.toggleClass(f.css.table+" "+e.tableClass+" tablesorter-"+e.theme,!1===b);a.hasInitialized=!1;"function"===typeof c&&c(a)}};f.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,chunks:/(^\\0|\\0$)/, hex:/^0x[0-9a-f]+$/i};f.sortNatural=function(a,b){if(a===b)return 0;var c,d,e,g,h,m;d=f.regex;if(d.hex.test(b)){c=parseInt(a.match(d.hex),16);e=parseInt(b.match(d.hex),16);if(ce)return 1}c=a.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0");d=b.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0");m=Math.max(c.length,d.length);for(h=0;hg)return 1}return 0};f.sortNaturalAsc=function(a,b,c,d,e){if(a===b)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===a&&0!==c?"boolean"===typeof c?c?-1:1:-c||-1:""===b&&0!==c?"boolean"===typeof c?c?1:-1:c||1:f.sortNatural(a,b)};f.sortNaturalDesc=function(a,b,c,d,e){if(a===b)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===a&&0!==c?"boolean"===typeof c?c?-1:1:c||1:""===b&&0!==c?"boolean"===typeof c?c?1:-1:-c||-1:f.sortNatural(b, a)};f.sortText=function(a,b){return a>b?1:ag.inArray(h[k].id,m))&&(e.debug&&d('Refeshing widgets: Removing "'+h[k].id+'"'),h[k].hasOwnProperty("remove")&&e.widgetInit[h[k].id]&&(h[k].remove(a,e,e.widgetOptions),e.widgetInit[h[k].id]=!1));!0!==c&&f.applyWidget(a,b)};f.getData=function(a,b,c){var d="";a=g(a);var e,f;if(!a.length)return"";e=g.metadata?a.metadata():!1;f=" "+(a.attr("class")||"");"undefined"!==typeof a.data(c)||"undefined"!==typeof a.data(c.toLowerCase())? d+=a.data(c)||a.data(c.toLowerCase()):e&&"undefined"!==typeof e[c]?d+=e[c]:b&&"undefined"!==typeof b[c]?d+=b[c]:" "!==f&&f.match(" "+c+"-")&&(d=f.match(RegExp("\\s"+c+"-([\\w-]+)"))[1]||"");return g.trim(d)};f.formatFloat=function(a,b){if("string"!==typeof a||""===a)return a;var c;a=(b&&b.config?!1!==b.config.usNumberFormat:"undefined"!==typeof b?b:1)?a.replace(/,/g,""):a.replace(/[\s|\.]/g,"").replace(/,/g,".");/^\s*\([.\d]+\)/.test(a)&&(a=a.replace(/^\s*\(([.\d]+)\)/,"-$1"));c=parseFloat(a);return isNaN(c)? g.trim(a):c};f.isDigit=function(a){return isNaN(a)?/^[\-+(]?\d+[)]?$/.test(a.toString().replace(/[,.'"\s]/g,"")):!0}}});var n=g.tablesorter;g.fn.extend({tablesorter:n.construct});n.addParser({id:"text",is:function(){return!0},format:function(d,v){var m=v.config;d&&(d=g.trim(m.ignoreCase?d.toLocaleLowerCase():d),d=m.sortLocaleCompare?n.replaceAccents(d):d);return d},type:"text"});n.addParser({id:"digit",is:function(d){return n.isDigit(d)},format:function(d,v){var m=n.formatFloat((d||"").replace(/[^\w,. \-()]/g, ""),v);return d&&"number"===typeof m?m:d?g.trim(d&&v.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});n.addParser({id:"currency",is:function(d){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((d||"").replace(/[+\-,. ]/g,""))},format:function(d,v){var m=n.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),v);return d&&"number"===typeof m?m:d?g.trim(d&&v.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});n.addParser({id:"ipAddress", is:function(d){return/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/.test(d)},format:function(d,g){var m,t=d?d.split("."):"",r="",w=t.length;for(m=0;md.length},format:function(d,g){return d?n.formatFloat(d.replace(/%/g,""),g):d},type:"numeric"});n.addParser({id:"usLongDate",is:function(d){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(d)||/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i.test(d)},format:function(d,g){return d?n.formatFloat((new Date(d.replace(/(\S)([AP]M)$/i, "$1 $2"))).getTime()||d,g):d},type:"numeric"});n.addParser({id:"shortDate",is:function(d){return/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/.test((d||"").replace(/\s+/g," ").replace(/[\-.,]/g,"/"))},format:function(d,g,m,t){if(d){m=g.config;var r=m.$headers.filter("[data-column="+t+"]:last");t=r.length&&r[0].dateFormat||n.getData(r,m.headers[t],"dateFormat")||m.dateFormat;d=d.replace(/\s+/g," ").replace(/[\-.,]/g,"/");"mmddyyyy"===t?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2"):"ddmmyyyy"===t?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$2/$1"):"yyyymmdd"===t&&(d=d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,"$1/$2/$3"))}return d?n.formatFloat((new Date(d)).getTime()||d,g):d},type:"numeric"});n.addParser({id:"time",is:function(d){return/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i.test(d)},format:function(d,g){return d?n.formatFloat((new Date("2000/01/01 "+d.replace(/(\S)([AP]M)$/i,"$1 $2"))).getTime()||d,g):d},type:"numeric"});n.addParser({id:"metadata", is:function(){return!1},format:function(d,n,m){d=n.config;d=d.parserMetadataName?d.parserMetadataName:"sortValue";return g(m).metadata()[d]},type:"numeric"});n.addWidget({id:"zebra",priority:90,format:function(d,v,m){var t,r,w,z,D,C,E=RegExp(v.cssChildRow,"i"),B=v.$tbodies;v.debug&&(D=new Date);for(d=0;d 1) { + var opt = '', + compareSelectClass = [ compareSelect.slice(1), ' ' + compareSelect.slice(1), '' ], + txt = options.cellText ? '' : ''; + $.each(options.compare, function(i, c){ + opt += ''; + }); + $cell + .wrapInner('
') + .prepend( txt + '') + .appendTo($cell) + // hidden filter update namespace trigger by filter widget + .bind('change' + c.namespace + 'filter', function(){ + updateSpinner({ value: this.value, delayed: false }); + }), + $shcell = [], + + // this function updates the hidden input and adds the current values to the header cell text + updateSpinner = function(ui, notrigger) { + var chkd = true, state, + // ui is not undefined on create + v = ui && ui.value && ts.formatFloat((ui.value + '').replace(/[><=]/g,'')) || + $cell.find('.spinner').val() || o.value, + compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '', + searchType = ui && typeof ui.delayed === 'boolean' ? ui.delayed : c.$table[0].hasInitialized ? o.delayed : true; + if (o.addToggle) { + chkd = $cell.find('.toggle').is(':checked'); + } + state = o.disabled || !chkd ? 'disable' : 'enable'; + $cell.find('.filter') + // add equal to the beginning, so we filter exact numbers + .val( chkd ? (compare ? compare : o.exactMatch ? '=' : '') + v : '' ) + .trigger( notrigger ? '' : 'search', searchType ).end() + .find('.spinner').spinner(state).val(v); + // update sticky header cell + if ($shcell.length) { + $shcell + .find('.spinner').spinner(state).val(v).end() + .find(compareSelect).val( compare ); + if (o.addToggle) { + $shcell.find('.toggle')[0].checked = chkd; + } + } + }; + + // add callbacks; preserve added callbacks + o.oldcreate = o.create; + o.oldspin = o.spin; + o.create = function(event, ui) { + updateSpinner(); // ui is an empty object on create + if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); } + }; + o.spin = function(event, ui) { + updateSpinner(ui); + if (typeof o.oldspin === 'function') { o.oldspin(event, ui); } + }; + if (o.addToggle) { + $('
' + + '
') + .appendTo($cell) + .find('.toggle') + .bind('change', function(){ + updateSpinner(); + }); + } + // make sure we use parsed data + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + // add a jQuery UI spinner! + $('') + .val(o.value) + .appendTo($cell) + .spinner(o) + .bind('change keyup', function(){ + updateSpinner(); + }); + + // update spinner from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + var val = tsff.updateCompare($cell, $input, o)[0]; + $cell.find('.spinner').val( val ); + updateSpinner({ value: val }, true); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($cell, indx, o); + $cell.find(compareSelect).bind('change', function(){ + updateSpinner(); + }); + } + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + if (o.addToggle) { + $('
' + + '
') + .appendTo($shcell) + .find('.toggle') + .bind('change', function(){ + $cell.find('.toggle')[0].checked = this.checked; + updateSpinner(); + }); + } + // add a jQuery UI spinner! + $('') + .val(o.value) + .appendTo($shcell) + .spinner(o) + .bind('change keyup', function(){ + $cell.find('.spinner').val( this.value ); + updateSpinner(); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($shcell, indx, o); + $shcell.find(compareSelect).bind('change', function(){ + $cell.find(compareSelect).val( $(this).val() ); + updateSpinner(); + }); + } + + }); + + // on reset + c.$table.bind('filterReset', function(){ + if ($.isArray(o.compare)) { + $cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); + } + // turn off the toggle checkbox + if (o.addToggle) { + $cell.find('.toggle')[0].checked = false; + } + $cell.find('.spinner').spinner('value', o.value); + setTimeout(function(){ + updateSpinner(); + }, 0); + }); + + updateSpinner(); + return $input; + }, + + /**********************\ + jQuery UI Slider + \**********************/ + uiSlider: function($cell, indx, sliderDef) { + var o = $.extend({ + // filter formatter options + delayed : true, + valueToHeader : false, + exactMatch : true, + cellText : '', + compare : '', + allText : 'all', + // include ANY jQuery UI spinner options below + // except values, since this is a non-range setup + value : 0, + min : 0, + max : 100, + step : 1, + range : "min" + }, sliderDef ), + c = $cell.closest('table')[0].config, + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update namespace trigger by filter widget + .bind('change' + c.namespace + 'filter', function(){ + updateSlider({ value: this.value }); + }), + $shcell = [], + + // this function updates the hidden input and adds the current values to the header cell text + updateSlider = function(ui, notrigger) { + // ui is not undefined on create + var v = typeof ui !== "undefined" ? ts.formatFloat((ui.value + '').replace(/[><=]/g,'')) || o.value : o.value, + val = o.compare ? v : v === o.min ? o.allText : v, + compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '', + result = compare + val, + searchType = ui && typeof ui.delayed === 'boolean' ? ui.delayed : c.$table[0].hasInitialized ? o.delayed : true; + if (o.valueToHeader) { + // add range indication to the header cell above! + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(' (' + result + ')'); + } else { + // add values to the handle data-value attribute so the css tooltip will work properly + $cell.find('.ui-slider-handle').addClass('value-popup').attr('data-value', result); + } + // update the hidden input; + // ****** ADD AN EQUAL SIGN TO THE BEGINNING! <- this makes the slide exactly match the number ****** + // when the value is at the minimum, clear the hidden input so all rows will be seen + + $cell.find('.filter') + .val( ( compare ? compare + v : v === o.min ? '' : (o.exactMatch ? '=' : '') + v ) ) + .trigger( notrigger ? '' : 'search', searchType ).end() + .find('.slider').slider('value', v); + + // update sticky header cell + if ($shcell.length) { + $shcell + .find(compareSelect).val( compare ).end() + .find('.slider').slider('value', v); + if (o.valueToHeader) { + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(' (' + result + ')'); + } else { + $shcell.find('.ui-slider-handle').addClass('value-popup').attr('data-value', result); + } + } + + }; + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + + // add span to header for value - only works if the line in the updateSlider() function is also un-commented out + if (o.valueToHeader) { + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append(''); + } + + // add callbacks; preserve added callbacks + o.oldcreate = o.create; + o.oldslide = o.slide; + o.create = function(event, ui) { + updateSlider(); // ui is an empty object on create + if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); } + }; + o.slide = function(event, ui) { + updateSlider(ui); + if (typeof o.oldslide === 'function') { o.oldslide(event, ui); } + }; + // add a jQuery UI slider! + $('
') + .appendTo($cell) + .slider(o); + + // update slider from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + var val = tsff.updateCompare($cell, $input, o)[0]; + $cell.find('.slider').slider('value', val ); + updateSlider({ value: val }, false); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($cell, indx, o); + $cell.find(compareSelect).bind('change', function(){ + updateSlider({ value: $cell.find('.slider').slider('value') }); + }); + } + + // on reset + c.$table.bind('filterReset', function(){ + if ($.isArray(o.compare)) { + $cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); + } + setTimeout(function(){ + updateSlider({ value: o.value }); + }, 0); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + + // add a jQuery UI slider! + $('
') + .val(o.value) + .appendTo($shcell) + .slider(o) + .bind('change keyup', function(){ + $cell.find('.slider').slider('value', this.value ); + updateSlider(); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($shcell, indx, o); + $shcell.find(compareSelect).bind('change', function(){ + $cell.find(compareSelect).val( $(this).val() ); + updateSlider(); + }); + } + + }); + + return $input; + }, + + /*************************\ + jQuery UI Range Slider (2 handles) + \*************************/ + uiRange: function($cell, indx, rangeDef) { + var o = $.extend({ + // filter formatter options + delayed : true, + valueToHeader : false, + // include ANY jQuery UI spinner options below + // except value, since this one is range specific) + values : [0, 100], + min : 0, + max : 100, + range : true + }, rangeDef ), + c = $cell.closest('table')[0].config, + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update namespace trigger by filter widget + .bind('change' + c.namespace + 'filter', function(){ + getRange(); + }), + $shcell = [], + + getRange = function(){ + var val = $input.val(), + v = val.split(' - '); + if (val === '') { v = [ o.min, o.max ]; } + if (v && v[1]) { + updateUiRange({ values: v, delay: false }, true); + } + }, + + // this function updates the hidden input and adds the current values to the header cell text + updateUiRange = function(ui, notrigger) { + // ui.values are undefined for some reason on create + var val = ui && ui.values || o.values, + result = val[0] + ' - ' + val[1], + // make range an empty string if entire range is covered so the filter row will hide (if set) + range = val[0] === o.min && val[1] === o.max ? '' : result, + searchType = ui && typeof ui.delayed === 'boolean' ? ui.delayed : c.$table[0].hasInitialized ? o.delayed : true; + if (o.valueToHeader) { + // add range indication to the header cell above (if not using the css method)! + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.currange').html(' (' + result + ')'); + } else { + // add values to the handle data-value attribute so the css tooltip will work properly + $cell.find('.ui-slider-handle') + .addClass('value-popup') + .eq(0).attr('data-value', val[0]).end() // adding value to data attribute + .eq(1).attr('data-value', val[1]); // value popup shown via css + } + // update the hidden input + $cell.find('.filter').val(range) + .trigger(notrigger ? '' : 'search', searchType).end() + .find('.range').slider('values', val); + // update sticky header cell + if ($shcell.length) { + $shcell.find('.range').slider('values', val); + if (o.valueToHeader) { + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.currange').html(' (' + result + ')'); + } else { + $shcell.find('.ui-slider-handle') + .addClass('value-popup') + .eq(0).attr('data-value', val[0]).end() // adding value to data attribute + .eq(1).attr('data-value', val[1]); // value popup shown via css + } + } + + }; + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + + // add span to header for value - only works if the line in the updateUiRange() function is also un-commented out + if (o.valueToHeader) { + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append(''); + } + + // add callbacks; preserve added callbacks + o.oldcreate = o.create; + o.oldslide = o.slide; + // add a jQuery UI range slider! + o.create = function(event, ui) { + updateUiRange(); // ui is an empty object on create + if (typeof o.oldcreate === 'function') { o.oldcreate(event, ui); } + }; + o.slide = function(event, ui) { + updateUiRange(ui); + if (typeof o.oldslide === 'function') { o.oldslide(event, ui); } + }; + $('
') + .appendTo($cell) + .slider(o); + + // update slider from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + getRange(); + }); + + // on reset + c.$table.bind('filterReset', function(){ + $cell.find('.range').slider('values', o.values); + setTimeout(function(){ + updateUiRange(); + }, 0); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + + // add a jQuery UI slider! + $('
') + .val(o.value) + .appendTo($shcell) + .slider(o) + .bind('change keyup', function(){ + $cell.find('.range').val( this.value ); + updateUiRange(); + }); + + }); + + // return the hidden input so the filter widget has a reference to it + return $input; + }, + + /*************************\ + jQuery UI Datepicker compare (1 input) + \*************************/ + uiDateCompare: function($cell, indx, defDate) { + var o = $.extend({ + // filter formatter options + cellText : '', + compare : '', + endOfDay : true, + // include ANY jQuery UI spinner options below + + defaultDate : '', + + changeMonth : true, + changeYear : true, + numberOfMonths : 1 + }, defDate), + + $date, + c = $cell.closest('table')[0].config, + // make sure we're using parsed dates in the search + $hdr = $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'), + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update namespace trigger by filter widget + .bind('change' + c.namespace + 'filter', function(){ + var v = this.value; + if (v) { + o.onClose(v); + } + }), + t, $shcell = [], + + // this function updates the hidden input + date1Compare = function(v, notrigger) { + var date, query, + getdate = v || $date.datepicker('getDate') || '', + compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '', + searchType = c.$table[0].hasInitialized ? o.delayed : true; + $date.datepicker('setDate', getdate === '' ? o.defaultDate || '' : getdate); + if (getdate === '') { notrigger = false; } + date = $date.datepicker('getDate'); + query = date ? ( o.endOfDay && /<=/.test(compare) ? date.setHours(23, 59, 59) : date.getTime() ) || '' : ''; + if (date && o.endOfDay && compare === '=') { + compare = ''; + query += ' - ' + date.setHours(23, 59, 59); + notrigger = false; + } + $cell.find('.dateCompare') + // add equal to the beginning, so we filter exact numbers + .val(compare + query) + .trigger( notrigger ? '' : 'search', searchType ).end(); + // update sticky header cell + if ($shcell.length) { + $shcell + .find('.dateCompare').val(compare + query).end() + .find(compareSelect).val(compare); + } + }; + + // Add date range picker + t = ''; + $date = $(t).appendTo($cell); + + // add callbacks; preserve added callbacks + o.oldonClose = o.onClose; + + o.onClose = function( selectedDate, ui ) { + date1Compare(); + if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); } + }; + $date.datepicker(o); + + // on reset + c.$table.bind('filterReset', function(){ + if ($.isArray(o.compare)) { + $cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); + } + $cell.add($shcell).find('.date').val(o.defaultDate).datepicker('setDate', ''); + setTimeout(function(){ + date1Compare(); + }, 0); + }); + + // update date compare from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + var num, v = $input.val(); + if (/\s+-\s+/.test(v)) { + // date range found; assume an exact match on one day + $cell.find(compareSelect).val('='); + num = new Date ( Number( v.split(/\s+-\s+/)[0] ) ); + $date.datepicker( 'setDate', num ); + } else { + num = (tsff.updateCompare($cell, $input, o)[1]).toString() || ''; + // differeniate 1388556000000 from 1/1/2014 using \d{5} regex + num = num !== '' ? new Date( /\d{5}/g.test(num) ? Number(num) : num ) || '' : ''; + } + $cell.add($shcell).find('.date').datepicker( 'setDate', num ); + date1Compare(num, true); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($cell, indx, o); + $cell.find(compareSelect).bind('change', function(){ + date1Compare(); + }); + } + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + + // add a jQuery datepicker! + $shcell + .append(t) + .find('.date') + .datepicker(o); + + if (o.compare) { + // add compare select + tsff.addCompare($shcell, indx, o); + $shcell.find(compareSelect).bind('change', function(){ + $cell.find(compareSelect).val( $(this).val() ); + date1Compare(); + }); + } + + }); + + // return the hidden input so the filter widget has a reference to it + return $input.val( o.defaultDate ? o.defaultDate : '' ); + }, + + /*************************\ + jQuery UI Datepicker (2 inputs) + \*************************/ + uiDatepicker: function($cell, indx, defDate) { + var o = $.extend({ + // filter formatter options + endOfDay : true, + textFrom : 'from', + textTo : 'to', + from : '', // defaultDate "from" input + to : '', // defaultDate "to" input + // include ANY jQuery UI spinner options below + changeMonth : true, + changeYear : true, + numberOfMonths : 1 + }, defDate), + t, closeTo, closeFrom, $shcell = [], + c = $cell.closest('table')[0].config, + // Add a hidden input to hold the range values + $input = $('') + .appendTo($cell) + // hidden filter update namespace trigger by filter widget + .bind('change' + c.namespace + 'filter', function(){ + var v = this.value; + if (v.match(' - ')) { + v = v.split(' - '); + $cell.find('.dateTo').val(v[1]); + closeFrom(v[0]); + } else if (v.match('>=')) { + closeFrom( v.replace('>=', '') ); + } else if (v.match('<=')) { + closeTo( v.replace('<=', '') ); + } + }); + + // make sure we're using parsed dates in the search + $cell.closest('thead').find('th[data-column=' + indx + ']').addClass('filter-parsed'); + // Add date range picker + t = ''; + $(t).appendTo($cell); + + // add callbacks; preserve added callbacks + o.oldonClose = o.onClose; + + var localfrom = o.defaultDate = o.from || o.defaultDate; + + closeFrom = o.onClose = function( selectedDate, ui ) { + var range, + from = new Date( $cell.find('.dateFrom').datepicker('getDate') ).getTime() || '', + to = $cell.find('.dateTo').datepicker('getDate') || ''; + to = to ? ( o.endOfDay ? to.setHours(23, 59, 59) : to.getTime() ) || '' : ''; + range = from ? ( to ? from + ' - ' + to : '>=' + from ) : (to ? '<=' + to : ''); + $cell + .find('.dateRange').val(range) + .trigger('search').end() + .find('.dateTo').datepicker('option', 'minDate', selectedDate ).end() + .find('.dateFrom').val(selectedDate); + + // update sticky header cell + if ($shcell.length) { + $shcell + .find('.dateTo').datepicker('option', 'minDate', selectedDate ).end() + .find('.dateFrom').val(selectedDate); + } + if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); } + }; + + $cell.find('.dateFrom').datepicker(o); + + o.defaultDate = o.to || '+7d'; // set to date +7 days from today (if not defined) + closeTo = o.onClose = function( selectedDate, ui ) { + var range, + from = new Date( $cell.find('.dateFrom').datepicker('getDate') ).getTime() || '', + to = $cell.find('.dateTo').datepicker('getDate') || ''; + to = to ? ( o.endOfDay ? to.setHours(23, 59, 59) : to.getTime() ) || '' : ''; + range = from ? ( to ? from + ' - ' + to : '>=' + from ) : (to ? '<=' + to : ''); + $cell + .find('.dateRange').val(range) + .trigger('search').end() + .find('.dateFrom').datepicker('option', 'maxDate', selectedDate ).end() + .find('.dateTo').val(selectedDate); + + // update sticky header cell + if ($shcell.length) { + $shcell + .find('.dateFrom').datepicker('option', 'maxDate', selectedDate ).end() + .find('.dateTo').val(selectedDate); + } + if (typeof o.oldonClose === 'function') { o.oldonClose(selectedDate, ui); } + }; + $cell.find('.dateTo').datepicker(o); + + // update date compare from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + var val = $input.val() || '', + from = '', + to = ''; + + // date range + if (/\s+-\s+/.test(val)){ + val = val.split(/\s+-\s+/) || []; + from = val[0] || ''; + to = val[1] || ''; + } else if (/>=/.test(val)) { + // greater than date (to date empty) + from = new Date(Number( val.replace(/>=/, '') )) || ''; + } else if (/<=/.test(val)) { + // less than date (from date empty) + to = new Date(Number( val.replace(/<=/, '') )) || ''; + } + $cell.add($shcell).find('.dateFrom').datepicker('setDate', from); + $cell.add($shcell).find('.dateTo').datepicker('setDate', to); + closeTo(to); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + $shcell.append(t); + + // add a jQuery datepicker! + o.onClose = closeTo; + $shcell.find('.dateTo').datepicker(o); + + o.defaultDate = localfrom; + o.onClose = closeFrom; + $shcell.find('.dateFrom').datepicker(o); + }); + + // on reset + $cell.closest('table').bind('filterReset', function(){ + $cell.add($shcell).find('.dateFrom').val('').datepicker('setDate', o.from ); + $cell.add($shcell).find('.dateTo').val('').datepicker('setDate', o.to ); + }); + + // return the hidden input so the filter widget has a reference to it + return $input.val( o.from ? ( o.to ? o.from + ' - ' + o.to : '>=' + o.from ) : (o.to ? '<=' + o.to : '') ); + }, + + /**********************\ + HTML5 Number (spinner) + \**********************/ + html5Number : function($cell, indx, def5Num) { + var t, o = $.extend({ + value : 0, + min : 0, + max : 100, + step : 1, + delayed : true, + disabled : false, + addToggle : false, + exactMatch : false, + cellText : '', + compare : '', + skipTest: false + }, def5Num), + + $input, + // test browser for HTML5 range support + $number = $('').appendTo($cell), + // test if HTML5 number is supported - from Modernizr + numberSupported = o.skipTest || $number.attr('type') === 'number' && $number.val() !== 'test', + $shcell = [], + c = $cell.closest('table')[0].config, + + updateNumber = function(delayed, notrigger){ + var chkd = o.addToggle ? $cell.find('.toggle').is(':checked') : true, + v = $cell.find('.number').val(), + compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '', + searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) : true; + $input + // add equal to the beginning, so we filter exact numbers + .val( !o.addToggle || chkd ? (compare ? compare : o.exactMatch ? '=' : '') + v : '' ) + .trigger( notrigger ? '' : 'search', searchType ).end() + .find('.number').val(v); + if ($cell.find('.number').length) { + $cell.find('.number')[0].disabled = (o.disabled || !chkd); + } + // update sticky header cell + if ($shcell.length) { + $shcell.find('.number').val(v)[0].disabled = (o.disabled || !chkd); + $shcell.find(compareSelect).val(compare); + if (o.addToggle) { + $shcell.find('.toggle')[0].checked = chkd; + } + } + }; + $number.remove(); + + if (numberSupported) { + t = o.addToggle ? '
' + + '
' : ''; + t += ''; + // add HTML5 number (spinner) + $cell + .append(t + '') + .find('.toggle, .number').bind('change', function(){ + updateNumber(); + }) + .closest('thead').find('th[data-column=' + indx + ']') + .addClass('filter-parsed') // get exact numbers from column + // on reset + .closest('table').bind('filterReset', function(){ + if ($.isArray(o.compare)) { + $cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); + } + // turn off the toggle checkbox + if (o.addToggle) { + $cell.find('.toggle')[0].checked = false; + if ($shcell.length) { + $shcell.find('.toggle')[0].checked = false; + } + } + $cell.find('.number').val( o.value ); + setTimeout(function(){ + updateNumber(); + }, 0); + }); + $input = $cell.find('input[type=hidden]').bind('change', function(){ + $cell.find('.number').val( this.value ); + updateNumber(); + }); + + // update slider from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + var val = tsff.updateCompare($cell, $input, o)[0] || o.value; + $cell.find('.number').val( ((val || '') + '').replace(/[><=]/g,'') ); + updateNumber(false, true); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($cell, indx, o); + $cell.find(compareSelect).bind('change', function(){ + updateNumber(); + }); + } + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + $shcell + .append(t) + .find('.toggle, .number').bind('change', function(){ + $cell.find('.number').val( $(this).val() ); + updateNumber(); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($shcell, indx, o); + $shcell.find(compareSelect).bind('change', function(){ + $cell.find(compareSelect).val( $(this).val() ); + updateNumber(); + }); + } + + updateNumber(); + }); + + updateNumber(); + + } + + return numberSupported ? $cell.find('input[type="hidden"]') : $(''); + }, + + /**********************\ + HTML5 range slider + \**********************/ + html5Range : function($cell, indx, def5Range) { + var o = $.extend({ + value : 0, + min : 0, + max : 100, + step : 1, + delayed : true, + valueToHeader : true, + exactMatch : true, + cellText : '', + compare : '', + allText : 'all', + skipTest : false + }, def5Range), + + $input, + // test browser for HTML5 range support + $range = $('').appendTo($cell), + // test if HTML5 range is supported - from Modernizr (but I left out the method to detect in Safari 2-4) + // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/inputtypes.js + rangeSupported = o.skipTest || $range.attr('type') === 'range' && $range.val() !== 'test', + $shcell = [], + c = $cell.closest('table')[0].config, + + updateRange = function(v, delayed, notrigger){ + /*jshint eqeqeq:false */ + // hidden input changes may include compare symbols + v = ( typeof v === "undefined" ? $input.val() : v ).toString().replace(/[<>=]/g,'') || o.value; + var compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '', + t = ' (' + (compare ? compare + v : v == o.min ? o.allText : v) + ')', + searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) : true; + $cell.find('input[type=hidden]') + // add equal to the beginning, so we filter exact numbers + .val( ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ) ) + //( val == o.min ? '' : val + (o.exactMatch ? '=' : '')) + .trigger( notrigger ? '' : 'search', searchType ).end() + .find('.range').val(v); + // or add current value to the header cell, if desired + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t); + // update sticky header cell + if ($shcell.length) { + $shcell + .find('.range').val(v).end() + .find(compareSelect).val( compare ); + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t); + } + }; + $range.remove(); + + if (rangeSupported) { + // add HTML5 range + $cell + .html('') + .closest('thead').find('th[data-column=' + indx + ']') + .addClass('filter-parsed') // get exact numbers from column + // add span to header for the current slider value + .find('.tablesorter-header-inner').append(''); + // hidden filter update namespace trigger by filter widget + $input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){ + /*jshint eqeqeq:false */ + var v = this.value, + compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || ''; + if (v !== this.lastValue) { + this.lastValue = ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ); + this.value = this.lastValue; + updateRange( v ); + } + }); + + $cell.find('.range').bind('change', function(){ + updateRange( this.value ); + }); + + // update spinner from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + var val = tsff.updateCompare($cell, $input, o)[0]; + $cell.find('.range').val( val ); + updateRange(val, false, true); + }); + + if (o.compare) { + // add compare select + tsff.addCompare($cell, indx, o); + $cell.find(compareSelect).bind('change', function(){ + updateRange(); + }); + } + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); + $shcell + .html('') + .find('.range').bind('change', function(){ + updateRange( $shcell.find('.range').val() ); + }); + updateRange(); + + if (o.compare) { + // add compare select + tsff.addCompare($shcell, indx, o); + $shcell.find(compareSelect).bind('change', function(){ + $cell.find(compareSelect).val( $(this).val() ); + updateRange(); + }); + } + + }); + + // on reset + $cell.closest('table').bind('filterReset', function(){ + if ($.isArray(o.compare)) { + $cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); + } + setTimeout(function(){ + updateRange(o.value, false, true); + }, 0); + }); + updateRange(); + + } + + return rangeSupported ? $cell.find('input[type="hidden"]') : $(''); + }, + + /**********************\ + HTML5 Color picker + \**********************/ + html5Color: function($cell, indx, defColor) { + var t, o = $.extend({ + value : '#000000', + disabled : false, + addToggle : true, + exactMatch : true, + valueToHeader : false, + skipTest : false + }, defColor), + $input, + // Add a hidden input to hold the range values + $color = $('').appendTo($cell), + // test if HTML5 color is supported - from Modernizr + colorSupported = o.skipTest || $color.attr('type') === 'color' && $color.val() !== 'test', + $shcell = [], + c = $cell.closest('table')[0].config, + + updateColor = function(v, notrigger){ + v = ( typeof v === "undefined" ? $input.val() : v ).toString().replace('=','') || o.value; + var chkd = true, + t = ' (' + v + ')'; + if (o.addToggle) { + chkd = $cell.find('.toggle').is(':checked'); + } + if ($cell.find('.colorpicker').length) { + $cell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd); + } + + $input + .val( chkd ? v + (o.exactMatch ? '=' : '') : '' ) + .trigger( !c.$table[0].hasInitialized || notrigger ? '' : 'search' ); + if (o.valueToHeader) { + // add current color to the header cell + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t); + } else { + // current color to span in cell + $cell.find('.currentColor').html(t); + } + + // update sticky header cell + if ($shcell.length) { + $shcell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd); + if (o.addToggle) { + $shcell.find('.toggle')[0].checked = chkd; + } + if (o.valueToHeader) { + // add current color to the header cell + $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t); + } else { + // current color to span in cell + $shcell.find('.currentColor').html(t); + } + } + }; + $color.remove(); + + if (colorSupported) { + t = '' + indx + Math.round(Math.random() * 100); + // add HTML5 color picker + t = '
' + + (o.addToggle ? '
' : '') + + '' + + (o.valueToHeader ? '' : '(#000000)') + '
'; + $cell.html(t); + // add span to header for the current color value - only works if the line in the updateColor() function is also un-commented out + if (o.valueToHeader) { + $cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append(''); + } + + $cell.find('.toggle, .colorpicker').bind('change', function(){ + updateColor( $cell.find('.colorpicker').val() ); + }); + + // hidden filter update namespace trigger by filter widget + $input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){ + updateColor( this.value ); + }); + + // update slider from hidden input, in case of saved filters + c.$table.bind('filterFomatterUpdate', function(){ + updateColor( $input.val(), true ); + }); + + // on reset + $cell.closest('table').bind('filterReset', function(){ + // just turn off the colorpicker + if (o.addToggle) { + $cell.find('.toggle')[0].checked = false; + } + // delay needed because default color needs to be set in the filter + // there is no compare option here, so if addToggle = false, + // default color is #000000 (even with no value set) + setTimeout(function(){ + updateColor(); + }, 0); + }); + + // has sticky headers? + c.$table.bind('stickyHeadersInit', function(){ + $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx); + $shcell + .html(t) + .find('.toggle, .colorpicker').bind('change', function(){ + updateColor( $shcell.find('.colorpicker').val() ); + }); + updateColor( $shcell.find('.colorpicker').val() ); + }); + + updateColor( o.value ); + } + return colorSupported ? $cell.find('input[type="hidden"]') : $(''); + } + +}; + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets-filter-formatter.min.js b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets-filter-formatter.min.js new file mode 100644 index 000000000..54a3b2cf8 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets-filter-formatter.min.js @@ -0,0 +1,6 @@ +/*! Filter widget formatter functions - updated 3/12/2014 (v2.15.9) + * requires: tableSorter 2.15+ and jQuery 1.4.3+ + * jQuery UI spinner, silder, range slider & datepicker (range) + * HTML5 number (spinner), range slider & color selector + */ +;(function(k){var s=k.tablesorter||{},n=s.filterFormatter={addCompare:function(b,e,h){if(h.compare&&k.isArray(h.compare)&&1'+h.cellText+"":"";k.each(h.compare,function(b,c){a+=""});b.wrapInner('
').prepend(m+'').appendTo(b).bind("change"+c.namespace+"filter", function(){d({value:this.value,delayed:!1})}),f=[],d=function(d,g){var p=!0,e,r=d&&d.value&&s.formatFloat((d.value+"").replace(/[><=]/g,""))||b.find(".spinner").val()||a.value,t=(k.isArray(a.compare)?b.find(".compare-select").val()||a.compare[a.selected||0]:a.compare)||"",h=d&&"boolean"===typeof d.delayed?d.delayed:c.$table[0].hasInitialized?a.delayed:!0;a.addToggle&&(p=b.find(".toggle").is(":checked"));e=a.disabled||!p?"disable":"enable";b.find(".filter").val(p?(t?t:a.exactMatch?"=":"")+r:"").trigger(g? "":"search",h).end().find(".spinner").spinner(e).val(r);f.length&&(f.find(".spinner").spinner(e).val(r).end().find(".compare-select").val(t),a.addToggle&&(f.find(".toggle")[0].checked=p))};a.oldcreate=a.create;a.oldspin=a.spin;a.create=function(b,c){d();"function"===typeof a.oldcreate&&a.oldcreate(b,c)};a.spin=function(b,c){d(c);"function"===typeof a.oldspin&&a.oldspin(b,c)};a.addToggle&&k('
').appendTo(b).find(".toggle").bind("change",function(){d()});b.closest("thead").find("th[data-column="+e+"]").addClass("filter-parsed");k('').val(a.value).appendTo(b).spinner(a).bind("change keyup",function(){d()});c.$table.bind("filterFomatterUpdate",function(){var c=n.updateCompare(b,m,a)[0];b.find(".spinner").val(c);d({value:c},!0)});a.compare&&(n.addCompare(b,e,a),b.find(".compare-select").bind("change",function(){d()}));c.$table.bind("stickyHeadersInit", function(){f=c.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e).empty();a.addToggle&&k('
').appendTo(f).find(".toggle").bind("change",function(){b.find(".toggle")[0].checked=this.checked;d()});k('').val(a.value).appendTo(f).spinner(a).bind("change keyup",function(){b.find(".spinner").val(this.value); d()});a.compare&&(n.addCompare(f,e,a),f.find(".compare-select").bind("change",function(){b.find(".compare-select").val(k(this).val());d()}))});c.$table.bind("filterReset",function(){k.isArray(a.compare)&&b.add(f).find(".compare-select").val(a.compare[a.selected||0]);a.addToggle&&(b.find(".toggle")[0].checked=!1);b.find(".spinner").spinner("value",a.value);setTimeout(function(){d()},0)});d();return m},uiSlider:function(b,e,h){var a=k.extend({delayed:!0,valueToHeader:!1,exactMatch:!0,cellText:"",compare:"", allText:"all",value:0,min:0,max:100,step:1,range:"min"},h),c=b.closest("table")[0].config,m=k('').appendTo(b).bind("change"+c.namespace+"filter",function(){d({value:this.value})}),f=[],d=function(d,g){var p="undefined"!==typeof d?s.formatFloat((d.value+"").replace(/[><=]/g,""))||a.value:a.value,q=a.compare?p:p===a.min?a.allText:p,r=(k.isArray(a.compare)?b.find(".compare-select").val()||a.compare[a.selected||0]:a.compare)||"",q=r+q,h=d&&"boolean"===typeof d.delayed? d.delayed:c.$table[0].hasInitialized?a.delayed:!0;a.valueToHeader?b.closest("thead").find("th[data-column="+e+"]").find(".curvalue").html(" ("+q+")"):b.find(".ui-slider-handle").addClass("value-popup").attr("data-value",q);b.find(".filter").val(r?r+p:p===a.min?"":(a.exactMatch?"=":"")+p).trigger(g?"":"search",h).end().find(".slider").slider("value",p);f.length&&(f.find(".compare-select").val(r).end().find(".slider").slider("value",p),a.valueToHeader?f.closest("thead").find("th[data-column="+e+"]").find(".curvalue").html(" ("+ q+")"):f.find(".ui-slider-handle").addClass("value-popup").attr("data-value",q))};b.closest("thead").find("th[data-column="+e+"]").addClass("filter-parsed");a.valueToHeader&&b.closest("thead").find("th[data-column="+e+"]").find(".tablesorter-header-inner").append('');a.oldcreate=a.create;a.oldslide=a.slide;a.create=function(b,c){d();"function"===typeof a.oldcreate&&a.oldcreate(b,c)};a.slide=function(b,c){d(c);"function"===typeof a.oldslide&&a.oldslide(b,c)};k('
').appendTo(b).slider(a);c.$table.bind("filterFomatterUpdate",function(){var c=n.updateCompare(b,m,a)[0];b.find(".slider").slider("value",c);d({value:c},!1)});a.compare&&(n.addCompare(b,e,a),b.find(".compare-select").bind("change",function(){d({value:b.find(".slider").slider("value")})}));c.$table.bind("filterReset",function(){k.isArray(a.compare)&&b.add(f).find(".compare-select").val(a.compare[a.selected||0]);setTimeout(function(){d({value:a.value})},0)});c.$table.bind("stickyHeadersInit", function(){f=c.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e).empty();k('
').val(a.value).appendTo(f).slider(a).bind("change keyup",function(){b.find(".slider").slider("value",this.value);d()});a.compare&&(n.addCompare(f,e,a),f.find(".compare-select").bind("change",function(){b.find(".compare-select").val(k(this).val());d()}))});return m},uiRange:function(b,e,h){var a=k.extend({delayed:!0,valueToHeader:!1,values:[0,100],min:0,max:100,range:!0}, h),c=b.closest("table")[0].config,m=k('').appendTo(b).bind("change"+c.namespace+"filter",function(){d()}),f=[],d=function(){var b=m.val(),c=b.split(" - ");""===b&&(c=[a.min,a.max]);c&&c[1]&&l({values:c,delay:!1},!0)},l=function(d,p){var q=d&&d.values||a.values,k=q[0]+" - "+q[1],h=q[0]===a.min&&q[1]===a.max?"":k,l=d&&"boolean"===typeof d.delayed?d.delayed:c.$table[0].hasInitialized?a.delayed:!0;a.valueToHeader?b.closest("thead").find("th[data-column="+e+"]").find(".currange").html(" ("+ k+")"):b.find(".ui-slider-handle").addClass("value-popup").eq(0).attr("data-value",q[0]).end().eq(1).attr("data-value",q[1]);b.find(".filter").val(h).trigger(p?"":"search",l).end().find(".range").slider("values",q);f.length&&(f.find(".range").slider("values",q),a.valueToHeader?f.closest("thead").find("th[data-column="+e+"]").find(".currange").html(" ("+k+")"):f.find(".ui-slider-handle").addClass("value-popup").eq(0).attr("data-value",q[0]).end().eq(1).attr("data-value",q[1]))};b.closest("thead").find("th[data-column="+ e+"]").addClass("filter-parsed");a.valueToHeader&&b.closest("thead").find("th[data-column="+e+"]").find(".tablesorter-header-inner").append('');a.oldcreate=a.create;a.oldslide=a.slide;a.create=function(b,c){l();"function"===typeof a.oldcreate&&a.oldcreate(b,c)};a.slide=function(b,c){l(c);"function"===typeof a.oldslide&&a.oldslide(b,c)};k('
').appendTo(b).slider(a);c.$table.bind("filterFomatterUpdate",function(){d()});c.$table.bind("filterReset", function(){b.find(".range").slider("values",a.values);setTimeout(function(){l()},0)});c.$table.bind("stickyHeadersInit",function(){f=c.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e).empty();k('
').val(a.value).appendTo(f).slider(a).bind("change keyup",function(){b.find(".range").val(this.value);l()})});return m},uiDateCompare:function(b,e,h){var a=k.extend({cellText:"",compare:"",endOfDay:!0,defaultDate:"",changeMonth:!0,changeYear:!0,numberOfMonths:1}, h),c,m=b.closest("table")[0].config;h=b.closest("thead").find("th[data-column="+e+"]").addClass("filter-parsed");var f=k('').appendTo(b).bind("change"+m.namespace+"filter",function(){var b=this.value;if(b)a.onClose(b)}),d,l=[],g=function(d,e){var f,g;f=d||c.datepicker("getDate")||"";var h=(k.isArray(a.compare)?b.find(".compare-select").val()||a.compare[a.selected||0]:a.compare)||"",n=m.$table[0].hasInitialized?a.delayed:!0;c.datepicker("setDate",""===f?a.defaultDate|| "":f);""===f&&(e=!1);g=(f=c.datepicker("getDate"))?(a.endOfDay&&/<=/.test(h)?f.setHours(23,59,59):f.getTime())||"":"";f&&a.endOfDay&&"="===h&&(h="",g+=" - "+f.setHours(23,59,59),e=!1);b.find(".dateCompare").val(h+g).trigger(e?"":"search",n).end();l.length&&l.find(".dateCompare").val(h+g).end().find(".compare-select").val(h)};d='';c=k(d).appendTo(b);a.oldonClose=a.onClose;a.onClose= function(b,c){g();"function"===typeof a.oldonClose&&a.oldonClose(b,c)};c.datepicker(a);m.$table.bind("filterReset",function(){k.isArray(a.compare)&&b.add(l).find(".compare-select").val(a.compare[a.selected||0]);b.add(l).find(".date").val(a.defaultDate).datepicker("setDate","");setTimeout(function(){g()},0)});m.$table.bind("filterFomatterUpdate",function(){var d;d=f.val();/\s+-\s+/.test(d)?(b.find(".compare-select").val("="),d=new Date(Number(d.split(/\s+-\s+/)[0])),c.datepicker("setDate",d)):(d=n.updateCompare(b, f,a)[1].toString()||"",d=""!==d?new Date(/\d{5}/g.test(d)?Number(d):d)||"":"");b.add(l).find(".date").datepicker("setDate",d);g(d,!0)});a.compare&&(n.addCompare(b,e,a),b.find(".compare-select").bind("change",function(){g()}));m.$table.bind("stickyHeadersInit",function(){l=m.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e).empty();l.append(d).find(".date").datepicker(a);a.compare&&(n.addCompare(l,e,a),l.find(".compare-select").bind("change",function(){b.find(".compare-select").val(k(this).val()); g()}))});return f.val(a.defaultDate?a.defaultDate:"")},uiDatepicker:function(b,e,h){var a=k.extend({endOfDay:!0,textFrom:"from",textTo:"to",from:"",to:"",changeMonth:!0,changeYear:!0,numberOfMonths:1},h),c,m,f,d=[],l=b.closest("table")[0].config,g=k('').appendTo(b).bind("change"+l.namespace+"filter",function(){var a=this.value;a.match(" - ")?(a=a.split(" - "),b.find(".dateTo").val(a[1]),f(a[0])):a.match(">=")?f(a.replace(">=","")):a.match("<=")&&m(a.replace("<=", ""))});b.closest("thead").find("th[data-column="+e+"]").addClass("filter-parsed");c="';k(c).appendTo(b);a.oldonClose=a.onClose;var p=a.defaultDate=a.from||a.defaultDate;f=a.onClose=function(c,e){var f;f=(new Date(b.find(".dateFrom").datepicker("getDate"))).getTime()||"";var g=b.find(".dateTo").datepicker("getDate")||"",g=g?(a.endOfDay?g.setHours(23,59,59):g.getTime())|| "":"";f=f?g?f+" - "+g:">="+f:g?"<="+g:"";b.find(".dateRange").val(f).trigger("search").end().find(".dateTo").datepicker("option","minDate",c).end().find(".dateFrom").val(c);d.length&&d.find(".dateTo").datepicker("option","minDate",c).end().find(".dateFrom").val(c);"function"===typeof a.oldonClose&&a.oldonClose(c,e)};b.find(".dateFrom").datepicker(a);a.defaultDate=a.to||"+7d";m=a.onClose=function(c,e){var f;f=(new Date(b.find(".dateFrom").datepicker("getDate"))).getTime()||"";var g=b.find(".dateTo").datepicker("getDate")|| "",g=g?(a.endOfDay?g.setHours(23,59,59):g.getTime())||"":"";f=f?g?f+" - "+g:">="+f:g?"<="+g:"";b.find(".dateRange").val(f).trigger("search").end().find(".dateFrom").datepicker("option","maxDate",c).end().find(".dateTo").val(c);d.length&&d.find(".dateFrom").datepicker("option","maxDate",c).end().find(".dateTo").val(c);"function"===typeof a.oldonClose&&a.oldonClose(c,e)};b.find(".dateTo").datepicker(a);l.$table.bind("filterFomatterUpdate",function(){var a=g.val()||"",c="",e="";/\s+-\s+/.test(a)?(a= a.split(/\s+-\s+/)||[],c=a[0]||"",e=a[1]||""):/>=/.test(a)?c=new Date(Number(a.replace(/>=/,"")))||"":/<=/.test(a)&&(e=new Date(Number(a.replace(/<=/,"")))||"");b.add(d).find(".dateFrom").datepicker("setDate",c);b.add(d).find(".dateTo").datepicker("setDate",e);m(e)});l.$table.bind("stickyHeadersInit",function(){d=l.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e).empty();d.append(c);a.onClose=m;d.find(".dateTo").datepicker(a);a.defaultDate=p;a.onClose=f;d.find(".dateFrom").datepicker(a)}); b.closest("table").bind("filterReset",function(){b.add(d).find(".dateFrom").val("").datepicker("setDate",a.from);b.add(d).find(".dateTo").val("").datepicker("setDate",a.to)});return g.val(a.from?a.to?a.from+" - "+a.to:">="+a.from:a.to?"<="+a.to:"")},html5Number:function(b,e,h){var a,c=k.extend({value:0,min:0,max:100,step:1,delayed:!0,disabled:!1,addToggle:!1,exactMatch:!1,cellText:"",compare:"",skipTest:!1},h),m;h=k('').appendTo(b);var f= c.skipTest||"number"===h.attr("type")&&"test"!==h.val(),d=[],l=b.closest("table")[0].config,g=function(a,e){var f=c.addToggle?b.find(".toggle").is(":checked"):!0,g=b.find(".number").val(),h=(k.isArray(c.compare)?b.find(".compare-select").val()||c.compare[c.selected||0]:c.compare)||"",n=l.$table[0].hasInitialized?a?a:c.delayed:!0;m.val(!c.addToggle||f?(h?h:c.exactMatch?"=":"")+g:"").trigger(e?"":"search",n).end().find(".number").val(g);b.find(".number").length&&(b.find(".number")[0].disabled=c.disabled|| !f);d.length&&(d.find(".number").val(g)[0].disabled=c.disabled||!f,d.find(".compare-select").val(h),c.addToggle&&(d.find(".toggle")[0].checked=f))};h.remove();f&&(a=c.addToggle?'
':"",a+='',b.append(a+'').find(".toggle, .number").bind("change",function(){g()}).closest("thead").find("th[data-column="+ e+"]").addClass("filter-parsed").closest("table").bind("filterReset",function(){k.isArray(c.compare)&&b.add(d).find(".compare-select").val(c.compare[c.selected||0]);c.addToggle&&(b.find(".toggle")[0].checked=!1,d.length&&(d.find(".toggle")[0].checked=!1));b.find(".number").val(c.value);setTimeout(function(){g()},0)}),m=b.find("input[type=hidden]").bind("change",function(){b.find(".number").val(this.value);g()}),l.$table.bind("filterFomatterUpdate",function(){var a=n.updateCompare(b,m,c)[0]||c.value; b.find(".number").val(((a||"")+"").replace(/[><=]/g,""));g(!1,!0)}),c.compare&&(n.addCompare(b,e,c),b.find(".compare-select").bind("change",function(){g()})),l.$table.bind("stickyHeadersInit",function(){d=l.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e).empty();d.append(a).find(".toggle, .number").bind("change",function(){b.find(".number").val(k(this).val());g()});c.compare&&(n.addCompare(d,e,c),d.find(".compare-select").bind("change",function(){b.find(".compare-select").val(k(this).val()); g()}));g()}),g());return f?b.find('input[type="hidden"]'):k('')},html5Range:function(b,e,h){var a=k.extend({value:0,min:0,max:100,step:1,delayed:!0,valueToHeader:!0,exactMatch:!0,cellText:"",compare:"",allText:"all",skipTest:!1},h),c;h=k('').appendTo(b);var m=a.skipTest||"range"===h.attr("type")&&"test"!==h.val(),f=[],d=b.closest("table")[0].config,l=function(g,h,l){g=("undefined"===typeof g?c.val():g).toString().replace(/[<>=]/g, "")||a.value;var m=(k.isArray(a.compare)?b.find(".compare-select").val()||a.compare[a.selected||0]:a.compare)||"",n=" ("+(m?m+g:g==a.min?a.allText:g)+")";h=d.$table[0].hasInitialized?h?h:a.delayed:!0;b.find("input[type=hidden]").val(m?m+g:g==a.min?"":(a.exactMatch?"=":"")+g).trigger(l?"":"search",h).end().find(".range").val(g);b.closest("thead").find("th[data-column="+e+"]").find(".curvalue").html(n);f.length&&(f.find(".range").val(g).end().find(".compare-select").val(m),f.closest("thead").find("th[data-column="+ e+"]").find(".curvalue").html(n))};h.remove();m&&(b.html('').closest("thead").find("th[data-column="+e+"]").addClass("filter-parsed").find(".tablesorter-header-inner").append(''),c=b.find("input[type=hidden]").bind("change"+d.namespace+"filter",function(){var c=this.value,d=(k.isArray(a.compare)?b.find(".compare-select").val()||a.compare[a.selected||0]:a.compare)|| "";c!==this.lastValue&&(this.value=this.lastValue=d?d+c:c==a.min?"":(a.exactMatch?"=":"")+c,l(c))}),b.find(".range").bind("change",function(){l(this.value)}),d.$table.bind("filterFomatterUpdate",function(){var d=n.updateCompare(b,c,a)[0];b.find(".range").val(d);l(d,!1,!0)}),a.compare&&(n.addCompare(b,e,a),b.find(".compare-select").bind("change",function(){l()})),d.$table.bind("stickyHeadersInit",function(){f=d.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e).empty();f.html('').find(".range").bind("change",function(){l(f.find(".range").val())});l();a.compare&&(n.addCompare(f,e,a),f.find(".compare-select").bind("change",function(){b.find(".compare-select").val(k(this).val());l()}))}),b.closest("table").bind("filterReset",function(){k.isArray(a.compare)&&b.add(f).find(".compare-select").val(a.compare[a.selected||0]);setTimeout(function(){l(a.value,!1,!0)},0)}),l());return m?b.find('input[type="hidden"]'):k('')}, html5Color:function(b,e,h){var a,c=k.extend({value:"#000000",disabled:!1,addToggle:!0,exactMatch:!0,valueToHeader:!1,skipTest:!1},h),m;h=k('').appendTo(b);var f=c.skipTest||"color"===h.attr("type")&&"test"!==h.val(),d=[],l=b.closest("table")[0].config,g=function(a,f){a=("undefined"===typeof a?m.val():a).toString().replace("=","")||c.value;var g=!0,h=" ("+a+")";c.addToggle&&(g=b.find(".toggle").is(":checked"));b.find(".colorpicker").length&& (b.find(".colorpicker").val(a)[0].disabled=c.disabled||!g);m.val(g?a+(c.exactMatch?"=":""):"").trigger(!l.$table[0].hasInitialized||f?"":"search");c.valueToHeader?b.closest("thead").find("th[data-column="+e+"]").find(".curcolor").html(h):b.find(".currentColor").html(h);d.length&&(d.find(".colorpicker").val(a)[0].disabled=c.disabled||!g,c.addToggle&&(d.find(".toggle")[0].checked=g),c.valueToHeader?d.closest("thead").find("th[data-column="+e+"]").find(".curcolor").html(h):d.find(".currentColor").html(h))}; h.remove();f&&(a=""+e+Math.round(100*Math.random()),a='
'+(c.addToggle?'
':"")+''+(c.valueToHeader?"":'(#000000)')+"
",b.html(a),c.valueToHeader&&b.closest("thead").find("th[data-column="+e+"]").find(".tablesorter-header-inner").append(''), b.find(".toggle, .colorpicker").bind("change",function(){g(b.find(".colorpicker").val())}),m=b.find("input[type=hidden]").bind("change"+l.namespace+"filter",function(){g(this.value)}),l.$table.bind("filterFomatterUpdate",function(){g(m.val(),!0)}),b.closest("table").bind("filterReset",function(){c.addToggle&&(b.find(".toggle")[0].checked=!1);setTimeout(function(){g()},0)}),l.$table.bind("stickyHeadersInit",function(){d=l.widgetOptions.$sticky.find(".tablesorter-filter-row").children().eq(e);d.html(a).find(".toggle, .colorpicker").bind("change", function(){g(d.find(".colorpicker").val())});g(d.find(".colorpicker").val())}),g(c.value));return f?b.find('input[type="hidden"]'):k('')}}})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets.js b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets.js new file mode 100644 index 000000000..e992a13db --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets.js @@ -0,0 +1,1549 @@ +/*! tableSorter 2.15+ widgets - updated 4/3/2014 (v2.15.13) + * + * Column Styles + * Column Filters + * Column Resizing + * Sticky Header + * UI Theme (generalized) + * Save Sort + * [ "columns", "filter", "resizable", "stickyHeaders", "uitheme", "saveSort" ] + */ +/*jshint browser:true, jquery:true, unused:false, loopfunc:true */ +/*global jQuery: false, localStorage: false, navigator: false */ +;(function($) { +"use strict"; +var ts = $.tablesorter = $.tablesorter || {}; + +ts.themes = { + "bootstrap" : { + table : 'table table-bordered table-striped', + caption : 'caption', + 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 glyphicon glyphicon-chevron-up', + sortDesc : 'icon-chevron-down glyphicon glyphicon-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 + caption : 'ui-widget-content ui-corner-all', + 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 + } +}; + +$.extend(ts.css, { + filterRow : 'tablesorter-filter-row', // filter + filter : 'tablesorter-filter', + wrapper : 'tablesorter-wrapper', // ui theme & resizable + resizer : 'tablesorter-resizer', // resizable + grip : 'tablesorter-resizer-grip', + sticky : 'tablesorter-stickyHeader', // stickyHeader + stickyVis : 'tablesorter-sticky-visible' +}); + +// *** 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 +*/ +ts.storage = function(table, key, value, options) { + table = $(table)[0]; + var cookieIndex, cookies, date, + hasLocalStorage = false, + values = {}, + c = table.config, + $table = $(table), + id = options && options.id || $table.attr(options && options.group || + 'data-table-group') || table.id || $('.tablesorter').index( $table ), + url = options && options.url || $table.attr(options && options.page || + 'data-table-page') || c && c.fixedUrl || window.location.pathname; + // https://gist.github.com/paulirish/5558557 + if ("localStorage" in window) { + try { + window.localStorage.setItem('_tmptest', 'temp'); + hasLocalStorage = true; + window.localStorage.removeItem('_tmptest'); + } catch(error) {} + } + // *** get value *** + if ($.parseJSON) { + if (hasLocalStorage) { + values = $.parseJSON(localStorage[key] || '{}'); + } else { + // old browser, using cookies + cookies = document.cookie.split(/[;\s|=]/); + // add one to get from the key to the value + cookieIndex = $.inArray(key, cookies) + 1; + values = (cookieIndex !== 0) ? $.parseJSON(cookies[cookieIndex] || '{}') : {}; + } + } + // allow value to be an empty string too + if ((value || value === '') && window.JSON && JSON.hasOwnProperty('stringify')) { + // add unique identifiers = url pathname > table ID/index on page > data + if (!values[url]) { + values[url] = {}; + } + values[url][id] = value; + // *** set value *** + if (hasLocalStorage) { + localStorage[key] = JSON.stringify(values); + } else { + date = new Date(); + date.setTime(date.getTime() + (31536e+6)); // 365 days + document.cookie = key + '=' + (JSON.stringify(values)).replace(/\"/g,'\"') + '; expires=' + date.toGMTString() + '; path=/'; + } + } else { + return values && values[url] ? values[url][id] : ''; + } +}; + +// Add a resize event to table headers +// ************************** +ts.addHeaderResizeEvent = function(table, disable, settings) { + var headers, + defaults = { + timer : 250 + }, + options = $.extend({}, defaults, settings), + c = table.config, + wo = c.widgetOptions, + checkSizes = function(triggerEvent) { + wo.resize_flag = true; + headers = []; + c.$headers.each(function() { + var $header = $(this), + sizes = $header.data('savedSizes') || [0,0], // fixes #394 + width = this.offsetWidth, + height = this.offsetHeight; + if (width !== sizes[0] || height !== sizes[1]) { + $header.data('savedSizes', [ width, height ]); + headers.push(this); + } + }); + if (headers.length && triggerEvent !== false) { + c.$table.trigger('resize', [ headers ]); + } + wo.resize_flag = false; + }; + checkSizes(false); + clearInterval(wo.resize_timer); + if (disable) { + wo.resize_flag = false; + return false; + } + wo.resize_timer = setInterval(function() { + if (wo.resize_flag) { return; } + checkSizes(); + }, options.timer); +}; + +// Widget: General UI theme +// "uitheme" option in "widgetOptions" +// ************************** +ts.addWidget({ + id: "uitheme", + priority: 10, + format: function(table, c, wo) { + var time, classes, $header, $icon, $tfoot, + themesAll = ts.themes, + $table = c.$table, + $headers = c.$headers, + theme = c.theme || 'jui', + themes = themesAll[theme] || themesAll.jui, + remove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc; + if (c.debug) { time = new Date(); } + // initialization code - run once + if (!$table.hasClass('tablesorter-' + theme) || c.theme === theme || !table.hasInitialized) { + // update zebra stripes + if (themes.even !== '') { wo.zebra[0] += ' ' + themes.even; } + if (themes.odd !== '') { wo.zebra[1] += ' ' + themes.odd; } + // add caption style + $table.find('caption').addClass(themes.caption); + // add table/footer class names + $tfoot = $table + // remove other selected themes + .removeClass( c.theme === '' ? '' : 'tablesorter-' + c.theme ) + .addClass('tablesorter-' + theme + ' ' + themes.table) // add theme widget class name + .find('tfoot'); + if ($tfoot.length) { + $tfoot + .find('tr').addClass(themes.footerRow) + .children('th, td').addClass(themes.footerCells); + } + // update header classes + $headers + .addClass(themes.header) + .not('.sorter-false') + .bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(event) { + // toggleClass with switch added in jQuery 1.3 + $(this)[ event.type === 'mouseenter' ? 'addClass' : 'removeClass' ](themes.hover); + }); + if (!$headers.find('.' + ts.css.wrapper).length) { + // Firefox needs this inner div to position the resizer correctly + $headers.wrapInner('
'); + } + if (c.cssIcon) { + // if c.cssIcon is '', then no is added to the header + $headers.find('.' + ts.css.icon).addClass(themes.icons); + } + if ($table.hasClass('hasFilters')) { + $headers.find('.' + ts.css.filterRow).addClass(themes.filterRow); + } + } + $.each($headers, function() { + $header = $(this); + $icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $header; + if (this.sortDisabled) { + // no sort arrows for disabled columns! + $header.removeClass(remove); + $icon.removeClass(remove + ' ' + themes.icons); + } else { + classes = ($header.hasClass(ts.css.sortAsc)) ? + themes.sortAsc : + ($header.hasClass(ts.css.sortDesc)) ? themes.sortDesc : + $header.hasClass(ts.css.header) ? themes.sortNone : ''; + $header[classes === themes.sortNone ? 'removeClass' : 'addClass'](themes.active); + $icon.removeClass(remove).addClass(classes); + } + }); + if (c.debug) { + ts.benchmark("Applying " + theme + " theme", time); + } + }, + remove: function(table, c, wo) { + var $table = c.$table, + theme = c.theme || 'jui', + themes = ts.themes[ theme ] || ts.themes.jui, + $headers = $table.children('thead').children(), + remove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc; + $table + .removeClass('tablesorter-' + theme + ' ' + themes.table) + .find(ts.css.header).removeClass(themes.header); + $headers + .unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover + .removeClass(themes.hover + ' ' + remove + ' ' + themes.active) + .find('.' + ts.css.filterRow) + .removeClass(themes.filterRow); + $headers.find('.' + ts.css.icon).removeClass(themes.icons); + } +}); + +// Widget: Column styles +// "columns", "columns_thead" (true) and +// "columns_tfoot" (true) options in "widgetOptions" +// ************************** +ts.addWidget({ + id: "columns", + priority: 30, + options : { + columns : [ "primary", "secondary", "tertiary" ] + }, + format: function(table, c, wo) { + var time, $tbody, tbodyIndex, $rows, rows, $row, $cells, remove, indx, + $table = c.$table, + $tbodies = c.$tbodies, + sortList = c.sortList, + len = sortList.length, + // removed c.widgetColumns support + css = wo && wo.columns || [ "primary", "secondary", "tertiary" ], + last = css.length - 1; + remove = css.join(' '); + if (c.debug) { + time = new Date(); + } + // check if there is a sort (on initialization there may not be one) + for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { + $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // detach tbody + $rows = $tbody.children('tr'); + // loop through the visible rows + $rows.each(function() { + $row = $(this); + if (this.style.display !== 'none') { + // remove all columns class names + $cells = $row.children().removeClass(remove); + // add appropriate column class names + if (sortList && sortList[0]) { + // primary sort column class + $cells.eq(sortList[0][0]).addClass(css[0]); + if (len > 1) { + for (indx = 1; indx < len; indx++) { + // secondary, tertiary, etc sort column classes + $cells.eq(sortList[indx][0]).addClass( css[indx] || css[last] ); + } + } + } + } + }); + ts.processTbody(table, $tbody, false); + } + // add classes to thead and tfoot + rows = wo.columns_thead !== false ? ['thead tr'] : []; + if (wo.columns_tfoot !== false) { + rows.push('tfoot tr'); + } + if (rows.length) { + $rows = $table.find( rows.join(',') ).children().removeClass(remove); + if (len) { + for (indx = 0; indx < len; indx++) { + // add primary. secondary, tertiary, etc sort column classes + $rows.filter('[data-column="' + sortList[indx][0] + '"]').addClass(css[indx] || css[last]); + } + } + } + if (c.debug) { + ts.benchmark("Applying Columns widget", time); + } + }, + remove: function(table, c, wo) { + var tbodyIndex, $tbody, + $tbodies = c.$tbodies, + remove = (wo.columns || [ "primary", "secondary", "tertiary" ]).join(' '); + c.$headers.removeClass(remove); + c.$table.children('tfoot').children('tr').children('th, td').removeClass(remove); + for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { + $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody + $tbody.children('tr').each(function() { + $(this).children().removeClass(remove); + }); + ts.processTbody(table, $tbody, false); // restore tbody + } + } +}); + +// Widget: filter +// ************************** +ts.addWidget({ + id: "filter", + priority: 50, + options : { + 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 : '', // css class name added to the filter row & each input in the row (tablesorter-filter is ALWAYS added) + filter_external : '', // jQuery selector string (or jQuery object) of external filters + filter_filteredRow : 'filtered', // class added to filtered rows; needed by pager plugin + filter_formatter : null, // add custom filter elements to the filter row + filter_functions : null, // add custom filter functions using this option + filter_hideEmpty : true, // hide filter row when table is empty + filter_hideFilters : false, // collapse filter row when mouse leaves the area + filter_ignoreCase : true, // if true, make all searches case-insensitive + filter_liveSearch : true, // if true, search column content while the user types (with a delay) + filter_onlyAvail : 'filter-onlyAvail', // a header with a select dropdown & this class name will only show available (visible) options within the drop down + filter_reset : null, // jQuery selector string of an element used to reset the filters + filter_saveFilters : false, // Use the $.tablesorter.storage utility to save the most recent 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. + filter_defaultAttrib : 'data-value' // data attribute in the header cell that contains the default filter value + }, + format: function(table, c, wo) { + if (!c.$table.hasClass('hasFilters')) { + ts.filter.init(table, c, wo); + } + }, + remove: function(table, c, wo) { + var tbodyIndex, $tbody, + $table = c.$table, + $tbodies = c.$tbodies; + $table + .removeClass('hasFilters') + // add .tsfilter namespace to all BUT search + .unbind('addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '.split(' ').join(c.namespace + 'filter ')) + .find('.' + ts.css.filterRow).remove(); + for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { + $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody + $tbody.children().removeClass(wo.filter_filteredRow).show(); + ts.processTbody(table, $tbody, false); // restore tbody + } + if (wo.filter_reset) { + $(document).undelegate(wo.filter_reset, 'click.tsfilter'); + } + } +}); + +ts.filter = { + + // regex used in filter "check" functions - not for general use and not documented + regex: { + regex : /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/, // regex to test for regex + child : /tablesorter-childRow/, // child row class name; this gets updated in the script + filtered : /filtered/, // filtered (hidden) row class name; updated in the script + type : /undefined|number/, // check type + exact : /(^[\"|\'|=]+)|([\"|\'|=]+$)/g, // exact match (allow '==') + nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser) + operators : /[<>=]/g // replace operators + }, + // function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed ) + // filter = array of filter input values; iFilter = same array, except lowercase + // exact = table cell text (or parsed data if column parser enabled) + // iExact = same as exact, except lowercase + // cached = table cell text from cache, so it has been parsed + // index = column index; table = table element (DOM) + // wo = widget options (table.config.widgetOptions) + // parsed = array (by column) of boolean values (from filter_useParsedData or "filter-parsed" class) + types: { + // Look for regex + regex: function( filter, iFilter, exact, iExact ) { + if ( ts.filter.regex.regex.test(iFilter) ) { + var matches, + regex = ts.filter.regex.regex.exec(iFilter); + try { + matches = new RegExp(regex[1], regex[2]).test( iExact ); + } catch (error) { + matches = false; + } + return matches; + } + return null; + }, + // Look for operators >, >=, < or <= + operators: function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed ) { + if ( /^[<>]=?/.test(iFilter) ) { + var cachedValue, result, + c = table.config, + query = ts.formatFloat( iFilter.replace(ts.filter.regex.operators, ''), table ), + parser = c.parsers[index], + savedSearch = query; + // parse filter value in case we're comparing numbers (dates) + if (parsed[index] || parser.type === 'numeric') { + cachedValue = parser.format( '' + iFilter.replace(ts.filter.regex.operators, ''), table, c.$headers.eq(index), index ); + query = ( typeof query === "number" && cachedValue !== '' && !isNaN(cachedValue) ) ? cachedValue : query; + } + // iExact may be numeric - see issue #149; + // check if cached is defined, because sometimes j goes out of range? (numeric columns) + cachedValue = ( parsed[index] || parser.type === 'numeric' ) && !isNaN(query) && cached ? cached : + isNaN(iExact) ? ts.formatFloat( iExact.replace(ts.filter.regex.nondigit, ''), table) : + ts.formatFloat( iExact, table ); + if ( />/.test(iFilter) ) { result = />=/.test(iFilter) ? cachedValue >= query : cachedValue > query; } + if ( /= 0 : fltr == iExact; + } + return null; + }, + // Look for a not match + notMatch: function( filter, iFilter, exact, iExact, cached, index, table, wo ) { + if ( /^\!/.test(iFilter) ) { + iFilter = iFilter.replace('!', ''); + var indx = iExact.search( $.trim(iFilter) ); + return iFilter === '' ? true : !(wo.filter_startsWith ? indx === 0 : indx >= 0); + } + return null; + }, + // Look for an AND or && operator (logical and) + and : function( filter, iFilter, exact, iExact ) { + if ( /\s+(AND|&&)\s+/g.test(filter) ) { + var query = iFilter.split( /(?:\s+(?:and|&&)\s+)/g ), + result = iExact.search( $.trim(query[0]) ) >= 0, + indx = query.length - 1; + while (result && indx) { + result = result && iExact.search( $.trim(query[indx]) ) >= 0; + indx--; + } + return result; + } + return null; + }, + // Look for a range (using " to " or " - ") - see issue #166; thanks matzhu! + range : function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed ) { + if ( /\s+(-|to)\s+/.test(iFilter) ) { + var result, tmp, + c = table.config, + query = iFilter.split(/(?: - | to )/), // make sure the dash is for a range and not indicating a negative number + range1 = ts.formatFloat(query[0].replace(ts.filter.regex.nondigit, ''), table), + range2 = ts.formatFloat(query[1].replace(ts.filter.regex.nondigit, ''), table); + // parse filter value in case we're comparing numbers (dates) + if (parsed[index] || c.parsers[index].type === 'numeric') { + result = c.parsers[index].format('' + query[0], table, c.$headers.eq(index), index); + range1 = (result !== '' && !isNaN(result)) ? result : range1; + result = c.parsers[index].format('' + query[1], table, c.$headers.eq(index), index); + range2 = (result !== '' && !isNaN(result)) ? result : range2; + } + result = ( parsed[index] || c.parsers[index].type === 'numeric' ) && !isNaN(range1) && !isNaN(range2) ? cached : + isNaN(iExact) ? ts.formatFloat( iExact.replace(ts.filter.regex.nondigit, ''), table) : + ts.formatFloat( iExact, table ); + if (range1 > range2) { tmp = range1; range1 = range2; range2 = tmp; } // swap + return (result >= range1 && result <= range2) || (range1 === '' || range2 === ''); + } + return null; + }, + // Look for wild card: ? = single, * = multiple, or | = logical OR + wild : function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed, rowArray ) { + if ( /[\?|\*]/.test(iFilter) || /\s+OR\s+/i.test(filter) ) { + var c = table.config, + query = iFilter.replace(/\s+OR\s+/gi,"|"); + // look for an exact match with the "or" unless the "filter-match" class is found + if (!c.$headers.filter('[data-column="' + index + '"]:last').hasClass('filter-match') && /\|/.test(query)) { + query = $.isArray(rowArray) ? '(' + query + ')' : '^(' + query + ')$'; + } + return new RegExp( query.replace(/\?/g, '\\S{1}').replace(/\*/g, '\\S*') ).test(iExact); + } + return null; + }, + // fuzzy text search; modified from https://github.com/mattyork/fuzzy (MIT license) + fuzzy: function( filter, iFilter, exact, iExact ) { + if ( /^~/.test(iFilter) ) { + var indx, + patternIndx = 0, + len = iExact.length, + pattern = iFilter.slice(1); + for (indx = 0; indx < len; indx++) { + if (iExact[indx] === pattern[patternIndx]) { + patternIndx += 1; + } + } + if (patternIndx === pattern.length) { + return true; + } + return false; + } + return null; + } + }, + init: function(table, c, wo) { + var options, string, $header, column, filters, time; + if (c.debug) { + time = new Date(); + } + c.$table.addClass('hasFilters'); + + ts.filter.regex.child = new RegExp(c.cssChildRow); + ts.filter.regex.filtered = new RegExp(wo.filter_filteredRow); + + // don't build filter row if columnFilters is false or all columns are set to "filter-false" - issue #156 + if (wo.filter_columnFilters !== false && c.$headers.filter('.filter-false').length !== c.$headers.length) { + // build filter row + ts.filter.buildRow(table, c, wo); + } + + c.$table.bind('addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '.split(' ').join(c.namespace + 'filter '), function(event, filter) { + c.$table.find('.' + ts.css.filterRow).toggle( !(wo.filter_hideEmpty && $.isEmptyObject(c.cache)) ); // fixes #450 + if ( !/(search|filter)/.test(event.type) ) { + event.stopPropagation(); + ts.filter.buildDefault(table, true); + } + if (event.type === 'filterReset') { + ts.filter.searching(table, []); + } else if (event.type === 'filterEnd') { + ts.filter.buildDefault(table, true); + } else { + // send false argument to force a new search; otherwise if the filter hasn't changed, it will return + filter = event.type === 'search' ? filter : event.type === 'updateComplete' ? c.$table.data('lastSearch') : ''; + if (/(update|add)/.test(event.type) && event.type !== "updateComplete") { + // force a new search since content has changed + c.lastCombinedFilter = null; + } + // pass true (skipFirst) to prevent the tablesorter.setFilters function from skipping the first input + // ensures all inputs are updated when a search is triggered on the table $('table').trigger('search', [...]); + ts.filter.searching(table, filter, true); + } + return false; + }); + + // reset button/link + if (wo.filter_reset) { + $(document) + .undelegate(wo.filter_reset, 'click.tsfilter') + .delegate(wo.filter_reset, 'click.tsfilter', function() { + // trigger a reset event, so other functions (filterFormatter) know when to reset + c.$table.trigger('filterReset'); + }); + } + if (wo.filter_functions) { + // column = column # (string) + for (column in wo.filter_functions) { + if (wo.filter_functions.hasOwnProperty(column) && typeof column === 'string') { + $header = c.$headers.filter('[data-column="' + column + '"]:last'); + options = ''; + if (wo.filter_functions[column] === true && !$header.hasClass('filter-false')) { + ts.filter.buildSelect(table, column); + } else if (typeof column === 'string' && !$header.hasClass('filter-false')) { + // add custom drop down list + for (string in wo.filter_functions[column]) { + if (typeof string === 'string') { + options += options === '' ? + '' : ''; + options += ''; + } + } + c.$table.find('thead').find('select.' + ts.css.filter + '[data-column="' + column + '"]').append(options); + } + } + } + } + // 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. + ts.filter.buildDefault(table, true); + + ts.filter.bindSearch( table, c.$table.find('.' + ts.css.filter), true ); + if (wo.filter_external) { + ts.filter.bindSearch( table, wo.filter_external ); + } + + if (wo.filter_hideFilters) { + ts.filter.hideFilters(table, c); + } + + // show processing icon + if (c.showProcessing) { + c.$table.bind('filterStart' + c.namespace + 'filter filterEnd' + c.namespace + 'filter', function(event, columns) { + // only add processing to certain columns to all columns + $header = (columns) ? c.$table.find('.' + ts.css.header).filter('[data-column]').filter(function() { + return columns[$(this).data('column')] !== ''; + }) : ''; + ts.isProcessing(table, event.type === 'filterStart', columns ? $header : ''); + }); + } + + if (c.debug) { + ts.benchmark("Applying Filter widget", time); + } + // add default values + c.$table.bind('tablesorter-initialized pagerInitialized', function() { + filters = ts.filter.setDefaults(table, c, wo) || []; + if (filters.length) { + ts.setFilters(table, filters, true); + } + c.$table.trigger('filterFomatterUpdate'); + ts.filter.checkFilters(table, filters); + }); + // filter widget initialized + wo.filter_initialized = true; + c.$table.trigger('filterInit'); + }, + setDefaults: function(table, c, wo) { + var isArray, saved, indx, + // get current (default) filters + filters = ts.getFilters(table) || []; + if (wo.filter_saveFilters && ts.storage) { + saved = ts.storage( table, 'tablesorter-filters' ) || []; + isArray = $.isArray(saved); + // make sure we're not just getting an empty array + if ( !(isArray && saved.join('') === '' || !isArray) ) { filters = saved; } + } + // if no filters saved, then check default settings + if (filters.join('') === '') { + for (indx = 0; indx < c.columns; indx++) { + filters[indx] = c.$headers.filter('[data-column="' + indx + '"]:last').attr(wo.filter_defaultAttrib) || filters[indx]; + } + } + c.$table.data('lastSearch', filters); + return filters; + }, + buildRow: function(table, c, wo) { + var column, $header, buildSelect, disabled, name, + // c.columns defined in computeThIndexes() + columns = c.columns, + buildFilter = ''; + for (column = 0; column < columns; column++) { + buildFilter += ''; + } + c.$filters = $(buildFilter += '').appendTo( c.$table.children('thead').eq(0) ).find('td'); + // build each filter input + for (column = 0; column < columns; column++) { + disabled = false; + // assuming last cell of a column is the main column + $header = c.$headers.filter('[data-column="' + column + '"]:last'); + buildSelect = (wo.filter_functions && wo.filter_functions[column] && typeof wo.filter_functions[column] !== 'function') || + $header.hasClass('filter-select'); + // get data from jQuery data, metadata, headers option or header class name + if (ts.getData) { + // get data from jQuery data, metadata, headers option or header class name + disabled = ts.getData($header[0], c.headers[column], 'filter') === 'false'; + } else { + // only class names and header options - keep this for compatibility with tablesorter v2.0.5 + disabled = (c.headers[column] && c.headers[column].hasOwnProperty('filter') && c.headers[column].filter === false) || + $header.hasClass('filter-false'); + } + if (buildSelect) { + buildFilter = $('').appendTo( c.$filters.eq(column) ); + } + if (buildFilter) { + buildFilter.attr('placeholder', $header.data('placeholder') || $header.attr('data-placeholder') || ''); + } + } + if (buildFilter) { + // add filter class name + name = ( $.isArray(wo.filter_cssFilter) ? + (typeof wo.filter_cssFilter[column] !== 'undefined' ? wo.filter_cssFilter[column] || '' : '') : + wo.filter_cssFilter ) || ''; + buildFilter.addClass( ts.css.filter + ' ' + name ).attr('data-column', column); + if (disabled) { + buildFilter.addClass('disabled')[0].disabled = true; // disabled! + } + } + } + }, + bindSearch: function(table, $el, internal) { + table = $(table)[0]; + $el = $($el); // allow passing a selector string + if (!$el.length) { return; } + var c = table.config, + wo = c.widgetOptions, + $ext = wo.filter_$externalFilters; + if (internal !== true) { + // save anyMatch element + wo.filter_$anyMatch = $el.filter('[data-column="all"]'); + if ($ext && $ext.length) { + wo.filter_$externalFilters = wo.filter_$externalFilters.add( $el ); + } else { + wo.filter_$externalFilters = $el; + } + // update values (external filters added after table initialization) + ts.setFilters(table, c.$table.data('lastSearch') || [], internal === false); + } + $el + // use data attribute instead of jQuery data since the head is cloned without including the data/binding + .attr('data-lastSearchTime', new Date().getTime()) + .unbind('keyup search change '.split(' ').join(c.namespace + 'filter ')) + // include change for select - fixes #473 + .bind('keyup search change '.split(' ').join(c.namespace + 'filter '), function(event, filters) { + $(this).attr('data-lastSearchTime', new Date().getTime()); + // emulate what webkit does.... escape clears the filter + if (event.which === 27) { + this.value = ''; + // liveSearch can contain a min value length; ignore arrow and meta keys, but allow backspace + } else if ( (typeof wo.filter_liveSearch === 'number' && this.value.length < wo.filter_liveSearch && this.value !== '') || + ( event.type === 'keyup' && ( (event.which < 32 && event.which !== 8 && wo.filter_liveSearch === true && event.which !== 13) || + ( event.which >= 37 && event.which <= 40 ) || (event.which !== 13 && wo.filter_liveSearch === false) ) ) ) { + return; + } + // true flag tells getFilters to skip newest timed input + ts.filter.searching( table, true, true ); + }); + c.$table.bind('filterReset', function(){ + $el.val(''); + }); + }, + checkFilters: function(table, filter, skipFirst) { + var c = table.config, + wo = c.widgetOptions, + filterArray = $.isArray(filter), + filters = (filterArray) ? filter : ts.getFilters(table, true), + combinedFilters = (filters || []).join(''); // combined filter values + // add filter array back into inputs + if (filterArray) { + ts.setFilters( table, filters, false, skipFirst !== true ); + } + if (wo.filter_hideFilters) { + // show/hide filter row as needed + c.$table.find('.' + ts.css.filterRow).trigger( combinedFilters === '' ? '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 (c.lastCombinedFilter === combinedFilters && filter !== false) { + return; + } else if (filter === false) { + // force filter refresh + c.lastCombinedFilter = null; + } + c.$table.trigger('filterStart', [filters]); + if (c.showProcessing) { + // give it time for the processing icon to kick in + setTimeout(function() { + ts.filter.findRows(table, filters, combinedFilters); + return false; + }, 30); + } else { + ts.filter.findRows(table, filters, combinedFilters); + return false; + } + }, + hideFilters: function(table, c) { + var $filterRow, $filterRow2, timer; + c.$table + .find('.' + ts.css.filterRow) + .addClass('hideme') + .bind('mouseenter mouseleave', function(e) { + // save event object - http://bugs.jquery.com/ticket/12140 + var event = e; + $filterRow = $(this); + clearTimeout(timer); + timer = setTimeout(function() { + if ( /enter|over/.test(event.type) ) { + $filterRow.removeClass('hideme'); + } else { + // don't hide if input has focus + // $(':focus') needs jQuery 1.6+ + if ( $(document.activeElement).closest('tr')[0] !== $filterRow[0] ) { + // don't hide row if any filter has a value + if (c.lastCombinedFilter === '') { + $filterRow.addClass('hideme'); + } + } + } + }, 200); + }) + .find('input, select').bind('focus blur', function(e) { + $filterRow2 = $(this).closest('tr'); + clearTimeout(timer); + var event = e; + timer = setTimeout(function() { + // don't hide row if any filter has a value + if (ts.getFilters(table).join('') === '') { + $filterRow2[ event.type === 'focus' ? 'removeClass' : 'addClass']('hideme'); + } + }, 200); + }); + }, + findRows: function(table, filters, combinedFilters) { + if (table.config.lastCombinedFilter === combinedFilters) { return; } + var cached, len, $rows, cacheIndex, rowIndex, tbodyIndex, $tbody, $cells, columnIndex, + childRow, childRowText, exact, iExact, iFilter, lastSearch, matches, result, + searchFiltered, filterMatched, showRow, time, + anyMatch, iAnyMatch, rowArray, rowText, iRowText, rowCache, + c = table.config, + wo = c.widgetOptions, + columns = c.columns, + $tbodies = c.$table.children('tbody'), // target all tbodies #568 + // anyMatch really screws up with these types of filters + anyMatchNotAllowedTypes = [ 'range', 'notMatch', 'operators' ], + // parse columns after formatter, in case the class is added at that point + parsed = c.$headers.map(function(columnIndex) { + return c.parsers && c.parsers[columnIndex] && c.parsers[columnIndex].parsed || ( ts.getData ? + ts.getData(c.$headers.filter('[data-column="' + columnIndex + '"]:last'), c.headers[columnIndex], 'filter') === 'parsed' : + $(this).hasClass('filter-parsed') ); + }).get(); + if (c.debug) { time = new Date(); } + for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { + if ($tbodies.eq(tbodyIndex).hasClass(c.cssInfoBlock || ts.css.info)) { continue; } // ignore info blocks, issue #264 + $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); + // skip child rows & widget added (removable) rows - fixes #448 thanks to @hempel! + $rows = $tbody.children('tr').not(c.selectorRemove); + len = $rows.length; + if (combinedFilters === '' || wo.filter_serversideFiltering) { + $tbody.children().removeClass(wo.filter_filteredRow).not('.' + c.cssChildRow).show(); + } else { + // optimize searching only through already filtered rows - see #313 + searchFiltered = true; + lastSearch = c.lastSearch || c.$table.data('lastSearch') || []; + $.each(filters, function(indx, val) { + // check for changes from beginning of filter; but ignore if there is a logical "or" in the string + searchFiltered = (val || '').indexOf(lastSearch[indx] || '') === 0 && searchFiltered && !/(\s+or\s+|\|)/g.test(val || ''); + }); + // can't search when all rows are hidden - this happens when looking for exact matches + if (searchFiltered && $rows.filter(':visible').length === 0) { searchFiltered = false; } + if ((wo.filter_$anyMatch && wo.filter_$anyMatch.length) || filters[c.columns]) { + anyMatch = wo.filter_$anyMatch && wo.filter_$anyMatch.val() || filters[c.columns] || ''; + if (c.sortLocaleCompare) { + // replace accents + anyMatch = ts.replaceAccents(anyMatch); + } + iAnyMatch = anyMatch.toLowerCase(); + } + + // loop through the rows + cacheIndex = 0; + for (rowIndex = 0; rowIndex < len; rowIndex++) { + childRow = $rows[rowIndex].className; + // skip child rows & already filtered rows + if ( ts.filter.regex.child.test(childRow) || (searchFiltered && ts.filter.regex.filtered.test(childRow)) ) { continue; } + showRow = true; + // *** nextAll/nextUntil not supported by Zepto! *** + childRow = $rows.eq(rowIndex).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 + childRowText = (childRow.length && wo.filter_childRows) ? childRow.text() : ''; + childRowText = wo.filter_ignoreCase ? childRowText.toLocaleLowerCase() : childRowText; + $cells = $rows.eq(rowIndex).children('td'); + + if (anyMatch) { + rowArray = $cells.map(function(i){ + var txt; + if (parsed[i]) { + txt = c.cache[tbodyIndex].normalized[cacheIndex][i]; + } else { + txt = wo.filter_ignoreCase ? $(this).text().toLowerCase() : $(this).text(); + if (c.sortLocaleCompare) { + txt = ts.replaceAccents(txt); + } + } + return txt; + }).get(); + rowText = rowArray.join(' '); + iRowText = rowText.toLowerCase(); + rowCache = c.cache[tbodyIndex].normalized[cacheIndex].join(' '); + filterMatched = null; + $.each(ts.filter.types, function(type, typeFunction) { + if ($.inArray(type, anyMatchNotAllowedTypes) < 0) { + matches = typeFunction( anyMatch, iAnyMatch, rowText, iRowText, rowCache, columns, table, wo, parsed, rowArray ); + if (matches !== null) { + filterMatched = matches; + return false; + } + } + }); + if (filterMatched !== null) { + showRow = filterMatched; + } else { + showRow = (iRowText + childRowText).indexOf(iAnyMatch) >= 0; + } + } + + for (columnIndex = 0; columnIndex < columns; columnIndex++) { + // ignore if filter is empty or disabled + if (filters[columnIndex]) { + cached = c.cache[tbodyIndex].normalized[cacheIndex][columnIndex]; + // check if column data should be from the cell or from parsed data + if (wo.filter_useParsedData || parsed[columnIndex]) { + exact = cached; + } else { + // using older or original tablesorter + exact = $.trim($cells.eq(columnIndex).text()); + exact = c.sortLocaleCompare ? ts.replaceAccents(exact) : exact; // issue #405 + } + iExact = !ts.filter.regex.type.test(typeof exact) && wo.filter_ignoreCase ? exact.toLocaleLowerCase() : exact; + result = showRow; // if showRow is true, show that row + + // replace accents - see #357 + filters[columnIndex] = c.sortLocaleCompare ? ts.replaceAccents(filters[columnIndex]) : filters[columnIndex]; + // val = case insensitive, filters[columnIndex] = case sensitive + iFilter = wo.filter_ignoreCase ? (filters[columnIndex] || '').toLocaleLowerCase() : filters[columnIndex]; + if (wo.filter_functions && wo.filter_functions[columnIndex]) { + if (wo.filter_functions[columnIndex] === true) { + // default selector; no "filter-select" class + result = (c.$headers.filter('[data-column="' + columnIndex + '"]:last').hasClass('filter-match')) ? + iExact.search(iFilter) >= 0 : filters[columnIndex] === exact; + } else if (typeof wo.filter_functions[columnIndex] === 'function') { + // filter callback( exact cell content, parser normalized content, filter input value, column index, jQuery row object ) + result = wo.filter_functions[columnIndex](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex)); + } else if (typeof wo.filter_functions[columnIndex][filters[columnIndex]] === 'function') { + // selector option function + result = wo.filter_functions[columnIndex][filters[columnIndex]](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex)); + } + } else { + filterMatched = null; + // cycle through the different filters + // filters return a boolean or null if nothing matches + $.each(ts.filter.types, function(type, typeFunction) { + matches = typeFunction( filters[columnIndex], iFilter, exact, iExact, cached, columnIndex, table, wo, parsed ); + if (matches !== null) { + filterMatched = matches; + return false; + } + }); + if (filterMatched !== null) { + result = filterMatched; + // Look for match, and add child row data for matching + } else { + exact = (iExact + childRowText).indexOf(iFilter); + result = ( (!wo.filter_startsWith && exact >= 0) || (wo.filter_startsWith && exact === 0) ); + } + } + showRow = (result) ? showRow : false; + } + } + $rows.eq(rowIndex) + .toggle(showRow) + .toggleClass(wo.filter_filteredRow, !showRow); + if (childRow.length) { + childRow.toggleClass(wo.filter_filteredRow, !showRow); + } + cacheIndex++; + } + } + ts.processTbody(table, $tbody, false); + } + c.lastCombinedFilter = combinedFilters; // save last search + c.lastSearch = filters; + c.$table.data('lastSearch', filters); + if (wo.filter_saveFilters && ts.storage) { + ts.storage( table, 'tablesorter-filters', filters ); + } + if (c.debug) { + ts.benchmark("Completed filter widget search", time); + } + c.$table.trigger('applyWidgets'); // make sure zebra widget is applied + c.$table.trigger('filterEnd'); + }, + buildSelect: function(table, column, updating, onlyavail) { + if (!table.config.cache || $.isEmptyObject(table.config.cache)) { return; } + column = parseInt(column, 10); + var indx, rowIndex, tbodyIndex, len, currentValue, txt, $filters, + c = table.config, + wo = c.widgetOptions, + $tbodies = c.$tbodies, + arry = [], + node = c.$headers.filter('[data-column="' + column + '"]:last'), + // t.data('placeholder') won't work in jQuery older than 1.4.3 + options = ''; + for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) { + len = c.cache[tbodyIndex].row.length; + // loop through the rows + for (rowIndex = 0; rowIndex < len; rowIndex++) { + // check if has class filtered + if (onlyavail && c.cache[tbodyIndex].row[rowIndex][0].className.match(wo.filter_filteredRow)) { continue; } + // get non-normalized cell content + if (wo.filter_useParsedData) { + arry.push( '' + c.cache[tbodyIndex].normalized[rowIndex][column] ); + } else { + node = c.cache[tbodyIndex].row[rowIndex][0].cells[column]; + if (node) { + arry.push( $.trim( node.textContent || node.innerText || $(node).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(value, indx) { + return $.inArray(value, arry) === indx; + }); + arry = (ts.sortNatural) ? arry.sort(function(a, b) { return ts.sortNatural(a, b); }) : arry.sort(true); + + // Get curent filter value + currentValue = c.$table.find('thead').find('select.' + ts.css.filter + '[data-column="' + column + '"]').val(); + + // build option list + for (indx = 0; indx < arry.length; indx++) { + txt = arry[indx].replace(/\"/g, """); + // replace quotes - fixes #242 & ignore empty strings - see http://stackoverflow.com/q/14990971/145346 + options += arry[indx] !== '' ? '' : ''; + } + // update all selects in the same column (clone thead in sticky headers & any external selects) - fixes 473 + $filters = ( c.$filters ? c.$filters : c.$table.children('thead') ).find('.' + ts.css.filter); + if (wo.filter_$externalFilters) { + $filters = $filters && $filters.length ? $filters.add(wo.filter_$externalFilters) : wo.filter_$externalFilters; + } + $filters.filter('select[data-column="' + column + '"]')[ updating ? 'html' : 'append' ](options); + }, + buildDefault: function(table, updating) { + var columnIndex, $header, + c = table.config, + wo = c.widgetOptions, + columns = c.columns; + // build default select dropdown + for (columnIndex = 0; columnIndex < columns; columnIndex++) { + $header = c.$headers.filter('[data-column="' + columnIndex + '"]:last'); + // look for the filter-select class; build/update it if found + if (($header.hasClass('filter-select') || wo.filter_functions && wo.filter_functions[columnIndex] === true) && + !$header.hasClass('filter-false')) { + if (!wo.filter_functions) { wo.filter_functions = {}; } + wo.filter_functions[columnIndex] = true; // make sure this select gets processed by filter_functions + ts.filter.buildSelect(table, columnIndex, updating, $header.hasClass(wo.filter_onlyAvail)); + } + } + }, + searching: function(table, filter, skipFirst) { + if (typeof filter === 'undefined' || filter === true) { + var wo = table.config.widgetOptions; + // delay filtering + clearTimeout(wo.searchTimer); + wo.searchTimer = setTimeout(function() { + ts.filter.checkFilters(table, filter, skipFirst ); + }, wo.filter_liveSearch ? wo.filter_searchDelay : 10); + } else { + // skip delay + ts.filter.checkFilters(table, filter, skipFirst); + } + } +}; + +ts.getFilters = function(table, getRaw, setFilters, skipFirst) { + var i, $filters, $column, + filters = false, + c = table ? $(table)[0].config : '', + wo = c ? c.widgetOptions : ''; + if (getRaw !== true && wo && !wo.filter_columnFilters) { + return $(table).data('lastSearch'); + } + if (c) { + if (c.$filters) { + $filters = c.$filters.find('.' + ts.css.filter); + } + if (wo.filter_$externalFilters) { + $filters = $filters && $filters.length ? $filters.add(wo.filter_$externalFilters) : wo.filter_$externalFilters; + } + if ($filters && $filters.length) { + filters = setFilters || []; + for (i = 0; i < c.columns + 1; i++) { + $column = $filters.filter('[data-column="' + (i === c.columns ? 'all' : i) + '"]'); + if ($column.length) { + // move the latest search to the first slot in the array + $column = $column.sort(function(a, b){ + return $(b).attr('data-lastSearchTime') - $(a).attr('data-lastSearchTime'); + }); + if ($.isArray(setFilters)) { + // skip first (latest input) to maintain cursor position while typing + (skipFirst ? $column.slice(1) : $column).val( setFilters[i] ).trigger('change.tsfilter'); + } else { + filters[i] = $column.val() || ''; + // don't change the first... it will move the cursor + $column.slice(1).val( filters[i] ); + } + // save any match input dynamically + if (i === c.columns && $column.length) { + wo.filter_$anyMatch = $column; + } + } + } + } + } + if (filters.length === 0) { + filters = false; + } + return filters; +}; + +ts.setFilters = function(table, filter, apply, skipFirst) { + var c = table ? $(table)[0].config : '', + valid = ts.getFilters(table, true, filter, skipFirst); + if (c && apply) { + // ensure new set filters are applied, even if the search is the same + c.lastCombinedFilter = null; + c.$table.trigger('search', [filter, false]).trigger('filterFomatterUpdate'); + } + return !!valid; +}; + +// Widget: Sticky headers +// based on this awesome article: +// http://css-tricks.com/13465-persistent-headers/ +// and https://github.com/jmosbech/StickyTableHeaders by Jonas Mosbech +// ************************** +ts.addWidget({ + id: "stickyHeaders", + priority: 60, // sticky widget must be initialized after the filter widget! + options: { + stickyHeaders : '', // extra class name added to the sticky header row + stickyHeaders_attachTo : null, // jQuery selector or object to attach sticky header to + stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element + stickyHeaders_cloneId : '-sticky', // added to table ID, if it exists + stickyHeaders_addResizeEvent : true, // trigger "resize" event on headers + stickyHeaders_includeCaption : true, // if false and a caption exist, it won't be included in the sticky header + stickyHeaders_zIndex : 2 // The zIndex of the stickyHeaders, allows the user to adjust this to their needs + }, + format: function(table, c, wo) { + // filter widget doesn't initialize on an empty table. Fixes #449 + if ( c.$table.hasClass('hasStickyHeaders') || ($.inArray('filter', c.widgets) >= 0 && !c.$table.hasClass('hasFilters')) ) { + return; + } + var $cell, + $table = c.$table, + $attach = $(wo.stickyHeaders_attachTo), + $thead = $table.children('thead:first'), + $win = $attach.length ? $attach : $(window), + $header = $thead.children('tr').not('.sticky-false').children(), + innerHeader = '.' + ts.css.headerIn, + $tfoot = $table.find('tfoot'), + $stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '', + stickyOffset = $attach.length ? 0 : $stickyOffset.length ? + $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0, + $stickyTable = wo.$sticky = $table.clone() + .addClass('containsStickyHeaders') + .css({ + position : $attach.length ? 'absolute' : 'fixed', + margin : 0, + top : stickyOffset, + left : 0, + visibility : 'hidden', + zIndex : wo.stickyHeaders_zIndex ? wo.stickyHeaders_zIndex : 2 + }), + $stickyThead = $stickyTable.children('thead:first').addClass(ts.css.sticky + ' ' + wo.stickyHeaders), + $stickyCells, + laststate = '', + spacing = 0, + nonwkie = $table.css('border-collapse') !== 'collapse' && !/(webkit|msie)/i.test(navigator.userAgent), + resizeHeader = function() { + stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0; + spacing = 0; + // yes, I dislike browser sniffing, but it really is needed here :( + // webkit automatically compensates for border spacing + if (nonwkie) { + // Firefox & Opera use the border-spacing + // update border-spacing here because of demos that switch themes + spacing = parseInt($header.eq(0).css('border-left-width'), 10) * 2; + } + $stickyTable.css({ + left : $attach.length ? (parseInt($attach.css('padding-left'), 10) || 0) + parseInt(c.$table.css('padding-left'), 10) + + parseInt(c.$table.css('margin-left'), 10) + parseInt($table.css('border-left-width'), 10) : + $thead.offset().left - $win.scrollLeft() - spacing, + width: $table.width() + }); + $stickyCells.filter(':visible').each(function(i) { + var $cell = $header.filter(':visible').eq(i), + // some wibbly-wobbly... timey-wimey... stuff, to make columns line up in Firefox + offset = nonwkie && $(this).attr('data-column') === ( '' + parseInt(c.columns/2, 10) ) ? 1 : 0; + $(this) + .css({ + width: $cell.width() - spacing, + height: $cell.height() + }) + .find(innerHeader).width( $cell.find(innerHeader).width() - offset ); + }); + }; + // fix clone ID, if it exists - fixes #271 + if ($stickyTable.attr('id')) { $stickyTable[0].id += wo.stickyHeaders_cloneId; } + // clear out cloned table, except for sticky header + // include caption & filter row (fixes #126 & #249) - don't remove cells to get correct cell indexing + $stickyTable.find('thead:gt(0), tr.sticky-false, tbody, tfoot').hide(); + if (!wo.stickyHeaders_includeCaption) { + $stickyTable.find('caption').remove(); + } else { + $stickyTable.find('caption').css( 'margin-left', '-1px' ); + } + // issue #172 - find td/th in sticky header + $stickyCells = $stickyThead.children().children(); + $stickyTable.css({ height:0, width:0, padding:0, margin:0, border:0 }); + // remove resizable block + $stickyCells.find('.' + ts.css.resizer).remove(); + // update sticky header class names to match real header after sorting + $table + .addClass('hasStickyHeaders') + .bind('sortEnd.tsSticky', function() { + $header.filter(':visible').each(function(indx) { + $cell = $stickyCells.filter(':visible').eq(indx) + .attr('class', $(this).attr('class')) + // remove processing icon + .removeClass(ts.css.processing + ' ' + c.cssProcessing); + if (c.cssIcon) { + $cell + .find('.' + ts.css.icon) + .attr('class', $(this).find('.' + ts.css.icon).attr('class')); + } + }); + }) + .bind('pagerComplete.tsSticky', function() { + resizeHeader(); + }); + + ts.bindEvents(table, $stickyThead.children().children('.tablesorter-header')); + + // add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned. + $table.after( $stickyTable ); + // make it sticky! + $win.bind('scroll.tsSticky resize.tsSticky', function(event) { + if (!$table.is(':visible')) { return; } // fixes #278 + var prefix = 'tablesorter-sticky-', + offset = $table.offset(), + captionHeight = (wo.stickyHeaders_includeCaption ? 0 : $table.find('caption').outerHeight(true)), + scrollTop = ($attach.length ? $attach.offset().top : $win.scrollTop()) + stickyOffset - captionHeight, + tableHeight = $table.height() - ($stickyTable.height() + ($tfoot.height() || 0)), + isVisible = (scrollTop > offset.top) && (scrollTop < offset.top + tableHeight) ? 'visible' : 'hidden', + cssSettings = { visibility : isVisible }; + if ($attach.length) { + cssSettings.top = $attach.scrollTop(); + } else { + // adjust when scrolling horizontally - fixes issue #143 + cssSettings.left = $thead.offset().left - $win.scrollLeft() - spacing; + } + $stickyTable + .removeClass(prefix + 'visible ' + prefix + 'hidden') + .addClass(prefix + isVisible) + .css(cssSettings); + if (isVisible !== laststate || event.type === 'resize') { + // make sure the column widths match + resizeHeader(); + laststate = isVisible; + } + }); + if (wo.stickyHeaders_addResizeEvent) { + ts.addHeaderResizeEvent(table); + } + + // look for filter widget + if ($table.hasClass('hasFilters')) { + // scroll table into view after filtering, if sticky header is active - #482 + $table.bind('filterEnd', function() { + // $(':focus') needs jQuery 1.6+ + var $td = $(document.activeElement).closest('td'), + column = $td.parent().children().index($td); + // only scroll if sticky header is active + if ($stickyTable.hasClass(ts.css.stickyVis)) { + // scroll to original table (not sticky clone) + window.scrollTo(0, $table.position().top); + // give same input/select focus + if (column >= 0) { + c.$filters.eq(column).find('a, select, input').filter(':visible').focus(); + } + } + }); + ts.filter.bindSearch( $table, $stickyCells.find('.' + ts.css.filter) ); + } + + $table.trigger('stickyHeadersInit'); + + }, + remove: function(table, c, wo) { + c.$table + .removeClass('hasStickyHeaders') + .unbind('sortEnd.tsSticky pagerComplete.tsSticky') + .find('.' + ts.css.sticky).remove(); + if (wo.$sticky && wo.$sticky.length) { wo.$sticky.remove(); } // remove cloned table + // don't unbind if any table on the page still has stickyheaders applied + if (!$('.hasStickyHeaders').length) { + $(window).unbind('scroll.tsSticky resize.tsSticky'); + } + ts.addHeaderResizeEvent(table, false); + } +}); + +// Add Column resizing widget +// this widget saves the column widths if +// $.tablesorter.storage function is included +// ************************** +ts.addWidget({ + id: "resizable", + priority: 40, + options: { + resizable : true, + resizable_addLastColumn : false, + resizable_widths : [] + }, + format: function(table, c, wo) { + if (c.$table.hasClass('hasResizable')) { return; } + c.$table.addClass('hasResizable'); + ts.resizableReset(table, true); // set default widths + var $rows, $columns, $column, column, + storedSizes = {}, + $table = c.$table, + mouseXPosition = 0, + $target = null, + $next = null, + fullWidth = Math.abs($table.parent().width() - $table.width()) < 20, + stopResize = function() { + if (ts.storage && $target && $next) { + storedSizes = {}; + storedSizes[$target.index()] = $target.width(); + storedSizes[$next.index()] = $next.width(); + $target.width( storedSizes[$target.index()] ); + $next.width( storedSizes[$next.index()] ); + if (wo.resizable !== false) { + // save all column widths + ts.storage(table, 'tablesorter-resizable', c.$headers.map(function(){ return $(this).width(); }).get() ); + } + } + mouseXPosition = 0; + $target = $next = null; + $(window).trigger('resize'); // will update stickyHeaders, just in case + }; + storedSizes = (ts.storage && wo.resizable !== false) ? ts.storage(table, 'tablesorter-resizable') : {}; + // process only if table ID or url match + if (storedSizes) { + for (column in storedSizes) { + if (!isNaN(column) && column < c.$headers.length) { + c.$headers.eq(column).width(storedSizes[column]); // set saved resizable widths + } + } + } + $rows = $table.children('thead:first').children('tr'); + // add resizable-false class name to headers (across rows as needed) + $rows.children().each(function() { + var canResize, + $column = $(this); + column = $column.attr('data-column'); + canResize = ts.getData( $column, c.headers[column], 'resizable') === "false"; + $rows.children().filter('[data-column="' + column + '"]')[canResize ? 'addClass' : 'removeClass']('resizable-false'); + }); + // add wrapper inside each cell to allow for positioning of the resizable target block + $rows.each(function() { + $column = $(this).children().not('.resizable-false'); + if (!$(this).find('.' + ts.css.wrapper).length) { + // Firefox needs this inner div to position the resizer correctly + $column.wrapInner('
'); + } + // don't include the last column of the row + if (!wo.resizable_addLastColumn) { $column = $column.slice(0,-1); } + $columns = $columns ? $columns.add($column) : $column; + }); + $columns + .each(function() { + var $column = $(this), + padding = parseInt($column.css('padding-right'), 10) + 10; // 10 is 1/2 of the 20px wide resizer grip + $column + .find('.' + ts.css.wrapper) + .append('
'); + }) + .bind('mousemove.tsresize', function(event) { + // ignore mousemove if no mousedown + if (mouseXPosition === 0 || !$target) { return; } + // resize columns + var leftEdge = event.pageX - mouseXPosition, + targetWidth = $target.width(); + $target.width( targetWidth + leftEdge ); + if ($target.width() !== targetWidth && fullWidth) { + $next.width( $next.width() - leftEdge ); + } + mouseXPosition = event.pageX; + }) + .bind('mouseup.tsresize', function() { + stopResize(); + }) + .find('.' + ts.css.resizer + ',.' + ts.css.grip) + .bind('mousedown', function(event) { + // save header cell and mouse position; closest() not supported by jQuery v1.2.6 + $target = $(event.target).closest('th'); + var $header = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]'); + if ($header.length > 1) { $target = $target.add($header); } + // if table is not as wide as it's parent, then resize the table + $next = event.shiftKey ? $target.parent().find('th').not('.resizable-false').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0); + mouseXPosition = event.pageX; + }); + $table.find('thead:first') + .bind('mouseup.tsresize mouseleave.tsresize', function() { + stopResize(); + }) + // right click to reset columns to default widths + .bind('contextmenu.tsresize', function() { + ts.resizableReset(table); + // $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset + var allowClick = $.isEmptyObject ? $.isEmptyObject(storedSizes) : true; + storedSizes = {}; + return allowClick; + }); + }, + remove: function(table, c) { + c.$table + .removeClass('hasResizable') + .children('thead') + .unbind('mouseup.tsresize mouseleave.tsresize contextmenu.tsresize') + .children('tr').children() + .unbind('mousemove.tsresize mouseup.tsresize') + // don't remove "tablesorter-wrapper" as uitheme uses it too + .find('.' + ts.css.resizer + ',.' + ts.css.grip).remove(); + ts.resizableReset(table); + } +}); +ts.resizableReset = function(table, nosave) { + $(table).each(function(){ + var $t, + c = this.config, + wo = c && c.widgetOptions; + if (table && c) { + c.$headers.each(function(i){ + $t = $(this); + if (wo.resizable_widths[i]) { + $t.css('width', wo.resizable_widths[i]); + } else if (!$t.hasClass('resizable-false')) { + // don't clear the width of any column that is not resizable + $t.css('width',''); + } + }); + if (ts.storage && !nosave) { ts.storage(this, '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 +// ************************** +ts.addWidget({ + id: 'saveSort', + priority: 20, + options: { + saveSort : true + }, + init: function(table, thisWidget, c, wo) { + // run widget format before all other widgets are applied to the table + thisWidget.format(table, c, wo, true); + }, + format: function(table, c, wo, init) { + var stored, time, + $table = c.$table, + saveSort = 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 (saveSort && table.hasInitialized && ts.storage) { + ts.storage( table, 'tablesorter-savesort', sortList ); + if (c.debug) { + ts.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 (ts.storage) { + stored = ts.storage( table, 'tablesorter-savesort' ); + sortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : ''; + if (c.debug) { + ts.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time); + } + $table.bind('saveSortReset', function(event) { + event.stopPropagation(); + ts.storage( table, 'tablesorter-savesort', '' ); + }); + } + // 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) { + // clear storage + if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); } + } +}); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets.min.js b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets.min.js new file mode 100644 index 000000000..8149a94fa --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/jquery.tablesorter.widgets.min.js @@ -0,0 +1,17 @@ +/*! tableSorter 2.15+ widgets - updated 4/10/2014 (v2.15.14) */ +;(function(l){ +var c=l.tablesorter=l.tablesorter||{}; +c.themes={bootstrap:{table:"table table-bordered table-striped",caption:"caption",header:"bootstrap-header",footerRow:"",footerCells:"",icons:"",sortNone:"bootstrap-icon-unsorted",sortAsc:"icon-chevron-up glyphicon glyphicon-chevron-up",sortDesc:"icon-chevron-down glyphicon glyphicon-chevron-down",active:"",hover:"",filterRow:"",even:"",odd:""},jui:{table:"ui-widget ui-widget-content ui-corner-all",caption:"ui-widget-content ui-corner-all",header:"ui-widget-header ui-corner-all ui-state-default", footerRow:"",footerCells:"",icons:"ui-icon",sortNone:"ui-icon-carat-2-n-s",sortAsc:"ui-icon-carat-1-n",sortDesc:"ui-icon-carat-1-s",active:"ui-state-active",hover:"ui-state-hover",filterRow:"",even:"ui-widget-content",odd:"ui-state-default"}};l.extend(c.css,{filterRow:"tablesorter-filter-row",filter:"tablesorter-filter",wrapper:"tablesorter-wrapper",resizer:"tablesorter-resizer",grip:"tablesorter-resizer-grip",sticky:"tablesorter-stickyHeader",stickyVis:"tablesorter-sticky-visible"}); +c.storage=function(b,a,e,c){b=l(b)[0];var d,g,h=!1;d={};g=b.config;var k=l(b);b=c&&c.id||k.attr(c&&c.group||"data-table-group")||b.id||l(".tablesorter").index(k);c=c&&c.url||k.attr(c&&c.page||"data-table-page")||g&&g.fixedUrl||window.location.pathname;if("localStorage"in window)try{window.localStorage.setItem("_tmptest","temp"),h=!0,window.localStorage.removeItem("_tmptest")}catch(q){}l.parseJSON&&(h?d=l.parseJSON(localStorage[a]||"{}"):(g=document.cookie.split(/[;\s|=]/),d=l.inArray(a,g)+1,d=0!==d?l.parseJSON(g[d]|| "{}"):{}));if((e||""===e)&&window.JSON&&JSON.hasOwnProperty("stringify"))d[c]||(d[c]={}),d[c][b]=e,h?localStorage[a]=JSON.stringify(d):(e=new Date,e.setTime(e.getTime()+31536E6),document.cookie=a+"="+JSON.stringify(d).replace(/\"/g,'"')+"; expires="+e.toGMTString()+"; path=/");else return d&&d[c]?d[c][b]:""}; +c.addHeaderResizeEvent=function(b,a,c){var f;c=l.extend({},{timer:250},c);var d=b.config,g=d.widgetOptions,h=function(a){g.resize_flag=!0;f=[];d.$headers.each(function(){var a=l(this),b=a.data("savedSizes")|| [0,0],c=this.offsetWidth,e=this.offsetHeight;if(c!==b[0]||e!==b[1])a.data("savedSizes",[c,e]),f.push(this)});f.length&&!1!==a&&d.$table.trigger("resize",[f]);g.resize_flag=!1};h(!1);clearInterval(g.resize_timer);if(a)return g.resize_flag=!1;g.resize_timer=setInterval(function(){g.resize_flag||h()},c.timer)}; +c.addWidget({id:"uitheme",priority:10,format:function(b,a,e){var f,d,g,h,k=c.themes,q=a.$table,n=a.$headers,p=a.theme||"jui",m=k[p]||k.jui,v=m.sortNone+" "+m.sortDesc+" "+m.sortAsc;a.debug&&(f= new Date);q.hasClass("tablesorter-"+p)&&a.theme!==p&&b.hasInitialized||(""!==m.even&&(e.zebra[0]+=" "+m.even),""!==m.odd&&(e.zebra[1]+=" "+m.odd),q.find("caption").addClass(m.caption),b=q.removeClass(""===a.theme?"":"tablesorter-"+a.theme).addClass("tablesorter-"+p+" "+m.table).find("tfoot"),b.length&&b.find("tr").addClass(m.footerRow).children("th, td").addClass(m.footerCells),n.addClass(m.header).not(".sorter-false").bind("mouseenter.tsuitheme mouseleave.tsuitheme",function(a){l(this)["mouseenter"=== a.type?"addClass":"removeClass"](m.hover)}),n.find("."+c.css.wrapper).length||n.wrapInner('
'),a.cssIcon&&n.find("."+c.css.icon).addClass(m.icons),q.hasClass("hasFilters")&&n.find("."+c.css.filterRow).addClass(m.filterRow));l.each(n,function(){g=l(this);h=c.css.icon?g.find("."+c.css.icon):g;this.sortDisabled?(g.removeClass(v),h.removeClass(v+" "+m.icons)):(d=g.hasClass(c.css.sortAsc)?m.sortAsc:g.hasClass(c.css.sortDesc)? m.sortDesc:g.hasClass(c.css.header)?m.sortNone:"",g[d===m.sortNone?"removeClass":"addClass"](m.active),h.removeClass(v).addClass(d))});a.debug&&c.benchmark("Applying "+p+" theme",f)},remove:function(b,a,e){b=a.$table;a=a.theme||"jui";e=c.themes[a]||c.themes.jui;var f=b.children("thead").children(),d=e.sortNone+" "+e.sortDesc+" "+e.sortAsc;b.removeClass("tablesorter-"+a+" "+e.table).find(c.css.header).removeClass(e.header);f.unbind("mouseenter.tsuitheme mouseleave.tsuitheme").removeClass(e.hover+" "+ d+" "+e.active).find("."+c.css.filterRow).removeClass(e.filterRow);f.find("."+c.css.icon).removeClass(e.icons)}}); +c.addWidget({id:"columns",priority:30,options:{columns:["primary","secondary","tertiary"]},format:function(b,a,e){var f,d,g,h,k,q,n,p,m=a.$table,v=a.$tbodies,s=a.sortList,u=s.length,w=e&&e.columns||["primary","secondary","tertiary"],x=w.length-1;n=w.join(" ");a.debug&&(f=new Date);for(g=0;g=]/g},types:{regex:function(b,a,e,f){if(c.filter.regex.regex.test(a)){var d; b=c.filter.regex.regex.exec(a);try{d=RegExp(b[1],b[2]).test(f)}catch(g){d=!1}return d}return null},operators:function(b,a,e,f,d,g,h,k,l){if(/^[<>]=?/.test(a)){var n,p;n=h.config;b=c.formatFloat(a.replace(c.filter.regex.operators,""),h);e=n.parsers[g];k=b;if(l[g]||"numeric"===e.type)n=e.format(""+a.replace(c.filter.regex.operators,""),h,n.$headers.eq(g),g),b="number"!==typeof b||""===n||isNaN(n)?b:n;n=!l[g]&&"numeric"!==e.type||isNaN(b)||!d?isNaN(f)?c.formatFloat(f.replace(c.filter.regex.nondigit, ""),h):c.formatFloat(f,h):d;/>/.test(a)&&(p=/>=/.test(a)?n>=b:n>b);/k&&(f=e,e=k,k=f);return a>=e&&a<=k||""===e||""===k}return null},wild:function(b,a,c,f,d,g,h,k,q,n){return/[\?|\*]/.test(a)||/\s+OR\s+/i.test(b)?(b=h.config,a=a.replace(/\s+OR\s+/gi,"|"),!b.$headers.filter('[data-column="'+g+'"]:last').hasClass("filter-match")&&/\|/.test(a)&&(a=l.isArray(n)?"("+a+")":"^("+a+")$"),RegExp(a.replace(/\?/g,"\\S{1}").replace(/\*/g, "\\S*")).test(f)):null},fuzzy:function(b,a,c,f){if(/^~/.test(a)){b=0;c=f.length;var d=a.slice(1);for(a=0;a'+(g.data("placeholder")||g.attr("data-placeholder")||"")+"":"",f+='");a.$table.find("thead").find("select."+c.css.filter+'[data-column="'+h+'"]').append(f)}c.filter.buildDefault(b,!0);c.filter.bindSearch(b,a.$table.find("."+c.css.filter),!0);e.filter_external&&c.filter.bindSearch(b,e.filter_external);e.filter_hideFilters&&c.filter.hideFilters(b,a);a.showProcessing&&a.$table.bind("filterStart"+a.namespace+"filter filterEnd"+ a.namespace+"filter",function(d,e){g=e?a.$table.find("."+c.css.header).filter("[data-column]").filter(function(){return""!==e[l(this).data("column")]}):"";c.isProcessing(b,"filterStart"===d.type,e?g:"")});a.debug&&c.benchmark("Applying Filter widget",q);a.$table.bind("tablesorter-initialized pagerInitialized",function(){k=c.filter.setDefaults(b,a,e)||[];k.length&&c.setFilters(b,k,!0);a.$table.trigger("filterFomatterUpdate");c.filter.checkFilters(b,k)});e.filter_initialized=!0;a.$table.trigger("filterInit")}, setDefaults:function(b,a,e){var f,d=c.getFilters(b)||[];e.filter_saveFilters&&c.storage&&(f=c.storage(b,"tablesorter-filters")||[],(b=l.isArray(f))&&""===f.join("")||!b||(d=f));if(""===d.join(""))for(b=0;b';for(b=0;b";a.$filters=l(d+"").appendTo(a.$table.children("thead").eq(0)).find("td"); for(b=0;b").appendTo(a.$filters.eq(b)):(e.filter_formatter&&l.isFunction(e.filter_formatter[b])?((d=e.filter_formatter[b](a.$filters.eq(b),b))&&0=== d.length&&(d=a.$filters.eq(b).children("input")),d&&(0===d.parent().length||d.parent().length&&d.parent()[0]!==a.$filters[b])&&a.$filters.eq(b).append(d)):d=l('').appendTo(a.$filters.eq(b)),d&&d.attr("placeholder",f.data("placeholder")||f.attr("data-placeholder")||"")),d&&(f=(l.isArray(e.filter_cssFilter)?"undefined"!==typeof e.filter_cssFilter[b]?e.filter_cssFilter[b]||"":"":e.filter_cssFilter)||"",d.addClass(c.css.filter+" "+f).attr("data-column",b),g&&(d.addClass("disabled")[0].disabled= !0))},bindSearch:function(b,a,e){b=l(b)[0];a=l(a);if(a.length){var f=b.config,d=f.widgetOptions,g=d.filter_$externalFilters;!0!==e&&(d.filter_$anyMatch=a.filter('[data-column="all"]'),d.filter_$externalFilters=g&&g.length?d.filter_$externalFilters.add(a):a,c.setFilters(b,f.$table.data("lastSearch")||[],!1===e));a.attr("data-lastSearchTime",(new Date).getTime()).unbind(["keyup","search","change",""].join(f.namespace+"filter ")).bind(["keyup","search","change",""].join(f.namespace+"filter "),function(a, e){l(this).attr("data-lastSearchTime",(new Date).getTime());if(27===a.which)this.value="";else if("number"===typeof d.filter_liveSearch&&this.value.lengtha.which&&8!==a.which&&!0===d.filter_liveSearch&&13!==a.which||37<=a.which&&40>=a.which||13!==a.which&&!1===d.filter_liveSearch))return;c.filter.searching(b,!0,!0)});f.$table.bind("filterReset",function(){a.val("")})}},checkFilters:function(b,a,e){var f=b.config,d=f.widgetOptions,g=l.isArray(a), h=g?a:c.getFilters(b,!0),k=(h||[]).join("");g&&c.setFilters(b,h,!1,!0!==e);d.filter_hideFilters&&f.$table.find("."+c.css.filterRow).trigger(""===k?"mouseleave":"mouseenter");if(f.lastCombinedFilter!==k||!1===a)if(!1===a&&(f.lastCombinedFilter=null),f.$table.trigger("filterStart",[h]),f.showProcessing)setTimeout(function(){c.filter.findRows(b,h,k);return!1},30);else return c.filter.findRows(b,h,k),!1},hideFilters:function(b,a){var e,f,d;a.$table.find("."+c.css.filterRow).addClass("hideme").bind("mouseenter mouseleave", function(b){e=l(this);clearTimeout(d);d=setTimeout(function(){/enter|over/.test(b.type)?e.removeClass("hideme"):l(document.activeElement).closest("tr")[0]!==e[0]&&""===a.lastCombinedFilter&&e.addClass("hideme")},200)}).find("input, select").bind("focus blur",function(a){f=l(this).closest("tr");clearTimeout(d);d=setTimeout(function(){if(""===c.getFilters(b).join(""))f["focus"===a.type?"removeClass":"addClass"]("hideme")},200)})},findRows:function(b,a,e){if(b.config.lastCombinedFilter!==e){var f,d, g,h,k,q,n,p,m,v,s,u,w,x,A,z,y,D,B,C,L,E,G,H,I,J,M,r=b.config,t=r.widgetOptions,N=r.columns,K=r.$table.children("tbody"),O=["range","notMatch","operators"],F=r.$headers.map(function(a){return r.parsers&&r.parsers[a]&&r.parsers[a].parsed||(c.getData?"parsed"===c.getData(r.$headers.filter('[data-column="'+a+'"]:last'),r.headers[a],"filter"):l(this).hasClass("filter-parsed"))}).get();r.debug&&(L=new Date);for(q=0;ql.inArray(a,O)&&(z=c(E,G,I,J,M,N,b,t,F,H),null!==z))return B=z,!1}),C=null!==B?B:0<=(J+s).indexOf(G));for(m=0;m'+(p.data("placeholder")||p.attr("data-placeholder")||"")+"";for(g=0;g"+n[f]+"":"";k=(k.$filters?k.$filters:k.$table.children("thead")).find("."+c.css.filter);b.filter_$externalFilters&& (k=k&&k.length?k.add(b.filter_$externalFilters):b.filter_$externalFilters);k.filter('select[data-column="'+a+'"]')[e?"html":"append"](m)}},buildDefault:function(b,a){var e,f,d=b.config,g=d.widgetOptions,h=d.columns;for(e=0;eb.top&&cMath.abs(q.parent().width()-q.width()), s=function(){c.storage&&p&&m&&(k={},k[p.index()]=p.width(),k[m.index()]=m.width(),p.width(k[p.index()]),m.width(k[m.index()]),!1!==e.resizable&&c.storage(b,"tablesorter-resizable",a.$headers.map(function(){return l(this).width()}).get()));n=0;p=m=null;l(window).trigger("resize")};if(k=c.storage&&!1!==e.resizable?c.storage(b,"tablesorter-resizable"):{})for(h in k)!isNaN(h)&&h
');e.resizable_addLastColumn||(g=g.slice(0,-1));d=d?d.add(g):g});d.each(function(){var a=l(this),b=parseInt(a.css("padding-right"), 10)+10;a.find("."+c.css.wrapper).append('
')}).bind("mousemove.tsresize",function(a){if(0!==n&&p){var b=a.pageX-n,c=p.width();p.width(c+b);p.width()!==c&&v&&m.width(m.width()-b);n=a.pageX}}).bind("mouseup.tsresize",function(){s()}).find("."+c.css.resizer+",."+c.css.grip).bind("mousedown",function(b){p=l(b.target).closest("th");var c=a.$headers.filter('[data-column="'+ p.attr("data-column")+'"]');1 50), it becomes 1980 + // if the 2 digit year is 50 (2050 - 2020 < 50), then it becomes 2050. + range = 50; + + ts.dates = $.extend({}, ts.dates, { + regxxxxyy: /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/, + regyyxxxx: /(\d{2})[\/\s](\d{1,2})[\/\s](\d{1,2})/ + }); + + ts.formatDate = function(s, regex, format, table){ + var n = s + // replace separators + .replace(/\s+/g," ").replace(/[-.,]/g, "/") + // reformat xx/xx/xx to mm/dd/19yy; + .replace(regex, format), + d = new Date(n), + y = d.getFullYear(), + rng = table && table.config.dateRange || range, + now = new Date().getFullYear(); + // if date > 50 years old (set range), add 100 years + // this will work when people start using "50" and mean "2050" + while (now - y > rng) { + y += 100; + } + return d.setFullYear(y) || s; + }; + + $.tablesorter.addParser({ + id: "ddmmyy", + is: function() { + return false; + }, + format: function(s, table) { + // reformat dd/mm/yy to mm/dd/19yy; + return ts.formatDate(s, ts.dates.regxxxxyy, "$2/$1/19$3", table); + }, + type: "numeric" + }); + + $.tablesorter.addParser({ + id: "mmddyy", + is: function() { + return false; + }, + format: function(s, table) { + // reformat mm/dd/yy to mm/dd/19yy + return ts.formatDate(s, ts.dates.regxxxxyy, "$1/$2/19$3", table); + }, + type: "numeric" + }); + + $.tablesorter.addParser({ + id: "yymmdd", + is: function() { + return false; + }, + format: function(s, table) { + // reformat yy/mm/dd to mm/dd/19yy + return ts.formatDate(s, ts.dates.regyyxxxx, "$2/$3/19$1", table); + }, + type: "numeric" + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-date-weekday.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-date-weekday.js new file mode 100644 index 000000000..62f4504ef --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-date-weekday.js @@ -0,0 +1,33 @@ +/*! Weekday parser + * Demo: http://jsfiddle.net/Mottie/abkNM/477/ + */ +/*jshint jquery:true */ +;(function($){ +"use strict"; + + var ts = $.tablesorter; + ts.dates = $.extend({}, ts.dates, { + // *** modify this array to change match the language *** + weekdayCased : [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ] + }); + ts.dates.weekdayLower = ts.dates.weekdayCased.join(',').toLocaleLowerCase().split(','); + + ts.addParser({ + id: "weekday", + is: function(){ + return false; + }, + format: function(s, table) { + var j = -1, c = table.config; + s = c.ignoreCase ? s.toLocaleLowerCase() : s; + $.each(ts.dates[ 'weekday' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){ + if (j < 0 && s.match(v)) { j = i; } + }); + // return s (original string) if there isn't a match + // (non-weekdays will sort separately and empty cells will sort as expected) + return j < 0 ? s : j; + }, + type: "numeric" + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-date.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-date.js new file mode 100644 index 000000000..52ece6c9c --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-date.js @@ -0,0 +1,36 @@ +/*! + * Extract dates using popular natural language date parsers + */ +/*jshint jquery:true */ +;(function($){ +"use strict"; + + /*! Sugar (http://sugarjs.com/dates#comparing_dates) + * demo: http://jsfiddle.net/Mottie/abkNM/551/ + */ + $.tablesorter.addParser({ + id: "sugar", + is: function() { + return false; + }, + format: function(s) { + return Date.create ? Date.create(s).getTime() || s : new Date(s).getTime() || s; + }, + type: "numeric" + }); + + /*! Datejs (http://www.datejs.com/) + * demo: http://jsfiddle.net/Mottie/abkNM/550/ + */ + $.tablesorter.addParser({ + id: "datejs", + is: function() { + return false; + }, + format: function(s) { + return Date.parse && Date.parse(s) || s; + }, + type: "numeric" + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-feet-inch-fraction.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-feet-inch-fraction.js new file mode 100644 index 000000000..79fdea83b --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-feet-inch-fraction.js @@ -0,0 +1,63 @@ +/*! Distance parser +* This parser will parser numbers like 5'10" (5 foot 10 inches) +* and 31½ into sortable values. +* Demo: http://jsfiddle.net/Mottie/abkNM/154/ +*/ +/*global jQuery: false */ +;(function($){ + "use strict"; + + var ts = $.tablesorter; + ts.symbolRegex = /[\u215b\u215c\u215d\u215e\u00bc\u00bd\u00be]/g; + ts.processFractions = function(n, table) { + if (n) { + var t, p = 0; + n = $.trim(n.replace(/\"/,'')); + // look for a space in the first part of the number: "10 3/4" and save the "10" + if (/\s/.test(n)) { + p = ts.formatFloat(n.split(' ')[0], table); + // remove stuff to the left of the space + n = $.trim(n.substring(n.indexOf(' '), n.length)); + } + // look for a "/" to calculate fractions + if (/\//g.test(n)) { + t = n.split('/'); + // turn 3/4 into .75; make sure we don't divide by zero + n = p + parseInt(t[0], 10) / parseInt(t[1] || 1, 10); + // look for fraction symbols + } else if (ts.symbolRegex.test(n)) { + n = p + n.replace(ts.symbolRegex, function(m){ + return { + '\u215b' : '.125', // 1/8 + '\u215c' : '.375', // 3/8 + '\u215d' : '.625', // 5/8 + '\u215e' : '.875', // 7/8 + '\u00bc' : '.25', // 1/4 + '\u00bd' : '.5', // 1/2 + '\u00be' : '.75' // 3/4 + }[m]; + }); + } + } + return n || 0; + }; + + $.tablesorter.addParser({ + id: 'distance', + is: function() { + // return false so this parser is not auto detected + return false; + }, + format: function(s, table) { + if (s === '') { return ''; } + // look for feet symbol = ' + // very generic test to catch 1.1', 1 1/2' and 1½' + var d = (/^\s*\S*(\s+\S+)?\s*\'/.test(s)) ? s.split("'") : [0,s], + f = ts.processFractions(d[0], table), // feet + i = ts.processFractions(d[1], table); // inches + return (/[\'\"]/).test(s) ? parseFloat(f) + (parseFloat(i)/12 || 0) : parseFloat(f) + parseFloat(i); + }, + type: 'numeric' + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-file-type.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-file-type.js new file mode 100644 index 000000000..c64a82cc8 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-file-type.js @@ -0,0 +1,73 @@ +/*! File Type parser + * When a file type extension is found, the equivalent name is + * prefixed into the parsed data, so sorting occurs in groups + */ +/*global jQuery: false */ +;(function($){ +"use strict"; + + // basic list from http://en.wikipedia.org/wiki/List_of_file_formats + // To add a custom equivalent, define: + // $.tablesorter.fileTypes.equivalents['xx'] = "A|B|C"; + $.tablesorter.fileTypes = { + // divides filetype extensions in the equivalent list below + separator : '|', + equivalents : { + "3D Image" : "3dm|3ds|dwg|max|obj", + "Audio" : "aif|aac|ape|flac|la|m4a|mid|midi|mp2|mp3|ogg|ra|raw|rm|wav|wma", + "Compressed" : "7z|bin|cab|cbr|gz|gzip|iso|lha|lz|rar|tar|tgz|zip|zipx|zoo", + "Database" : "csv|dat|db|dbf|json|ldb|mdb|myd|pdb|sql|tsv|wdb|wmdb|xlr|xls|xlsx|xml", + "Development" : "asm|c|class|cls|cpp|cc|cs|cxx|cbp|cs|dba|fla|h|java|lua|pl|py|pyc|pyo|sh|sln|r|rb|vb", + "Document" : "doc|docx|odt|ott|pages|pdf|rtf|tex|wpd|wps|wrd|wri", + "Executable" : "apk|app|com|exe|gadget|lnk|msi", + "Fonts" : "eot|fnt|fon|otf|ttf|woff", + "Icons" : "ani|cur|icns|ico", + "Images" : "bmp|gif|jpg|jpeg|jpe|jp2|pic|png|psd|tga|tif|tiff|wmf|webp", + "Presentation" : "pps|ppt", + "Published" : "chp|epub|lit|pub|ppp|fm|mobi", + "Script" : "as|bat|cgi|cmd|jar|js|lua|scpt|scptd|sh|vbs|vb|wsf", + "Styles" : "css|less|sass", + "Text" : "info|log|md|markdown|nfo|tex|text|txt", + "Vectors" : "awg|ai|eps|cdr|ps|svg", + "Video" : "asf|avi|flv|m4v|mkv|mov|mp4|mpe|mpeg|mpg|ogg|rm|rv|swf|vob|wmv", + "Web" : "asp|aspx|cer|cfm|htm|html|php|url|xhtml" + } + }; + + $.tablesorter.addParser({ + id: 'filetype', + is: function() { + return false; + }, + format: function(s, table) { + var t, + c = table.config, + wo = c.widgetOptions, + i = s.lastIndexOf('.'), + sep = $.tablesorter.fileTypes.separator, + m = $.tablesorter.fileTypes.matching, + types = $.tablesorter.fileTypes.equivalents; + if (!m) { + // make a string to "quick" match the existing equivalents + var t = []; + $.each(types, function(i,v){ + t.push(v); + }); + m = $.tablesorter.fileTypes.matching = sep + t.join(sep) + sep; + } + if (i >= 0) { + t = sep + s.substring(i + 1, s.length) + sep; + if (m.indexOf(t) >= 0) { + for (i in types) { + if ((sep + types[i] + sep).indexOf(t) >= 0) { + return i + (wo.group_separator ? wo.group_separator : '-') + s; + } + } + } + } + return s; + }, + type: 'text' + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-ignore-articles.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-ignore-articles.js new file mode 100644 index 000000000..d8429807e --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-ignore-articles.js @@ -0,0 +1,47 @@ +/*! Title parser + * This parser will remove "The", "A" and "An" from the beginning of a book + * or movie title, so it sorts by the second word or number + * Demo: http://jsfiddle.net/Mottie/abkNM/5/ + */ +/*global jQuery: false */ +;(function($){ +"use strict"; + + // basic list from http://en.wikipedia.org/wiki/Article_%28grammar%29 + $.tablesorter.ignoreArticles = { + "en" : "the, a, an", + "de" : "der, die, das, des, dem, den, ein, eine, einer, eines, einem, einen", + "nl" : "de, het, de, een", + "es" : "el, la, lo, los, las, un, una, unos, unas", + "pt" : "o, a, os, as, um, uma, uns, umas", + "fr" : "le, la, l'_, les, un, une, des", + "it" : "il, lo, la, l'_, i, gli, le, un', uno, una, un", + "hu" : "a, az, egy" + }; + + // To add a custom parser, define: + // $.tablesorter.ignoreArticles['xx'] = "A, B, C"; + // and then set the language id 'xx' in the headers option + // ignoreArticles : 'xx' + + $.tablesorter.addParser({ + id: 'ignoreArticles', + is: function() { + return false; + }, + format: function(s, table, cell, cellIndex) { + var c = table.config, art, lang; + if ( !(c.headers && c.headers[cellIndex] && c.headers[cellIndex].ignoreArticlesRegex) ) { + // initialize - save regex in c.headers[cellIndex].ignoreArticles + if (!c.headers) { c.headers = {}; } + if (!c.headers[cellIndex]) { c.headers[cellIndex] = {}; } + lang = $.tablesorter.getData(c.$headers.eq(cellIndex), c.headers[cellIndex], 'ignoreArticles'); + art = ($.tablesorter.ignoreArticles[lang] || "the, a, an" ) + ""; + c.headers[cellIndex].ignoreArticlesRegex = new RegExp('^(' + $.trim( art.split(/\s*\,\s*/).join('\\s|') + "\\s" ).replace("_\\s","") + ')', 'i'); + } + return (s || '').replace(c.headers[cellIndex].ignoreArticlesRegex, ''); + }, + type: 'text' + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-input-select.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-input-select.js new file mode 100644 index 000000000..6d79c9a99 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-input-select.js @@ -0,0 +1,87 @@ +/*! input & select parsers for jQuery 1.7+ & tablesorter 2.7.11+ + * Updated 2/19/2014 (v2.15.0) + * Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html + */ +/*jshint browser: true, jquery:true, unused:false */ +;(function($){ +"use strict"; + + var resort = true, // resort table after update + updateServer = function(event, $table, $input){ + // do something here to update your server, if needed + // event = change event object + // $table = jQuery object of the table that was just updated + // $input = jQuery object of the input or select that was modified + }; + + // Custom parser for parsing input values + // updated dynamically using the "change" function below + $.tablesorter.addParser({ + id: "inputs", + is: function(){ + return false; + }, + format: function(s, table, cell) { + return $(cell).find('input').val() || s; + }, + parsed : true, // filter widget flag + type: "text" + }); + + // Custom parser for including checkbox status if using the grouping widget + // updated dynamically using the "change" function below + $.tablesorter.addParser({ + id: "checkbox", + is: function(){ + return false; + }, + format: function(s, table, cell, cellIndex) { + var $c = $(cell), + $input = $c.find('input[type="checkbox"]'), + isChecked = $input.length ? $input[0].checked : ''; + // adding class to row, indicating that a checkbox is checked; includes + // a column index in case more than one checkbox happens to be in a row + $c.closest('tr').toggleClass('checked-' + cellIndex, isChecked); + // returning plain language here because this is what is shown in the + // group headers - change it as desired + return $input.length ? isChecked ? 'checked' : 'unchecked' : s; + }, + parsed : true, // filter widget flag + type: "text" + }); + + // Custom parser which returns the currently selected options + // updated dynamically using the "change" function below + $.tablesorter.addParser({ + id: "select", + is: function(){ + return false; + }, + format: function(s, table, cell) { + return $(cell).find('select').val() || s; + }, + parsed : true, // filter widget flag + type: "text" + }); + + // update select and all input types in the tablesorter cache when the change event fires. + // This method only works with jQuery 1.7+ + // you can change it to use delegate (v1.4.3+) or live (v1.3+) as desired + // if this code interferes somehow, target the specific table $('#mytable'), instead of $('table') + $(window).load(function(){ + // this flag prevents the updateCell event from being spammed + // it happens when you modify input text and hit enter + var alreadyUpdating = false; + $('table').find('tbody').on('change', 'select, input', function(e){ + if (!alreadyUpdating) { + var $tar = $(e.target), + $table = $tar.closest('table'); + alreadyUpdating = true; + $table.trigger('updateCell', [ $tar.closest('td'), resort ]); + updateServer(e, $table, $tar); + setTimeout(function(){ alreadyUpdating = false; }, 10); + } + }); + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-ipv6.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-ipv6.js new file mode 100644 index 000000000..121bc37ba --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-ipv6.js @@ -0,0 +1,76 @@ +/*! IPv6 Address parser (WIP) +* IPv6 Address (ffff:0000:0000:0000:0000:0000:0000:0000) +* needs to support short versions like "::8" or "1:2::7:8" +* and "::00:192.168.10.184" (embedded IPv4 address) +* see http://www.intermapper.com/support/tools/IPV6-Validator.aspx +*/ +/*global jQuery: false */ +;(function($){ + "use strict"; + + var ts = $.tablesorter; + + $.extend( ts.regex, {}, { + ipv4Validate : /((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/, + ipv4Extract : /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/, + + // simplified regex from http://www.intermapper.com/support/tools/IPV6-Validator.aspx + // (specifically from http://download.dartware.com/thirdparty/ipv6validator.js) + ipv6Validate : /^\s*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/i + }); + + ts.addParser({ + id: "ipv6Address", + is: function(s) { + return ts.regex.ipv6Validate.test(s); + }, + format: function(address, table) { + // code modified from http://forrst.com/posts/JS_Expand_Abbreviated_IPv6_Addresses-1OR + var i, t, sides, groups, groupsPresent, + hex = table ? (typeof table === "boolean" ? table : table && table.config.ipv6HexFormat || false) : false, + fullAddress = '', + expandedAddress = '', + validGroupCount = 8, + validGroupSize = 4; + // remove any extra spaces + address = address.replace(/\s*/g, ''); + // look for embedded ipv4 + if (ts.regex.ipv4Validate.test(address)) { + groups = address.match(ts.regex.ipv4Extract); + t = ''; + for (i = 1; i < groups.length; i++){ + t += ('00' + (parseInt(groups[i], 10).toString(16)) ).slice(-2) + ( i === 2 ? ':' : '' ); + } + address = address.replace( ts.regex.ipv4Extract, t ); + } + + if (address.indexOf("::") == -1) { + // All eight groups are present + fullAddress = address; + } else { + // Consecutive groups of zeroes have been collapsed with "::". + sides = address.split("::"); + groupsPresent = 0; + for (i = 0; i < sides.length; i++) { + groupsPresent += sides[i].split(":").length; + } + fullAddress += sides[0] + ":"; + for (i = 0; i < validGroupCount - groupsPresent; i++) { + fullAddress += "0000:"; + } + fullAddress += sides[1]; + } + groups = fullAddress.split(":"); + for (i = 0; i < validGroupCount; i++) { + // it's fastest & easiest for tablesorter to sort decimal values (vs hex) + groups[i] = hex ? ('0000' + groups[i]).slice(-4) : + ('00000' + (parseInt(groups[i], 16) || 0)).slice(-5); + expandedAddress += ( i != validGroupCount-1) ? groups[i] + ':' : groups[i]; + } + return hex ? expandedAddress : expandedAddress.replace(/:/g, ''); + }, + // uses natural sort hex compare + type: "numeric" + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-metric.js b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-metric.js new file mode 100644 index 000000000..db1f85ad0 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/parsers/parser-metric.js @@ -0,0 +1,77 @@ +/*! Metric parser + * Demo: http://jsfiddle.net/Mottie/abkNM/382/ + * Set the metric name in the header (defaults to "m|meter"), e.g. + * HDD Size + * Distance + */ +/*jshint jquery:true */ +;(function($){ +"use strict"; + + var prefixes = { + // "prefix" : [ base 10, base 2 ] + // skipping IEEE 1541 defined prefixes: kibibyte, mebibyte, etc, for now. + "Y|Yotta|yotta" : [ 1e24, Math.pow(1024, 8) ], // 1024^8 + "Z|Zetta|zetta" : [ 1e21, Math.pow(1024, 7) ], // 1024^7 + "E|Exa|exa" : [ 1e18, Math.pow(1024, 6) ], // 1024^6 + "P|Peta|peta" : [ 1e15, Math.pow(1024, 5) ], // 1024^5 + "T|Tera|tera" : [ 1e12, Math.pow(1024, 4) ], // 1024^4 + "G|Giga|giga" : [ 1e9, Math.pow(1024, 3) ], // 1024^3 + "M|Mega|mega" : [ 1e6, Math.pow(1024, 2) ], // 1024^2 + "k|Kilo|kilo" : [ 1e3, 1024 ], // 1024 + // prefixes below here are rarely, if ever, used in binary + "h|hecto" : [ 1e2, 1e2 ], + "da|deka" : [ 1e1, 1e1 ], + "d|deci" : [ 1e-1, 1e-1 ], + "c|centi" : [ 1e-2, 1e-2], + "m|milli" : [ 1e-3, 1e-3 ], + "µ|micro" : [ 1e-6, 1e-6 ], + "n|nano" : [ 1e-9, 1e-9 ], + "p|pico" : [ 1e-12, 1e-12 ], + "f|femto" : [ 1e-15, 1e-15 ], + "a|atto" : [ 1e-18, 1e-18 ], + "z|zepto" : [ 1e-21, 1e-21 ], + "y|yocto" : [ 1e-24, 1e-24 ] + }, + // the \\d+ will not catch digits with spaces, commas or decimals; so use the value from n instead + RegLong = "(\\d+)(\\s+)?([Zz]etta|[Ee]xa|[Pp]eta|[Tt]era|[Gg]iga|[Mm]ega|kilo|hecto|deka|deci|centi|milli|micro|nano|pico|femto|atto|zepto|yocto)(", + RegAbbr = "(\\d+)(\\s+)?(Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)("; + + $.tablesorter.addParser({ + id: 'metric', + is: function() { + return false; + }, + format: function(s, table, cell, cellIndex) { + var v = 'm|meter', + b, t, + // process number here to get a numerical format (us or eu) + n = $.tablesorter.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table), + $t = table.config.$headers.filter('[data-column="' + cellIndex + '"]'), + m = $t.data('metric'); + if (!m) { + // stored values + t = ($t.attr('data-metric-name') || v).split('|'); + m = [ t[1] || t[0].substring(1), t[0] ]; + m[2] = new RegExp(RegLong + m[0] + "|" + m[1] + ")"); + m[3] = new RegExp(RegAbbr + m[1] + ")"); + $t.data('metric', m); + } + // find match to full name or abbreviation + t = s.match(m[2]) || s.match(m[3]); + if (t) { + for (v in prefixes) { + if (t[3].match(v)) { + // exception when using binary prefix + // change base for binary use + b = /^[b|bit|byte|o|octet]/.test(t[4]) ? 1 : 0; + return n * prefixes[v][b]; + } + } + } + return n; + }, + type: 'numeric' + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-alignChar.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-alignChar.js new file mode 100644 index 000000000..982db1b49 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-alignChar.js @@ -0,0 +1,145 @@ +/*! tablesorter Align Character widget - updated 3/12/2014 (core v2.15.8) + * Requires tablesorter v2.8+ and jQuery 1.7+ + * by Rob Garrison + */ +/*jshint browser:true, jquery:true, unused:false */ +/*global jQuery: false */ +;(function($){ +"use strict"; +var ts = $.tablesorter; + +ts.alignChar = { + + init : function(table, c, wo) { + c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){ + var $this = $(this), + vars = { + column : this.column, + align : $this.attr(wo.alignChar_charAttrib), + alignIndex : parseInt( $this.attr(wo.alignChar_indexAttrib) || 0, 10), + adjust : parseFloat($this.attr(wo.alignChar_adjustAttrib)) || 0, + }; + vars.regex = new RegExp('\\' + vars.align, 'g'); + if (typeof vars.align !== 'undefined') { + wo.alignChar_savedVars[this.column] = vars; + ts.alignChar.setup(table, c, wo, vars); + } + }); + }, + + setup: function(table, c, wo, v){ + // do nothing for empty tables + if ($.isEmptyObject(c.cache)) { return; } + var tbodyIndex, rowIndex, start, end, last, index, rows, val, count, + len, wLeft, wRight, alignChar, $row, + left = [], + right = []; + for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){ + rows = c.cache[tbodyIndex]; + len = rows.normalized.length; + for (rowIndex = 0; rowIndex < len; rowIndex++) { + // set up to work with modified cache v2.16.0+ + $row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row; + val = $row.find('td').eq(v.column).text().replace(/[ ]/g, "\u00a0"); + // count how many "align" characters are in the string + count = (val.match( v.regex ) || []).length; + // set alignment @ alignIndex (one-based index) + if (count > 0 && v.alignIndex > 0) { + end = Math.min(v.alignIndex, count); + start = 0; + index = 0; + last = 0; + // find index of nth align character based on alignIndex (data-align-index) + while (start++ < end) { + last = val.indexOf(v.align, last + 1); + index = last < 0 ? index : last; + } + } else { + index = val.indexOf(v.align); + } + if ( index >= 0 ) { + left.push( val.substring(0, index) || '' ); + right.push( val.substring(index, val.length) || '' ); + } else { + // no align character found! + // put val in right or left based on the align index + left.push( (count >= 1 && v.alignIndex >= count) ? '' : val || '' ); + right.push( (count >= 1 && v.alignIndex >= count) ? val || '' : '' ); + } + } + } + + // find widest segments + wLeft = ($.extend([], left)).sort(function(a,b){ return b.length - a.length; })[0]; + wRight = ($.extend([], right)).sort(function(a,b){ return b.length - a.length; })[0]; + // calculate percentage widths + v.width = v.width || ( Math.floor(wLeft.length / (wLeft.length + wRight.length) * 100) + v.adjust ); + wLeft = 'min-width:' + v.width + '%'; + wRight = 'min-width:' + (100 - v.width) + '%'; + + for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){ + rows = c.cache[tbodyIndex]; + len = rows.normalized.length; + for (rowIndex = 0; rowIndex < len; rowIndex++) { + alignChar = $(wo.alignChar_wrap).length ? $(wo.alignChar_wrap).html(v.align)[0].outerHTML : v.align; + $row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row; + $row.find('td').eq(v.column).html( + '' + left[rowIndex] + '' + + '' + alignChar + + right[rowIndex].slice(v.align.length) + '' + ); + } + } + wo.alignChar_initialized = true; + + }, + remove: function(table, c, column){ + if ($.isEmptyObject(c.cache)) { return; } + var tbodyIndex, rowIndex, len, rows, $row, $cell; + for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++){ + rows = c.cache[tbodyIndex]; + len = rows.normalized.length; + for (rowIndex = 0; rowIndex < len; rowIndex++) { + $row = rows.row ? rows.row[rowIndex] : rows.normalized[rowIndex][c.columns].$row; + $cell = $row.find('td').eq(column); + $cell.html( $cell.text().replace(/\s/g, ' ') ); + } + } + } +}; + +ts.addWidget({ + id: 'alignChar', + priority: 100, + options: { + alignChar_wrap : '', + alignChar_charAttrib : 'data-align-char', + alignChar_indexAttrib : 'data-align-index', + alignChar_adjustAttrib : 'data-align-adjust' // percentage width adjustments + }, + init: function(table, thisWidget, c, wo){ + wo.alignChar_initialized = false; + wo.alignChar_savedVars = []; + ts.alignChar.init(table, c, wo); + c.$table.on('pagerEnd refreshAlign', function(){ + c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){ + ts.alignChar.remove(table, c, this.column); + }); + ts.alignChar.init(table, c, wo); + }); + }, + format : function(table, c, wo){ + // reinitialize in case table is empty when first initialized + if (!wo.alignChar_initialized) { + c.$table.trigger('refreshAlign'); + } + }, + remove : function(table, c, wo){ + c.$headers.filter('[' + wo.alignChar_charAttrib + ']').each(function(){ + ts.alignChar.remove(table, c, this.column); + }); + wo.alignChar_initialized = false; + } +}); + +})(jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-build-table.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-build-table.js new file mode 100644 index 000000000..1922cc5a5 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-build-table.js @@ -0,0 +1,441 @@ +/*! Build Table widget * by Rob Garrison */ +/*jshint browser:true, jquery:true, unused:false */ +/*global jQuery: false */ +;(function($){ +"use strict"; +var ts = $.tablesorter = $.tablesorter || {}, + + // build a table from data (requires existing tag) + // data.header contains an array of header titles + // data.rows contains an array of rows which contains an array of cells + bt = ts.buildTable = function(tar, c){ + // add table if one doesn't exist + var $tbl = tar.tagName === 'TABLE' ? $(tar) : $('
').appendTo(tar), + table = $tbl[0], + wo = c.widgetOptions = $.extend( true, {}, bt.defaults, c.widgetOptions ), + p = wo.build_processing, + typ = wo.build_type, + d = wo.build_source || c.data, + + // determine type: html, json, array, csv, object + runType = function(d){ + var t = $.type(d), + jq = d instanceof jQuery; + // run any processing if set + if ( typeof p === 'function' ) { d = p(d, wo); } + // store processed data in table.config.data + c.data = d; + // String (html or unprocessed json) or jQuery object + if ( jq || t === 'string' ) { + // look for closing tag, then we have an HTML string + if ( jq || /<\s*\/tr\s*>/.test(d) ) { + return bt.html( table, d, wo ); + } + try { + d = $.parseJSON(d); + if (d) { + // valid JSON! + return bt.object( table, d, wo ); + } + } catch(ignore) {} + // fall through in case it's a csv string + } + // Array + if (t === 'array' || t === 'string' || typ === 'array' || typ === 'csv') { + // build table using an array (csv & array combined script) + return bt.csv( table, d, wo ); + } + // if we got here, it's an object, or nothing + return bt.object( table, d, wo ); + }; + + // store config + table.config = c; + + // even if wo.build_type is undefined, we can try to figure out the type + if ( !ts.buildTable.hasOwnProperty(typ) && typ !== '' ) { + if (c.debug) { ts.log('aborting build table widget, incorrect build type'); } + return false; + } + + if ( d instanceof jQuery ) { + // get data from within a jQuery object (csv) + runType( $.trim( d.html() ) ); + } else if ( d && ( d.hasOwnProperty('url') || typ === 'json' ) ) { + // load data via ajax + $.ajax( wo.build_source ) + .done(function(data) { + runType(data); + }) + .fail(function( jqXHR, textStatus, errorThrown) { + if (c.debug) { ts.log('aborting build table widget, failed ajax load'); } + $tbl.html(''); + }); + } else { + runType(d); + } + }; + + bt.defaults = { + // *** build widget core *** + build_type : '', // array, csv, object, json, html + build_source : '', // array, object, jQuery Object or ajaxObject { url: '', dataType: 'json' }, + build_processing : null, // function that returns a useable build_type (e.g. string to array) + build_complete : 'tablesorter-build-complete', // triggered event when build completes + + // *** CSV & Array *** + build_headers : { + rows : 1, // Number of header rows from the csv + classes : [], // Header classes to apply to cells + text : [], // Header cell text + widths : [] // set header cell widths (set in colgroup) + }, + build_footers : { + rows : 1, // Number of header rows from the csv + classes : [], // Footer classes to apply to cells + text : [] // Footer cell text + }, + build_numbers : { + addColumn : false, // include row numbering column? + sortable : false // make column sortable? + }, + + // *** CSV only options *** + build_csvStartLine : 0, // line within the csv to start adding to table + build_csvSeparator : ",", // csv separator + + // *** build object options *** + build_objectRowKey : 'rows', // object key containing table rows + build_objectCellKey : 'cells', // object key containing table cells (within the rows object) + build_objectHeaderKey : 'headers', // object key containing table headers + build_objectFooterKey : 'footers' // object key containing table footers + }; + + bt.build = { + colgroup : function(widths) { + var t = ''; + // add colgroup if widths set + if (widths && widths.length) { + t += ''; + $.each(widths, function(i, w){ + t += ''; + }); + t += ''; + } + return t; + }, + // d = cell data; typ = 'th' or 'td'; first = save widths from first header row only + cell : function(d, wo, typ, col, first){ + var j, $td, + $col = first ? $('') : '', + cls = wo.build_headers.classes, + cw = wo.build_headers.widths; + // d is just an array + if (/string|number/.test(typeof d)) { + // add classes from options, but not text + $td = $('<' + typ + (cls && cls[col] ? ' class="' + cls[col] + '"' : '') + '>' + d + ''); + // get widths from options (only from first row) + if (first && cw && cw[col]) { + $col.width(cw[col] || ''); + } + } else { + // assume we have an object + $td = $('<' + typ + '>'); + for (j in d) { + if (d.hasOwnProperty(j)){ + if (j === 'text' || j === 'html') { + $td[j]( d[j] ); + } else if (first && j === 'width') { + // set column width, but only from first row + $col.width(d[j] || ''); + } else { + $td.attr(j, d[j]); + } + } + } + } + return [ $td, $col ]; + }, + // h1 = header text from data + header : function(h1, wo){ + var h2 = wo.build_headers.text, + cls = wo.build_headers.classes, + t = '' + (wo.build_numbers.addColumn ? '' + wo.build_numbers.addColumn + '' : ''); + $.each(h1, function(i, h) { + t += '' + + (h2 && h2[i] ? h2[i] : h) + ''; + }); + return t + ''; + }, + rows : function(items, txt, c, wo, num, ftr){ + var h = (ftr ? 'th' : 'td'), + t = '' + (wo.build_numbers.addColumn ? '<' + h + '>' + (ftr ? '' : num) + '' : ''); + $.each(items, function(i, item) { + t += '<' + (ftr ? h + (c && c[i] ? ' class="' + c[i] + '"' : '') : h) + '>' + + (ftr && txt && txt.length && txt[i] ? txt[i] : item) + ''; + }); + return t + ''; + } + }; + + bt.buildComplete = function(table, wo){ + $(table).trigger(wo.build_complete); + ts.setup(table, table.config); + }; + + /* ==== Array example ==== + [ + [ "header1", "header2", ... "headerN" ], + [ "row1cell1", "row1cell2", ... "row1cellN" ], + [ "row2cell1", "row2cell2", ... "row2cellN" ], + ... + [ "rowNcell1", "rowNcell2", ... "rowNcellN" ] + ] + */ + bt.array = function(table, data, wo) { + return bt.csv(table, data, wo); + }; + + /* ==== CSV example ==== + ID, Name, Age, Date + A42b, Parker, 28, "Jul 6, 2006 8:14 AM" + A255, Hood, 33, "Dec 10, 2002 5:14 AM" + A33, Kent, 18, "Jan 12, 2003 11:14 AM" + A1, Franklin, 45, "Jan 18, 2001 9:12 AM" + A102, Evans, 22, "Jan 18, 2007 9:12 AM" + A42a, Everet, 22, "Jan 18, 2007 9:12 AM" + ID, Name, Age, Date + */ + // Adapted & modified from csvToTable.js by Steve Sobel + // MIT license: https://code.google.com/p/jquerycsvtotable/ + bt.csv = function(table, data, wo) { + var c, h, + csv = wo.build_type === 'csv' || typeof data === 'string', + $t = $(table), + lines = csv ? data.replace('\r','').split('\n') : data, + len = lines.length, + printedLines = 0, + infooter = false, + r = wo.build_headers.rows + (csv ? wo.build_csvStartLine : 0), + f = wo.build_footers.rows, + headerCount = 0, + error = '', + items, + tableHTML = bt.build.colgroup( wo.build_headers.widths ) + ''; + + $.each(lines, function(n, line) { + if ( n >= len - f ) { infooter = true; } + // build header + if ( (csv ? n >= wo.build_csvStartLine : true) && ( n < r ) ) { + h = csv ? bt.splitCSV( line, wo.build_csvSeparator ) : line; + headerCount = h.length; + tableHTML += bt.build.header(h, wo); + } else if ( n >= r ) { + // build tbody & tfoot rows + if (n === r) { + tableHTML += ''; + } + items = csv ? bt.splitCSV( line, wo.build_csvSeparator ) : line; + if (infooter && f > 0) { + tableHTML += (n === len - f ? '' : '') + + (n === len ? '' : ''); + } + if (items.length > 1) { + printedLines++; + if ( items.length !== headerCount ) { + error += 'error on line ' + n + ': Item count (' + items.length + + ') does not match header count (' + headerCount + ') \n'; + } + c = infooter ? wo.build_footers.classes : ''; + tableHTML += bt.build.rows(items, wo.build_footers.text, c, wo, printedLines, infooter); + } + } + }); + tableHTML += (f > 0 ? '' : ''); + if (error) { + $t.html(error); + } else { + $t.html(tableHTML); + bt.buildComplete(table, wo); + } + }; + + // CSV Parser by Brian Huisman (http://www.greywyvern.com/?post=258) + bt.splitCSV = function(str, sep) { + var x, tl, + thisCSV = $.trim(str).split(sep = sep || ","); + for ( x = thisCSV.length - 1; x >= 0; x-- ) { + if ( thisCSV[x].replace(/\"\s+$/, '"').charAt(thisCSV[x].length - 1) === '"' ) { + if ( (tl = thisCSV[x].replace(/^\s+\"/, '"')).length > 1 && tl.charAt(0) === '"' ) { + thisCSV[x] = thisCSV[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"'); + } else if (x) { + thisCSV.splice(x - 1, 2, [thisCSV[x - 1], thisCSV[x]].join(sep)); + } else { + thisCSV = thisCSV.shift().split(sep).concat(thisCSV); + } + } else { + thisCSV[x].replace(/""/g, '"'); + } + } + return thisCSV; + }; + + // data may be a jQuery object after processing + bt.html = function(table, data, wo) { + var $t = $(table); + if ( data instanceof jQuery ) { + $t.empty().append(data); + } else { + $t.html(data); + } + bt.buildComplete(table, wo); + }; + +/* ==== Object example ==== + data : { + headers : [ + [ + { text: 'First Name', class: 'fname', width: '20%' }, // row 1 cell 1 + 'Last Name', + { text: 'Age', class: 'age', 'data-sorter' : false }, + 'Total', + { text: 'Discount', class : 'sorter-false' }, + { text: 'Date', class : 'date' } // row 1 cell 6 + ] + ], + footers : 'clone', // clone headers or assign array like headers + rows : [ + // TBODY 1 + [ 'Peter', 'Parker', 28, '$9.99', '20%', 'Jul 6, 2006 8:14 AM' ], // row 1 + [ 'John', 'Hood', 33, '$19.99', '25%', 'Dec 10, 2002 5:14 AM' ], // row 2 + [ 'Clark', 'Kent', 18, '$15.89', '44%', 'Jan 12, 2003 11:14 AM' ], // row 3 + + // TBODY 2 + { newTbody: true, class: 'tablesorter-infoOnly' }, + { cells : [ { text: 'Info Row', colSpan: 6 } ] }, // row 4 + + // TBODY 3 + { newTbody: true }, + [ 'Bruce', 'Evans', 22, '$13.19', '11%', 'Jan 18, 2007 9:12 AM' ], // row 5 + [ 'Brice', 'Almighty', 45, '$153.19', '44%', 'Jan 18, 2001 9:12 AM' ], // row 6 + + { class: 'specialRow', // row 7 + cells: [ + { text: 'Fred', class: 'fname' }, + { text: 'Smith', class: 'lname' }, + { text: 18, class: 'age', 'data-info': 'fake ID!, he is really 16' }, + { text: '$22.44', class: 'total' }, + { text: '8%', class: 'discount' }, + { text: 'Aug 20, 2012 10:15 AM', class: 'date' } + ], + 'data-info' : 'This row likes turtles' + } + ] + } +*/ + bt.object = function(table, data, wo) { + // "rows" + var j, l, t, $c, $t, $tb, $tr, + c = table.config, + kh = wo.build_objectHeaderKey, + kr = wo.build_objectRowKey, + h = data.hasOwnProperty(kh) && !$.isEmptyObject(data.kh) ? data.kh : data.hasOwnProperty('headers') ? data.headers : false, + r = data.hasOwnProperty(kr) && !$.isEmptyObject(data.kr) ? data.kr : data.hasOwnProperty('rows') ? data.rows : false; + + if (!h || !r || h.length === 0 || r.length === 0) { + if (c.debug) { ts.log('aborting build table widget, missing data for object build'); } + return false; + } + + $c = $(''); + $t = $('
' + jqXHR.status + ' ' + textStatus + '
'); + + // Build thead + // h = [ ['headerRow1Cell1', 'headerRow1Cell2', ... 'headerRow1CellN' ], ['headerRow2Cell1', ... ] ] + // or h = [ [ { text: 'firstCell', class: 'fc', width: '20%' }, ..., { text: 'last Cell' } ], [ /* second row */ ] ] + $.each(h, function(i, d){ + $tr = $('').appendTo( $t.find('thead') ); + l = d.length; // header row + for ( j = 0; j < l; j++ ) { + // cell(cellData, widgetOptions, 'th', first row) + t = bt.build.cell(d[j], wo, 'th', j, i === 0); + if (t[0] && t[0].length) { t[0].appendTo( $tr ); } // add cell + if (i === 0 && t[1]) { t[1].appendTo( $c ); } // add col to colgroup + } + }); + if ($c.find('col[style]').length) { + // add colgroup if it contains col elements + $t.prepend( $c ); + } + + $tb = $(''); + // Build tbody + $.each(r, function(i, d){ + t = $.type(d) === 'object'; + // add new tbody + if (t && d.newTbody) { + $tb = $('').appendTo( $t ); + for (j in d) { + if (d.hasOwnProperty(j) && j !== 'newTbody'){ + $tb.attr(j, d[j]); + } + } + } else { + if (i === 0) { + // add tbody, if the first item in the object isn't a call for a new tbody + $tb.appendTo( $t ); + } + + $tr = $('').appendTo( $tb ); + if (t) { + // row defined by object + for (j in d) { + if (d.hasOwnProperty(j) && j !== wo.build_objectCellKey){ + $tr.attr(j, d[j]); + } + } + if (d.hasOwnProperty(wo.build_objectCellKey)) { + // cells contains each cell info + d = d.cells; + } + } + + l = d.length; + for ( j = 0; j < l; j++ ) { + // cell(cellData, widgetOptions, 'td') + $c = bt.build.cell(d[j], wo, 'td', j); + if ($c[0] && $c[0].length) { $c[0].appendTo( $tr ); } // add cell + } + } + }); + + // add footer + if (data.hasOwnProperty(wo.build_objectFooterKey)) { + t = data[wo.build_objectFooterKey]; + if (t === 'clone') { + $c = $t.find('thead').html(); + $t.append('' + $c + ''); + } else { + $c = $('').appendTo( $t ); + $.each(t, function(i, d) { + $tr = $('').appendTo( $c ); + l = d.length; // footer cells + for ( j = 0; j < l; j++ ) { + // cell(cellData, widgetOptions, 'th') + $tb = bt.build.cell(d[j], wo, 'th', j); + if ($tb[0] && $tb[0].length) { $tb[0].appendTo( $tr ); } // add cell + } + }); + } + } + + $(table).html( $t.html() ); + bt.buildComplete(table, wo); + }; + + bt.ajax = bt.json = function(table, data, wo) { + return bt.object(table, data, wo); + }; + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-columnSelector.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-columnSelector.js new file mode 100644 index 000000000..89d627947 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-columnSelector.js @@ -0,0 +1,306 @@ +/* Column Selector/Responsive table widget (beta) for TableSorter 3/31/2014 (v2.15.12) + * Requires tablesorter v2.8+ and jQuery 1.7+ + * by Justin Hallett & Rob Garrison + */ +/*jshint browser:true, jquery:true, unused:false */ +/*global jQuery: false */ +;(function($){ +"use strict"; + +var ts = $.tablesorter, +namespace = '.tscolsel', +tsColSel = ts.columnSelector = { + + queryAll : '@media only all { [columns] { display: none; } }', + queryBreak : '@media screen and (min-width: [size]) { [columns] { display: table-cell; } }', + + init: function(table, c, wo) { + var $t, colSel; + + // abort if no input is contained within the layout + $t = $(wo.columnSelector_layout); + if (!$t.find('input').add( $t.filter('input') ).length) { + if (c.debug) { + ts.log('*** ERROR: Column Selector aborting, no input found in the layout! ***'); + } + return; + } + + // unique table class name + c.tableId = 'tablesorter' + new Date().getTime(); + c.$table.addClass( c.tableId ); + + // build column selector/state array + colSel = c.selector = { $container : $(wo.columnSelector_container || '
') }; + colSel.$style = $('').prop('disabled', true).appendTo('head'); + colSel.$breakpoints = $('').prop('disabled', true).appendTo('head'); + + colSel.isInitializing = true; + tsColSel.setupSelector(table, c, wo); + + if (wo.columnSelector_mediaquery) { + tsColSel.setupBreakpoints(c, wo); + } + + colSel.isInitializing = false; + if (colSel.$container.length) { + tsColSel.updateCols(c, wo); + } + + }, + + setupSelector: function(table, c, wo) { + var name, + colSel = c.selector, + $container = colSel.$container, + useStorage = wo.columnSelector_saveColumns && ts.storage, + // get stored column states + saved = useStorage ? ts.storage( table, 'tablesorter-columnSelector' ) : [], + state = useStorage ? ts.storage( table, 'tablesorter-columnSelector-auto') : {}; + + // initial states + colSel.auto = $.isEmptyObject(state) || $.type(state.auto) !== "boolean" ? wo.columnSelector_mediaqueryState : state.auto; + colSel.states = []; + colSel.$column = []; + colSel.$wrapper = []; + colSel.$checkbox = []; + // populate the selector container + c.$table.children('thead').find('tr:first th', table).each(function() { + var $this = $(this), + // if no data-priority is assigned, default to 1, but don't remove it from the selector list + priority = $this.attr(wo.columnSelector_priority) || 1, + colId = $this.attr('data-column'), + state = ts.getData(this, c.headers[colId], 'columnSelector'); + + + // if this column not hidable at all + // include getData check (includes "columnSelector-false" class, data attribute, etc) + if ( isNaN(priority) && priority.length > 0 || state === 'disable' || + ( wo.columnSelector_columns[colId] && wo.columnSelector_columns[colId] === 'disable') ) { + return true; // goto next + } + + // set default state; storage takes priority + colSel.states[colId] = saved && typeof(saved[colId]) !== 'undefined' ? + saved[colId] : typeof(wo.columnSelector_columns[colId]) !== 'undefined' ? + wo.columnSelector_columns[colId] : (state === 'true' || !(state === 'false')); + colSel.$column[colId] = $(this); + + // set default col title + name = $this.attr(wo.columnSelector_name) || $this.text(); + + if ($container.length) { + colSel.$wrapper[colId] = $(wo.columnSelector_layout.replace(/\{name\}/g, name)).appendTo($container); + colSel.$checkbox[colId] = colSel.$wrapper[colId] + // input may not be wrapped within the layout template + .find('input').add( colSel.$wrapper[colId].filter('input') ) + .attr('data-column', colId) + .prop('checked', colSel.states[colId]) + .on('change', function(){ + colSel.states[colId] = this.checked; + tsColSel.updateCols(c, wo); + }).change(); + } + }); + + }, + + setupBreakpoints: function(c, wo){ + var colSel = c.selector; + + // add responsive breakpoints + if (wo.columnSelector_mediaquery) { + // used by window resize function + colSel.lastIndex = -1; + wo.columnSelector_breakpoints.sort(); + tsColSel.updateBreakpoints(c, wo); + c.$table.off('updateAll' + namespace).on('updateAll' + namespace, function(){ + tsColSel.updateBreakpoints(c, wo); + tsColSel.updateCols(c, wo); + }); + } + + if (colSel.$container.length) { + // Add media queries toggle + if (wo.columnSelector_mediaquery) { + colSel.$auto = $( wo.columnSelector_layout.replace(/\{name\}/g, wo.columnSelector_mediaqueryName) ).prependTo(colSel.$container); + colSel.$auto + // needed in case the input in the layout is not wrapped + .find('input').add( colSel.$auto.filter('input') ) + .attr('data-column', 'auto') + .prop('checked', colSel.auto) + .on('change', function(){ + colSel.auto = this.checked; + $.each( colSel.$checkbox, function(i, $cb){ + if ($cb) { + $cb[0].disabled = colSel.auto; + colSel.$wrapper[i].toggleClass('disabled', colSel.auto); + } + }); + if (wo.columnSelector_mediaquery) { + tsColSel.updateBreakpoints(c, wo); + } + tsColSel.updateCols(c, wo); + // copy the column selector to a popup/tooltip + if (c.selector.$popup) { + c.selector.$popup.find('.tablesorter-column-selector') + .html( colSel.$container.html() ) + .find('input').each(function(){ + var indx = $(this).attr('data-column'); + $(this).prop( 'checked', indx === 'auto' ? colSel.auto : colSel.states[indx] ); + }); + } + if (wo.columnSelector_saveColumns && ts.storage) { + ts.storage( c.$table[0], 'tablesorter-columnSelector-auto', { auto : colSel.auto } ); + } + }).change(); + } + // Add a bind on update to re-run col setup + c.$table.off('update' + namespace).on('update' + namespace, function() { + tsColSel.updateCols(c, wo); + }); + } + }, + + updateBreakpoints: function(c, wo) { + var priority, column, breaks, + colSel = c.selector, + prefix = '.' + c.tableId, + mediaAll = [], + breakpts = ''; + if (wo.columnSelector_mediaquery && !colSel.auto) { + colSel.$breakpoints.prop('disabled', true); + colSel.$style.prop('disabled', false); + return; + } + + // only 6 breakpoints (same as jQuery Mobile) + for (priority = 0; priority < 6; priority++){ + /*jshint loopfunc:true */ + breaks = []; + c.$headers.filter('[' + wo.columnSelector_priority + '=' + (priority + 1) + ']').each(function(){ + column = parseInt($(this).attr('data-column'), 10) + 1; + breaks.push(prefix + ' tr th:nth-child(' + column + ')'); + breaks.push(prefix + ' tr td:nth-child(' + column + ')'); + }); + if (breaks.length) { + mediaAll = mediaAll.concat( breaks ); + breakpts += tsColSel.queryBreak + .replace(/\[size\]/g, wo.columnSelector_breakpoints[priority]) + .replace(/\[columns\]/g, breaks.join(',')); + } + } + if (colSel.$style) { + colSel.$style.prop('disabled', true); + } + colSel.$breakpoints + .prop('disabled', false) + .html( tsColSel.queryAll.replace(/\[columns\]/g, mediaAll.join(',')) + breakpts ); + }, + + updateCols: function(c, wo) { + if (wo.columnSelector_mediaquery && c.selector.auto || c.selector.isInitializing) { + return; + } + var column, + colSel = c.selector, + styles = [], + prefix = '.' + c.tableId; + colSel.$container.find('input[data-column]').filter('[data-column!="auto"]').each(function(){ + if (!this.checked) { + column = parseInt( $(this).attr('data-column'), 10 ) + 1; + styles.push(prefix + ' tr th:nth-child(' + column + ')'); + styles.push(prefix + ' tr td:nth-child(' + column + ')'); + } + }); + if (wo.columnSelector_mediaquery){ + colSel.$breakpoints.prop('disabled', true); + } + if (colSel.$style) { + colSel.$style.prop('disabled', false).html( styles.length ? styles.join(',') + ' { display: none; }' : '' ); + } + if (wo.columnSelector_saveColumns && ts.storage) { + ts.storage( c.$table[0], 'tablesorter-columnSelector', colSel.states ); + } + }, + + attachTo : function(table, elm) { + table = $(table)[0]; + var colSel, wo, indx, + c = table.config, + $popup = $(elm); + if ($popup.length && c) { + if (!$popup.find('.tablesorter-column-selector').length) { + // add a wrapper to add the selector into, in case the popup has other content + $popup.append(''); + } + colSel = c.selector; + wo = c.widgetOptions; + $popup.find('.tablesorter-column-selector') + .html( colSel.$container.html() ) + .find('input').each(function(){ + var indx = $(this).attr('data-column'); + $(this).prop( 'checked', indx === 'auto' ? colSel.auto : colSel.states[indx] ); + }); + colSel.$popup = $popup.on('change', 'input', function(){ + // data input + indx = $(this).attr('data-column'); + // update original popup + colSel.$container.find('input[data-column="' + indx + '"]') + .prop('checked', this.checked) + .trigger('change'); + }); + } + } + +}; + +ts.addWidget({ + id: "columnSelector", + priority: 10, + options: { + // target the column selector markup + columnSelector_container : null, + // column status, true = display, false = hide + // disable = do not display on list + columnSelector_columns : {}, + // remember selected columns + columnSelector_saveColumns: true, + + // container layout + columnSelector_layout : '', + // data attribute containing column name to use in the selector container + columnSelector_name : 'data-selector-name', + + /* Responsive Media Query settings */ + // enable/disable mediaquery breakpoints + columnSelector_mediaquery: true, + // toggle checkbox name + columnSelector_mediaqueryName: 'Auto: ', + // breakpoints checkbox initial setting + columnSelector_mediaqueryState: true, + // responsive table hides columns with priority 1-6 at these breakpoints + // see http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/#Applyingapresetbreakpoint + // *** set to false to disable *** + columnSelector_breakpoints : [ '20em', '30em', '40em', '50em', '60em', '70em' ], + // data attribute containing column priority + // duplicates how jQuery mobile uses priorities: + // http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/ + columnSelector_priority : 'data-priority' + + }, + init: function(table, thisWidget, c, wo) { + tsColSel.init(table, c, wo); + }, + remove: function(table, c){ + var csel = c.selector; + csel.$container.empty(); + csel.$popup.empty(); + csel.$style.remove(); + csel.$breakpoints.remove(); + c.$table.off('updateAll' + namespace + ' update' + namespace); + } + +}); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-cssStickyHeaders.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-cssStickyHeaders.js new file mode 100644 index 000000000..94bf6a11e --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-cssStickyHeaders.js @@ -0,0 +1,67 @@ +/*! tablesorter CSS Sticky Headers widget - updated 12/17/2013 (v2.15.0) +* Requires a modern browser, tablesorter v2.8+ +*/ +/*global jQuery: false, unused:false */ +;(function($){ + "use strict"; + + $.tablesorter.addWidget({ + id: "cssStickyHeaders", + priority: 10, + options: { + cssStickyHeaders_offset : 0, + cssStickyHeaders_addCaption : false, + cssStickyHeaders_attachTo : null, + cssStickyHeaders_zIndex : 10 + }, + init : function(table, thisWidget, c, wo) { + var $attach = $(wo.cssStickyHeaders_attachTo), + namespace = '.cssstickyheader', + $thead = c.$table.children('thead'), + $caption = c.$table.find('caption'), + $win = $attach.length ? $attach : $(window); + $win.bind('scroll resize '.split(' ').join(namespace + ' '), function() { + var top = $attach.length ? $attach.offset().top : $win.scrollTop(), + // add caption height; include table padding top & border-spacing or text may be above the fold (jQuery UI themes) + // border-spacing needed in Firefox, but not webkit... not sure if I should account for that + captionTop = wo.cssStickyHeaders_addCaption ? $caption.outerHeight(true) + + (parseInt(c.$table.css('padding-top'), 10) || 0) + (parseInt(c.$table.css('border-spacing'), 10) || 0) : 0, + bottom = c.$table.height() - $thead.height() - (c.$table.find('tfoot').height() || 0) - captionTop, + deltaY = top - $thead.offset().top + (parseInt(c.$table.css('border-top-width'), 10) || 0) + + (wo.cssStickyHeaders_offset || 0) + captionTop, + finalY = (deltaY > 0 && deltaY <= bottom ? deltaY : 0), + // IE can only transform header cells - fixes #447 thanks to @gakreol! + $cells = $thead.children().children(); + if (wo.cssStickyHeaders_addCaption) { + $cells = $cells.add($caption); + } + $cells.css({ + "position" : "relative", + "z-index" : wo.cssStickyHeaders_zIndex, + "transform" : finalY === 0 ? "" : "translate(0px," + finalY + "px)", + "-ms-transform" : finalY === 0 ? "" : "translate(0px," + finalY + "px)", + "-webkit-transform" : finalY === 0 ? "" : "translate(0px," + finalY + "px)" + }); + }); + c.$table.bind('filterEnd', function() { + // scroll top of table into view + window.scrollTo(0, c.$table.position().top); + }); + + }, + remove: function(table, c, wo){ + var namespace = '.cssstickyheader'; + $(window).unbind('scroll resize '.split(' ').join(namespace + ' ')); + c.$table + .unbind('update updateAll '.split(' ').join(namespace + ' ')) + .children('thead, caption').css({ + "position" : "", + "z-index" : "", + "transform" : "", + "-ms-transform" : "", + "-webkit-transform" : "" + }); + } + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-editable.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-editable.js new file mode 100644 index 000000000..44b95eff0 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-editable.js @@ -0,0 +1,89 @@ +/*! tablesorter Editable Content widget - updated 1/24/2014 (core v2.15.0) + * Requires tablesorter v2.8+ and jQuery 1.7+ + * by Rob Garrison + */ +/*jshint browser:true, jquery:true, unused:false */ +/*global jQuery: false */ +;(function($){ + "use strict"; + + $.tablesorter.addWidget({ + id: 'editable', + options : { + editable_columns : [], + editable_enterToAccept : true, + editable_autoResort : false, + editable_noEdit : 'no-edit', + editable_editComplete : 'editComplete' + }, + init: function(table, thisWidget, c, wo){ + if (!wo.editable_columns.length) { return; } + var indx, tmp, $t, cols = []; + if (wo.editable_columns.indexOf('-') >= 0) { + // editable_columns can contain a range string (i.e. "2-4" ) + tmp = wo.editable_columns.split('-'); + indx = parseInt(tmp[0],10) || 0; + tmp = parseInt(tmp[1],10) || (c.columns - 1); + if (tmp > c.columns) { tmp = c.columns - 1; } + for (; indx <= tmp; indx++) { + cols.push('td:nth-child(' + (indx + 1) + ')'); + } + } else if ($.isArray(wo.editable_columns)) { + $.each(wo.editable_columns, function(i, col){ + cols.push('td:nth-child(' + (col + 1) + ')'); + }); + } + // IE does not allow making TR/TH/TD cells directly editable (issue #404) + // so add a div or span inside ( it's faster than using wrapInner() ) + c.$tbodies.find( cols.join(',') ).not('.' + wo.editable_noEdit).each(function(){ + // test for children, if they exist, then make the children editable + $t = $(this); + ( $t.children().length ? $t.children() : $t ).prop('contenteditable', true); + }); + c.$tbodies + .on('mouseleave.tseditable', function(){ + if (c.$table.data('contentFocused')) { + $(':focus').trigger('blur'); + } + }) + .on('focus.tseditable', '[contenteditable]', function(){ + c.$table.data('contentFocused', true); + var $this = $(this), v = $this.html(); + if (wo.editable_enterToAccept) { + // prevent enter from adding into the content + $this.on('keydown.tseditable', function(e){ + if (e.which === 13) { + e.preventDefault(); + } + }); + } + $this.data({ before : v, original: v }); + }) + .on('blur focusout keyup '.split(' ').join('.tseditable '), '[contenteditable]', function(e){ + if (!c.$table.data('contentFocused')) { return; } + var $this = $(e.target), t; + if (e.which === 27) { + // user cancelled + $this.html( $this.data('original') ).trigger('blur.tseditable'); + c.$table.data('contentFocused', false); + return false; + } + t = e.type !== 'keyup' || (wo.editable_enterToAccept && e.which === 13); + // change if new or user hits enter (if option set) + if ($this.data('before') !== $this.html() || t) { + $this.data('before', $this.html()).trigger('change'); + if (t) { + c.$table + .data('contentFocused', false) + .trigger('updateCell', [ $this.closest('td'), wo.editable_autoResort, function(table){ + $this.trigger( wo.editable_editComplete ); + c.$table.trigger('applyWidgets'); + } ]); + $this.trigger('blur.tseditable'); + } + } + }); + } + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-grouping.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-grouping.js new file mode 100644 index 000000000..7813b363c --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-grouping.js @@ -0,0 +1,249 @@ +/*! tablesorter Grouping widget - updated 3/7/2014 (core v2.15.6) + * Requires tablesorter v2.8+ and jQuery 1.7+ + * by Rob Garrison + */ +/*jshint browser:true, jquery:true, unused:false */ +/*global jQuery: false */ +;(function($){ +"use strict"; +var ts = $.tablesorter; + +ts.grouping = { + + types : { + number : function(c, $column, txt, num, group){ + var value, word; + if (num > 1 && txt !== '') { + if ($column.hasClass(ts.css.sortAsc)) { + value = Math.floor(parseFloat(txt)/num) * num; + return value > parseFloat(group || 0) ? value : parseFloat(group || 0); + } else { + value = Math.ceil(parseFloat(txt)/num) * num; + return value < parseFloat(group || num) - value ? parseFloat(group || num) - value : value; + } + } else { + word = (txt + '').match(/\d+/g); + return word && word.length >= num ? word[num - 1] : txt || ''; + } + }, + separator : function(c, $column, txt, num){ + var word = (txt + '').split(c.widgetOptions.group_separator); + return $.trim(word && num > 0 && word.length >= num ? word[(num || 1) - 1] : ''); + }, + word : function(c, $column, txt, num){ + var word = (txt + ' ').match(/\w+/g); + return word && word.length >= num ? word[num - 1] : txt || ''; + }, + letter : function(c, $column, txt, num){ + return txt ? (txt + ' ').substring(0, num) : ''; + }, + date : function(c, $column, txt, part, group){ + var wo = c.widgetOptions, + time = new Date(txt || ''), + hours = time.getHours(); + return part === 'year' ? time.getFullYear() : + part === 'month' ? wo.group_months[time.getMonth()] : + part === 'day' ? wo.group_months[time.getMonth()] + ' ' + time.getDate() : + part === 'week' ? wo.group_week[time.getDay()] : + part === 'time' ? ('00' + (hours > 12 ? hours - 12 : hours === 0 ? hours + 12 : hours)).slice(-2) + ':' + + ('00' + time.getMinutes()).slice(-2) + ' ' + ('00' + wo.group_time[hours >= 12 ? 1 : 0]).slice(-2) : + wo.group_dateString(time); + } + }, + + update : function(table, c, wo){ + if ($.isEmptyObject(c.cache)) { return; } + var rowIndex, tbodyIndex, currentGroup, $rows, groupClass, grouping, time, cache, saveName, direction, + lang = wo.grouping_language, + group = '', + savedGroup = false, + column = c.sortList[0] ? c.sortList[0][0] : -1; + c.$table + .find('tr.group-hidden').removeClass('group-hidden').end() + .find('tr.group-header').remove(); + if (wo.group_collapsible) { + // clear pager saved spacer height (in case the rows are collapsed) + c.$table.data('pagerSavedHeight', 0); + } + if (column >= 0 && !c.$headers.filter('[data-column="' + column + '"]:last').hasClass('group-false')) { + if (c.debug){ time = new Date(); } + wo.group_currentGroup = ''; // save current groups + wo.group_currentGroups = {}; + + // group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}" + groupClass = (c.$headers.filter('[data-column="' + column + '"]:last').attr('class') || '').match(/(group-\w+(-\w+)?)/g); + // grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ] + grouping = groupClass ? groupClass[0].split('-') : ['group','letter',1]; // default to letter 1 + + // save current grouping + if (wo.group_collapsible && wo.group_saveGroups && ts.storage) { + wo.group_currentGroups = ts.storage( table, 'tablesorter-groups' ) || {}; + // include direction when grouping numbers > 1 (reversed direction shows different range values) + direction = (grouping[1] === 'number' && grouping[2] > 1) ? 'dir' + c.sortList[0][1] : ''; + // combine column, sort direction & grouping as save key + saveName = wo.group_currentGroup = '' + column + direction + grouping.join(''); + if (!wo.group_currentGroups[saveName]) { + wo.group_currentGroups[saveName] = []; + } else { + savedGroup = true; + } + } + for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) { + cache = c.cache[tbodyIndex].normalized; + group = ''; // clear grouping across tbodies + $rows = c.$tbodies.eq(tbodyIndex).children('tr').not('.' + c.cssChildRow); + for (rowIndex = 0; rowIndex < $rows.length; rowIndex++) { + if ( $rows.eq(rowIndex).is(':visible') ) { + // fixes #438 + if (ts.grouping.types[grouping[1]]) { + currentGroup = cache[rowIndex] ? + ts.grouping.types[grouping[1]]( c, c.$headers.filter('[data-column="' + column + '"]:last'), cache[rowIndex][column], /date/.test(groupClass) ? + grouping[2] : parseInt(grouping[2] || 1, 10) || 1, group, lang ) : currentGroup; + if (group !== currentGroup) { + group = currentGroup; + // show range if number > 1 + if (grouping[1] === 'number' && grouping[2] > 1 && currentGroup !== '') { + currentGroup += ' - ' + (parseInt(currentGroup, 10) + + ((parseInt(grouping[2],10) - 1) * (c.$headers.filter('[data-column="' + column + '"]:last').hasClass(ts.css.sortAsc) ? 1 : -1))); + } + if ($.isFunction(wo.group_formatter)) { + currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup; + } + $rows.eq(rowIndex).before('' + (wo.group_collapsible ? '' : '') + '' + + currentGroup + ''); + if (wo.group_saveGroups && !savedGroup && wo.group_collapsed && wo.group_collapsible) { + // all groups start collapsed + wo.group_currentGroups[wo.group_currentGroup].push(currentGroup); + } + } + } + } + } + } + c.$table.find('tr.group-header') + .bind('selectstart', false) + .each(function(){ + var isHidden, $label, name, + $row = $(this), + $rows = $row.nextUntil('tr.group-header').filter(':visible'); + if (wo.group_count || $.isFunction(wo.group_callback)) { + $label = $row.find('.group-count'); + if ($label.length) { + if (wo.group_count) { + $label.html( wo.group_count.replace(/\{num\}/g, $rows.length) ); + } + if ($.isFunction(wo.group_callback)) { + wo.group_callback($row.find('td'), $rows, column, table); + } + } + } + if (wo.group_saveGroups && wo.group_currentGroups[wo.group_currentGroup].length) { + name = $row.find('.group-name').text().toLowerCase(); + isHidden = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] ) > -1; + $row.toggleClass('collapsed', isHidden); + $rows.toggleClass('group-hidden', isHidden); + } else if (wo.group_collapsed && wo.group_collapsible) { + $row.addClass('collapsed'); + $rows.addClass('group-hidden'); + } + }); + c.$table.trigger(wo.group_complete); + if (c.debug) { + $.tablesorter.benchmark("Applying groups widget: ", time); + } + } + }, + + bindEvents : function(table, c, wo){ + if (wo.group_collapsible) { + wo.group_currentGroups = []; + // .on() requires jQuery 1.7+ + c.$table.on('click toggleGroup', 'tr.group-header', function(event){ + event.stopPropagation(); + var isCollapsed, $groups, indx, + $this = $(this), + name = $this.find('.group-name').text().toLowerCase(); + // use shift-click to toggle ALL groups + if (event.type === 'click' && event.shiftKey) { + $this.siblings('.group-header').trigger('toggleGroup'); + } + $this.toggleClass('collapsed'); + // nextUntil requires jQuery 1.4+ + $this.nextUntil('tr.group-header').toggleClass('group-hidden', $this.hasClass('collapsed') ); + // save collapsed groups + if (wo.group_saveGroups && ts.storage) { + $groups = c.$table.find('.group-header'); + isCollapsed = $this.hasClass('collapsed'); + if (!wo.group_currentGroups[wo.group_currentGroup]) { + wo.group_currentGroups[wo.group_currentGroup] = []; + } + if (isCollapsed && wo.group_currentGroup) { + wo.group_currentGroups[wo.group_currentGroup].push( name ); + } else if (wo.group_currentGroup) { + indx = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] ); + if (indx > -1) { + wo.group_currentGroups[wo.group_currentGroup].splice( indx, 1 ); + } + } + ts.storage( table, 'tablesorter-groups', wo.group_currentGroups ); + } + }); + } + $(wo.group_saveReset).on('click', function(){ + ts.grouping.clearSavedGroups(table); + }); + c.$table.on('pagerChange.tsgrouping', function(){ + ts.grouping.update(table, c, wo); + }); + }, + + clearSavedGroups: function(table){ + if (table && ts.storage) { + ts.storage(table, 'tablesorter-groups', ''); + ts.grouping.update(table, table.config, table.config.widgetOptions); + } + } + +}; + +ts.addWidget({ + id: 'group', + priority: 100, + options: { + group_collapsible : true, // make the group header clickable and collapse the rows below it. + group_collapsed : false, // start with all groups collapsed + group_saveGroups : true, // remember collapsed groups + group_saveReset : null, // element to clear saved collapsed groups + group_count : ' ({num})', // if not false, the "{num}" string is replaced with the number of rows in the group + group_separator : '-', // group name separator; used when group-separator-# class is used. + group_formatter : null, // function(txt, column, table, c, wo) { return txt; } + group_callback : null, // function($cell, $rows, column, table){}, callback allowing modification of the group header labels + group_complete : 'groupingComplete', // event triggered on the table when the grouping widget has finished work + + // change these default date names based on your language preferences + group_months : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], + group_week : [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ], + group_time : [ 'AM', 'PM' ], + // this function is used when "group-date" is set to create the date string + // you can just return date, date.toLocaleString(), date.toLocaleDateString() or d.toLocaleTimeString() + // reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Conversion_getter + group_dateString : function(date) { return date.toLocaleString(); } + }, + init: function(table, thisWidget, c, wo){ + ts.grouping.bindEvents(table, c, wo); + }, + format: function(table, c, wo) { + ts.grouping.update(table, c, wo); + }, + remove : function(table, c, wo){ + c.$table + .off('click', 'tr.group-header') + .off('pagerChange.tsgrouping') + .find('.group-hidden').removeClass('group-hidden').end() + .find('tr.group-header').remove(); + } +}); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-headerTitles.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-headerTitles.js new file mode 100644 index 000000000..39d2970d7 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-headerTitles.js @@ -0,0 +1,91 @@ +/*! tablesorter headerTitles widget - updated 3/5/2014 (core v2.15.6) + * Requires tablesorter v2.8+ and jQuery 1.7+ + * by Rob Garrison + */ +/*jshint browser:true, jquery:true, unused:false */ +/*global jQuery: false */ +;(function($){ +"use strict"; +var ts = $.tablesorter; + + ts.addWidget({ + id: 'headerTitles', + options: { + // use aria-label text + // e.g. "First Name: Ascending sort applied, activate to apply a descending sort" + headerTitle_useAria : false, + // add tooltip class + headerTitle_tooltip : '', + // custom titles [ ascending, descending, unsorted ] + headerTitle_cur_text : [ ' sort: A - Z', ' sort: Z - A', 'ly unsorted' ], + headerTitle_cur_numeric : [ ' sort: 0 - 9', ' sort: 9 - 0', 'ly unsorted' ], + headerTitle_nxt_text : [ ' sort: A - Z', ' sort: Z - A', 'remove sort' ], + headerTitle_nxt_numeric : [ ' sort: 0 - 9', ' sort: 9 - 0', 'remove sort' ], + + // title display; {prefix} adds above prefix + // {type} adds the current sort order from above (text or numeric) + // {next} adds the next sort direction using the sort order above + headerTitle_output_sorted : 'current{current}; activate to {next}', + headerTitle_output_unsorted : 'current{current}; activate to {next} ', + headerTitle_output_nosort : 'No sort available', + // use this type to override the parser detection result + // e.g. use for numerically parsed columns (e.g. dates), but you + // want the user to see a text sort, e.g. [ 'text', 'numeric' ] + headerTitle_type : [], + // manipulate the title as desired + headerTitle_callback : null // function($cell, txt) { return txt; } + }, + init: function(table, thisWidget, c, wo){ + // force refresh + c.$table.on('refreshHeaderTitle', function(){ + thisWidget.format(table, c, wo); + }); + // add tooltip class + if ($.isArray(wo.headerTitle_tooltip)) { + c.$headers.each(function(){ + $(this).addClass( wo.headerTitle_tooltip[this.column] || '' ); + }); + } else if (wo.headerTitle_tooltip !== '') { + c.$headers.addClass( wo.headerTitle_tooltip ); + } + }, + format: function (table, c, wo) { + var txt; + c.$headers.each(function(){ + var t = this, + $this = $(this), + sortType = wo.headerTitle_type[t.column] || c.parsers[ t.column ].type || 'text', + sortDirection = $this.hasClass(ts.css.sortAsc) ? 0 : $this.hasClass(ts.css.sortDesc) ? 1 : 2, + sortNext = t.order[(t.count + 1) % (c.sortReset ? 3 : 2)]; + if (wo.headerTitle_useAria) { + txt = $this.hasClass('sorter-false') ? wo.headerTitle_output_nosort : $this.attr('aria-label') || ''; + } else { + txt = (wo.headerTitle_prefix || '') + // now deprecated + ($this.hasClass('sorter-false') ? wo.headerTitle_output_nosort : + ts.isValueInArray( t.column, c.sortList ) >= 0 ? wo.headerTitle_output_sorted : wo.headerTitle_output_unsorted); + txt = txt.replace(/\{(current|next|name)\}/gi, function(m){ + return { + '{name}' : $this.text(), + '{current}' : wo[ 'headerTitle_cur_' + sortType ][ sortDirection ] || '', + '{next}' : wo[ 'headerTitle_nxt_' + sortType ][ sortNext ] || '' + }[m.toLowerCase()]; + }); + } + $this.attr('title', $.isFunction(wo.headerTitle_callback) ? wo.headerTitle_callback($this, txt) : txt); + }); + }, + remove: function (table, c, wo) { + c.$headers.attr('title', ''); + c.$table.off('refreshHeaderTitle'); + // remove tooltip class + if ($.isArray(wo.headerTitle_tooltip)) { + c.$headers.each(function(){ + $(this).removeClass( wo.headerTitle_tooltip[this.column] || '' ); + }); + } else if (wo.headerTitle_tooltip !== '') { + c.$headers.removeClass( wo.headerTitle_tooltip ); + } + } + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-pager.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-pager.js new file mode 100644 index 000000000..5d2425746 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-pager.js @@ -0,0 +1,864 @@ +/* Pager widget (beta) for TableSorter 4/10/2014 (v2.15.14) */ +/*jshint browser:true, jquery:true, unused:false */ +;(function($){ +"use strict"; +var tsp, + ts = $.tablesorter; + +ts.addWidget({ + id: "pager", + priority: 55, // load pager after filter widget + options : { + // output default: '{page}/{totalPages}' + // possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} + pager_output: '{startRow} to {endRow} of {totalRows} rows', // '{page}/{totalPages}' + + // apply disabled classname to the pager arrows when the rows at either extreme is visible + pager_updateArrows: true, + + // starting page of the pager (zero based index) + pager_startPage: 0, + + // Number of visible rows + pager_size: 10, + + // Save pager page & size if the storage script is loaded (requires $.tablesorter.storage in jquery.tablesorter.widgets.js) + pager_savePages: true, + + //defines custom storage key + pager_storageKey: 'tablesorter-pager', + + // 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 + pager_fixedHeight: false, + + // count child rows towards the set page size? (set true if it is a visible table row within the pager) + // if true, child row(s) may not appear to be attached to its parent row, may be split across pages or + // may distort the table if rowspan or cellspans are included. + pager_countChildRows: 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. + pager_removeRows: false, // removing rows in larger tables speeds up the sort + + // 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 + pager_ajaxUrl: null, + + // modify the url after all processing has been applied + pager_customAjaxUrl: function(table, url) { return url; }, + + // modify the $.ajax object to allow complete control over your ajax requests + pager_ajaxObject: { + dataType: 'json' + }, + + // set this to false if you want to block ajax loading on init + pager_processAjaxOnInit: true, + + // 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 + // ] + pager_ajaxProcessing: function(ajax){ return [ 0, [], null ]; }, + + // css class names of pager arrows + pager_css: { + container : 'tablesorter-pager', + errorRow : 'tablesorter-errorRow', // error information row (don't include period at beginning) + disabled : 'disabled' // class added to arrows @ extremes (i.e. prev/first arrows "disabled" on first page) + }, + + // jQuery selectors + pager_selectors: { + container : '.pager', // target the pager markup + first : '.first', // go to first page arrow + prev : '.prev', // previous page arrow + next : '.next', // next page arrow + last : '.last', // go to last page arrow + goto : '.gotoPage', // go to page selector - select dropdown that sets the current page + pageDisplay : '.pagedisplay', // location of where the "output" is displayed + pageSize : '.pagesize' // page size selector - select dropdown that sets the "size" option + } + }, + init: function(table){ + tsp.init(table); + }, + // only update to complete sorter initialization + format: function(table, c){ + if (!(c.pager && c.pager.initialized)){ + return tsp.initComplete(table, c); + } + tsp.moveToPage(table, c.pager, false); + }, + remove: function(table, c){ + tsp.destroyPager(table, c); + } +}); + +/* pager widget functions */ +tsp = ts.pager = { + + init: function(table) { + // check if tablesorter has initialized + if (table.hasInitialized && table.config.pager.initialized) { return; } + var t, + c = table.config, + wo = c.widgetOptions, + s = wo.pager_selectors, + + // save pager variables + p = c.pager = $.extend({ + totalPages: 0, + filteredRows: 0, + filteredPages: 0, + currentFilters: [], + page: wo.pager_startPage, + size: wo.pager_size, + startRow: 0, + endRow: 0, + ajaxCounter: 0, + $size: null, + last: {} + }, c.pager); + + // pager initializes multiple times before table has completed initialization + if (p.isInitializing) { return; } + + p.isInitializing = true; + if (c.debug) { + ts.log('Pager initializing'); + } + + // added in case the pager is reinitialized after being destroyed. + p.$container = $(s.container).addClass(wo.pager_css.container).show(); + // goto selector + p.$goto = p.$container.find(s.goto); + // page size selector + p.$size = p.$container.find(s.pageSize); + p.totalRows = c.$tbodies.eq(0).children().length; + p.oldAjaxSuccess = p.oldAjaxSuccess || wo.pager_ajaxObject.success; + c.appender = tsp.appender; + if (ts.filter && $.inArray('filter', c.widgets) >= 0) { + // get any default filter settings (data-value attribute) fixes #388 + p.currentFilters = c.$table.data('lastSearch') || ts.filter.setDefaults(table, c, wo) || []; + // set, but don't apply current filters + ts.setFilters(table, p.currentFilters, false); + } + if (wo.pager_savePages && ts.storage) { + t = ts.storage(table, wo.pager_storageKey) || {}; // fixes #387 + p.page = isNaN(t.page) ? p.page : t.page; + p.size = ( isNaN(t.size) ? p.size : t.size ) || 10; + $.data(table, 'pagerLastSize', p.size); + } + // clear initialized flag + p.initialized = false; + // before initialization event + c.$table.trigger('pagerBeforeInitialized', c); + + tsp.enablePager(table, c, false); + + if ( typeof(wo.pager_ajaxUrl) === 'string' ) { + // ajax pager; interact with database + p.ajax = true; + // When filtering with ajax, allow only custom filtering function, disable default filtering since it will be done server side. + wo.filter_serversideFiltering = true; + c.serverSideSorting = true; + tsp.moveToPage(table, p); + } else { + p.ajax = false; + // Regular pager; all rows stored in memory + c.$table.trigger("appendCache", [{}, true]); + tsp.hideRowsSetup(table, c); + } + + }, + + initComplete: function(table, c){ + var p = c.pager; + tsp.changeHeight(table, c); + tsp.bindEvents(table, c); + + // pager initialized + p.initialized = true; + p.isInitializing = false; + tsp.setPageSize(table, 0, c); // page size 0 is ignored + c.$table.trigger('pagerInitialized', c); + + }, + + bindEvents: function(table, c){ + var ctrls, fxn, + p = c.pager, + wo = c.widgetOptions, + s = wo.pager_selectors; + + c.$table + .unbind('filterStart filterEnd sortEnd disable enable destroy update updateRows updateAll addRows pageSize '.split(' ').join('.pager ')) + .bind('filterStart.pager', function(e, filters) { + p.currentFilters = filters; + p.page = 0; // fixes #456 + }) + // update pager after filter widget completes + .bind('filterEnd.pager sortEnd.pager', function() { + if (p.initialized) { + tsp.moveToPage(table, p, false); + tsp.updatePageDisplay(table, c, false); + tsp.fixHeight(table, c); + } + }) + .bind('disable.pager', function(e){ + e.stopPropagation(); + tsp.showAllRows(table, c); + }) + .on('enable.pager', function(e){ + e.stopPropagation(); + tsp.enablePager(table, c, true); + }) + .on('destroy.pager', function(e){ + e.stopPropagation(); + tsp.destroyPager(table, c); + }) + .on('update updateRows updateAll addRows '.split(' ').join('.pager '), function(e){ + e.stopPropagation(); + tsp.hideRows(table, c); + // make sure widgets are applied - fixes #450 + c.$table.trigger('applyWidgets'); + }) + .on('pageSize.pager', function(e,v){ + e.stopPropagation(); + tsp.setPageSize(table, parseInt(v, 10) || 10, c); + tsp.hideRows(table, c); + tsp.updatePageDisplay(table, c, false); + if (p.$size.length) { p.$size.val(p.size); } // twice? + }) + .on('pageSet.pager', function(e,v){ + e.stopPropagation(); + p.page = (parseInt(v, 10) || 1) - 1; + if (p.$goto.length) { p.$goto.val(c.size); } // twice? + tsp.moveToPage(table, p); + tsp.updatePageDisplay(table, c, false); + }); + + // clicked controls + ctrls = [ s.first, s.prev, s.next, s.last ]; + fxn = [ 'moveToFirstPage', 'moveToPrevPage', 'moveToNextPage', 'moveToLastPage' ]; + p.$container.find(ctrls.join(',')) + .attr("tabindex", 0) + .unbind('click.pager') + .bind('click.pager', function(e){ + e.stopPropagation(); + var i, + $c = $(this), + l = ctrls.length; + if ( !$c.hasClass(wo.pager_css.disabled) ) { + for (i = 0; i < l; i++) { + if ($c.is(ctrls[i])) { + tsp[fxn[i]](table, p); + break; + } + } + } + }); + + if ( p.$goto.length ) { + p.$goto + .unbind('change') + .bind('change', function(){ + p.page = $(this).val() - 1; + tsp.moveToPage(table, p); + tsp.updatePageDisplay(table, c, false); + }); + } + + if ( p.$size.length ) { + p.$size + .unbind('change.pager') + .bind('change.pager', function() { + p.$size.val( $(this).val() ); // in case there are more than one pagers + if ( !$(this).hasClass(wo.pager_css.disabled) ) { + tsp.setPageSize(table, parseInt( $(this).val(), 10 ), c); + tsp.changeHeight(table, c); + } + return false; + }); + } + + }, + + // hide arrows at extremes + pagerArrows: function(c, disable) { + var p = c.pager, + dis = !!disable, + first = dis || p.page === 0, + tp = Math.min( p.totalPages, p.filteredPages ), + last = dis || p.page === tp - 1 || p.totalPages === 0, + wo = c.widgetOptions, + s = wo.pager_selectors; + if ( wo.pager_updateArrows ) { + p.$container.find(s.first + ',' + s.prev).toggleClass(wo.pager_css.disabled, first).attr('aria-disabled', first); + p.$container.find(s.next + ',' + s.last).toggleClass(wo.pager_css.disabled, last).attr('aria-disabled', last); + } + }, + + updatePageDisplay: function(table, c, completed) { + var i, pg, s, out, + wo = c.widgetOptions, + p = c.pager, + f = c.$table.hasClass('hasFilters') && !wo.pager_ajaxUrl, + t = (c.widgetOptions && c.widgetOptions.filter_filteredRow || 'filtered') + ',' + c.selectorRemove + + (wo.pager_countChildRows ? '' : ',.' + c.cssChildRow), + sz = p.size || 10; // don't allow dividing by zero + p.$size.add(p.$goto).removeClass(wo.pager_css.disabled).removeAttr('disabled').attr('aria-disabled', 'false'); + p.totalPages = Math.ceil( p.totalRows / sz ); // needed for "pageSize" method + p.filteredRows = (f) ? c.$tbodies.eq(0).children('tr').not('.' + t).length : p.totalRows; + p.filteredPages = (f) ? Math.ceil( p.filteredRows / sz ) || 1 : p.totalPages; + if ( Math.min( p.totalPages, p.filteredPages ) >= 0 ) { + t = (p.size * p.page > p.filteredRows); + p.startRow = (t) ? 1 : (p.filteredRows === 0 ? 0 : p.size * p.page + 1); + p.page = (t) ? 0 : p.page; + p.endRow = Math.min( p.filteredRows, p.totalRows, p.size * ( p.page + 1 ) ); + out = p.$container.find(wo.pager_selectors.pageDisplay); + // form the output string (can now get a new output string from the server) + s = ( p.ajaxData && p.ajaxData.output ? p.ajaxData.output || wo.pager_output : wo.pager_output ) + // {page} = one-based index; {page+#} = zero based index +/- value + .replace(/\{page([\-+]\d+)?\}/gi, function(m,n){ + return p.totalPages ? p.page + (n ? parseInt(n, 10) : 1) : 0; + }) + // {totalPages}, {extra}, {extra:0} (array) or {extra : key} (object) + .replace(/\{\w+(\s*:\s*\w+)?\}/gi, function(m){ + var str = m.replace(/[{}\s]/g,''), + extra = str.split(':'), + data = p.ajaxData, + // return zero for default page/row numbers + deflt = /(rows?|pages?)$/i.test(str) ? 0 : ''; + return extra.length > 1 && data && data[extra[0]] ? data[extra[0]][extra[1]] : p[str] || (data ? data[str] : deflt) || deflt; + }); + if (out.length) { + out[ (out[0].tagName === 'INPUT') ? 'val' : 'html' ](s); + if ( p.$goto.length ) { + t = ''; + pg = Math.min( p.totalPages, p.filteredPages ); + for ( i = 1; i <= pg; i++ ) { + t += ''; + } + p.$goto.html(t).val( p.page + 1 ); + } + } + } + tsp.pagerArrows(c); + if (p.initialized && completed !== false) { + c.$table.trigger('pagerComplete', c); + // save pager info to storage + if (wo.pager_savePages && ts.storage) { + ts.storage(table, wo.pager_storageKey, { + page : p.page, + size : p.size + }); + } + } + }, + + fixHeight: function(table, c) { + var d, h, + p = c.pager, + wo = c.widgetOptions, + $b = c.$tbodies.eq(0); + if (wo.pager_fixedHeight) { + $b.find('tr.pagerSavedHeightSpacer').remove(); + h = $.data(table, 'pagerSavedHeight'); + if (h) { + d = h - $b.height(); + if ( d > 5 && $.data(table, 'pagerLastSize') === p.size && $b.children('tr:visible').length < p.size ) { + $b.append(''); + } + } + } + }, + + changeHeight: function(table, c) { + var $b = c.$tbodies.eq(0); + $b.find('tr.pagerSavedHeightSpacer').remove(); + $.data(table, 'pagerSavedHeight', $b.height()); + tsp.fixHeight(table, c); + $.data(table, 'pagerLastSize', c.pager.size); + }, + + hideRows: function(table, c){ + if (!c.widgetOptions.pager_ajaxUrl) { + var i, + lastIndex = 0, + p = c.pager, + wo = c.widgetOptions, + rows = c.$tbodies.eq(0).children(), + l = rows.length, + s = ( p.page * p.size ), + e = s + p.size, + f = wo && wo.filter_filteredRow || 'filtered', + j = 0; // size counter + for ( i = 0; i < l; i++ ){ + if ( !rows[i].className.match(f) ) { + if (j === s && rows[i].className.match(c.cssChildRow)) { + // hide child rows @ start of pager (if already visible) + rows[i].style.display = 'none'; + } else { + rows[i].style.display = ( j >= s && j < e ) ? '' : 'none'; + // don't count child rows + j += rows[i].className.match(c.cssChildRow + '|' + c.selectorRemove.slice(1)) && !wo.pager_countChildRows ? 0 : 1; + if ( j === e && rows[i].style.display !== 'none' && rows[i].className.match(ts.css.cssHasChild) ) { + lastIndex = i; + } + } + } + } + // add any attached child rows to last row of pager. Fixes part of issue #396 + if ( lastIndex > 0 && rows[lastIndex].className.match(ts.css.cssHasChild) ) { + while ( ++lastIndex < l && rows[lastIndex].className.match(c.cssChildRow) ) { + rows[lastIndex].style.display = ''; + } + } + } + }, + + hideRowsSetup: function(table, c){ + var p = c.pager; + p.size = parseInt( p.$size.val(), 10 ) || p.size; + $.data(table, 'pagerLastSize', p.size); + tsp.pagerArrows(c); + if ( !c.widgetOptions.pager_removeRows ) { + tsp.hideRows(table, c); + c.$table.on('sortEnd.pager filterEnd.pager', function(){ + tsp.hideRows(table, c); + }); + } + }, + + renderAjax: function(data, table, c, xhr, exception){ + var p = c.pager, + wo = c.widgetOptions; + // process data + if ( $.isFunction(wo.pager_ajaxProcessing) ) { + // ajaxProcessing result: [ total, rows, headers ] + var i, j, t, hsh, $f, $sh, th, d, l, rr_count, + $t = c.$table, + tds = '', + result = wo.pager_ajaxProcessing(data, table) || [ 0, [] ], + hl = $t.find('thead th').length; + + // Clean up any previous error. + ts.showError(table); + + if ( exception ) { + if (c.debug) { + ts.log('Ajax Error', xhr, exception); + } + ts.showError(table, exception.message + ' (' + xhr.status + ')'); + c.$tbodies.eq(0).empty(); + p.totalRows = 0; + } else { + // process ajax object + if (!$.isArray(result)) { + p.ajaxData = result; + p.totalRows = result.total; + th = result.headers; + d = result.rows; + } else { + // allow [ total, rows, headers ] or [ rows, total, headers ] + t = isNaN(result[0]) && !isNaN(result[1]); + // ensure a zero returned row count doesn't fail the logical || + rr_count = result[t ? 1 : 0]; + p.totalRows = isNaN(rr_count) ? p.totalRows || 0 : rr_count; + d = p.totalRows === 0 ? [""] : result[t ? 0 : 1] || []; // row data + th = result[2]; // headers + } + l = d.length; + if (d instanceof jQuery) { + if (wo.pager_processAjaxOnInit) { + // append jQuery object + c.$tbodies.eq(0).empty().append(d); + } + } else if (l) { + // build table from array + for ( i = 0; i < l; i++ ) { + tds += ''; + for ( j = 0; j < d[i].length; j++ ) { + // build tbody cells; watch for data containing HTML markup - see #434 + tds += /^\s*' + d[i][j] + ''; + } + tds += ''; + } + // add rows to first tbody + if (wo.pager_processAjaxOnInit) { + c.$tbodies.eq(0).html( tds ); + } + } + wo.pager_processAjaxOnInit = true; + // only add new header text if the length matches + if ( th && th.length === hl ) { + hsh = $t.hasClass('hasStickyHeaders'); + $sh = hsh ? wo.$sticky.children('thead:first').children().children() : ''; + $f = $t.find('tfoot tr:first').children(); + // don't change td headers (may contain pager) + c.$headers.filter('th').each(function(j){ + var $t = $(this), icn; + // add new test within the first span it finds, or just in the header + if ( $t.find('.' + ts.css.icon).length ) { + icn = $t.find('.' + ts.css.icon).clone(true); + $t.find('.tablesorter-header-inner').html( th[j] ).append(icn); + if ( hsh && $sh.length ) { + icn = $sh.eq(j).find('.' + ts.css.icon).clone(true); + $sh.eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icn); + } + } else { + $t.find('.tablesorter-header-inner').html( th[j] ); + if (hsh && $sh.length) { + $sh.eq(j).find('.tablesorter-header-inner').html( th[j] ); + } + } + $f.eq(j).html( th[j] ); + }); + } + } + if (c.showProcessing) { + ts.isProcessing(table); // remove loading icon + } + // make sure last pager settings are saved, prevents multiple server side calls with + // the same parameters + p.totalPages = Math.ceil( p.totalRows / ( p.size || 10 ) ); + p.last.totalRows = p.totalRows; + p.last.currentFilters = p.currentFilters; + p.last.sortList = (c.sortList || []).join(','); + tsp.updatePageDisplay(table, c); + tsp.fixHeight(table, c); + $t.trigger('updateCache', [function(){ + if (p.initialized) { + // apply widgets after table has rendered + $t.trigger('applyWidgets'); + $t.trigger('pagerChange', p); + } + }]); + } + if (!p.initialized) { + c.$table.trigger('applyWidgets'); + } + }, + + getAjax: function(table, c){ + var counter, + url = tsp.getAjaxUrl(table, c), + $doc = $(document), + wo = c.widgetOptions, + p = c.pager; + if ( url !== '' ) { + if (c.showProcessing) { + ts.isProcessing(table, true); // show loading icon + } + $doc.on('ajaxError.pager', function(e, xhr, settings, exception) { + tsp.renderAjax(null, table, c, xhr, exception); + $doc.unbind('ajaxError.pager'); + }); + counter = ++p.ajaxCounter; + wo.pager_ajaxObject.url = url; // from the ajaxUrl option and modified by customAjaxUrl + wo.pager_ajaxObject.success = function(data) { + // Refuse to process old ajax commands that were overwritten by new ones - see #443 + if (counter < p.ajaxCounter){ + return; + } + tsp.renderAjax(data, table, c); + $doc.unbind('ajaxError.pager'); + if (typeof p.oldAjaxSuccess === 'function') { + p.oldAjaxSuccess(data); + } + }; + if (c.debug) { + ts.log('ajax initialized', wo.pager_ajaxObject); + } + $.ajax(wo.pager_ajaxObject); + } + }, + + getAjaxUrl: function(table, c) { + var p = c.pager, + wo = c.widgetOptions, + url = (wo.pager_ajaxUrl) ? wo.pager_ajaxUrl + // allow using "{page+1}" in the url string to switch to a non-zero based index + .replace(/\{page([\-+]\d+)?\}/, function(s,n){ return p.page + (n ? parseInt(n, 10) : 0); }) + .replace(/\{size\}/g, p.size) : '', + sl = c.sortList, + fl = p.currentFilters || $(table).data('lastSearch') || [], + sortCol = url.match(/\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/), + filterCol = url.match(/\{\s*filter(?:List)?\s*:\s*(\w*)\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(/\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/g, arry.length ? arry.join('&') : sortCol ); + arry = []; + } + 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(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/g, arry.length ? arry.join('&') : filterCol ); + p.currentFilters = fl; + } + if ( $.isFunction(wo.pager_customAjaxUrl) ) { + url = wo.pager_customAjaxUrl(table, url); + } + if (c.debug) { + ts.log('Pager ajax url: ' + url); + } + return url; + }, + + renderTable: function(table, rows) { + var i, $tb, + c = table.config, + p = c.pager, + wo = c.widgetOptions, + l = rows && rows.length || 0, // rows may be undefined + s = ( p.page * p.size ), + e = ( s + p.size ); + if ( l < 1 ) { return; } // empty table, abort! + if ( p.page >= p.totalPages ) { + // lets not render the table more than once + return tsp.moveToLastPage(table, p); + } + p.isDisabled = false; // needed because sorting will change the page and re-enable the pager + if (p.initialized) { c.$table.trigger('pagerChange', c); } + + if ( !wo.pager_removeRows ) { + tsp.hideRows(table, c); + } else { + if ( e > rows.length ) { + e = rows.length; + } + ts.clearTableBody(table); + $tb = ts.processTbody(table, c.$tbodies.eq(0), true); + for ( i = s; i < e; i++ ) { + $tb.append(rows[i]); + } + ts.processTbody(table, $tb, false); + } + + tsp.updatePageDisplay(table, c); + if ( !p.isDisabled ) { tsp.fixHeight(table, c); } + + wo.pager_startPage = p.page; + wo.pager_size = p.size; + c.$table.trigger('applyWidgets'); + if (table.isUpdating) { + c.$table.trigger('updateComplete'); + } + + }, + + showAllRows: function(table, c){ + var p = c.pager, + wo = c.widgetOptions; + if ( p.ajax ) { + tsp.pagerArrows(c, true); + } else { + p.isDisabled = true; + $.data(table, 'pagerLastPage', p.page); + $.data(table, 'pagerLastSize', p.size); + p.page = 0; + p.size = p.totalRows; + p.totalPages = 1; + c.$table + .addClass('pagerDisabled') + .removeAttr('aria-describedby') + .find('tr.pagerSavedHeightSpacer').remove(); + tsp.renderTable(table, c.rowsCopy); + if (c.debug) { + ts.log('pager disabled'); + } + } + // disable size selector + p.$size.add(p.$goto).each(function(){ + $(this).attr('aria-disabled', 'true').addClass(wo.pager_css.disabled)[0].disabled = true; + }); + }, + + moveToPage: function(table, p, pageMoved) { + if ( p.isDisabled ) { return; } + var c = table.config, + l = p.last, + pg = Math.min( p.totalPages, p.filteredPages ); + if ( p.page < 0 ) { p.page = 0; } + if ( p.page > ( pg - 1 ) && pg !== 0 ) { p.page = pg - 1; } + // fixes issue where one current filter is [] and the other is ['','',''], + // making the next if comparison think the filters as different. Fixes #202. + l.currentFilters = (l.currentFilters || []).join('') === '' ? [] : l.currentFilters; + p.currentFilters = (p.currentFilters || []).join('') === '' ? [] : p.currentFilters; + // don't allow rendering multiple times on the same page/size/totalRows/filters/sorts + if ( l.page === p.page && l.size === p.size && l.totalRows === p.totalRows && + (l.currentFilters || []).join(',') === (p.currentFilters || []).join(',') && + l.sortList === (c.sortList || []).join(',') ) { + return; + } + if (c.debug) { + ts.log('Pager changing to page ' + p.page); + } + p.last = { + page : p.page, + size : p.size, + // fixes #408; modify sortList otherwise it auto-updates + sortList : (c.sortList || []).join(','), + totalRows : p.totalRows, + currentFilters : p.currentFilters || [] + }; + if (p.ajax) { + tsp.getAjax(table, c); + } else if (!p.ajax) { + tsp.renderTable(table, c.rowsCopy); + } + $.data(table, 'pagerLastPage', p.page); + if (p.initialized && pageMoved !== false) { + c.$table.trigger('pageMoved', c); + if (!p.ajax && table.isUpdating) { + c.$table.trigger('updateComplete'); + } + } + }, + + setPageSize: function(table, size, c) { + var p = c.pager; + p.size = size || p.size || 10; + p.$size.val(p.size); + $.data(table, 'pagerLastPage', p.page); + $.data(table, 'pagerLastSize', p.size); + p.totalPages = Math.ceil( p.totalRows / p.size ); + p.filteredPages = Math.ceil( p.filteredRows / p.size ); + tsp.moveToPage(table, p); + }, + + moveToFirstPage: function(table, p) { + p.page = 0; + tsp.moveToPage(table, p); + }, + + moveToLastPage: function(table, p) { + p.page = ( Math.min( p.totalPages, p.filteredPages ) - 1 ); + tsp.moveToPage(table, p); + }, + + moveToNextPage: function(table, p) { + p.page++; + if ( p.page >= ( Math.min( p.totalPages, p.filteredPages ) - 1 ) ) { + p.page = ( Math.min( p.totalPages, p.filteredPages ) - 1 ); + } + tsp.moveToPage(table, p); + }, + + moveToPrevPage: function(table, p) { + p.page--; + if ( p.page <= 0 ) { + p.page = 0; + } + tsp.moveToPage(table, p); + }, + + destroyPager: function(table, c){ + var p = c.pager; + tsp.showAllRows(table, c); + p.$container.hide(); // hide pager + c.appender = null; // remove pager appender function + p.initialized = false; + c.$table.unbind('destroy.pager sortEnd.pager filterEnd.pager enable.pager disable.pager'); + if (ts.storage) { + ts.storage(table, c.widgetOptions.pager_storageKey, ''); + } + }, + + enablePager: function(table, c, triggered){ + var info, p = c.pager; + p.isDisabled = false; + p.page = $.data(table, 'pagerLastPage') || p.page || 0; + p.size = $.data(table, 'pagerLastSize') || parseInt(p.$size.find('option[selected]').val(), 10) || p.size || 10; + p.$size.val(p.size); // set page size + p.totalPages = Math.ceil( Math.min( p.totalRows, p.filteredRows ) / p.size ); + c.$table.removeClass('pagerDisabled'); + // if table id exists, include page display with aria info + if ( table.id ) { + info = table.id + '_pager_info'; + p.$container.find(c.widgetOptions.pager_selectors.pageDisplay).attr('id', info); + c.$table.attr('aria-describedby', info); + } + if ( triggered ) { + c.$table.trigger('updateRows'); + tsp.setPageSize(table, p.size, c); + tsp.hideRowsSetup(table, c); + tsp.fixHeight(table, c); + if (c.debug) { + ts.log('pager enabled'); + } + } + }, + + appender: function(table, rows) { + var c = table.config, + wo = c.widgetOptions, + p = c.pager; + if ( !p.ajax ) { + c.rowsCopy = rows; + p.totalRows = c.widgetOptions.pager_countChildRows ? c.$tbodies.eq(0).children().length : rows.length; + p.size = $.data(table, 'pagerLastSize') || p.size || wo.pager_size || 10; + p.totalPages = Math.ceil( p.totalRows / p.size ); + tsp.moveToPage(table, p, true); + // update display here in case all rows are removed + tsp.updatePageDisplay(table, c, false); + } else { + tsp.moveToPage(table, p, true); + } + } + +}; + +// see #486 +ts.showError = function(table, message){ + $(table).each(function(){ + var $row, + c = this.config, + errorRow = c.pager && c.pager.cssErrorRow || c.widgetOptions.pager_css && c.widgetOptions.pager_css.errorRow || 'tablesorter-errorRow'; + if (c) { + if (typeof message === 'undefined') { + c.$table.find('thead').find(c.selectorRemove).remove(); + } else { + $row = ( /tr\>/.test(message) ? $(message) : $('' + message + '') ) + .click(function(){ + $(this).remove(); + }) + // add error row to thead instead of tbody, or clicking on the header will result in a parser error + .appendTo( c.$table.find('thead:first') ) + .addClass( errorRow + ' ' + c.selectorRemove.replace(/^[.#]/, '') ) + .attr({ + role : 'alert', + 'aria-live' : 'assertive' + }); + } + } + }); +}; + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-repeatheaders.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-repeatheaders.js new file mode 100644 index 000000000..c5513336e --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-repeatheaders.js @@ -0,0 +1,50 @@ +/*! tablesorter repeatHeaders widget - updated 4/12/2013 +* Requires tablesorter v2.8+ and jQuery 1.7+ +* Original by Christian Bach from the example-widgets.html demo +*/ +/*global jQuery: false */ +;(function($){ + "use strict"; + + $.tablesorter.addWidget({ + id: "repeatHeaders", + priority: 10, + options: { + rowsToSkip : 4 + }, + // format is called on init and when a sorting has finished + format: function(table, c, wo) { + var h = '', i, $tr, l, skip; + // cache and collect all TH headers + if (!wo.repeatHeaders) { + h = ''; + $.each(c.headerContent, function(i,t) { + h += '' + t + ''; + }); + // "remove-me" class was added in case the table needs to be updated, the "remove-me" rows will be + // removed prior to the update to prevent including the rows in the update - see "selectorRemove" option + wo.repeatHeaders = h + ''; + } + + // number of rows to skip + skip = wo && wo.rowsToSkip || 4; + + // remove appended headers by classname + c.$table.find("tr.repeated-header").remove(); + $tr = c.$tbodies.find('tr'); + l = $tr.length; + // loop all tr elements and insert a copy of the "headers" + for (i = skip; i < l; i += skip) { + // insert a copy of the table head every X rows + $tr.eq(i).before(wo.repeatHeaders); + } + }, + // this remove function is called when using the refreshWidgets method or when destroying the tablesorter plugin + // this function only applies to tablesorter v2.4+ + remove: function(table, c){ + c.$table.find("tr.repeated-header").remove(); + } + + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-scroller.js b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-scroller.js new file mode 100644 index 000000000..cc6672660 --- /dev/null +++ b/ajax/libs/jquery.tablesorter/2.15.14/widgets/widget-scroller.js @@ -0,0 +1,241 @@ +/*! + Copyright (C) 2011 T. Connell & Associates, Inc. + + Dual-licensed under the MIT and GPL licenses + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Resizable scroller widget for the jQuery tablesorter plugin + + Version 2.0 - modified by Rob Garrison (4/12/2013) + Requires jQuery, v1.2.3 or higher + Requires the tablesorter plugin, v2.0 or higher, available at http://mottie.github.com/tablesorter/docs/ + + Usage: + + $(function() { + + $('table.tablesorter').tablesorter({ + widgets: ['zebra', 'scroller'], + widgetOptions : { + scroller_height : 300, // height of scroll window + scroller_barWidth : 17, // scroll bar width + scroller_jumpToHeader : true, // header snap to browser top when scrolling the tbody + scroller_idPrefix : 's_' // cloned thead id prefix (random number added to end) + } + }); + + }); + + Website: www.tconnell.com +*/ +/*jshint browser:true, jquery:true, unused:false */ +;(function($){ +"use strict"; + +$.fn.hasScrollBar = function(){ + return this.get(0).scrollHeight > this.height(); +}; +var ts = $.tablesorter; + +ts.window_resize = function(){ + if (this.resize_timer) { + clearTimeout(this.resize_timer); + } + this.resize_timer = setTimeout(function(){ + $(this).trigger('resizeEnd'); + }, 250); +}; + +// Add extra scroller css +$(function(){ + var s = ''; + $(s).appendTo('body'); +}); + +ts.addWidget({ + id: 'scroller', + priority: 60, // run after the filter widget + options: { + scroller_height : 300, + scroller_barWidth : 17, + scroller_jumpToHeader: true, + scroller_idPrefix : 's_' + }, + init: function(table, thisWidget, c, wo){ + var $win = $(window); + //Setup window.resizeEnd event + $win + .bind('resize', ts.window_resize) + .bind('resizeEnd', function(e) { + // init is run before format, so scroller_resizeWidth + // won't be defined within the "c" or "wo" parameters + if (typeof table.config.widgetOptions.scroller_resizeWidth === 'function') { + //IE calls resize when you modify content, so we have to unbind the resize event + //so we don't end up with an infinite loop. we can rebind after we're done. + $win.unbind('resize', ts.window_resize); + table.config.widgetOptions.scroller_resizeWidth(); + $win.bind('resize', ts.window_resize); + } + }); + }, + format: function(table, c, wo) { + var h, $hdr, id, t, resize, $cells, + $win = $(window), + $tbl = c.$table, + flag = false, + filterInputs = 'input, select'; + + if (!c.isScrolling) { + h = wo.scroller_height || 300; + t = $tbl.find('tbody').height(); + if (t !== 0 && h > t) { h = t + 10; } // Table is less than h px + id = wo.scroller_id = wo.scroller_idPrefix + Math.floor(Math.random() * 101); + + $hdr = $('' + $tbl.find('thead:first').html() + '
'); + $tbl + .wrap('
') + .before($hdr) + .find('.tablesorter-filter-row').addClass('hideme'); + + $cells = $hdr + .wrap('
') + .find('.' + ts.css.header) + .bind('mousedown', function(){ + this.onselectstart = function(){ return false; }; + return false; + }); + + $tbl + .wrap('
') + .unbind('sortEnd.tsScroller') + .bind('sortEnd.tsScroller', function(){ + c.$headers.each(function(i){ + var t = $cells.eq(i); + t + .attr('class', $(this).attr('class')) + // remove processing icon + .removeClass(ts.css.processing + ' ' + c.cssProcessing); + if (ts.css.icon){ + t + .find('.' + ts.css.icon) + .attr('class', $(this).find('.' + ts.css.icon).attr('class')); + } + }); + }); + + // make scroller header sortable + c.$headers.find(c.selectorSort).add( c.$headers.filter(c.selectorSort) ).each(function(i){ + var t = $(this); + $cells.eq(i) + // clicking on new header will trigger a sort + .bind('mouseup', function(e){ + t.trigger(e, true); // external mouseup flag (click timer is ignored) + }) + // prevent header text selection + .bind('mousedown', function(){ + this.onselectstart = function(){ return false; }; + return false; + }); + }); + + // look for filter widget + $tbl.bind('filterEnd', function(){ + if (flag) { return; } + $cells.each(function(i){ + $(this).find(filterInputs).val( c.$filters.find(filterInputs).eq(i).val() ); + }); + }); + $hdr.find(filterInputs).bind('keyup search', function(e){ + // ignore arrow and meta keys; allow backspace + if ((e.which < 32 && e.which !== 8) || (e.which >= 37 && e.which <=40)) { return; } + flag = true; + var $f = $(this), col = $f.attr('data-column'); + c.$filters.find(filterInputs).eq(col) + .val( $f.val() ) + .trigger('search'); + setTimeout(function(){ + flag = false; + }, wo.filter_searchDelay); + }); + + resize = function(){ + var d, + //Hide other scrollers so we can resize + $div = $('div.scroller[id != "' + id + '"]').hide(); + + $tbl.find('thead').show(); + + //Reset sizes so parent can resize. + $hdr + .width(0) + .parent().width(0) + .find('th,td').width(0); + + $tbl + .width(0) + .find('thead').find('th,td').width(0); + d = $tbl.parent(); + d.width(0); + + d.parent().trigger('resize'); + // Shrink a bit to accommodate scrollbar + d.width( d.parent().innerWidth() - ( d.parent().hasScrollBar() ? wo.scroller_barWidth : 0 ) ); + + $tbl.width( d.innerWidth() - ( d.hasScrollBar() ? wo.scroller_barWidth : 0 ) ); + $tbl.find('thead').find('th,td').filter(':visible').each(function(i, c){ + var $th = $(c), + //Wrap in browser detect?? + w = parseInt( $th.css('min-width').replace('auto', '0').replace(/(px|em)/, ''), 10 ); + if ( $th.width() < w ) { + $th.width(w); + } else { + w = $th.width(); + } + $hdr.find('th,td').eq(i).width(w); + }); + + $hdr.width($tbl.innerWidth()); + $div.show(); + }; + + //Expose to external calls + wo.scroller_resizeWidth = resize; + + resize(); + + $tbl.find('thead').css('visibility', 'hidden'); + c.isScrolling = true; + + t = $tbl.parent().parent().height(); + // The header will always jump into view if scrolling the table body + $tbl.parent().bind('scroll', function(){ + if (wo.scroller_jumpToHeader) { + var pos = $win.scrollTop() - $hdr.offset().top; + if ($(this).scrollTop() !== 0 && pos < t && pos > 0) { + $win.scrollTop( $hdr.offset().top ); + } + } + }); + + } + + //Sorting, so scroll to top + $tbl.parent().animate({ scrollTop: 0 }, 'fast'); + + }, + remove : function(table, c, wo){ + + } + }); + +})(jQuery); diff --git a/ajax/libs/jquery.tablesorter/package.json b/ajax/libs/jquery.tablesorter/package.json index 587ca6fdb..b3a76c5b2 100644 --- a/ajax/libs/jquery.tablesorter/package.json +++ b/ajax/libs/jquery.tablesorter/package.json @@ -1,7 +1,7 @@ { "name": "jquery.tablesorter", "filename": "jquery.tablesorter.min.js", - "version": "2.13.3", + "version": "2.15.14", "description": "tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.\n\nThis forked version adds lots of new enhancements including: alphanumeric sorting, pager callback functons, multiple widgets providing column styling, ui theme application, sticky headers, column filters and resizer, as well as extended documentation with a lot more demos.", "author": "Christian Bach, Mottie", "homepage": "http://mottie.github.com/tablesorter/docs/",