Updated some compiler methods, added footable3, fixed some known issus.

This commit is contained in:
2016-04-22 13:03:43 +01:00
parent 3bc71a935c
commit 6871bfd9a2
438 changed files with 9212 additions and 1221 deletions

View File

@ -7,8 +7,8 @@
*
**/
// No direct access.
defined('_JEXEC') or die;
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
class Chartbuilder
{

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,14 @@
Copyright (c) 2015 Steven Usher & Brad Vincent
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,266 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
table.footable,
table.footable-details {
position: relative;
width: 100%;
border-spacing: 0;
border-collapse: collapse;
}
table.footable-details {
margin-bottom: 0;
}
table > tbody > tr > td > span.footable-toggle {
margin-right: 8px;
opacity: 0.3;
}
table > tbody > tr > td > span.footable-toggle.last-column {
margin-left: 8px;
float: right;
}
table.table-condensed > tbody > tr > td > span.footable-toggle {
margin-right: 5px;
}
table.footable-details > tbody > tr > th:nth-child(1) {
min-width: 40px;
width: 120px;
}
table.footable-details > tbody > tr > td:nth-child(2) {
word-break: break-all;
}
table.footable-details > thead > tr:first-child > th,
table.footable-details > thead > tr:first-child > td,
table.footable-details > tbody > tr:first-child > th,
table.footable-details > tbody > tr:first-child > td,
table.footable-details > tfoot > tr:first-child > th,
table.footable-details > tfoot > tr:first-child > td {
border-top-width: 0;
}
table.footable-details.table-bordered > thead > tr:first-child > th,
table.footable-details.table-bordered > thead > tr:first-child > td,
table.footable-details.table-bordered > tbody > tr:first-child > th,
table.footable-details.table-bordered > tbody > tr:first-child > td,
table.footable-details.table-bordered > tfoot > tr:first-child > th,
table.footable-details.table-bordered > tfoot > tr:first-child > td {
border-top-width: 1px;
}
div.footable-loader {
vertical-align: middle;
text-align: center;
height: 300px;
position: relative;
}
div.footable-loader > span.fooicon {
display: inline-block;
opacity: 0.3;
font-size: 30px;
line-height: 32px;
width: 32px;
height: 32px;
margin-top: -16px;
margin-left: -16px;
position: absolute;
top: 50%;
left: 50%;
-webkit-animation: fooicon-spin-r 2s infinite linear;
animation: fooicon-spin-r 2s infinite linear;
}
table.footable > tbody > tr.footable-empty > td {
vertical-align: middle;
text-align: center;
font-size: 30px;
}
table.footable > tbody > tr > td,
table.footable > tbody > tr > th {
display: none;
}
table.footable > tbody > tr.footable-empty > td,
table.footable > tbody > tr.footable-empty > th,
table.footable > tbody > tr.footable-detail-row > td,
table.footable > tbody > tr.footable-detail-row > th {
display: table-cell;
}
@-webkit-keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fooicon {
position: relative;
top: 1px;
display: inline-block;
font-family: 'Glyphicons Halflings' !important;
font-style: normal;
font-weight: 400;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fooicon:before,
.fooicon:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.fooicon-loader:before {
content: "\e030";
}
.fooicon-plus:before {
content: "\2b";
}
.fooicon-minus:before {
content: "\2212";
}
.fooicon-search:before {
content: "\e003";
}
.fooicon-remove:before {
content: "\e014";
}
.fooicon-sort:before {
content: "\e150";
}
.fooicon-sort-asc:before {
content: "\e155";
}
.fooicon-sort-desc:before {
content: "\e156";
}
.fooicon-pencil:before {
content: "\270f";
}
.fooicon-trash:before {
content: "\e020";
}
.fooicon-eye-close:before {
content: "\e106";
}
.fooicon-flash:before {
content: "\e162";
}
.fooicon-cog:before {
content: "\e019";
}
table.footable > thead > tr.footable-filtering > th {
border-bottom-width: 1px;
font-weight: normal;
}
table.footable > thead > tr.footable-filtering > th,
table.footable.footable-filtering-right > thead > tr.footable-filtering > th {
text-align: right;
}
table.footable.footable-filtering-left > thead > tr.footable-filtering > th {
text-align: left;
}
table.footable.footable-filtering-center > thead > tr.footable-filtering > th {
text-align: center;
}
table.footable > thead > tr.footable-filtering > th div.form-group {
margin-bottom: 0;
}
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
margin-top: 5px;
}
table.footable > thead > tr.footable-filtering > th div.input-group {
width: 100%;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox {
margin: 0;
display: block;
position: relative;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox > label {
display: block;
padding-left: 20px;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox input[type="checkbox"] {
position: absolute;
margin-left: -20px;
}
@media (min-width: 768px) {
table.footable > thead > tr.footable-filtering > th div.input-group {
width: auto;
}
table.footable > thead > tr.footable-filtering > th div.form-group {
margin-left: 2px;
margin-right: 2px;
}
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
margin-top: 0;
}
}
td.footable-sortable,
th.footable-sortable {
position: relative;
padding-right: 30px;
cursor: pointer;
}
td.footable-sortable > span.fooicon,
th.footable-sortable > span.fooicon {
position: absolute;
right: 6px;
top: 50%;
margin-top: -7px;
opacity: 0;
transition: opacity 0.3s ease-in;
}
td.footable-sortable:hover > span.fooicon,
th.footable-sortable:hover > span.fooicon {
opacity: 1;
}
td.footable-sortable.footable-asc > span.fooicon,
th.footable-sortable.footable-asc > span.fooicon,
td.footable-sortable.footable-desc > span.fooicon,
th.footable-sortable.footable-desc > span.fooicon {
opacity: 1;
}
table.footable > tfoot > tr.footable-paging > td > ul.pagination {
margin: 10px 0 0 0;
}
table.footable > tfoot > tr.footable-paging > td > span.label {
display: inline-block;
margin: 0 0 10px 0;
padding: 4px 10px;
}
table.footable > tfoot > tr.footable-paging > td,
table.footable-paging-center > tfoot > tr.footable-paging > td {
text-align: center;
}
table.footable-paging-left > tfoot > tr.footable-paging > td {
text-align: left;
}
table.footable-paging-right > tfoot > tr.footable-paging > td {
text-align: right;
}
ul.pagination > li.footable-page {
display: none;
}
ul.pagination > li.footable-page.visible {
display: inline;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,169 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
table.footable,
table.footable-details {
position: relative;
width: 100%;
border-spacing: 0;
border-collapse: collapse;
}
table.footable-details {
margin-bottom: 0;
}
table > tbody > tr > td > span.footable-toggle {
margin-right: 8px;
opacity: 0.3;
}
table > tbody > tr > td > span.footable-toggle.last-column {
margin-left: 8px;
float: right;
}
table.table-condensed > tbody > tr > td > span.footable-toggle {
margin-right: 5px;
}
table.footable-details > tbody > tr > th:nth-child(1) {
min-width: 40px;
width: 120px;
}
table.footable-details > tbody > tr > td:nth-child(2) {
word-break: break-all;
}
table.footable-details > thead > tr:first-child > th,
table.footable-details > thead > tr:first-child > td,
table.footable-details > tbody > tr:first-child > th,
table.footable-details > tbody > tr:first-child > td,
table.footable-details > tfoot > tr:first-child > th,
table.footable-details > tfoot > tr:first-child > td {
border-top-width: 0;
}
table.footable-details.table-bordered > thead > tr:first-child > th,
table.footable-details.table-bordered > thead > tr:first-child > td,
table.footable-details.table-bordered > tbody > tr:first-child > th,
table.footable-details.table-bordered > tbody > tr:first-child > td,
table.footable-details.table-bordered > tfoot > tr:first-child > th,
table.footable-details.table-bordered > tfoot > tr:first-child > td {
border-top-width: 1px;
}
div.footable-loader {
vertical-align: middle;
text-align: center;
height: 300px;
position: relative;
}
div.footable-loader > span.fooicon {
display: inline-block;
opacity: 0.3;
font-size: 30px;
line-height: 32px;
width: 32px;
height: 32px;
margin-top: -16px;
margin-left: -16px;
position: absolute;
top: 50%;
left: 50%;
-webkit-animation: fooicon-spin-r 2s infinite linear;
animation: fooicon-spin-r 2s infinite linear;
}
table.footable > tbody > tr.footable-empty > td {
vertical-align: middle;
text-align: center;
font-size: 30px;
}
table.footable > tbody > tr > td,
table.footable > tbody > tr > th {
display: none;
}
table.footable > tbody > tr.footable-empty > td,
table.footable > tbody > tr.footable-empty > th,
table.footable > tbody > tr.footable-detail-row > td,
table.footable > tbody > tr.footable-detail-row > th {
display: table-cell;
}
@-webkit-keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fooicon {
position: relative;
top: 1px;
display: inline-block;
font-family: 'Glyphicons Halflings' !important;
font-style: normal;
font-weight: 400;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fooicon:before,
.fooicon:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.fooicon-loader:before {
content: "\e030";
}
.fooicon-plus:before {
content: "\2b";
}
.fooicon-minus:before {
content: "\2212";
}
.fooicon-search:before {
content: "\e003";
}
.fooicon-remove:before {
content: "\e014";
}
.fooicon-sort:before {
content: "\e150";
}
.fooicon-sort-asc:before {
content: "\e155";
}
.fooicon-sort-desc:before {
content: "\e156";
}
.fooicon-pencil:before {
content: "\270f";
}
.fooicon-trash:before {
content: "\e020";
}
.fooicon-eye-close:before {
content: "\e106";
}
.fooicon-flash:before {
content: "\e162";
}
.fooicon-cog:before {
content: "\e019";
}

View File

@ -0,0 +1,630 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
/* globals - instead we house them under the .footable.table class as the root of FooTable is always the table itself. */
.footable.table, .footable.table *,
.footable-details.table, .footable-details.table * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.footable.table th,
.footable-details.table th {
text-align: left;
}
/* tables */
.footable.table,
.footable-details.table {
width: 100%;
max-width: 100%;
margin-bottom: 20px;
}
.footable.table > caption + thead > tr:first-child > th,
.footable.table > colgroup + thead > tr:first-child > th,
.footable.table > thead:first-child > tr:first-child > th,
.footable.table > caption + thead > tr:first-child > td,
.footable.table > colgroup + thead > tr:first-child > td,
.footable.table > thead:first-child > tr:first-child > td,
.footable-details.table > caption + thead > tr:first-child > th,
.footable-details.table > colgroup + thead > tr:first-child > th,
.footable-details.table > thead:first-child > tr:first-child > th,
.footable-details.table > caption + thead > tr:first-child > td,
.footable-details.table > colgroup + thead > tr:first-child > td,
.footable-details.table > thead:first-child > tr:first-child > td {
border-top: 0;
}
.footable.table > thead > tr > th,
.footable.table > tbody > tr > th,
.footable.table > tfoot > tr > th,
.footable.table > thead > tr > td,
.footable.table > tbody > tr > td,
.footable.table > tfoot > tr > td,
.footable-details.table > thead > tr > th,
.footable-details.table > tbody > tr > th,
.footable-details.table > tfoot > tr > th,
.footable-details.table > thead > tr > td,
.footable-details.table > tbody > tr > td,
.footable-details.table > tfoot > tr > td {
padding: 8px;
line-height: 1.42857143;
vertical-align: top;
border-top: 1px solid #ddd;
}
.footable.table > thead > tr > th,
.footable.table > thead > tr > td,
.footable-details.table > thead > tr > th,
.footable-details.table > thead > tr > td {
vertical-align: bottom;
border-bottom: 2px solid #ddd;
}
.footable.table-condensed > thead > tr > th,
.footable.table-condensed > tbody > tr > th,
.footable.table-condensed > tfoot > tr > th,
.footable.table-condensed > thead > tr > td,
.footable.table-condensed > tbody > tr > td,
.footable.table-condensed > tfoot > tr > td,
.footable-details.table-condensed > thead > tr > th,
.footable-details.table-condensed > tbody > tr > th,
.footable-details.table-condensed > tfoot > tr > th,
.footable-details.table-condensed > thead > tr > td,
.footable-details.table-condensed > tbody > tr > td,
.footable-details.table-condensed > tfoot > tr > td {
padding: 5px;
}
.footable.table-bordered,
.footable-details.table-bordered {
border: 1px solid #ddd;
}
.footable.table-bordered > thead > tr > th,
.footable.table-bordered > tbody > tr > th,
.footable.table-bordered > tfoot > tr > th,
.footable.table-bordered > thead > tr > td,
.footable.table-bordered > tbody > tr > td,
.footable.table-bordered > tfoot > tr > td,
.footable-details.table-bordered > thead > tr > th,
.footable-details.table-bordered > tbody > tr > th,
.footable-details.table-bordered > tfoot > tr > th,
.footable-details.table-bordered > thead > tr > td,
.footable-details.table-bordered > tbody > tr > td,
.footable-details.table-bordered > tfoot > tr > td {
border: 1px solid #ddd;
}
.footable.table-bordered > thead > tr > th,
.footable.table-bordered > thead > tr > td,
.footable-details.table-bordered > thead > tr > th,
.footable-details.table-bordered > thead > tr > td {
border-bottom-width: 2px;
}
.footable.table-striped > tbody > tr:nth-child(odd),
.footable-details.table-striped > tbody > tr:nth-child(odd) {
background-color: #f9f9f9;
}
.footable.table-hover > tbody > tr:hover,
.footable-details.table-hover > tbody > tr:hover {
background-color: #f5f5f5;
}
/* buttons */
.footable .btn {
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
-webkit-appearance: button;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
overflow: visible;
text-transform: none;
}
.footable .btn:hover,
.footable .btn:focus,
.footable .btn.focus {
color: #333;
text-decoration: none;
}
.footable .btn-default {
color: #333;
background-color: #fff;
border-color: #ccc;
}
.footable .btn-default:hover,
.footable .btn-default:focus,
.footable .btn-default.focus,
.footable .btn-default:active,
.footable .btn-default.active,
.footable .open > .dropdown-toggle.btn-default {
color: #333;
background-color: #e6e6e6;
border-color: #adadad;
}
.footable .btn-primary {
color: #fff;
background-color: #337ab7;
border-color: #2e6da4;
}
.footable .btn-primary:hover,
.footable .btn-primary:focus,
.footable .btn-primary.focus,
.footable .btn-primary:active,
.footable .btn-primary.active,
.footable .open > .dropdown-toggle.btn-primary {
color: #fff;
background-color: #286090;
border-color: #204d74;
}
/* caret */
.footable .caret {
display: inline-block;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: 4px solid;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
.footable .btn .caret {
margin-left: 0;
}
/* form-group */
.form-group {
margin-bottom: 15px;
}
/* form-control */
.footable .form-control {
display: block;
width: 100%;
height: 34px;
padding: 6px 12px;
margin: 0;
font-family: inherit;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
/* input-group */
.footable .input-group {
position: relative;
display: table;
border-collapse: separate;
}
.footable .input-group .form-control {
position: relative;
z-index: 2;
float: left;
width: 100%;
margin-bottom: 0;
}
.footable .input-group-btn {
position: relative;
font-size: 0;
white-space: nowrap;
}
.footable .input-group-addon,
.footable .input-group-btn {
width: 1%;
white-space: nowrap;
vertical-align: middle;
}
.footable .input-group-addon,
.footable .input-group-btn,
.footable .input-group .form-control {
display: table-cell;
}
.footable .input-group-btn > .btn + .btn,
.footable .input-group-btn:last-child > .btn,
.footable .input-group-btn:last-child > .btn-group {
margin-left: -1px;
}
.footable .input-group-btn > .btn {
position: relative;
}
.footable .input-group-btn > .btn:hover,
.footable .input-group-btn > .btn:focus,
.footable .input-group-btn > .btn:active {
z-index: 2;
}
.footable .input-group .form-control:first-child,
.footable .input-group-addon:first-child,
.footable .input-group-btn:first-child > .btn,
.footable .input-group-btn:first-child > .btn-group > .btn,
.footable .input-group-btn:first-child > .dropdown-toggle,
.footable .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
.footable .input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.footable .input-group .form-control:last-child,
.footable .input-group-addon:last-child,
.footable .input-group-btn:last-child > .btn,
.footable .input-group-btn:last-child > .btn-group > .btn,
.footable .input-group-btn:last-child > .dropdown-toggle,
.footable .input-group-btn:first-child > .btn:not(:first-child),
.footable .input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
/* checkboxes & radios */
.footable .radio,
.footable .checkbox {
position: relative;
display: block;
margin-top: 10px;
margin-bottom: 10px;
}
.footable .radio label,
.footable .checkbox label {
max-width: 100%;
min-height: 20px;
padding-left: 20px;
margin-bottom: 0;
font-weight: 400;
cursor: pointer;
}
.footable .radio input[type=radio],
.footable .radio-inline input[type=radio],
.footable .checkbox input[type=checkbox],
.footable .checkbox-inline input[type=checkbox] {
position: absolute;
margin: 4px 0 0 -20px;
line-height: normal;
}
/* dropdown-menu */
.footable .dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
font-size: 14px;
text-align: left;
list-style: none;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, .15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.footable .open > .dropdown-menu {
display: block;
}
.footable .dropdown-menu-right {
right: 0;
left: auto;
}
.footable .dropdown-menu > li > a {
display: block;
padding: 3px 20px;
clear: both;
font-weight: 400;
line-height: 1.42857143;
color: #333;
white-space: nowrap;
}
.footable .dropdown-menu > li > a:hover,
.footable .dropdown-menu > li > a:focus {
color: #262626;
text-decoration: none;
background-color: #f5f5f5;
}
/* pagination */
.footable .pagination {
display: inline-block;
padding-left: 0;
margin: 20px 0;
border-radius: 4px;
}
.footable .pagination > li {
display: inline;
}
.footable .pagination > li:first-child > a,
.footable .pagination > li:first-child > span {
margin-left: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.footable .pagination > li > a,
.footable .pagination > li > span {
position: relative;
float: left;
padding: 6px 12px;
margin-left: -1px;
line-height: 1.42857143;
color: #337ab7;
text-decoration: none;
background-color: #fff;
border: 1px solid #ddd;
}
.footable .pagination > li > a:hover,
.footable .pagination > li > span:hover,
.footable .pagination > li > a:focus,
.footable .pagination > li > span:focus {
color: #23527c;
background-color: #eee;
border-color: #ddd;
}
.footable .pagination > .active > a,
.footable .pagination > .active > span,
.footable .pagination > .active > a:hover,
.footable .pagination > .active > span:hover,
.footable .pagination > .active > a:focus,
.footable .pagination > .active > span:focus {
z-index: 2;
color: #fff;
cursor: default;
background-color: #337ab7;
border-color: #337ab7;
}
.footable .pagination > .disabled > span,
.footable .pagination > .disabled > span:hover,
.footable .pagination > .disabled > span:focus,
.footable .pagination > .disabled > a,
.footable .pagination > .disabled > a:hover,
.footable .pagination > .disabled > a:focus {
color: #777;
cursor: not-allowed;
background-color: #fff;
border-color: #ddd;
}
/* labels */
.footable .label {
display: inline;
padding: .2em .6em .3em;
font-size: 75%;
font-weight: 700;
line-height: 1;
color: #fff;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: .25em;
}
.footable .label-default {
background-color: #777;
}
/* wells */
.footable-loader.well {
min-height: 20px;
padding: 19px;
margin-bottom: 20px;
background-color: #f5f5f5;
border: 1px solid #e3e3e3;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
}
/* screen reader only */
.footable .sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}
/* form-inline */
@media (min-width: 768px) {
.footable .form-inline .form-group {
display:inline-block;
margin-bottom: 0;
vertical-align: middle
}
.footable .form-inline .form-control {
display: inline-block;
width: auto;
vertical-align: middle
}
.footable .form-inline .input-group {
display: inline-table;
vertical-align: middle
}
.footable .form-inline .input-group .input-group-addon,
.footable .form-inline .input-group .input-group-btn,
.footable .form-inline .input-group .form-control {
width: auto
}
.footable .form-inline .input-group>.form-control {
width: 100%
}
}
table.footable,
table.footable-details {
position: relative;
width: 100%;
border-spacing: 0;
border-collapse: collapse;
}
table.footable-details {
margin-bottom: 0;
}
table > tbody > tr > td > span.footable-toggle {
margin-right: 8px;
opacity: 0.3;
}
table > tbody > tr > td > span.footable-toggle.last-column {
margin-left: 8px;
float: right;
}
table.table-condensed > tbody > tr > td > span.footable-toggle {
margin-right: 5px;
}
table.footable-details > tbody > tr > th:nth-child(1) {
min-width: 40px;
width: 120px;
}
table.footable-details > tbody > tr > td:nth-child(2) {
word-break: break-all;
}
table.footable-details > thead > tr:first-child > th,
table.footable-details > thead > tr:first-child > td,
table.footable-details > tbody > tr:first-child > th,
table.footable-details > tbody > tr:first-child > td,
table.footable-details > tfoot > tr:first-child > th,
table.footable-details > tfoot > tr:first-child > td {
border-top-width: 0;
}
table.footable-details.table-bordered > thead > tr:first-child > th,
table.footable-details.table-bordered > thead > tr:first-child > td,
table.footable-details.table-bordered > tbody > tr:first-child > th,
table.footable-details.table-bordered > tbody > tr:first-child > td,
table.footable-details.table-bordered > tfoot > tr:first-child > th,
table.footable-details.table-bordered > tfoot > tr:first-child > td {
border-top-width: 1px;
}
div.footable-loader {
vertical-align: middle;
text-align: center;
height: 300px;
position: relative;
}
div.footable-loader > span.fooicon {
display: inline-block;
opacity: 0.3;
font-size: 30px;
line-height: 32px;
width: 32px;
height: 32px;
margin-top: -16px;
margin-left: -16px;
position: absolute;
top: 50%;
left: 50%;
-webkit-animation: fooicon-spin-r 2s infinite linear;
animation: fooicon-spin-r 2s infinite linear;
}
table.footable > tbody > tr.footable-empty > td {
vertical-align: middle;
text-align: center;
font-size: 30px;
}
table.footable > tbody > tr > td,
table.footable > tbody > tr > th {
display: none;
}
table.footable > tbody > tr.footable-empty > td,
table.footable > tbody > tr.footable-empty > th,
table.footable > tbody > tr.footable-detail-row > td,
table.footable > tbody > tr.footable-detail-row > th {
display: table-cell;
}
@-webkit-keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fooicon {
display: inline-block;
font-size: inherit;
font-family: FontAwesome !important;
font-style: normal;
font-weight: 400;
line-height: 1;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transform: translate(0, 0);
}
.fooicon:before,
.fooicon:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.fooicon-loader:before {
content: "\f01e";
}
.fooicon-plus:before {
content: "\f067";
}
.fooicon-minus:before {
content: "\f068";
}
.fooicon-search:before {
content: "\f002";
}
.fooicon-remove:before {
content: "\f00d";
}
.fooicon-sort:before {
content: "\f0dc";
}
.fooicon-sort-asc:before {
content: "\f160";
}
.fooicon-sort-desc:before {
content: "\f161";
}
.fooicon-pencil:before {
content: "\f040";
}
.fooicon-trash:before {
content: "\f1f8";
}
.fooicon-eye-close:before {
content: "\f070";
}
.fooicon-flash:before {
content: "\f0e7";
}
.fooicon-cog:before {
content: "\f013";
}

View File

@ -0,0 +1,55 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
table.footable > thead > tr.footable-filtering > th {
border-bottom-width: 1px;
font-weight: normal;
}
table.footable > thead > tr.footable-filtering > th,
table.footable.footable-filtering-right > thead > tr.footable-filtering > th {
text-align: right;
}
table.footable.footable-filtering-left > thead > tr.footable-filtering > th {
text-align: left;
}
table.footable.footable-filtering-center > thead > tr.footable-filtering > th {
text-align: center;
}
table.footable > thead > tr.footable-filtering > th div.form-group {
margin-bottom: 0;
}
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
margin-top: 5px;
}
table.footable > thead > tr.footable-filtering > th div.input-group {
width: 100%;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox {
margin: 0;
display: block;
position: relative;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox > label {
display: block;
padding-left: 20px;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox input[type="checkbox"] {
position: absolute;
margin-left: -20px;
}
@media (min-width: 768px) {
table.footable > thead > tr.footable-filtering > th div.input-group {
width: auto;
}
table.footable > thead > tr.footable-filtering > th div.form-group {
margin-left: 2px;
margin-right: 2px;
}
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
margin-top: 0;
}
}

View File

@ -0,0 +1 @@
table.footable>thead>tr.footable-filtering>th{border-bottom-width:1px;font-weight:400}table.footable.footable-filtering-right>thead>tr.footable-filtering>th,table.footable>thead>tr.footable-filtering>th{text-align:right}table.footable.footable-filtering-left>thead>tr.footable-filtering>th{text-align:left}table.footable.footable-filtering-center>thead>tr.footable-filtering>th{text-align:center}table.footable>thead>tr.footable-filtering>th div.form-group{margin-bottom:0}table.footable>thead>tr.footable-filtering>th div.form-group+div.form-group{margin-top:5px}table.footable>thead>tr.footable-filtering>th div.input-group{width:100%}table.footable>thead>tr.footable-filtering>th ul.dropdown-menu>li>a.checkbox{margin:0;display:block;position:relative}table.footable>thead>tr.footable-filtering>th ul.dropdown-menu>li>a.checkbox>label{display:block;padding-left:20px}table.footable>thead>tr.footable-filtering>th ul.dropdown-menu>li>a.checkbox input[type=checkbox]{position:absolute;margin-left:-20px}@media (min-width:768px){table.footable>thead>tr.footable-filtering>th div.input-group{width:auto}table.footable>thead>tr.footable-filtering>th div.form-group{margin-left:2px;margin-right:2px}table.footable>thead>tr.footable-filtering>th div.form-group+div.form-group{margin-top:0}}

View File

@ -0,0 +1,31 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
table.footable > tfoot > tr.footable-paging > td > ul.pagination {
margin: 10px 0 0 0;
}
table.footable > tfoot > tr.footable-paging > td > span.label {
display: inline-block;
margin: 0 0 10px 0;
padding: 4px 10px;
}
table.footable > tfoot > tr.footable-paging > td,
table.footable-paging-center > tfoot > tr.footable-paging > td {
text-align: center;
}
table.footable-paging-left > tfoot > tr.footable-paging > td {
text-align: left;
}
table.footable-paging-right > tfoot > tr.footable-paging > td {
text-align: right;
}
ul.pagination > li.footable-page {
display: none;
}
ul.pagination > li.footable-page.visible {
display: inline;
}

View File

@ -0,0 +1 @@
table.footable>tfoot>tr.footable-paging>td>ul.pagination{margin:10px 0 0}table.footable>tfoot>tr.footable-paging>td>span.label{display:inline-block;margin:0 0 10px;padding:4px 10px}table.footable-paging-center>tfoot>tr.footable-paging>td,table.footable>tfoot>tr.footable-paging>td{text-align:center}table.footable-paging-left>tfoot>tr.footable-paging>td{text-align:left}table.footable-paging-right>tfoot>tr.footable-paging>td{text-align:right}ul.pagination>li.footable-page{display:none}ul.pagination>li.footable-page.visible{display:inline}

View File

@ -0,0 +1,32 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
td.footable-sortable,
th.footable-sortable {
position: relative;
padding-right: 30px;
cursor: pointer;
}
td.footable-sortable > span.fooicon,
th.footable-sortable > span.fooicon {
position: absolute;
right: 6px;
top: 50%;
margin-top: -7px;
opacity: 0;
transition: opacity 0.3s ease-in;
}
td.footable-sortable:hover > span.fooicon,
th.footable-sortable:hover > span.fooicon {
opacity: 1;
}
td.footable-sortable.footable-asc > span.fooicon,
th.footable-sortable.footable-asc > span.fooicon,
td.footable-sortable.footable-desc > span.fooicon,
th.footable-sortable.footable-desc > span.fooicon {
opacity: 1;
}

View File

@ -0,0 +1 @@
td.footable-sortable,th.footable-sortable{position:relative;padding-right:30px;cursor:pointer}td.footable-sortable>span.fooicon,th.footable-sortable>span.fooicon{position:absolute;right:6px;top:50%;margin-top:-7px;opacity:0;transition:opacity .3s ease-in}td.footable-sortable.footable-asc>span.fooicon,td.footable-sortable.footable-desc>span.fooicon,td.footable-sortable:hover>span.fooicon,th.footable-sortable.footable-asc>span.fooicon,th.footable-sortable.footable-desc>span.fooicon,th.footable-sortable:hover>span.fooicon{opacity:1}

View File

@ -0,0 +1,727 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
/* globals - instead we house them under the .footable.table class as the root of FooTable is always the table itself. */
.footable.table, .footable.table *,
.footable-details.table, .footable-details.table * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.footable.table th,
.footable-details.table th {
text-align: left;
}
/* tables */
.footable.table,
.footable-details.table {
width: 100%;
max-width: 100%;
margin-bottom: 20px;
}
.footable.table > caption + thead > tr:first-child > th,
.footable.table > colgroup + thead > tr:first-child > th,
.footable.table > thead:first-child > tr:first-child > th,
.footable.table > caption + thead > tr:first-child > td,
.footable.table > colgroup + thead > tr:first-child > td,
.footable.table > thead:first-child > tr:first-child > td,
.footable-details.table > caption + thead > tr:first-child > th,
.footable-details.table > colgroup + thead > tr:first-child > th,
.footable-details.table > thead:first-child > tr:first-child > th,
.footable-details.table > caption + thead > tr:first-child > td,
.footable-details.table > colgroup + thead > tr:first-child > td,
.footable-details.table > thead:first-child > tr:first-child > td {
border-top: 0;
}
.footable.table > thead > tr > th,
.footable.table > tbody > tr > th,
.footable.table > tfoot > tr > th,
.footable.table > thead > tr > td,
.footable.table > tbody > tr > td,
.footable.table > tfoot > tr > td,
.footable-details.table > thead > tr > th,
.footable-details.table > tbody > tr > th,
.footable-details.table > tfoot > tr > th,
.footable-details.table > thead > tr > td,
.footable-details.table > tbody > tr > td,
.footable-details.table > tfoot > tr > td {
padding: 8px;
line-height: 1.42857143;
vertical-align: top;
border-top: 1px solid #ddd;
}
.footable.table > thead > tr > th,
.footable.table > thead > tr > td,
.footable-details.table > thead > tr > th,
.footable-details.table > thead > tr > td {
vertical-align: bottom;
border-bottom: 2px solid #ddd;
}
.footable.table-condensed > thead > tr > th,
.footable.table-condensed > tbody > tr > th,
.footable.table-condensed > tfoot > tr > th,
.footable.table-condensed > thead > tr > td,
.footable.table-condensed > tbody > tr > td,
.footable.table-condensed > tfoot > tr > td,
.footable-details.table-condensed > thead > tr > th,
.footable-details.table-condensed > tbody > tr > th,
.footable-details.table-condensed > tfoot > tr > th,
.footable-details.table-condensed > thead > tr > td,
.footable-details.table-condensed > tbody > tr > td,
.footable-details.table-condensed > tfoot > tr > td {
padding: 5px;
}
.footable.table-bordered,
.footable-details.table-bordered {
border: 1px solid #ddd;
}
.footable.table-bordered > thead > tr > th,
.footable.table-bordered > tbody > tr > th,
.footable.table-bordered > tfoot > tr > th,
.footable.table-bordered > thead > tr > td,
.footable.table-bordered > tbody > tr > td,
.footable.table-bordered > tfoot > tr > td,
.footable-details.table-bordered > thead > tr > th,
.footable-details.table-bordered > tbody > tr > th,
.footable-details.table-bordered > tfoot > tr > th,
.footable-details.table-bordered > thead > tr > td,
.footable-details.table-bordered > tbody > tr > td,
.footable-details.table-bordered > tfoot > tr > td {
border: 1px solid #ddd;
}
.footable.table-bordered > thead > tr > th,
.footable.table-bordered > thead > tr > td,
.footable-details.table-bordered > thead > tr > th,
.footable-details.table-bordered > thead > tr > td {
border-bottom-width: 2px;
}
.footable.table-striped > tbody > tr:nth-child(odd),
.footable-details.table-striped > tbody > tr:nth-child(odd) {
background-color: #f9f9f9;
}
.footable.table-hover > tbody > tr:hover,
.footable-details.table-hover > tbody > tr:hover {
background-color: #f5f5f5;
}
/* buttons */
.footable .btn {
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
-webkit-appearance: button;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
overflow: visible;
text-transform: none;
}
.footable .btn:hover,
.footable .btn:focus,
.footable .btn.focus {
color: #333;
text-decoration: none;
}
.footable .btn-default {
color: #333;
background-color: #fff;
border-color: #ccc;
}
.footable .btn-default:hover,
.footable .btn-default:focus,
.footable .btn-default.focus,
.footable .btn-default:active,
.footable .btn-default.active,
.footable .open > .dropdown-toggle.btn-default {
color: #333;
background-color: #e6e6e6;
border-color: #adadad;
}
.footable .btn-primary {
color: #fff;
background-color: #337ab7;
border-color: #2e6da4;
}
.footable .btn-primary:hover,
.footable .btn-primary:focus,
.footable .btn-primary.focus,
.footable .btn-primary:active,
.footable .btn-primary.active,
.footable .open > .dropdown-toggle.btn-primary {
color: #fff;
background-color: #286090;
border-color: #204d74;
}
/* caret */
.footable .caret {
display: inline-block;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: 4px solid;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
.footable .btn .caret {
margin-left: 0;
}
/* form-group */
.form-group {
margin-bottom: 15px;
}
/* form-control */
.footable .form-control {
display: block;
width: 100%;
height: 34px;
padding: 6px 12px;
margin: 0;
font-family: inherit;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
/* input-group */
.footable .input-group {
position: relative;
display: table;
border-collapse: separate;
}
.footable .input-group .form-control {
position: relative;
z-index: 2;
float: left;
width: 100%;
margin-bottom: 0;
}
.footable .input-group-btn {
position: relative;
font-size: 0;
white-space: nowrap;
}
.footable .input-group-addon,
.footable .input-group-btn {
width: 1%;
white-space: nowrap;
vertical-align: middle;
}
.footable .input-group-addon,
.footable .input-group-btn,
.footable .input-group .form-control {
display: table-cell;
}
.footable .input-group-btn > .btn + .btn,
.footable .input-group-btn:last-child > .btn,
.footable .input-group-btn:last-child > .btn-group {
margin-left: -1px;
}
.footable .input-group-btn > .btn {
position: relative;
}
.footable .input-group-btn > .btn:hover,
.footable .input-group-btn > .btn:focus,
.footable .input-group-btn > .btn:active {
z-index: 2;
}
.footable .input-group .form-control:first-child,
.footable .input-group-addon:first-child,
.footable .input-group-btn:first-child > .btn,
.footable .input-group-btn:first-child > .btn-group > .btn,
.footable .input-group-btn:first-child > .dropdown-toggle,
.footable .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
.footable .input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.footable .input-group .form-control:last-child,
.footable .input-group-addon:last-child,
.footable .input-group-btn:last-child > .btn,
.footable .input-group-btn:last-child > .btn-group > .btn,
.footable .input-group-btn:last-child > .dropdown-toggle,
.footable .input-group-btn:first-child > .btn:not(:first-child),
.footable .input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
/* checkboxes & radios */
.footable .radio,
.footable .checkbox {
position: relative;
display: block;
margin-top: 10px;
margin-bottom: 10px;
}
.footable .radio label,
.footable .checkbox label {
max-width: 100%;
min-height: 20px;
padding-left: 20px;
margin-bottom: 0;
font-weight: 400;
cursor: pointer;
}
.footable .radio input[type=radio],
.footable .radio-inline input[type=radio],
.footable .checkbox input[type=checkbox],
.footable .checkbox-inline input[type=checkbox] {
position: absolute;
margin: 4px 0 0 -20px;
line-height: normal;
}
/* dropdown-menu */
.footable .dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
font-size: 14px;
text-align: left;
list-style: none;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, .15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.footable .open > .dropdown-menu {
display: block;
}
.footable .dropdown-menu-right {
right: 0;
left: auto;
}
.footable .dropdown-menu > li > a {
display: block;
padding: 3px 20px;
clear: both;
font-weight: 400;
line-height: 1.42857143;
color: #333;
white-space: nowrap;
}
.footable .dropdown-menu > li > a:hover,
.footable .dropdown-menu > li > a:focus {
color: #262626;
text-decoration: none;
background-color: #f5f5f5;
}
/* pagination */
.footable .pagination {
display: inline-block;
padding-left: 0;
margin: 20px 0;
border-radius: 4px;
}
.footable .pagination > li {
display: inline;
}
.footable .pagination > li:first-child > a,
.footable .pagination > li:first-child > span {
margin-left: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.footable .pagination > li > a,
.footable .pagination > li > span {
position: relative;
float: left;
padding: 6px 12px;
margin-left: -1px;
line-height: 1.42857143;
color: #337ab7;
text-decoration: none;
background-color: #fff;
border: 1px solid #ddd;
}
.footable .pagination > li > a:hover,
.footable .pagination > li > span:hover,
.footable .pagination > li > a:focus,
.footable .pagination > li > span:focus {
color: #23527c;
background-color: #eee;
border-color: #ddd;
}
.footable .pagination > .active > a,
.footable .pagination > .active > span,
.footable .pagination > .active > a:hover,
.footable .pagination > .active > span:hover,
.footable .pagination > .active > a:focus,
.footable .pagination > .active > span:focus {
z-index: 2;
color: #fff;
cursor: default;
background-color: #337ab7;
border-color: #337ab7;
}
.footable .pagination > .disabled > span,
.footable .pagination > .disabled > span:hover,
.footable .pagination > .disabled > span:focus,
.footable .pagination > .disabled > a,
.footable .pagination > .disabled > a:hover,
.footable .pagination > .disabled > a:focus {
color: #777;
cursor: not-allowed;
background-color: #fff;
border-color: #ddd;
}
/* labels */
.footable .label {
display: inline;
padding: .2em .6em .3em;
font-size: 75%;
font-weight: 700;
line-height: 1;
color: #fff;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: .25em;
}
.footable .label-default {
background-color: #777;
}
/* wells */
.footable-loader.well {
min-height: 20px;
padding: 19px;
margin-bottom: 20px;
background-color: #f5f5f5;
border: 1px solid #e3e3e3;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
}
/* screen reader only */
.footable .sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}
/* form-inline */
@media (min-width: 768px) {
.footable .form-inline .form-group {
display:inline-block;
margin-bottom: 0;
vertical-align: middle
}
.footable .form-inline .form-control {
display: inline-block;
width: auto;
vertical-align: middle
}
.footable .form-inline .input-group {
display: inline-table;
vertical-align: middle
}
.footable .form-inline .input-group .input-group-addon,
.footable .form-inline .input-group .input-group-btn,
.footable .form-inline .input-group .form-control {
width: auto
}
.footable .form-inline .input-group>.form-control {
width: 100%
}
}
table.footable,
table.footable-details {
position: relative;
width: 100%;
border-spacing: 0;
border-collapse: collapse;
}
table.footable-details {
margin-bottom: 0;
}
table > tbody > tr > td > span.footable-toggle {
margin-right: 8px;
opacity: 0.3;
}
table > tbody > tr > td > span.footable-toggle.last-column {
margin-left: 8px;
float: right;
}
table.table-condensed > tbody > tr > td > span.footable-toggle {
margin-right: 5px;
}
table.footable-details > tbody > tr > th:nth-child(1) {
min-width: 40px;
width: 120px;
}
table.footable-details > tbody > tr > td:nth-child(2) {
word-break: break-all;
}
table.footable-details > thead > tr:first-child > th,
table.footable-details > thead > tr:first-child > td,
table.footable-details > tbody > tr:first-child > th,
table.footable-details > tbody > tr:first-child > td,
table.footable-details > tfoot > tr:first-child > th,
table.footable-details > tfoot > tr:first-child > td {
border-top-width: 0;
}
table.footable-details.table-bordered > thead > tr:first-child > th,
table.footable-details.table-bordered > thead > tr:first-child > td,
table.footable-details.table-bordered > tbody > tr:first-child > th,
table.footable-details.table-bordered > tbody > tr:first-child > td,
table.footable-details.table-bordered > tfoot > tr:first-child > th,
table.footable-details.table-bordered > tfoot > tr:first-child > td {
border-top-width: 1px;
}
div.footable-loader {
vertical-align: middle;
text-align: center;
height: 300px;
position: relative;
}
div.footable-loader > span.fooicon {
display: inline-block;
opacity: 0.3;
font-size: 30px;
line-height: 32px;
width: 32px;
height: 32px;
margin-top: -16px;
margin-left: -16px;
position: absolute;
top: 50%;
left: 50%;
-webkit-animation: fooicon-spin-r 2s infinite linear;
animation: fooicon-spin-r 2s infinite linear;
}
table.footable > tbody > tr.footable-empty > td {
vertical-align: middle;
text-align: center;
font-size: 30px;
}
table.footable > tbody > tr > td,
table.footable > tbody > tr > th {
display: none;
}
table.footable > tbody > tr.footable-empty > td,
table.footable > tbody > tr.footable-empty > th,
table.footable > tbody > tr.footable-detail-row > td,
table.footable > tbody > tr.footable-detail-row > th {
display: table-cell;
}
@-webkit-keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fooicon-spin-r {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fooicon {
display: inline-block;
font-size: inherit;
font-family: FontAwesome !important;
font-style: normal;
font-weight: 400;
line-height: 1;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transform: translate(0, 0);
}
.fooicon:before,
.fooicon:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.fooicon-loader:before {
content: "\f01e";
}
.fooicon-plus:before {
content: "\f067";
}
.fooicon-minus:before {
content: "\f068";
}
.fooicon-search:before {
content: "\f002";
}
.fooicon-remove:before {
content: "\f00d";
}
.fooicon-sort:before {
content: "\f0dc";
}
.fooicon-sort-asc:before {
content: "\f160";
}
.fooicon-sort-desc:before {
content: "\f161";
}
.fooicon-pencil:before {
content: "\f040";
}
.fooicon-trash:before {
content: "\f1f8";
}
.fooicon-eye-close:before {
content: "\f070";
}
.fooicon-flash:before {
content: "\f0e7";
}
.fooicon-cog:before {
content: "\f013";
}
table.footable > thead > tr.footable-filtering > th {
border-bottom-width: 1px;
font-weight: normal;
}
table.footable > thead > tr.footable-filtering > th,
table.footable.footable-filtering-right > thead > tr.footable-filtering > th {
text-align: right;
}
table.footable.footable-filtering-left > thead > tr.footable-filtering > th {
text-align: left;
}
table.footable.footable-filtering-center > thead > tr.footable-filtering > th {
text-align: center;
}
table.footable > thead > tr.footable-filtering > th div.form-group {
margin-bottom: 0;
}
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
margin-top: 5px;
}
table.footable > thead > tr.footable-filtering > th div.input-group {
width: 100%;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox {
margin: 0;
display: block;
position: relative;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox > label {
display: block;
padding-left: 20px;
}
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox input[type="checkbox"] {
position: absolute;
margin-left: -20px;
}
@media (min-width: 768px) {
table.footable > thead > tr.footable-filtering > th div.input-group {
width: auto;
}
table.footable > thead > tr.footable-filtering > th div.form-group {
margin-left: 2px;
margin-right: 2px;
}
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
margin-top: 0;
}
}
td.footable-sortable,
th.footable-sortable {
position: relative;
padding-right: 30px;
cursor: pointer;
}
td.footable-sortable > span.fooicon,
th.footable-sortable > span.fooicon {
position: absolute;
right: 6px;
top: 50%;
margin-top: -7px;
opacity: 0;
transition: opacity 0.3s ease-in;
}
td.footable-sortable:hover > span.fooicon,
th.footable-sortable:hover > span.fooicon {
opacity: 1;
}
td.footable-sortable.footable-asc > span.fooicon,
th.footable-sortable.footable-asc > span.fooicon,
td.footable-sortable.footable-desc > span.fooicon,
th.footable-sortable.footable-desc > span.fooicon {
opacity: 1;
}
table.footable > tfoot > tr.footable-paging > td > ul.pagination {
margin: 10px 0 0 0;
}
table.footable > tfoot > tr.footable-paging > td > span.label {
display: inline-block;
margin: 0 0 10px 0;
padding: 4px 10px;
}
table.footable > tfoot > tr.footable-paging > td,
table.footable-paging-center > tfoot > tr.footable-paging > td {
text-align: center;
}
table.footable-paging-left > tfoot > tr.footable-paging > td {
text-align: left;
}
table.footable-paging-right > tfoot > tr.footable-paging > td {
text-align: right;
}
ul.pagination > li.footable-page {
display: none;
}
ul.pagination > li.footable-page.visible {
display: inline;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

View File

@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,925 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
(function(F){
F.Filter = F.Class.extend(/** @lends FooTable.Filter */{
/**
* The filter object contains the query to filter by and the columns to apply it to.
* @constructs
* @extends FooTable.Class
* @param {string} name - The name for the filter.
* @param {string} query - The query for the filter.
* @param {Array.<FooTable.Column>} columns - The columns to apply the query to.
* @param {string} [space="AND"] - How the query treats space chars.
* @param {boolean} [connectors=true] - Whether or not to replace phrase connectors (+.-_) with spaces.
* @returns {FooTable.Filter}
*/
construct: function(name, query, columns, space, connectors){
/**
* The name of the filter.
* @instance
* @type {string}
*/
this.name = name;
/**
* A string specifying how the filter treats space characters. Can be either "OR" or "AND".
* @instance
* @type {string}
*/
this.space = F.is.string(space) && (space == 'OR' || space == 'AND') ? space : 'AND';
/**
* Whether or not to replace phrase connectors (+.-_) with spaces before executing the query.
* @instance
* @type {boolean}
*/
this.connectors = F.is.boolean(connectors) ? connectors : true;
/**
* The query for the filter.
* @instance
* @type {(string|FooTable.Query)}
*/
this.query = new F.Query(query, this.space, this.connectors);
/**
* The columns to apply the query to.
* @instance
* @type {Array.<FooTable.Column>}
*/
this.columns = columns;
},
/**
* Checks if the current filter matches the supplied string.
* If the current query property is a string it will be auto converted to a {@link FooTable.Query} object to perform the match.
* @instance
* @param {string} str - The string to check.
* @returns {boolean}
*/
match: function(str){
if (!F.is.string(str)) return false;
if (F.is.string(this.query)){
this.query = new F.Query(this.query, this.space, this.connectors);
}
return this.query instanceof F.Query ? this.query.match(str) : false;
},
/**
* Checks if the current filter matches the supplied {@link FooTable.Row}.
* @instance
* @param {FooTable.Row} row - The row to check.
* @returns {boolean}
*/
matchRow: function(row){
var self = this, text = F.arr.map(row.cells, function(cell){
return F.arr.contains(self.columns, cell.column) ? cell.filterValue : null;
}).join(' ');
return self.match(text);
}
});
})(FooTable);
(function ($, F) {
F.Filtering = F.Component.extend(/** @lends FooTable.Filtering */{
/**
* The filtering component adds a search input and column selector dropdown to the table allowing users to filter the using space delimited queries.
* @constructs
* @extends FooTable.Component
* @param {FooTable.Table} table - The parent {@link FooTable.Table} object for the component.
* @returns {FooTable.Filtering}
*/
construct: function (table) {
// call the constructor of the base class
this._super(table, table.o.filtering.enabled);
/* PUBLIC */
/**
* The filters to apply to the current {@link FooTable.Rows#array}.
* @instance
* @type {Array.<FooTable.Filter>}
*/
this.filters = table.o.filtering.filters;
/**
* The delay in milliseconds before the query is auto applied after a change.
* @instance
* @type {number}
*/
this.delay = table.o.filtering.delay;
/**
* The minimum number of characters allowed in the search input before it is auto applied.
* @instance
* @type {number}
*/
this.min = table.o.filtering.min;
/**
* Specifies how whitespace in a filter query is handled.
* @instance
* @type {string}
*/
this.space = table.o.filtering.space;
/**
* Whether or not to replace phrase connectors (+.-_) with spaces before executing the query.
* @instance
* @type {boolean}
*/
this.connectors = table.o.filtering.connectors;
/**
* The placeholder text to display within the search $input.
* @instance
* @type {string}
*/
this.placeholder = table.o.filtering.placeholder;
/**
* The position of the $search input within the filtering rows cell.
* @type {string}
*/
this.position = table.o.filtering.position;
/**
* The jQuery row object that contains all the filtering specific elements.
* @instance
* @type {jQuery}
*/
this.$row = null;
/**
* The jQuery cell object that contains the search input and column selector.
* @instance
* @type {jQuery}
*/
this.$cell = null;
/**
* The jQuery object of the column selector dropdown.
* @instance
* @type {jQuery}
*/
this.$dropdown = null;
/**
* The jQuery object of the search input.
* @instance
* @type {jQuery}
*/
this.$input = null;
/**
* The jQuery object of the search button.
* @instance
* @type {jQuery}
*/
this.$button = null;
/* PRIVATE */
/**
* The timeout ID for the filter changed event.
* @instance
* @private
* @type {?number}
*/
this._filterTimeout = null;
},
/* PROTECTED */
/**
* Checks the supplied data and options for the filtering component.
* @instance
* @protected
* @param {object} data - The jQuery data object from the parent table.
* @fires FooTable.Filtering#"preinit.ft.filtering"
*/
preinit: function(data){
var self = this;
/**
* The preinit.ft.filtering event is raised before the UI is created and provides the tables jQuery data object for additional options parsing.
* Calling preventDefault on this event will disable the component.
* @event FooTable.Filtering#"preinit.ft.filtering"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {object} data - The jQuery data object of the table raising the event.
*/
this.ft.raise('preinit.ft.filtering').then(function(){
// first check if filtering is enabled via the class being applied
if (self.ft.$el.hasClass('footable-filtering'))
self.enabled = true;
// then check if the data-filtering-enabled attribute has been set
self.enabled = F.is.boolean(data.filtering)
? data.filtering
: self.enabled;
// if filtering is not enabled exit early as we don't need to do anything else
if (!self.enabled) return;
self.space = F.is.string(data.filterSpace)
? data.filterSpace
: self.space;
self.min = F.is.number(data.filterMin)
? data.filterMin
: self.min;
self.connectors = F.is.number(data.filterConnectors)
? data.filterConnectors
: self.connectors;
self.delay = F.is.number(data.filterDelay)
? data.filterDelay
: self.delay;
self.placeholder = F.is.number(data.filterPlaceholder)
? data.filterPlaceholder
: self.placeholder;
self.filters = F.is.array(data.filterFilters)
? self.ensure(data.filterFilters)
: self.ensure(self.filters);
if (self.ft.$el.hasClass('footable-filtering-left'))
self.position = 'left';
if (self.ft.$el.hasClass('footable-filtering-center'))
self.position = 'center';
if (self.ft.$el.hasClass('footable-filtering-right'))
self.position = 'right';
self.position = F.is.string(data.filterPosition)
? data.filterPosition
: self.position;
},function(){
self.enabled = false;
});
},
/**
* Initializes the filtering component for the plugin.
* @instance
* @protected
* @fires FooTable.Filtering#"init.ft.filtering"
*/
init: function () {
var self = this;
/**
* The init.ft.filtering event is raised before its UI is generated.
* Calling preventDefault on this event will disable the component.
* @event FooTable.Filtering#"init.ft.filtering"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
*/
this.ft.raise('init.ft.filtering').then(function(){
self.$create();
}, function(){
self.enabled = false;
});
},
/**
* Destroys the filtering component removing any UI from the table.
* @instance
* @protected
* @fires FooTable.Filtering#"destroy.ft.filtering"
*/
destroy: function () {
/**
* The destroy.ft.filtering event is raised before its UI is removed.
* Calling preventDefault on this event will prevent the component from being destroyed.
* @event FooTable.Filtering#"destroy.ft.filtering"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
*/
var self = this;
this.ft.raise('destroy.ft.filtering').then(function(){
self.ft.$el.removeClass('footable-filtering')
.find('thead > tr.footable-filtering').remove();
});
},
/**
* Creates the filtering UI from the current options setting the various jQuery properties of this component.
* @instance
* @protected
* @this FooTable.Filtering
*/
$create: function () {
var self = this;
// generate the cell that actually contains all the UI.
var $form_grp = $('<div/>', {'class': 'form-group'})
.append($('<label/>', {'class': 'sr-only', text: 'Search'})),
$input_grp = $('<div/>', {'class': 'input-group'}).appendTo($form_grp),
$input_grp_btn = $('<div/>', {'class': 'input-group-btn'}),
$dropdown_toggle = $('<button/>', {type: 'button', 'class': 'btn btn-default dropdown-toggle'})
.on('click', { self: self }, self._onDropdownToggleClicked)
.append($('<span/>', {'class': 'caret'})),
position;
switch (self.position){
case 'left': position = 'footable-filtering-left'; break;
case 'center': position = 'footable-filtering-center'; break;
default: position = 'footable-filtering-right'; break;
}
self.ft.$el.addClass('footable-filtering').addClass(position);
// add it to a row and then populate it with the search input and column selector dropdown.
self.$row = $('<tr/>', {'class': 'footable-filtering'}).prependTo(self.ft.$el.children('thead'));
self.$cell = $('<th/>').attr('colspan', self.ft.columns.visibleColspan).appendTo(self.$row);
self.$form = $('<form/>', {'class': 'form-inline'}).append($form_grp).appendTo(self.$cell);
self.$input = $('<input/>', {type: 'text', 'class': 'form-control', placeholder: self.placeholder});
self.$button = $('<button/>', {type: 'button', 'class': 'btn btn-primary'})
.on('click', { self: self }, self._onSearchButtonClicked)
.append($('<span/>', {'class': 'fooicon fooicon-search'}));
self.$dropdown = $('<ul/>', {'class': 'dropdown-menu dropdown-menu-right'}).append(
F.arr.map(self.ft.columns.array, function (col) {
return col.filterable && col.visible ? $('<li/>').append(
$('<a/>', {'class': 'checkbox'}).append(
$('<label/>', {text: col.title}).prepend(
$('<input/>', {type: 'checkbox', checked: true}).data('__FooTableColumn__', col)
)
)
) : null;
})
);
if (self.delay > 0){
self.$input.on('keypress keyup', { self: self }, self._onSearchInputChanged);
self.$dropdown.on('click', 'input[type="checkbox"]', {self: self}, self._onSearchColumnClicked);
}
$input_grp_btn.append(self.$button, $dropdown_toggle, self.$dropdown);
$input_grp.append(self.$input, $input_grp_btn);
},
/**
* Performs the filtering of rows before they are appended to the page.
* @instance
* @protected
*/
predraw: function(){
if (F.is.emptyArray(this.filters))
return;
var self = this;
self.ft.rows.array = $.grep(self.ft.rows.array, function(r){
return r.filtered(self.filters);
});
},
/**
* As the rows are drawn by the {@link FooTable.Rows#draw} method this simply updates the colspan for the UI.
* @instance
* @protected
*/
draw: function(){
this.$cell.attr('colspan', this.ft.columns.visibleColspan);
},
/* PUBLIC */
/**
* Adds or updates the filter using the supplied name, query and columns.
* @param {string} name - The name for the filter.
* @param {(string|FooTable.Query)} query - The query for the filter.
* @param {(Array.<number>|Array.<string>|Array.<FooTable.Column>)} columns - The columns to apply the filter to.
*/
addFilter: function(name, query, columns){
var f = F.arr.first(this.filters, function(f){ return f.name == name; });
if (f instanceof F.Filter){
f.name = name;
f.query = query;
f.columns = columns;
} else {
this.filters.push({name: name, query: query, columns: columns});
}
},
/**
* Removes the filter using the supplied name if it exists.
* @param {string} name - The name of the filter to remove.
*/
removeFilter: function(name){
F.arr.remove(this.filters, function(f){ return f.name == name; });
},
/**
* Creates a new search filter from the supplied parameters and applies it to the rows. If no parameters are supplied the current search input value
* and selected columns are used to create or update the search filter. If there is no search input value then the search filter is removed.
* @instance
* @param {string} [query] - The query to filter the rows by.
* @param {(Array.<string>|Array.<number>|Array.<FooTable.Column>)} [columns] - The columns to apply the filter to in each row.
* @returns {jQuery.Promise}
* @fires FooTable.Filtering#"before.ft.filtering"
* @fires FooTable.Filtering#"after.ft.filtering"
*/
filter: function(query, columns){
if (F.is.undef(query)){
query = $.trim(this.$input.val() || '');
} else {
this.$input.val(query);
}
if (!F.is.emptyString(query)) {
this.addFilter('search', query, columns);
} else {
this.removeFilter('search');
}
this.$button.children('.fooicon').removeClass('fooicon-search').addClass('fooicon-remove');
return this._filter();
},
/**
* Removes the current search filter.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Filtering#"before.ft.filtering"
* @fires FooTable.Filtering#"after.ft.filtering"
*/
clear: function(){
this.$button.children('.fooicon').removeClass('fooicon-remove').addClass('fooicon-search');
this.$input.val(null);
this.removeFilter('search');
return this._filter();
},
/**
* Gets an array of {@link FooTable.Column} to apply the search filter to. This also doubles as the default columns for filters which do not specify any columns.
* @instance
* @returns {Array.<FooTable.Column>}
*/
columns: function(){
if (F.is.jq(this.$dropdown)){
// if we have a dropdown containing the column names get the selected columns from there
return this.$dropdown.find('input:checked').map(function(){
return $(this).data('__FooTableColumn__');
}).get();
} else {
// otherwise find all columns that are set to be filterable.
return this.ft.columns.get(function(c){ return c.filterable; });
}
},
/**
* Takes an array of plain objects containing the filter values or actual {@link FooTable.Filter} objects and ensures that an array of only {@link FooTable.Filter} is returned.
* If supplied a plain object that object must contain a name, query and columns properties which are used to create a new {@link FooTable.Filter}.
* @instance
* @param {({name: string, query: (string|FooTable.Query), columns: (Array.<string>|Array.<number>|Array.<FooTable.Column>)}|Array.<FooTable.Filter>)} filters - The array of filters to check.
* @returns {Array.<FooTable.Filter>}
*/
ensure: function(filters){
var self = this, parsed = [], filterable = self.columns();
if (!F.is.emptyArray(filters)){
F.arr.each(filters, function(f){
if (F.is.object(f) && (!F.is.emptyString(f.query) || f.query instanceof F.Query)) {
f.name = F.is.emptyString(f.name) ? 'anon' : f.name;
f.columns = F.is.emptyArray(f.columns) ? filterable : self.ft.columns.ensure(f.columns);
parsed.push(f instanceof F.Filter ? f : new F.Filter(f.name, f.query, f.columns, self.space, self.connectors));
}
});
}
return parsed;
},
/* PRIVATE */
/**
* Performs the required steps to handle filtering including the raising of the {@link FooTable.Filtering#"before.ft.filtering"} and {@link FooTable.Filtering#"after.ft.filtering"} events.
* @instance
* @private
* @returns {jQuery.Promise}
* @fires FooTable.Filtering#"before.ft.filtering"
* @fires FooTable.Filtering#"after.ft.filtering"
*/
_filter: function(){
var self = this;
self.filters = self.ensure(self.filters);
/**
* The before.ft.filtering event is raised before a filter is applied and allows listeners to modify the filter or cancel it completely by calling preventDefault on the jQuery.Event object.
* @event FooTable.Filtering#"before.ft.filtering"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {Array.<FooTable.Filter>} filters - The filters that are about to be applied.
*/
return self.ft.raise('before.ft.filtering', [self.filters]).then(function(){
self.filters = self.ensure(self.filters);
return self.ft.draw().then(function(){
/**
* The after.ft.filtering event is raised after a filter has been applied.
* @event FooTable.Filtering#"after.ft.filtering"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {FooTable.Filter} filter - The filters that were applied.
*/
self.ft.raise('after.ft.filtering', [self.filters]);
});
});
},
/**
* Handles the change event for the {@link FooTable.Filtering#$input}.
* @instance
* @private
* @param {jQuery.Event} e - The event object for the event.
*/
_onSearchInputChanged: function (e) {
var self = e.data.self;
var alpha = e.type == 'keypress' && !F.is.emptyString(String.fromCharCode(e.charCode)),
ctrl = e.type == 'keyup' && (e.which == 8 || e.which == 46); // backspace & delete
// if alphanumeric characters or specific control characters
if(alpha || ctrl) {
if (e.which == 13) e.preventDefault();
if (self._filterTimeout != null) clearTimeout(self._filterTimeout);
self._filterTimeout = setTimeout(function(){
self._filterTimeout = null;
self.filter();
}, self.delay);
}
},
/**
* Handles the click event for the {@link FooTable.Filtering#$button}.
* @instance
* @private
* @param {jQuery.Event} e - The event object for the event.
*/
_onSearchButtonClicked: function (e) {
e.preventDefault();
var self = e.data.self;
if (self._filterTimeout != null) clearTimeout(self._filterTimeout);
var $icon = self.$button.children('.fooicon');
if ($icon.hasClass('fooicon-remove')) self.clear();
else self.filter();
},
/**
* Handles the click event for the column checkboxes in the {@link FooTable.Filtering#$dropdown}.
* @instance
* @private
* @param {jQuery.Event} e - The event object for the event.
*/
_onSearchColumnClicked: function (e) {
var self = e.data.self;
if (self._filterTimeout != null) clearTimeout(self._filterTimeout);
self._filterTimeout = setTimeout(function(){
self._filterTimeout = null;
var $icon = self.$button.children('.fooicon');
if ($icon.hasClass('fooicon-remove')){
$icon.removeClass('fooicon-remove').addClass('fooicon-search');
self.filter();
}
}, self.delay);
},
/**
* Handles the click event for the {@link FooTable.Filtering#$dropdown} toggle.
* @instance
* @private
* @param {jQuery.Event} e - The event object for the event.
*/
_onDropdownToggleClicked: function (e) {
e.preventDefault();
e.stopPropagation();
var self = e.data.self;
self.$dropdown.parent().toggleClass('open');
if (self.$dropdown.parent().hasClass('open')) $(document).on('click.footable', { self: self }, self._onDocumentClicked);
else $(document).off('click.footable', self._onDocumentClicked);
},
/**
* Checks all click events when the dropdown is visible and closes the menu if the target is not the dropdown.
* @instance
* @private
* @param {jQuery.Event} e - The event object for the event.
*/
_onDocumentClicked: function(e){
if ($(e.target).closest('.dropdown-menu').length == 0){
e.preventDefault();
var self = e.data.self;
self.$dropdown.parent().removeClass('open');
$(document).off('click.footable', self._onDocumentClicked);
}
}
});
F.components.core.register('filtering', F.Filtering, 10);
})(jQuery, FooTable);
(function(F){
F.Query = F.Class.extend(/** @lends FooTable.Query */{
/**
* The query object is used to parse and test the filtering component's queries
* @constructs
* @extends FooTable.Class
* @param {string} query - The string value of the query.
* @param {string} [space="AND"] - How the query treats whitespace.
* @param {boolean} [connectors=true] - Whether or not to replace phrase connectors (+.-_) with spaces.
* @returns {FooTable.Query}
*/
construct: function(query, space, connectors){
/* PRIVATE */
/**
* Holds the previous value of the query and is used internally in the {@link FooTable.Query#val} method.
* @type {string}
* @private
*/
this._original = null;
/**
* Holds the value for the query. Access to this variable is provided through the {@link FooTable.Query#val} method.
* @type {string}
* @private
*/
this._value = null;
/* PUBLIC */
/**
* A string specifying how the query treats whitespace. Can be either "OR" or "AND".
* @type {string}
*/
this.space = F.is.string(space) && (space == 'OR' || space == 'AND') ? space : 'AND';
/**
* Whether or not to replace phrase connectors (+.-_) with spaces before executing the query.
* @instance
* @type {boolean}
*/
this.connectors = F.is.boolean(connectors) ? connectors : true;
/**
* The left side of the query if one exists. OR takes precedence over AND.
* @type {FooTable.Query}
* @example <caption>The below shows what is meant by the "left" side of a query</caption>
* query = "Dave AND Mary" - "Dave" is the left side of the query.
* query = "Dave AND Mary OR John" - "Dave and Mary" is the left side of the query.
*/
this.left = null;
/**
* The right side of the query if one exists. OR takes precedence over AND.
* @type {FooTable.Query}
* @example <caption>The below shows what is meant by the "right" side of a query</caption>
* query = "Dave AND Mary" - "Mary" is the right side of the query.
* query = "Dave AND Mary OR John" - "John" is the right side of the query.
*/
this.right = null;
/**
* The parsed parts of the query. This contains the information used to actually perform a match against a string.
* @type {Array}
*/
this.parts = [];
/**
* The type of operand to apply to the results of the individual parts of the query.
* @type {string}
*/
this.operator = null;
this.val(query);
},
/**
* Gets or sets the value for the query. During set the value is parsed setting all properties as required.
* @param {string} [value] - If supplied the value to set for this query.
* @returns {(string|undefined)}
*/
val: function(value){
// get
if (F.is.emptyString(value)) return this._value;
// set
if (F.is.emptyString(this._original)) this._original = value;
else if (this._original == value) return;
this._value = value;
this._parse();
},
/**
* Tests the supplied string against the query.
* @param {string} str - The string to test.
* @returns {boolean}
*/
match: function(str){
if (F.is.emptyString(this.operator) || this.operator === 'OR')
return this._left(str, false) || this._match(str, false) || this._right(str, false);
if (this.operator === 'AND')
return this._left(str, true) && this._match(str, true) && this._right(str, true);
},
/**
* Matches this queries parts array against the supplied string.
* @param {string} str - The string to test.
* @param {boolean} def - The default value to return based on the operand.
* @returns {boolean}
* @private
*/
_match: function(str, def){
var self = this, result = false;
if (F.is.emptyArray(self.parts) && self.left instanceof F.Query) return def;
if (F.is.emptyArray(self.parts)) return result;
if (self.space === 'OR'){
// with OR we give the str every part to test and if any match it is a success, we do exit early if a negated match occurs
F.arr.each(self.parts, function(p){
var match = F.str.contains(str, p.query, true);
if (match && !p.negate) result = true;
if (match && p.negate) {
result = false;
return result;
}
});
} else {
// otherwise with AND we check until the first failure and then exit
result = true;
F.arr.each(self.parts, function(p){
var match = F.str.contains(str, p.query, true);
if ((!match && !p.negate) || (match && p.negate)) result = false;
return result;
});
}
return result;
},
/**
* Matches the left side of the query if one exists with the supplied string.
* @param {string} str - The string to test.
* @param {boolean} def - The default value to return based on the operand.
* @returns {boolean}
* @private
*/
_left: function(str, def){
return (this.left instanceof F.Query) ? this.left.match(str) : def;
},
/**
* Matches the right side of the query if one exists with the supplied string.
* @param {string} str - The string to test.
* @param {boolean} def - The default value to return based on the operand.
* @returns {boolean}
* @private
*/
_right: function(str, def){
return (this.right instanceof F.Query) ? this.right.match(str) : def;
},
/**
* Parses the private {@link FooTable.Query#_value} property and populates the object.
* @private
*/
_parse: function(){
if (F.is.emptyString(this._value)) return;
// OR takes precedence so test for it first
if (/\sOR\s/.test(this._value)){
// we have an OR so split the value on the first occurrence of OR to get the left and right sides of the statement
this.operator = 'OR';
var or = this._value.split(/(?:\sOR\s)(.*)?/);
this.left = new F.Query(or[0], this.space, this.connectors);
this.right = new F.Query(or[1], this.space, this.connectors);
} else if (/\sAND\s/.test(this._value)) {
// there are no more OR's so start with AND
this.operator = 'AND';
var and = this._value.split(/(?:\sAND\s)(.*)?/);
this.left = new F.Query(and[0], this.space, this.connectors);
this.right = new F.Query(and[1], this.space, this.connectors);
} else {
// we have no more statements to parse so set the parts array by parsing each part of the remaining query
var self = this;
this.parts = F.arr.map(this._value.match(/(?:[^\s"]+|"[^"]*")+/g), function(str){
return self._part(str);
});
}
},
/**
* Parses a single part of a query into an object to use during matching.
* @param {string} str - The string representation of the part.
* @returns {{query: string, negate: boolean, phrase: boolean, exact: boolean}}
* @private
*/
_part: function(str){
var p = {
query: str,
negate: false,
phrase: false,
exact: false
};
// support for NEGATE operand - (minus sign). Remove this first so we can get onto phrase checking
if (F.str.startsWith(p.query, '-')){
p.query = F.str.from(p.query, '-');
p.negate = true;
}
// support for PHRASES (exact matches)
if (/^"(.*?)"$/.test(p.query)){ // if surrounded in quotes strip them and nothing else
p.query = p.query.replace(/^"(.*?)"$/, '$1');
p.phrase = true;
p.exact = true;
} else if (this.connectors && /(?:\w)+?([-_\+\.])(?:\w)+?/.test(p.query)) { // otherwise replace supported phrase connectors (-_+.) with spaces
p.query = p.query.replace(/(?:\w)+?([-_\+\.])(?:\w)+?/g, function(match, p1){
return match.replace(p1, ' ');
});
p.phrase = true;
}
return p;
}
});
})(FooTable);
(function(F){
/**
* The value used by the filtering component during filter operations. Must be a string and can be set using the data-filter-value attribute on the cell itself.
* If this is not supplied it is set to the result of the toString method called on the value for the cell. Added by the {@link FooTable.Filtering} component.
* @type {string}
* @default null
*/
F.Cell.prototype.filterValue = null;
// this is used to define the filtering specific properties on cell creation
F.Cell.prototype.__filtering_define__ = function(valueOrElement){
this.filterValue = this.column.filterValue.call(this.column, valueOrElement);
};
// this is used to update the filterValue property whenever the cell value is changed
F.Cell.prototype.__filtering_val__ = function(value){
if (F.is.defined(value)){
// set only
this.filterValue = this.column.filterValue.call(this.column, value);
}
};
// overrides the public define method and replaces it with our own
F.Cell.extend('define', function(valueOrElement){
this._super(valueOrElement);
this.__filtering_define__(valueOrElement);
});
// overrides the public val method and replaces it with our own
F.Cell.extend('val', function(value){
var val = this._super(value);
this.__filtering_val__(value);
return val;
});
})(FooTable);
(function($, F){
/**
* Whether or not the column can be used during filtering. Added by the {@link FooTable.Filtering} component.
* @type {boolean}
* @default true
*/
F.Column.prototype.filterable = true;
/**
* This is supplied either the cell value or jQuery object to parse. A string value must be returned from this method and will be used during filtering operations.
* @param {(*|jQuery)} valueOrElement - The value or jQuery cell object.
* @returns {string}
* @this FooTable.Column
*/
F.Column.prototype.filterValue = function(valueOrElement){
// if we have an element or a jQuery object use jQuery to get the value
if (F.is.element(valueOrElement) || F.is.jq(valueOrElement)) return $(valueOrElement).data('filterValue') || $(valueOrElement).text();
// if options are supplied with the value
if (F.is.hash(valueOrElement) && F.is.hash(valueOrElement.options)){
if (F.is.string(valueOrElement.options.filterValue)) return valueOrElement.options.filterValue;
if (F.is.defined(valueOrElement.value)) valueOrElement = valueOrElement.value;
}
if (F.is.defined(valueOrElement) && valueOrElement != null) return valueOrElement+''; // use the native toString of the value
return ''; // otherwise we have no value so return an empty string
};
// this is used to define the filtering specific properties on column creation
F.Column.prototype.__filtering_define__ = function(definition){
this.filterable = F.is.boolean(definition.filterable) ? definition.filterable : this.filterable;
};
// overrides the public define method and replaces it with our own
F.Column.extend('define', function(definition){
this._super(definition); // call the base so we don't have to redefine any previously set properties
this.__filtering_define__(definition); // then call our own
});
})(jQuery, FooTable);
(function(F){
/**
* An object containing the filtering options for the plugin. Added by the {@link FooTable.Filtering} component.
* @type {object}
* @prop {boolean} enabled=false - Whether or not to allow filtering on the table.
* @prop {({name: string, query: (string|FooTable.Query), columns: (Array.<string>|Array.<number>|Array.<FooTable.Column>)}|Array.<FooTable.Filter>)} filters - The filters to apply to the current {@link FooTable.Rows#array}.
* @prop {number} delay=1200 - The delay in milliseconds before the query is auto applied after a change (any value equal to or less than zero will disable this).
* @prop {number} min=3 - The minimum number of characters allowed in the search input before it is auto applied.
* @prop {string} space="AND" - Specifies how whitespace in a filter query is handled.
* @prop {string} placeholder="Search" - The string used as the placeholder for the search input.
* @prop {string} position="right" - The string used to specify the alignment of the search input.
* @prop {string} connectors=true - Whether or not to replace phrase connectors (+.-_) with space before executing the query.
*/
F.Defaults.prototype.filtering = {
enabled: false,
filters: [],
delay: 1200,
min: 3,
space: 'AND',
placeholder: 'Search',
position: 'right',
connectors: true
};
})(FooTable);
(function(F){
/**
* Checks if the row is filtered using the supplied filters.
* @this FooTable.Row
* @param {Array.<FooTable.Filter>} filters - The filters to apply.
* @returns {boolean}
*/
F.Row.prototype.filtered = function(filters){
var result = true, self = this;
F.arr.each(filters, function(f){
if ((result = f.matchRow(self)) == false) return false;
});
return result;
};
})(FooTable);
(function(F){
/**
* Filter the table using the supplied query and columns. Added by the {@link FooTable.Filtering} component.
* @instance
* @param {string} query - The query to filter the rows by.
* @param {(Array.<string>|Array.<number>|Array.<FooTable.Column>)} [columns] - The columns to apply the filter to in each row.
* @returns {jQuery.Promise}
* @fires FooTable.Filtering#before.ft.filtering
* @fires FooTable.Filtering#after.ft.filtering
* @see FooTable.Filtering#filter
*/
F.Table.prototype.applyFilter = function(query, columns){
return this.use(F.Filtering).filter(query, columns);
};
/**
* Clear the current filter from the table. Added by the {@link FooTable.Filtering} component.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Filtering#before.ft.filtering
* @fires FooTable.Filtering#after.ft.filtering
* @see FooTable.Filtering#clear
*/
F.Table.prototype.clearFilter = function(){
return this.use(F.Filtering).clear();
};
})(FooTable);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,710 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
(function($, F){
F.Pager = F.Class.extend(/** @lends FooTable.Pager */{
/**
* The pager object contains the page number and direction to page to.
* @constructs
* @extends FooTable.Class
* @param {number} total - The total number of pages available.
* @param {number} current - The current page number.
* @param {number} size - The number of rows per page.
* @param {number} page - The page number to goto.
* @param {boolean} forward - A boolean indicating the direction of paging, TRUE = forward, FALSE = back.
* @returns {FooTable.Pager}
*/
construct: function(total, current, size, page, forward){
/**
* The total number of pages available.
* @type {number}
*/
this.total = total;
/**
* The current page number.
* @type {number}
*/
this.current = current;
/**
* The number of rows per page.
* @type {number}
*/
this.size = size;
/**
* The page number to goto.
* @type {number}
*/
this.page = page;
/**
* A boolean indicating the direction of paging, TRUE = forward, FALSE = back.
* @type {boolean}
*/
this.forward = forward;
}
});
})(jQuery, FooTable);
(function($, F){
F.Paging = F.Component.extend(/** @lends FooTable.Paging */{
/**
* The paging component adds a pagination control to the table allowing users to navigate table rows via pages.
* @constructs
* @extends FooTable.Component
* @param {FooTable.Table} table - The parent {@link FooTable.Table} object for the component.
* @returns {FooTable.Filtering}
*/
construct: function(table){
// call the base constructor
this._super(table, table.o.paging.enabled);
/* PROTECTED */
/**
* An object containing the strings used by the paging buttons.
* @type {{ first: string, prev: string, next: string, last: string }}
*/
this.strings = table.o.paging.strings;
/* PUBLIC */
/**
* The current page number to display.
* @instance
* @type {number}
*/
this.current = table.o.paging.current;
/**
* The number of rows to display per page.
* @instance
* @type {number}
*/
this.size = table.o.paging.size;
/**
* The maximum number of page links to display at once.
* @type {number}
*/
this.limit = table.o.paging.limit;
/**
* The position of the pagination control within the paging rows cell.
* @type {string}
*/
this.position = table.o.paging.position;
/**
* The format string used to generate the text displayed under the pagination control.
* @type {string}
*/
this.countFormat = table.o.paging.countFormat;
/**
* The total number of pages.
* @instance
* @type {number}
*/
this.total = -1;
/**
* The jQuery row object that contains all the paging specific elements.
* @instance
* @type {jQuery}
*/
this.$row = null;
/**
* The jQuery cell object that contains the pagination control and total count.
* @instance
* @type {jQuery}
*/
this.$cell = null;
/**
* The jQuery object that contains the links for the pagination control.
* @type {jQuery}
*/
this.$pagination = null;
/**
* The jQuery object that contains the row count.
* @type {jQuery}
*/
this.$count = null;
/* PRIVATE */
/**
* A number indicating the previous page displayed.
* @private
* @type {number}
*/
this._previous = 1;
/**
* Used to hold the number of rows in the {@link FooTable.Rows#array} before paging is applied.
* @type {number}
* @private
*/
this._total = 0;
},
/* PROTECTED */
/**
* Checks the supplied data and options for the paging component.
* @instance
* @protected
* @param {object} data - The jQuery data object from the parent table.
* @fires FooTable.Paging#"preinit.ft.paging"
*/
preinit: function(data){
var self = this;
/**
* The preinit.ft.paging event is raised before the UI is created and provides the tables jQuery data object for additional options parsing.
* Calling preventDefault on this event will disable the component.
* @event FooTable.Paging#"preinit.ft.paging"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {object} data - The jQuery data object of the table raising the event.
*/
this.ft.raise('preinit.ft.paging', [data]).then(function(){
if (self.ft.$el.hasClass('footable-paging'))
self.enabled = true;
self.enabled = F.is.boolean(data.paging)
? data.paging
: self.enabled;
if (!self.enabled) return;
self.size = F.is.number(data.pagingSize)
? data.pagingSize
: self.size;
self.current = F.is.number(data.pagingCurrent)
? data.pagingCurrent
: self.current;
self.limit = F.is.number(data.pagingLimit)
? data.pagingLimit
: self.limit;
if (self.ft.$el.hasClass('footable-paging-left'))
self.position = 'left';
if (self.ft.$el.hasClass('footable-paging-center'))
self.position = 'center';
if (self.ft.$el.hasClass('footable-paging-right'))
self.position = 'right';
self.position = F.is.string(data.pagingPosition)
? data.pagingPosition
: self.position;
self.countFormat = F.is.string(data.pagingCountFormat)
? data.pagingCountFormat
: self.countFormat;
self.total = Math.ceil(self.ft.rows.array.length / self.size);
self._total = self.total;
}, function(){
self.enabled = false;
});
},
/**
* Initializes the paging component for the plugin using the supplied table and options.
* @instance
* @protected
* @fires FooTable.Paging#"init.ft.paging"
*/
init: function(){
/**
* The init.ft.paging event is raised before its UI is generated.
* Calling preventDefault on this event will disable the component.
* @event FooTable.Paging#"init.ft.paging"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
*/
var self = this;
this.ft.raise('init.ft.paging').then(function(){
self.$create();
}, function(){
self.enabled = false;
});
},
/**
* Destroys the paging component removing any UI generated from the table.
* @instance
* @protected
* @fires FooTable.Paging#"destroy.ft.paging"
*/
destroy: function () {
/**
* The destroy.ft.paging event is raised before its UI is removed.
* Calling preventDefault on this event will prevent the component from being destroyed.
* @event FooTable.Paging#"destroy.ft.paging"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
*/
var self = this;
this.ft.raise('destroy.ft.paging').then(function(){
self.ft.$el.removeClass('footable-paging')
.find('tfoot > tr.footable-paging').remove();
});
},
/**
* Performs the actual paging against the {@link FooTable.Rows#current} array removing all rows that are not on the current visible page.
* @instance
* @protected
*/
predraw: function(){
this.total = Math.ceil(this.ft.rows.array.length / this.size);
this.current = this.current > this.total ? this.total : (this.current < 1 ? 1 : this.current);
this._total = this.ft.rows.array.length;
if (this.ft.rows.array.length > this.size)
this.ft.rows.array = this.ft.rows.array.splice((this.current - 1) * this.size, this.size);
},
/**
* Updates the paging UI setting the state of the pagination control.
* @instance
* @protected
*/
draw: function(){
this.$cell.attr('colspan', this.ft.columns.visibleColspan);
this._setVisible(this.current, this.current > this._previous);
this._setNavigation(true);
},
/**
* Creates the paging UI from the current options setting the various jQuery properties of this component.
* @instance
* @protected
*/
$create: function(){
var self = this,
multiple = self.total > 1,
link = function(attr, html, klass){
return $('<li/>', {
'class': klass
}).attr('data-page', attr)
.append($('<a/>', {
'class': 'footable-page-link',
href: '#'
}).data('page', attr).html(html));
},
position;
if (!multiple) return;
switch (self.position){
case 'left': position = 'footable-paging-left'; break;
case 'right': position = 'footable-paging-right'; break;
default: position = 'footable-paging-center'; break;
}
self.ft.$el.addClass('footable-paging').addClass(position);
self.$cell = $('<td/>').attr('colspan', self.ft.columns.visibleColspan);
var $tfoot = self.ft.$el.children('tfoot');
if ($tfoot.length == 0){
$tfoot = $('<tfoot/>');
self.ft.$el.append($tfoot);
}
self.$row = $('<tr/>', { 'class': 'footable-paging' }).append(self.$cell).appendTo($tfoot);
self.$pagination = $('<ul/>', { 'class': 'pagination' }).on('click.footable', 'a.footable-page-link', { self: self }, self._onPageClicked);
self.$count = $('<span/>', { 'class': 'label label-default' });
self.$pagination.empty();
if (multiple) {
self.$pagination.append(link('first', self.strings.first, 'footable-page-nav'));
self.$pagination.append(link('prev', self.strings.prev, 'footable-page-nav'));
if (self.limit > 0 && self.limit < self.total){
self.$pagination.append(link('prev-limit', self.strings.prevPages, 'footable-page-nav'));
}
}
for (var i = 0, $li; i < self.total; i++){
$li = link(i + 1, i + 1, 'footable-page');
self.$pagination.append($li);
}
if (multiple){
if (self.limit > 0 && self.limit < self.total){
self.$pagination.append(link('next-limit', self.strings.nextPages, 'footable-page-nav'));
}
self.$pagination.append(link('next', self.strings.next, 'footable-page-nav'));
self.$pagination.append(link('last', self.strings.last, 'footable-page-nav'));
}
self.$cell.append(self.$pagination, $('<div/>', {'class': 'divider'}), self.$count);
self._total = self.total;
},
/* PUBLIC */
/**
* Pages to the first page.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#"before.ft.paging"
* @fires FooTable.Paging#"after.ft.paging"
*/
first: function(){
return this._set(1);
},
/**
* Pages to the previous page.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#"before.ft.paging"
* @fires FooTable.Paging#"after.ft.paging"
*/
prev: function(){
return this._set(this.current - 1 > 0 ? this.current - 1 : 1);
},
/**
* Pages to the next page.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#"before.ft.paging"
* @fires FooTable.Paging#"after.ft.paging"
*/
next: function(){
return this._set(this.current + 1 < this.total ? this.current + 1 : this.total);
},
/**
* Pages to the last page.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#"before.ft.paging"
* @fires FooTable.Paging#"after.ft.paging"
*/
last: function(){
return this._set(this.total);
},
/**
* Pages to the specified page.
* @instance
* @param {number} page - The page number to go to.
* @returns {jQuery.Promise}
* @fires FooTable.Paging#"before.ft.paging"
* @fires FooTable.Paging#"after.ft.paging"
*/
goto: function(page){
return this._set(page > this.total ? this.total : (page < 1 ? 1 : page));
},
/**
* Shows the previous X number of pages in the pagination control where X is the value set by the {@link FooTable.Defaults#paging} - limit option value.
* @instance
*/
prevPages: function(){
var page = this.$pagination.children('li.footable-page.visible:first').data('page') - 1;
this._setVisible(page, true);
this._setNavigation(false);
},
/**
* Shows the next X number of pages in the pagination control where X is the value set by the {@link FooTable.Defaults#paging} - limit option value.
* @instance
*/
nextPages: function(){
var page = this.$pagination.children('li.footable-page.visible:last').data('page') + 1;
this._setVisible(page, false);
this._setNavigation(false);
},
/**
* Gets or sets the current page size
* @instance
* @param {number} [value] - The new page size to use.
* @returns {(number|undefined)}
*/
pageSize: function(value){
if (!F.is.number(value)){
return this.size;
}
this.size = value;
this.total = Math.ceil(this.ft.rows.all.length / this.size);
if (F.is.jq(this.$row)) this.$row.remove();
this.$create();
this.ft.draw();
},
/* PRIVATE */
/**
* Performs the required steps to handle paging including the raising of the {@link FooTable.Paging#"before.ft.paging"} and {@link FooTable.Paging#"after.ft.paging"} events.
* @instance
* @private
* @param {number} page - The page to set.
* @returns {jQuery.Promise}
* @fires FooTable.Paging#"before.ft.paging"
* @fires FooTable.Paging#"after.ft.paging"
*/
_set: function(page){
var self = this,
pager = new F.Pager(self.total, self.current, self.size, page, page > self.current);
/**
* The before.ft.paging event is raised before a sort is applied and allows listeners to modify the pager or cancel it completely by calling preventDefault on the jQuery.Event object.
* @event FooTable.Paging#"before.ft.paging"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {FooTable.Pager} pager - The pager that is about to be applied.
*/
return self.ft.raise('before.ft.paging', [pager]).then(function(){
pager.page = pager.page > pager.total ? pager.total : pager.page;
pager.page = pager.page < 1 ? 1 : pager.page;
if (self.current == page) return $.when();
self._previous = self.current;
self.current = pager.page;
return self.ft.draw().then(function(){
/**
* The after.ft.paging event is raised after a pager has been applied.
* @event FooTable.Paging#"after.ft.paging"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {FooTable.Pager} pager - The pager that has been applied.
*/
self.ft.raise('after.ft.paging', [pager]);
});
});
},
/**
* Sets the state for the navigation links of the pagination control and optionally sets the active class state on the current page link.
* @instance
* @private
* @param {boolean} active - Whether or not to set the active class state on the individual page links.
*/
_setNavigation: function(active){
if (this.current == 1) {
this.$pagination.children('li[data-page="first"],li[data-page="prev"]').addClass('disabled');
} else {
this.$pagination.children('li[data-page="first"],li[data-page="prev"]').removeClass('disabled');
}
if (this.current == this.total) {
this.$pagination.children('li[data-page="next"],li[data-page="last"]').addClass('disabled');
} else {
this.$pagination.children('li[data-page="next"],li[data-page="last"]').removeClass('disabled');
}
if ((this.$pagination.children('li.footable-page.visible:first').data('page') || 1) == 1) {
this.$pagination.children('li[data-page="prev-limit"]').addClass('disabled');
} else {
this.$pagination.children('li[data-page="prev-limit"]').removeClass('disabled');
}
if ((this.$pagination.children('li.footable-page.visible:last').data('page') || this.limit) == this.total) {
this.$pagination.children('li[data-page="next-limit"]').addClass('disabled');
} else {
this.$pagination.children('li[data-page="next-limit"]').removeClass('disabled');
}
if (this.limit > 0 && this.total < this.limit){
this.$pagination.children('li[data-page="prev-limit"],li[data-page="next-limit"]').hide();
} else {
this.$pagination.children('li[data-page="prev-limit"],li[data-page="next-limit"]').show();
}
if (active){
this.$pagination.children('li.footable-page').removeClass('active').filter('li[data-page="' + this.current + '"]').addClass('active');
}
},
/**
* Sets the visible page using the supplied parameters.
* @instance
* @private
* @param {number} page - The page to make visible.
* @param {boolean} right - If set to true the supplied page will be the right most visible pagination link.
*/
_setVisible: function(page, right){
if (this.limit > 0 && this.total > this.limit){
if (!this.$pagination.children('li.footable-page[data-page="'+page+'"]').hasClass('visible')){
var start = 0, end = 0;
if (right == true){
end = page > this.total ? this.total : page;
start = end - this.limit;
} else {
start = page < 1 ? 0 : page - 1;
end = start + this.limit;
}
if (start < 0){
start = 0;
end = this.limit > this.total ? this.total : this.limit;
}
if (end > this.total){
end = this.total;
start = this.total - this.limit < 0 ? 0 : this.total - this.limit;
}
this.$pagination.children('li.footable-page').removeClass('visible').slice(start, end).addClass('visible');
}
} else {
this.$pagination.children('li.footable-page').removeClass('visible').slice(0, this.total).addClass('visible');
}
var first = (this.size * (page - 1)) + 1,
last = this.size * page;
if (this.ft.rows.array.length == 0){
first = 0;
last = 0;
} else {
last = last > this._total ? this._total : last;
}
this._setCount(page, this.total, first, last, this._total);
},
/**
* Uses the countFormat option to generate the text using the supplied parameters.
* @param {number} currentPage - The current page.
* @param {number} totalPages - The total number of pages.
* @param {number} pageFirst - The first row number of the current page.
* @param {number} pageLast - The last row number of the current page.
* @param {number} totalRows - The total number of rows.
* @private
*/
_setCount: function(currentPage, totalPages, pageFirst, pageLast, totalRows){
this.$count.text(this.countFormat.replace(/\{CP}/g, currentPage)
.replace(/\{TP}/g, totalPages)
.replace(/\{PF}/g, pageFirst)
.replace(/\{PL}/g, pageLast)
.replace(/\{TR}/g, totalRows));
},
/**
* Handles the click event for all links in the pagination control.
* @instance
* @private
* @param {jQuery.Event} e - The event object for the event.
*/
_onPageClicked: function(e){
e.preventDefault();
if ($(e.target).closest('li').is('.active,.disabled')) return;
var self = e.data.self, page = $(this).data('page');
switch(page){
case 'first': self.first();
return;
case 'prev': self.prev();
return;
case 'next': self.next();
return;
case 'last': self.last();
return;
case 'prev-limit': self.prevPages();
return;
case 'next-limit': self.nextPages();
return;
default: self._set(page);
return;
}
}
});
F.components.core.register('paging', F.Paging, 0);
})(jQuery, FooTable);
(function(F){
/**
* An object containing the paging options for the plugin. Added by the {@link FooTable.Paging} component.
* @type {object}
* @prop {boolean} enabled=false - Whether or not to allow paging on the table.
* @prop {string} countFormat="{CP} of {TP}" - A string format used to generate the page count text.
* @prop {number} current=1 - The page number to display.
* @prop {number} limit=5 - The maximum number of page links to display at once.
* @prop {string} position="center" - The string used to specify the alignment of the pagination control.
* @prop {number} size=10 - The number of rows displayed per page.
* @prop {object} strings - An object containing the strings used by the paging buttons.
* @prop {string} strings.first="&laquo;" - The string used for the 'first' button.
* @prop {string} strings.prev="&lsaquo;" - The string used for the 'previous' button.
* @prop {string} strings.next="&rsaquo;" - The string used for the 'next' button.
* @prop {string} strings.last="&raquo;" - The string used for the 'last' button.
* @prop {string} strings.prevPages="..." - The string used for the 'previous X pages' button.
* @prop {string} strings.nextPages="..." - The string used for the 'next X pages' button.
*/
F.Defaults.prototype.paging = {
enabled: false,
countFormat: '{CP} of {TP}',
current: 1,
limit: 5,
position: 'center',
size: 10,
strings: {
first: '&laquo;',
prev: '&lsaquo;',
next: '&rsaquo;',
last: '&raquo;',
prevPages: '...',
nextPages: '...'
}
};
})(FooTable);
(function(F){
/**
* Navigates to the specified page number. Added by the {@link FooTable.Paging} component.
* @instance
* @param {number} num - The page number to go to.
* @returns {jQuery.Promise}
* @fires FooTable.Paging#paging_changing
* @fires FooTable.Paging#paging_changed
* @see FooTable.Paging#goto
*/
F.Table.prototype.gotoPage = function(num){
return this.use(F.Paging).goto(num);
};
/**
* Navigates to the next page. Added by the {@link FooTable.Paging} component.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#paging_changing
* @fires FooTable.Paging#paging_changed
* @see FooTable.Paging#next
*/
F.Table.prototype.nextPage = function(){
return this.use(F.Paging).next();
};
/**
* Navigates to the previous page. Added by the {@link FooTable.Paging} component.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#paging_changing
* @fires FooTable.Paging#paging_changed
* @see FooTable.Paging#prev
*/
F.Table.prototype.prevPage = function(){
return this.use(F.Paging).prev();
};
/**
* Navigates to the first page. Added by the {@link FooTable.Paging} component.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#paging_changing
* @fires FooTable.Paging#paging_changed
* @see FooTable.Paging#first
*/
F.Table.prototype.firstPage = function(){
return this.use(F.Paging).first();
};
/**
* Navigates to the last page. Added by the {@link FooTable.Paging} component.
* @instance
* @returns {jQuery.Promise}
* @fires FooTable.Paging#paging_changing
* @fires FooTable.Paging#paging_changed
* @see FooTable.Paging#last
*/
F.Table.prototype.lastPage = function(){
return this.use(F.Paging).last();
};
/**
* Shows the next X number of pages in the pagination control where X is the value set by the {@link FooTable.Defaults#paging} - limit.size option value. Added by the {@link FooTable.Paging} component.
* @instance
* @see FooTable.Paging#nextPages
*/
F.Table.prototype.nextPages = function(){
return this.use(F.Paging).nextPages();
};
/**
* Shows the previous X number of pages in the pagination control where X is the value set by the {@link FooTable.Defaults#paging} - limit.size option value. Added by the {@link FooTable.Paging} component.
* @instance
* @see FooTable.Paging#prevPages
*/
F.Table.prototype.prevPages = function(){
return this.use(F.Paging).prevPages();
};
/**
* Gets or sets the current page size
* @instance
* @param {number} [value] - The new page size to use.
* @returns {(number|undefined)}
* @see FooTable.Paging#pageSize
*/
F.Table.prototype.pageSize = function(value){
return this.use(F.Paging).pageSize(value);
};
})(FooTable);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,435 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
(function($, F){
F.Sorter = F.Class.extend(/** @lends FooTable.Sorter */{
/**
* The sorter object contains the column and direction to sort by.
* @constructs
* @extends FooTable.Class
* @param {FooTable.Column} column - The column to sort.
* @param {string} direction - The direction to sort by.
* @returns {FooTable.Sorter}
*/
construct: function(column, direction){
/**
* The column to sort.
* @type {FooTable.Column}
*/
this.column = column;
/**
* The direction to sort by.
* @type {string}
*/
this.direction = direction;
}
});
})(jQuery, FooTable);
(function ($, F) {
F.Sorting = F.Component.extend(/** @lends FooTable.Sorting */{
/**
* The sorting component adds a small sort button to specified column headers allowing users to sort those columns in the table.
* @constructs
* @extends FooTable.Component
* @param {FooTable.Table} table - The parent {@link FooTable.Table} object for the component.
* @returns {FooTable.Sorting}
*/
construct: function (table) {
// call the constructor of the base class
this._super(table, table.o.sorting.enabled);
/* PROTECTED */
/**
* This provides a shortcut to the {@link FooTable.Table#options}.[sorting]{@link FooTable.Defaults#sorting} object.
* @instance
* @protected
* @type {object}
*/
this.o = table.o.sorting;
/**
* The current sorted column.
* @instance
* @type {FooTable.Column}
*/
this.column = null;
/* PRIVATE */
/**
* Sets a flag indicating whether or not the sorting has changed. When set to true the {@link FooTable.Sorting#sorting_changing} and {@link FooTable.Sorting#sorting_changed} events
* will be raised during the drawing operation.
* @private
* @type {boolean}
*/
this._changed = false;
},
/* PROTECTED */
/**
* Checks the supplied data and options for the sorting component.
* @instance
* @protected
* @param {object} data - The jQuery data object from the parent table.
* @fires FooTable.Sorting#"preinit.ft.sorting"
* @this FooTable.Sorting
*/
preinit: function(data){
var self = this;
/**
* The preinit.ft.sorting event is raised before the UI is created and provides the tables jQuery data object for additional options parsing.
* Calling preventDefault on this event will disable the component.
* @event FooTable.Sorting#"preinit.ft.sorting"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {object} data - The jQuery data object of the table raising the event.
*/
this.ft.raise('preinit.ft.sorting', [data]).then(function(){
if (self.ft.$el.hasClass('footable-sorting'))
self.enabled = true;
self.enabled = F.is.boolean(data.sorting)
? data.sorting
: self.enabled;
if (!self.enabled) return;
self.column = F.arr.first(self.ft.columns.array, function(col){ return col.sorted; });
}, function(){
self.enabled = false;
});
},
/**
* Initializes the sorting component for the plugin using the supplied table and options.
* @instance
* @protected
* @fires FooTable.Sorting#"init.ft.sorting"
* @this FooTable.Sorting
*/
init: function () {
/**
* The init.ft.sorting event is raised before its UI is generated.
* Calling preventDefault on this event will disable the component.
* @event FooTable.Sorting#"init.ft.sorting"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
*/
var self = this;
this.ft.raise('init.ft.sorting').then(function(){
F.arr.each(self.ft.columns.array, function(col){
if (col.sortable){
col.$el.addClass('footable-sortable').append($('<span/>', {'class': 'fooicon fooicon-sort'}));
}
});
self.ft.$el.on('click.footable', '.footable-sortable', { self: self }, self._onSortClicked);
}, function(){
self.enabled = false;
});
},
/**
* Destroys the sorting component removing any UI generated from the table.
* @instance
* @protected
* @fires FooTable.Sorting#"destroy.ft.sorting"
*/
destroy: function () {
/**
* The destroy.ft.sorting event is raised before its UI is removed.
* Calling preventDefault on this event will prevent the component from being destroyed.
* @event FooTable.Sorting#"destroy.ft.sorting"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
*/
var self = this;
this.ft.raise('destroy.ft.paging').then(function(){
self.ft.$el.off('click.footable', '.footable-sortable', self._onSortClicked);
self.ft.$el.children('thead').children('tr.footable-header')
.children('.footable-sortable').removeClass('footable-sortable')
.find('span.fooicon').remove();
});
},
/**
* Performs the actual sorting against the {@link FooTable.Rows#current} array.
* @instance
* @protected
*/
predraw: function () {
if (!this.column) return;
var self = this, col = self.column;
//self.ft.rows.array.sort(function (a, b) {
// return col.direction == 'ASC'
// ? col.sorter(a.cells[col.index].value, b.cells[col.index].value)
// : col.sorter(b.cells[col.index].value, a.cells[col.index].value);
//});
self.ft.rows.array.sort(function (a, b) {
return col.direction == 'ASC'
? col.sorter(a.cells[col.index].sortValue, b.cells[col.index].sortValue)
: col.sorter(b.cells[col.index].sortValue, a.cells[col.index].sortValue);
});
},
/**
* Updates the sorting UI setting the state of the sort buttons.
* @instance
* @protected
*/
draw: function () {
if (!this.column) return;
var self = this,
$sortable = self.ft.$el.find('thead > tr > .footable-sortable'),
$active = self.column.$el;
$sortable.removeClass('footable-asc footable-desc').children('.fooicon').removeClass('fooicon-sort fooicon-sort-asc fooicon-sort-desc');
$sortable.not($active).children('.fooicon').addClass('fooicon-sort');
$active.addClass(self.column.direction == 'ASC' ? 'footable-asc' : 'footable-desc')
.children('.fooicon').addClass(self.column.direction == 'ASC' ? 'fooicon-sort-asc' : 'fooicon-sort-desc');
},
/* PUBLIC */
/**
* Sets the sorting options and calls the {@link FooTable.Table#draw} method to perform the actual sorting.
* @instance
* @param {(string|number|FooTable.Column)} column - The column name, index or the actual {@link FooTable.Column} object to sort by.
* @param {string} [direction="ASC"] - The direction to sort by, either ASC or DESC.
* @returns {jQuery.Promise}
* @fires FooTable.Sorting#"before.ft.sorting"
* @fires FooTable.Sorting#"after.ft.sorting"
*/
sort: function(column, direction){
return this._sort(column, direction);
},
/* PRIVATE */
/**
* Performs the required steps to handle sorting including the raising of the {@link FooTable.Sorting#"before.ft.sorting"} and {@link FooTable.Sorting#"after.ft.sorting"} events.
* @instance
* @private
* @param {(string|number|FooTable.Column)} column - The column name, index or the actual {@link FooTable.Column} object to sort by.
* @param {string} [direction="ASC"] - The direction to sort by, either ASC or DESC.
* @returns {jQuery.Promise}
* @fires FooTable.Sorting#"before.ft.sorting"
* @fires FooTable.Sorting#"after.ft.sorting"
*/
_sort: function(column, direction){
var self = this;
var sorter = new F.Sorter(self.ft.columns.get(column), F.Sorting.dir(direction));
/**
* The before.ft.sorting event is raised before a sort is applied and allows listeners to modify the sorter or cancel it completely by calling preventDefault on the jQuery.Event object.
* @event FooTable.Sorting#"before.ft.sorting"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {FooTable.Sorter} sorter - The sorter that is about to be applied.
*/
return self.ft.raise('before.ft.sorting', [sorter]).then(function(){
F.arr.each(self.ft.columns.array, function(col){
if (col != self.column) col.direction = null;
});
self.column = self.ft.columns.get(sorter.column);
if (self.column) self.column.direction = F.Sorting.dir(sorter.direction);
return self.ft.draw().then(function(){
/**
* The after.ft.sorting event is raised after a sorter has been applied.
* @event FooTable.Sorting#"after.ft.sorting"
* @param {jQuery.Event} e - The jQuery.Event object for the event.
* @param {FooTable.Table} ft - The instance of the plugin raising the event.
* @param {FooTable.Sorter} sorter - The sorter that has been applied.
*/
self.ft.raise('after.ft.sorting', [sorter]);
});
});
},
/**
* Handles the sort button clicked event.
* @instance
* @private
* @param {jQuery.Event} e - The event object for the event.
*/
_onSortClicked: function (e) {
e.preventDefault();
var self = e.data.self, $header = $(this).closest('th,td'),
direction = $header.is('.footable-asc, .footable-desc')
? ($header.hasClass('footable-desc') ? 'ASC' : 'DESC')
: 'ASC';
self._sort($header.index(), direction);
}
});
/**
* Checks the supplied string is a valid direction and if not returns ASC as default.
* @static
* @protected
* @param {string} str - The string to check.
*/
F.Sorting.dir = function(str){
return F.is.string(str) && (str == 'ASC' || str == 'DESC') ? str : 'ASC';
};
F.components.core.register('sorting', F.Sorting, 5);
})(jQuery, FooTable);
(function(F){
/**
* The value used by the sorting component during sort operations. Can be set using the data-sort-value attribute on the cell itself.
* If this is not supplied it is set to the result of the toString method called on the value for the cell. Added by the {@link FooTable.Sorting} component.
* @type {string}
* @default null
*/
F.Cell.prototype.sortValue = null;
// this is used to define the sorting specific properties on cell creation
F.Cell.prototype.__sorting_define__ = function(valueOrElement){
this.sortValue = this.column.sortValue.call(this.column, valueOrElement);
};
// this is used to update the sortValue property whenever the cell value is changed
F.Cell.prototype.__sorting_val__ = function(value){
if (F.is.defined(value)){
// set only
this.sortValue = this.column.sortValue.call(this.column, value);
}
};
// overrides the public define method and replaces it with our own
F.Cell.extend('define', function(valueOrElement){
this._super(valueOrElement);
this.__sorting_define__(valueOrElement);
});
// overrides the public val method and replaces it with our own
F.Cell.extend('val', function(value){
var val = this._super(value);
this.__sorting_val__(value);
return val;
});
})(FooTable);
(function($, F){
/**
* The direction to sort if the {@link FooTable.Column#sorted} property is set to true. Can be "ASC", "DESC" or NULL. Added by the {@link FooTable.Sorting} component.
* @type {string}
* @default null
*/
F.Column.prototype.direction = null;
/**
* Whether or not the column can be sorted. Added by the {@link FooTable.Sorting} component.
* @type {boolean}
* @default true
*/
F.Column.prototype.sortable = true;
/**
* Whether or not the column is sorted. Added by the {@link FooTable.Sorting} component.
* @type {boolean}
* @default false
*/
F.Column.prototype.sorted = false;
/**
* This is supplied two values from the column for a comparison to be made and the result returned. Added by the {@link FooTable.Sorting} component.
* @param {*} a - The first value to be compared.
* @param {*} b - The second value to compare to the first.
* @returns {number}
* @example <caption>This example shows using pseudo code what a sort function would look like.</caption>
* "sorter": function(a, b){
* if (a is less than b by some ordering criterion) {
* return -1;
* }
* if (a is greater than b by the ordering criterion) {
* return 1;
* }
* // a must be equal to b
* return 0;
* }
*/
F.Column.prototype.sorter = function(a, b){
if (typeof a === 'string') a = a.toLowerCase();
if (typeof b === 'string') b = b.toLowerCase();
if (a === b) return 0;
if (a < b) return -1;
return 1;
};
/**
* This is supplied either the cell value or jQuery object to parse. A value must be returned from this method and will be used during sorting operations.
* @param {(*|jQuery)} valueOrElement - The value or jQuery cell object.
* @returns {*}
* @this FooTable.Column
*/
F.Column.prototype.sortValue = function(valueOrElement){
// if we have an element or a jQuery object use jQuery to get the value
if (F.is.element(valueOrElement) || F.is.jq(valueOrElement)) return $(valueOrElement).data('sortValue') || this.parser(valueOrElement);
// if options are supplied with the value
if (F.is.hash(valueOrElement) && F.is.hash(valueOrElement.options)){
if (F.is.string(valueOrElement.options.sortValue)) return valueOrElement.options.sortValue;
if (F.is.defined(valueOrElement.value)) valueOrElement = valueOrElement.value;
}
if (F.is.defined(valueOrElement) && valueOrElement != null) return valueOrElement;
return null;
};
// this is used to define the sorting specific properties on column creation
F.Column.prototype.__sorting_define__ = function(definition){
this.sorter = F.checkFnValue(this, definition.sorter, this.sorter);
this.direction = F.is.type(definition.direction, 'string') ? F.Sorting.dir(definition.direction) : null;
this.sortable = F.is.boolean(definition.sortable) ? definition.sortable : true;
this.sorted = F.is.boolean(definition.sorted) ? definition.sorted : false;
};
// overrides the public define method and replaces it with our own
F.Column.extend('define', function(definition){
this._super(definition);
this.__sorting_define__(definition);
});
})(jQuery, FooTable);
(function(F){
/**
* An object containing the sorting options for the plugin. Added by the {@link FooTable.Sorting} component.
* @type {object}
* @prop {boolean} enabled=false - Whether or not to allow sorting on the table.
*/
F.Defaults.prototype.sorting = {
enabled: false
};
})(FooTable);
(function($, F){
F.HTMLColumn.extend('__sorting_define__', function(definition){
this._super(definition);
this.sortUse = F.is.string(definition.sortUse) && $.inArray(definition.sortUse, ['html','text']) !== -1 ? definition.sortUse : 'html';
});
/**
* This is supplied either the cell value or jQuery object to parse. A value must be returned from this method and will be used during sorting operations.
* @param {(*|jQuery)} valueOrElement - The value or jQuery cell object.
* @returns {*}
* @this FooTable.HTMLColumn
*/
F.HTMLColumn.prototype.sortValue = function(valueOrElement){
// if we have an element or a jQuery object use jQuery to get the data value or pass it off to the parser
if (F.is.element(valueOrElement) || F.is.jq(valueOrElement)){
return $(valueOrElement).data('sortValue') || $.trim($(valueOrElement)[this.sortUse]());
}
// if options are supplied with the value
if (F.is.hash(valueOrElement) && F.is.hash(valueOrElement.options)){
if (F.is.string(valueOrElement.options.sortValue)) return valueOrElement.options.sortValue;
if (F.is.defined(valueOrElement.value)) valueOrElement = valueOrElement.value;
}
if (F.is.defined(valueOrElement) && valueOrElement != null) return valueOrElement;
return null;
};
})(jQuery, FooTable);
(function(F){
/**
* Sort the table using the specified column and direction. Added by the {@link FooTable.Sorting} component.
* @instance
* @param {(string|number|FooTable.Column)} column - The column name, index or the actual {@link FooTable.Column} object to sort by.
* @param {string} [direction="ASC"] - The direction to sort by, either ASC or DESC.
* @returns {jQuery.Promise}
* @fires FooTable.Sorting#"change.ft.sorting"
* @fires FooTable.Sorting#"changed.ft.sorting"
* @see FooTable.Sorting#sort
*/
F.Table.prototype.sort = function(column, direction){
return this.use(F.Sorting).sort(column, direction);
};
})(FooTable);

View File

@ -0,0 +1,8 @@
/*
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
* @version 3.0.6
* @link http://fooplugins.com
* @copyright Steven Usher & Brad Vincent 2015
* @license Released under the GPLv3 license.
*/
!function(a,b){b.Sorter=b.Class.extend({construct:function(a,b){this.column=a,this.direction=b}})}(jQuery,FooTable),function(a,b){b.Sorting=b.Component.extend({construct:function(a){this._super(a,a.o.sorting.enabled),this.o=a.o.sorting,this.column=null,this._changed=!1},preinit:function(a){var c=this;this.ft.raise("preinit.ft.sorting",[a]).then(function(){c.ft.$el.hasClass("footable-sorting")&&(c.enabled=!0),c.enabled=b.is["boolean"](a.sorting)?a.sorting:c.enabled,c.enabled&&(c.column=b.arr.first(c.ft.columns.array,function(a){return a.sorted}))},function(){c.enabled=!1})},init:function(){var c=this;this.ft.raise("init.ft.sorting").then(function(){b.arr.each(c.ft.columns.array,function(b){b.sortable&&b.$el.addClass("footable-sortable").append(a("<span/>",{"class":"fooicon fooicon-sort"}))}),c.ft.$el.on("click.footable",".footable-sortable",{self:c},c._onSortClicked)},function(){c.enabled=!1})},destroy:function(){var a=this;this.ft.raise("destroy.ft.paging").then(function(){a.ft.$el.off("click.footable",".footable-sortable",a._onSortClicked),a.ft.$el.children("thead").children("tr.footable-header").children(".footable-sortable").removeClass("footable-sortable").find("span.fooicon").remove()})},predraw:function(){if(this.column){var a=this,b=a.column;a.ft.rows.array.sort(function(a,c){return"ASC"==b.direction?b.sorter(a.cells[b.index].sortValue,c.cells[b.index].sortValue):b.sorter(c.cells[b.index].sortValue,a.cells[b.index].sortValue)})}},draw:function(){if(this.column){var a=this,b=a.ft.$el.find("thead > tr > .footable-sortable"),c=a.column.$el;b.removeClass("footable-asc footable-desc").children(".fooicon").removeClass("fooicon-sort fooicon-sort-asc fooicon-sort-desc"),b.not(c).children(".fooicon").addClass("fooicon-sort"),c.addClass("ASC"==a.column.direction?"footable-asc":"footable-desc").children(".fooicon").addClass("ASC"==a.column.direction?"fooicon-sort-asc":"fooicon-sort-desc")}},sort:function(a,b){return this._sort(a,b)},_sort:function(a,c){var d=this,e=new b.Sorter(d.ft.columns.get(a),b.Sorting.dir(c));return d.ft.raise("before.ft.sorting",[e]).then(function(){return b.arr.each(d.ft.columns.array,function(a){a!=d.column&&(a.direction=null)}),d.column=d.ft.columns.get(e.column),d.column&&(d.column.direction=b.Sorting.dir(e.direction)),d.ft.draw().then(function(){d.ft.raise("after.ft.sorting",[e])})})},_onSortClicked:function(b){b.preventDefault();var c=b.data.self,d=a(this).closest("th,td"),e=d.is(".footable-asc, .footable-desc")?d.hasClass("footable-desc")?"ASC":"DESC":"ASC";c._sort(d.index(),e)}}),b.Sorting.dir=function(a){return!b.is.string(a)||"ASC"!=a&&"DESC"!=a?"ASC":a},b.components.core.register("sorting",b.Sorting,5)}(jQuery,FooTable),function(a){a.Cell.prototype.sortValue=null,a.Cell.prototype.__sorting_define__=function(a){this.sortValue=this.column.sortValue.call(this.column,a)},a.Cell.prototype.__sorting_val__=function(b){a.is.defined(b)&&(this.sortValue=this.column.sortValue.call(this.column,b))},a.Cell.extend("define",function(a){this._super(a),this.__sorting_define__(a)}),a.Cell.extend("val",function(a){var b=this._super(a);return this.__sorting_val__(a),b})}(FooTable),function(a,b){b.Column.prototype.direction=null,b.Column.prototype.sortable=!0,b.Column.prototype.sorted=!1,b.Column.prototype.sorter=function(a,b){return"string"==typeof a&&(a=a.toLowerCase()),"string"==typeof b&&(b=b.toLowerCase()),a===b?0:b>a?-1:1},b.Column.prototype.sortValue=function(c){if(b.is.element(c)||b.is.jq(c))return a(c).data("sortValue")||this.parser(c);if(b.is.hash(c)&&b.is.hash(c.options)){if(b.is.string(c.options.sortValue))return c.options.sortValue;b.is.defined(c.value)&&(c=c.value)}return b.is.defined(c)&&null!=c?c:null},b.Column.prototype.__sorting_define__=function(a){this.sorter=b.checkFnValue(this,a.sorter,this.sorter),this.direction=b.is.type(a.direction,"string")?b.Sorting.dir(a.direction):null,this.sortable=b.is["boolean"](a.sortable)?a.sortable:!0,this.sorted=b.is["boolean"](a.sorted)?a.sorted:!1},b.Column.extend("define",function(a){this._super(a),this.__sorting_define__(a)})}(jQuery,FooTable),function(a){a.Defaults.prototype.sorting={enabled:!1}}(FooTable),function(a,b){b.HTMLColumn.extend("__sorting_define__",function(c){this._super(c),this.sortUse=b.is.string(c.sortUse)&&-1!==a.inArray(c.sortUse,["html","text"])?c.sortUse:"html"}),b.HTMLColumn.prototype.sortValue=function(c){if(b.is.element(c)||b.is.jq(c))return a(c).data("sortValue")||a.trim(a(c)[this.sortUse]());if(b.is.hash(c)&&b.is.hash(c.options)){if(b.is.string(c.options.sortValue))return c.options.sortValue;b.is.defined(c.value)&&(c=c.value)}return b.is.defined(c)&&null!=c?c:null}}(jQuery,FooTable),function(a){a.Table.prototype.sort=function(b,c){return this.use(a.Sorting).sort(b,c)}}(FooTable);

View File

@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>