Browse Source

copying files to public repo

master
Alan 3 years ago
commit
96d50fd698
  1. 2
      .gitattributes
  2. 2
      .gitignore
  3. 12
      .travis.yml
  4. 22
      Gruntfile.js
  5. 21
      LICENSE
  6. 160
      README.md
  7. 9
      dist/fancyTable.min.js
  8. 200
      example/index.html
  9. 487
      gs_sortable.js
  10. 56
      index.html
  11. 33
      package.json
  12. 327
      sort-table.js
  13. BIN
      sorting-filtering-pagination-fancytable.zip
  14. 227
      src/fancyTable.js
  15. 67
      table_sort.css
  16. 30
      table_sort.js
  17. 10
      test.html

2
.gitattributes vendored

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

2
.gitignore vendored

@ -0,0 +1,2 @@
node_modules/
.vscode

12
.travis.yml

@ -0,0 +1,12 @@
language: node_js
node_js:
- 14
sudo: false
install:
- npm install
cache:
directories:
- node_modules

22
Gruntfile.js

@ -0,0 +1,22 @@
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*!\n'+
' * jQuery fancyTable plugin v<%= pkg.version %>\n'+
' * https://github.com/myspace-nu\n'+
' *\n'+
' * Copyright 2018 Johan Johansson\n'+
' * Released under the MIT license\n'+
' */\n'
},
build: {
src: 'src/fancyTable.js',
dest: 'dist/fancyTable.min.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
};

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Johan Johansson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

160
README.md

@ -0,0 +1,160 @@
# jQuery.fancyTable
A jQuery plugin for making html tables searchable and sortable with pagination.
[![Build Status](https://travis-ci.com/myspace-nu/jquery.fancyTable.svg?branch=master)](https://travis-ci.com/myspace-nu/jquery.fancyTable)
[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/myspace-nu/jquery.fancyTable/blob/master/LICENSE)
## Live demo
See a live demo on [CodePen](https://codepen.io/myspace-nu/full/ZVEKyR)
## Installation
Using npm
npm install jquery.fancytable --save
Using CDN
<script src="https://cdn.jsdelivr.net/npm/jquery.fancytable/dist/fancyTable.min.js"></script>
Or manually by including the script *after* the jQuery library
<script src="/path/to/fancyTable.min.js"></script>
## Usage
<script type="text/javascript">
$(document).ready(function() {
$(".sampleTable").fancyTable({
sortColumn:0,
pagination: true,
perPage:10,
globalSearch:true
});
});
</script>
## Options
**globalSearch** - Use global search for all columns
globalSearch: false
*Default: false*
**globalSearchExcludeColumns** - Defines a number of columns to exclude from the global search.
globalSearchExcludeColumns: [2,5] // Exclude 2nd and 5th column.
*Default: undefined*
**inputPlaceholder** - Placeholder to use for &lt;input&gt;
inputPlaceholder: 'Sök...'
*Default: 'Search...'*
**inputStyle** - Style attributes to use for &lt;input&gt;
inputStyle: 'color:black;'
*Default: ''*
**onInit** - Function called after initialization
onInit:function(){
console.log({ element:this });
}
**onUpdate** - Function called after each update (sort and search)
onUpdate:function(){
console.log({ element:this });
}
**pagination** - Use pagination or not
pagination: true
*Default: false*
**paginationClass** - CSS class to use for pagination buttons
pagination: 'btn btn-primary'
*Default: 'btn btn-light'*
**paginationClassActive** - CSS class to use for active pagination buttons
pagination: 'someClass'
*Default: 'active'*
**paginationElement** - Selector for element to place pagination controls in.
paginationElement: '#someElement'
*Default: undefined* - Undefined will create a (remove any existing) table footer to place controls in.
**pagClosest** - Create pagination buttons for tbe n closest pages
pagClosest: 5
*Default: 3*
**perPage** - Rows per page when using pagination
perPage: 5
*Default: 10*
**searchable** - Should the table be searchable or not
searchable: false
*Default: true*
**sortable** - Should the table be sortable or not
sortable: false
*Default: true*
**sortColumn** - Column number for initial sorting
sortColumn: 5
*Default: undefined*
**sortOrder** - Initial sort order
sortOrder: 'descending' // Valid values are 'desc', 'descending', 'asc', 'ascending', -1 (descending) and 1 (ascending)
*Default: 'ascending'*
## Data attributes
**data-sortas="numeric"** - Used in the table header element <th> to define that values in the column should be sorted in numerical order (..., 8, 9, 10, 10.1, 12, ...)
<th data-sortas="numeric">
**data-sortas="case-insensitive"** - Used in the table header element <th> to define that values in the column should be sorted case insensitive (a, B, c, D, ...)
<th data-sortas="case-insensitive">
**data-sortvalue="`<value>`"** - Used in the table data element <td> to define an alternate value to be used when sorting
<td>1</td>
<td data-sortvalue="2">Two</td>
<td>3</td>
<td>Ghost</td>
<td data-sortvalue="Fox and the Hound, The">The Fox and the Hound</td>
<td>I Know What You Did Last Summer</td>
### Author: [Johan Johansson](https://github.com/myspace-nu)
### This library has been modified/used to meet the needs of Brookens Library

9
dist/fancyTable.min.js vendored

File diff suppressed because one or more lines are too long

200
example/index.html

@ -0,0 +1,200 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Sample</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h3>Table with sortable headings and global search</h3>
<table id="sampleTableA" class="table table-striped sampleTable">
<thead>
<tr>
<th>Col A</th>
<th>Col B</th>
<th>Col C</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<p>
<button id="loadDataSimulation" class="btn btn-success">Load new data</button>
</p>
<h3>Simple table with column search</h3>
<table id="sampleTableB" class="table table-striped sampleTable">
</table>
<h3>Sort by nearest city</h3>
<table id="sampleTableC" class="table table-striped sampleTable">
<thead>
<tr>
<th>City</th>
<th>Coordinates</th>
<th data-sortas="numeric">Distance</th>
</tr>
</thead>
<tbody>
<tr><td>Lindesberg</td><td>@59.5994689,15.2132325</td><td></td></tr>
<tr><td>Tokyo</td><td>@35.6708364,139.7532926</td><td></td></tr>
<tr><td>Sydney</td><td>@-33.8981029,151.1612396</td><td></td></tr>
<tr><td>Stockholm</td><td>@59.3275993,18.0524296</td><td></td></tr>
<tr><td>New York</td><td>@40.7026091,-74.1197629</td><td></td></tr>
<tr><td>Rio de Janeiro</td><td>@-22.9097071,-43.1925625</td><td></td></tr>
</tbody>
</table>
<form class="form-inline">
<button type="button" class="form-control btn btn-light" id="getNavigatorLocation">Find my location</button>
or, find by Swedish zip code <input type="text" class="form-control" id="zipCode" placeholder="Zip code"> <button type="button" class="form-control btn btn-light" id="getZipCodeLocation">Find</button>
</form>
<style>
.form-inline .form-control {
margin: 5px;
}
</style>
<h3>Case insensitive and sort value</h3>
<table id="sampleTableD" class="table table-striped sampleTable">
<thead>
<tr>
<th>Case sensitive text values</th>
<th data-sortas="case-insensitive">Case insensitive text values</th>
<th data-sortas="numeric">Numeric values</th>
</tr>
</thead>
<tbody>
<tr>
<td>bbb</td>
<td>bbb</td>
<td data-sortvalue="2">Two</td>
</tr>
<tr>
<td>AAA</td>
<td>AAA</td>
<td>3</td>
</tr>
<tr>
<td>DDD</td>
<td>DDD</td>
<td>4</td>
</tr>
<tr>
<td>ccc</td>
<td>ccc</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js.geotools/dist/geotools.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js.geotools/dist/geotools-swedish-zipcodes.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../src/fancyTable.js"></script>
<script type="text/javascript">
// Word genarator
function rWord(r){var t,n="bcdfghjklmnpqrstvwxyz",a="aeiou",e=function(r){return Math.floor(Math.random()*r)},o="";r=parseInt(r,10),n=n.split(""),a=a.split("");for(t=0;t<r/2;t++){var l=n[e(n.length)],p=a[e(a.length)];o+=0===t?l.toUpperCase():l,o+=2*t<r-1?p:""}return o}
$(document).ready(function() {
// Generate a big table
for(var n=0;n<1000;n++){
var row = $("<tr>");
$("#sampleTableA").find("thead th").each(function() {
$("<td>",{
html: rWord(8),
style:"padding:2px;"
}).appendTo($(row));
});
row.appendTo($("#sampleTableA").find("tbody"));
}
// Load data simulation
$("#loadDataSimulation").click(function() {
$(fancyTableA).find("tbody").empty();
for(var n=0;n<1000;n++){
var row = $("<tr>");
$(fancyTableA).find("thead tr:nth-child(1) th").each(function() {
$("<td>",{
html: rWord(8),
style:"padding:2px;"
}).appendTo($(row));
});
row.appendTo($(fancyTableA).find("tbody"));
}
fancyTableA.reinit();
});
// And a simple one
for(var n=0;n<10;n++){
var row = $("<tr>");
for(var nn=0;nn<5;nn++){
$("<td>",{
html: rWord(8),
style:"padding:2px;"
}).appendTo($(row));
}
$(row).find("td:last").first().html( moment(new Date(Math.floor(new Date().getTime()*Math.random()))).format('l') );
row.appendTo($("#sampleTableB"));
}
// And one with location data
$('#getNavigatorLocation').bind("click",function(){
window.navigator.geolocation.getCurrentPosition(function(pos) {
var myLocation = new geotools().position(pos.coords.latitude, pos.coords.longitude);
$("#sampleTableC").find("tbody tr").each(function() {
var arr = $(this).find("td").eq(1).html().match(/([\-\d\.]+)/g);
if(arr.length==2){
var dest = new geotools().position(arr[0],arr[1]);
$(this).find("td").eq(2).html((Math.round(myLocation.distanceTo(dest)/100)/10)+" km");
}
});
$('#sampleTableC td:nth-child(3),#sampleTableC th:nth-child(3)').show();
$("#sampleTableC")[0].fancyTable.sortColumn=2;
$("#sampleTableC")[0].fancyTable.sortOrder=1;
$.fn.fancyTable().tableSort($("#sampleTableC")[0]);
});
});
$('#getZipCodeLocation').bind("click",function(){
var myLocation = new geotools().position().fromZip($('#zipCode').val());
if(!myLocation.latitude){
return;
}
$("#sampleTableC").find("tbody tr").each(function() {
var arr = $(this).find("td").eq(1).html().match(/([\-\d\.]+)/g);
if(arr.length==2){
var dest = new geotools().position(arr[0],arr[1]);
$(this).find("td").eq(2).html((Math.round(myLocation.distanceTo(dest)/100)/10)+" km");
}
});
$('#sampleTableC td:nth-child(3),#sampleTableC th:nth-child(3)').show();
$("#sampleTableC")[0].fancyTable.sortColumn=2;
$("#sampleTableC")[0].fancyTable.sortOrder=1;
$.fn.fancyTable().tableSort($("#sampleTableC")[0]);
});
$('#sampleTableC td:nth-child(2),#sampleTableC th:nth-child(2)').hide();
$('#sampleTableC td:nth-child(3),#sampleTableC th:nth-child(3)').hide();
// And make them fancy
var fancyTableA = $("#sampleTableA").fancyTable({
sortColumn:0,
pagination: true,
perPage:5,
globalSearch:true
});
$("#sampleTableB").fancyTable({
pagination: true,
perPage:5
});
$("#sampleTableC").fancyTable({
searchable: false
});
$("#sampleTableD").fancyTable({
searchable: false
});
});
</script>
</body>
</html>

487
gs_sortable.js

@ -0,0 +1,487 @@
// Copyright 2007 - 2012 Gennadiy Shvets
// The program is distributed under the terms of the GNU General
// Public License 3.0
//
// See http://www.allmyscripts.com/Table_Sort/index.html for usage details.
// Script version 1.9
var TSort_Store;
var TSort_All;
function TSort_StoreDef() {
this.sorting = [];
this.nodes = [];
this.rows = [];
this.row_clones = [];
this.row_nosort = [];
this.sort_state = [];
this.initialized = 0;
this.append_classes = 0;
this.n_columns = 3;
// this.last_sorted = -1;
this.history = [];
this.sort_keys = [];
this.sort_colors = ['#FF0000', '#800080', '#0000FF'];
};
function tsInitOnload() {
// If TSort_All is not initialized - do it now (simulate old behavior)
if (TSort_All == null)
tsRegister();
for (var id in TSort_All) {
tsSetTable(id);
tsInit();
}
if (window.onload_sort_table)
window.onload_sort_table();
}
function tsInit() {
if (TSort_Data.push == null)
return;
var table_id = TSort_Data[0];
var table = document.getElementById(table_id);
// Find thead & tbody data
var cols, i, node, len, tr;
var thead = table.getElementsByTagName('thead')[0];
var tbody = table.getElementsByTagName('tbody')[0];
if (thead == null) {
thead = document.createElement('thead');
table.insertBefore(thead, tbody);
tr = tbody.getElementsByTagName('tr');
len = tr.length;
if (len == 0) {
alert('Cannot find THEAD and TH tags!');
return;
}
var trh = new Array();
for (i = 0; i < len; i++) {
cols = tr[i].getElementsByTagName('th');
if (!cols.length) continue;
trh.push(tr[i]);
}
len = trh.length;
for (i = 0; i < len; i++) {
tbody.removeChild(trh[i]);
thead.appendChild(trh[i]);
}
}
tr = thead.getElementsByTagName('tr');
if (tr.length == 0) return;
if (tr.length > 1) {
var cols0 = tr[0].getElementsByTagName('th');
if (cols0.length == 0)
cols0 = tr[0].getElementsByTagName('td');
var cols1;
var cols1 = tr[1].getElementsByTagName('th');
if (cols1.length == 0)
cols1 = tr[1].getElementsByTagName('td');
cols = new Array();
var j0, j1, n;
len = cols0.length;
for (j0 = 0, j1 = 0; j0 < len; j0++) {
node = cols0[j0];
n = node.colSpan;
if (n > 1) {
while (n > 0) {
cols.push(cols1[j1++]);
n--;
}
} else {
if (node.rowSpan == 1)
j1++;
cols.push(node);
}
}
} else {
cols = tr[0].getElementsByTagName('th');
if (cols.length == 0)
cols = tr[0].getElementsByTagName('td');
}
var cols_len = cols.length;
for (var i = 0; i < cols_len; i++) {
if (i >= TSort_Data.length - 1)
break;
node = cols[i];
var sorting = TSort_Data[i + 1].toLowerCase();
if (sorting == null) sorting = '';
TSort_Store.sorting.push(sorting);
if ((sorting != null) && (sorting != '')) {
// node.tsort_col_id = i;
// node.tsort_table_id = table_id;
// node.onclick = tsDraw;
node.innerHTML = "<a href='' onClick=\"tsDraw(" + i + ",'" +
table_id + "'); return false\">" + node.innerHTML +
'</a><b><span id="TS_' + i + '_' + table_id + '"></span></b>';
node.style.cursor = "pointer";
}
}
// Parse body rows
var rows = tbody.getElementsByTagName('tr');
if (rows.length == 0) return;
var date = new Date();
var text, a, cn, k;
var attached = TSort_Store.row_nosort;
for (i = 0, k = -1; i < rows.length; i++) {
var row = rows[i];
cn = row.className;
if ((cn != null) && (cn.match(/(^| )_nosort( |$)/))) {
// Save a reference to the TR element
var new_row = row.cloneNode(true);
if (attached[k + 1] == null)
attached[k + 1] = new Array(new_row);
else
attached[k + 1].push(new_row);
continue;
}
var cols = row.getElementsByTagName('td');
len = cols.length;
var row_data = [];
for (j = 0; j < len; j++) {
// Get cell text
text = cols[j].innerHTML;
var sorting = TSort_Store.sorting[j];
if (sorting != 's') {
text = text.replace(/<[^>]+>/g, '');
text = text.replace(/\&nbsp;/, ' ');
}
text = text.replace(/^\s+/, '');
text = text.replace(/\s+$/, '');
if (sorting == 'h') {
text = text.toLowerCase();
} else if (sorting == 's')
text = text.toLowerCase();
else if (sorting == 'i') {
text = parseInt(text);
if (isNaN(text)) text = 0;
} else if (sorting == 'n') {
text = text.replace(/(\d)\,(?=\d\d\d)/g, "$1");
text = parseInt(text);
if (isNaN(text)) text = 0;
} else if (sorting == 'c') {
text = text.replace(/^(\-?)\$/, "$1");
text = text.replace(/(\d)\,(?=\d\d\d)/g, "$1");
text = parseFloat(text);
if (isNaN(text)) text = 0;
} else if (sorting == 'f') {
text = parseFloat(text);
if (isNaN(text)) text = 0;
} else if (sorting == 'g') {
text = text.replace(/(\d)\,(?=\d\d\d)/g, "$1");
text = parseFloat(text);
if (isNaN(text)) text = 0;
} else if (sorting == 'd') {
if (text.match(/^\d\d\d\d\-\d\d?\-\d\d?(?: \d\d?:\d\d?:\d\d?)?$/)) {
a = text.split(/[\s\-:]/);
text = (a[3] == null) ?
Date.UTC(a[0], a[1] - 1, a[2], 0, 0, 0, 0) :
Date.UTC(a[0], a[1] - 1, a[2], a[3], a[4], a[5], 0);
} else
text = Date.parse(text);
if (isNaN(text)) text = 0;
}
row_data.push(text);
}
// Initialize the rest of the columns, that are not in <tr>
for (; j < cols_len; j++) {
// Get cell text
var sorting = TSort_Store.sorting[j];
text = '';
if ((sorting == 'h') || (sorting == 's'))
text = '';
else
text = 0;
row_data.push(text);
}
TSort_Store.rows.push(row_data);
// Save a reference to the TR element
var new_row = row.cloneNode(true);
k++;
new_row.tsort_row_id = k;
TSort_Store.row_clones[k] = new_row;
}
TSort_Store.initialized = 1;
if (TSort_Store.cookie) {
var allc = document.cookie;
i = allc.indexOf(TSort_Store.cookie + '=');
if (i != -1) {
i += TSort_Store.cookie.length + 1;
len = allc.indexOf(";", i);
text = decodeURIComponent(allc.substring(i, (len == -1) ?
allc.length : len));
TSort_Store.initial = (text == '') ? null : text.split(/\s*,\s*/);
}
}
var initial = TSort_Store.initial;
if (initial != null) {
var itype = typeof initial;
if ((itype == 'number') || (itype == 'string'))
tsDraw(initial);
else {
for (i = initial.length - 1; i >= 0; i--)
tsDraw(initial[i]);
}
}
}
function tsDraw(p_id, p_table) {
if (p_table != null)
tsSetTable(p_table);
if ((TSort_Store == null) || (TSort_Store.initialized == 0))
return;
var i = 0;
var sort_keys = TSort_Store.sort_keys;
var id;
var new_order = '';
if (p_id != null) {
if (typeof p_id == 'number')
id = p_id;
else if ((typeof p_id == 'string') && (p_id.match(/^\d+[ADU]$/i))) {
id = p_id.replace(/^(\d+)[ADU]$/i, "$1");
new_order = p_id.replace(/^\d+([ADU])$/i, "$1").toUpperCase();
}
}
if (id == null) {
id = this.tsort_col_id;
if ((p_table == null) && (this.tsort_table_id != null))
tsSetTable(this.tsort_table_id);
}
var table_id = TSort_Data[0];
var order = TSort_Store.sort_state[id];
if (new_order == 'U') {
if (order != null) {
TSort_Store.sort_state[id] = null;
obj = document.getElementById('TS_' + id + '_' + table_id);
if (obj != null) obj.innerHTML = '';
}
} else if (new_order != '') {
TSort_Store.sort_state[id] = (new_order == 'A') ? true : false;
// Add column number to the sort keys array
sort_keys.unshift(id);
i = 1;
} else {
if ((order == null) || (order == true)) {
TSort_Store.sort_state[id] = (order == null) ? true : false;
// Add column number to the sort keys array
sort_keys.unshift(id);
i = 1;
} else {
TSort_Store.sort_state[id] = null;
obj = document.getElementById('TS_' + id + '_' + table_id);
if (obj != null) obj.innerHTML = '';
}
}
var len = sort_keys.length;
// This will either remove the column completely from the sort_keys
// array (i = 0) or remove duplicate column number if present (i = 1).
while (i < len) {
if (sort_keys[i] == id) {
sort_keys.splice(i, 1);
len--;
break;
}
i++;
}
if (len > TSort_Store.n_columns) {
i = sort_keys.pop();
obj = document.getElementById('TS_' + i + '_' + table_id);
if (obj != null) obj.innerHTML = '';
TSort_Store.sort_state[i] = null;
}
// Sort the rows
TSort_Store.row_clones.sort(tsSort);
// Save the currently selected order
var new_tbody = document.createElement('tbody');
var row_clones = TSort_Store.row_clones;
len = row_clones.length;
var classes = TSort_Store.classes;
var alen, j, cn;
var arows = TSort_Store.row_nosort[0];
if (classes == null) {
if (arows != null) {
alen = arows.length;
for (j = 0; j < alen; j++)
new_tbody.appendChild(arows[j].cloneNode(true));
}
for (i = 0; i < len; i++) {
row = row_clones[i];
new_tbody.appendChild(row.cloneNode(true));
arows = TSort_Store.row_nosort[row.tsort_row_id + 1];
if (arows == null) continue;
alen = arows.length;
for (j = 0; j < alen; j++)
new_tbody.appendChild(arows[j].cloneNode(true));
}
} else {
var clone;
var cl = 0;
var cl_len = classes.length;
var append = TSort_Store.append_classes;
if (arows != null) {
alen = arows.length;
for (j = 0; j < alen; j++) {
clone = arows[j].cloneNode(true);
cn = clone.className;
clone.className = ((append) && (cn != null) && (cn.length > 0)) ?
cn + ' ' + classes[cl] : classes[cl];
new_tbody.appendChild(clone);
}
cl++;
if (cl >= cl_len) cl = 0;
}
for (i = 0; i < len; i++) {
row = row_clones[i];
clone = row.cloneNode(true);
cn = clone.className;
clone.className = ((append) && (cn != null) && (cn.length > 0)) ?
cn + ' ' + classes[cl] : classes[cl];
new_tbody.appendChild(clone);
arows = TSort_Store.row_nosort[row.tsort_row_id + 1];
if (arows != null) {
alen = arows.length;
for (j = 0; j < alen; j++) {
clone = arows[j].cloneNode(true);
cn = clone.className;
clone.className = ((append) && (cn != null) && (cn.length > 0)) ?
cn + ' ' + classes[cl] : classes[cl];
new_tbody.appendChild(clone);
}
}
cl++;
if (cl >= cl_len) cl = 0;
}
}
// Replace table body
var table = document.getElementById(table_id);
var tbody = table.getElementsByTagName('tbody')[0];
table.removeChild(tbody);
table.appendChild(new_tbody);
var obj, color, icon, state;
len = sort_keys.length;
var sorting = new Array();
for (i = 0; i < len; i++) {
id = sort_keys[i];
obj = document.getElementById('TS_' + id + '_' + table_id);
if (obj == null) continue;
state = (TSort_Store.sort_state[id]) ? 0 : 1;
icon = TSort_Store.icons[state];
obj.innerHTML = (icon.match(/</)) ? icon :
'<font color="' + TSort_Store.sort_colors[i] + '">' + icon + '</font>';
sorting.push(id + ((state) ? 'D' : 'A'));
}
if (TSort_Store.cookie) {
// Store the contents of "sorting" array into a cookie for 30 days
var date = new Date();
date.setTime(date.getTime() + 2592000);
document.cookie = TSort_Store.cookie + "=" +
encodeURIComponent(sorting.join(',')) + "; expires=" +
date.toGMTString() + "; path=/";
}
}
function tsSort(a, b) {
var data_a = TSort_Store.rows[a.tsort_row_id];
var data_b = TSort_Store.rows[b.tsort_row_id];
var sort_keys = TSort_Store.sort_keys;
var len = sort_keys.length;
var id;
var type;
var order;
var result;
for (var i = 0; i < len; i++) {
id = sort_keys[i];
type = TSort_Store.sorting[id];
var v_a = data_a[id];
var v_b = data_b[id];
if (v_a == v_b) continue;
if ((type == 'i') || (type == 'f') || (type == 'd'))
result = v_a - v_b;
else
result = (v_a < v_b) ? -1 : 1;
order = TSort_Store.sort_state[id];
return (order) ? result : 0 - result;
}
return (a.tsort_row_id < b.tsort_row_id) ? -1 : 1;
}
function tsRegister() {
if (typeof TSort_Data == 'undefined') return;
if (TSort_All == null)
TSort_All = new Object();
var ts_obj = new TSort_StoreDef();
ts_obj.sort_data = TSort_Data;
TSort_Data = null;
if (typeof TSort_Classes != 'undefined') {
ts_obj.classes = TSort_Classes;
TSort_Classes = null;
}
if (typeof TSort_Initial != 'undefined') {
ts_obj.initial = TSort_Initial;
TSort_Initial = null;
}
if (typeof TSort_Cookie != 'undefined') {
ts_obj.cookie = TSort_Cookie;
TSort_Cookie = null;
}
if (typeof TSort_Icons != 'undefined') {
ts_obj.icons = TSort_Icons;
TSort_Icons = null;
}
if (ts_obj.icons == null)
ts_obj.icons = new Array("\u2193", "\u2191");
if (typeof TSort_AppendClasses != 'undefined') {
ts_obj.append_classes = TSort_AppendClasses;
TSort_AppendClasses = null;
}
if (typeof TSort_NColumns != 'undefined') {
ts_obj.n_columns = TSort_NColumns;
TSort_NColumns = null;
if (ts_obj.n_columns == null)
ts_obj.n_columns = 3;
}
if (ts_obj.sort_data != null)
TSort_All[ts_obj.sort_data[0]] = ts_obj;
}
function tsSetTable(p_id) {
TSort_Store = TSort_All[p_id];
if (TSort_Store == null) {
alert("Cannot set table '" + p_id + "' - table is not registered");
return;
}
TSort_Data = TSort_Store.sort_data;
}
if (window.addEventListener)
window.addEventListener("load", tsInitOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", tsInitOnload);
else {
if ((window.onload_sort_table == null) && (window.onload != null))
window.onload_sort_table = window.onload;
// Assign new onload function
window.onload = tsInitOnload;
}

56
index.html

@ -0,0 +1,56 @@
<script type="text/javascript" src="/sort-table.js"></script>
<!-- <style>
table.js-sort-table.js-sort-asc thead tr>.js-sort-active:not(.js-sort-none):after {
content: "\25b2";
font-size: 0.7em;
padding-left: 3px;
line-height: 0.7em;
}
table.js-sort-table.js-sort-desc thead tr>.js-sort-active:not(.js-sort-none):after {
content: "\25bc";
font-size: 0.7em;
padding-left: 3px;
line-height: 0.7em;
}
</style> -->
<head>
</head>
<body>
<table class="table" id="my_Table" style="border: 1px solid rgb(221, 221, 221);">
<tbody>
<tr>
<th class="ck_border" style="border: 1px solid rgb(221, 221, 221);">Name</th>
<th class="ck_border" style="border: 1px solid rgb(221, 221, 221);">here are some words in front date this is more words</th>
</tr>
<tr>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">Alpha</td>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">12/24/1983</td>
</tr>
<tr>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">Bravo</td>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">02/23/2014</td>
</tr>
<tr>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">Charlie</td>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">10/09/2022</td>
</tr>
<tr>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">Delta</td>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">04/03/1968</td>
</tr>
<tr>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">Echo</td>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">05/26/1974</td>
</tr>
<tr>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">Foxtrot</td>
<td class="ck_border" style="border: 1px solid rgb(221, 221, 221);">06/16/1997</td>
</tr>
</tbody>
</table>
</body>

33
package.json

@ -0,0 +1,33 @@
{
"name": "jquery.fancytable",
"version": "1.0.20",
"description": "A jQuery plugin for making html tables searchable and sortable with pagination.",
"main": "dist/fancyTable.min.js",
"directories": {
"example": "example"
},
"scripts": {
"test": "grunt"
},
"repository": {
"type": "git",
"url": "git+https://github.com/myspace-nu/jquery.fancyTable.git"
},
"keywords": [
"jquery",
"table",
"searchable",
"sortable",
"pagination"
],
"author": "Johan Johansson",
"license": "MIT",
"bugs": {
"url": "https://github.com/myspace-nu/jquery.fancyTable/issues"
},
"homepage": "https://github.com/myspace-nu/jquery.fancyTable#readme",
"devDependencies": {
"grunt": "^1.3.0",
"grunt-contrib-uglify": "^5.0.0"
}
}

327
sort-table.js

@ -0,0 +1,327 @@
/**
* sort-table.js
* A pure JavaScript (no dependencies) solution to make HTML
* Tables sortable
*
* Copyright (c) 2013 Tyler Uebele
* Released under the MIT license. See included LICENSE.txt
* or http://opensource.org/licenses/MIT
*
* latest version available at https://github.com/tyleruebele/sort-table
*/
/**
* Sort the rows in a HTML Table
*
* @param Table The Table DOM object
* @param col The zero-based column number by which to sort
* @param dir Optional. The sort direction; pass 1 for asc; -1 for desc
* @returns void
*/
function sortTable(Table, col, dir) {
var sortClass, i;
// get previous sort column
sortTable.sortCol = -1;
sortClass = Table.className.match(/js-sort-\d+/);
if (null != sortClass) {
sortTable.sortCol = sortClass[0].replace(/js-sort-/, '');
Table.className = Table.className.replace(new RegExp(' ?' + sortClass[0] + '\\b'), '');
}
// If sort column was not passed, use previous
if ('undefined' === typeof col) {
col = sortTable.sortCol;
}
if ('undefined' !== typeof dir) {
// Accept -1 or 'desc' for descending. All else is ascending
sortTable.sortDir = dir == -1 || dir == 'desc' ? -1 : 1;
} else {
// sort direction was not passed, use opposite of previous
sortClass = Table.className.match(/js-sort-(a|de)sc/);
if (null != sortClass && sortTable.sortCol == col) {
sortTable.sortDir = 'js-sort-asc' == sortClass[0] ? -1 : 1;
} else {
sortTable.sortDir = 1;
}
}
Table.className = Table.className.replace(/ ?js-sort-(a|de)sc/g, '');
// update sort column
Table.className += ' js-sort-' + col;
sortTable.sortCol = col;
// update sort direction
Table.className += ' js-sort-' + (sortTable.sortDir == -1 ? 'desc' : 'asc');
// get sort type
if (col < Table.tHead.rows[Table.tHead.rows.length - 1].cells.length) {
sortClass = Table.tHead.rows[Table.tHead.rows.length - 1].cells[col].className.match(/js-sort-[-\w]+/);
}
// Improved support for colspan'd headers
for (i = 0; i < Table.tHead.rows[Table.tHead.rows.length - 1].cells.length; i++) {
if (col == Table.tHead.rows[Table.tHead.rows.length - 1].cells[i].getAttribute('data-js-sort-colNum')) {
sortClass = Table.tHead.rows[Table.tHead.rows.length - 1].cells[i].className.match(/js-sort-[-\w]+/);
}
}
if (null != sortClass) {
sortTable.sortFunc = sortClass[0].replace(/js-sort-/, '');
} else {
sortTable.sortFunc = 'string';
}
// Set the headers for the active column to have the decorative class
Table.querySelectorAll('.js-sort-active').forEach(function(Node) {
Node.className = Node.className.replace(/ ?js-sort-active\b/, '');
});
Table.querySelectorAll('[data-js-sort-colNum="' + col + '"]:not(:empty)').forEach(function(Node) {
Node.className += ' js-sort-active';
});
// sort!
var rows = [],
TBody = Table.tBodies[0];
for (i = 0; i < TBody.rows.length; i++) {
rows[i] = TBody.rows[i];
}
if ('none' != sortTable.sortFunc) {
rows.sort(sortTable.compareRow);
}
while (TBody.firstChild) {
TBody.removeChild(TBody.firstChild);
}
for (i = 0; i < rows.length; i++) {
TBody.appendChild(rows[i]);
}
}
/**
* Compare two table rows based on current settings
*
* @param RowA A TR DOM object
* @param RowB A TR DOM object
* @returns {number} 1 if RowA is greater, -1 if RowB, 0 if equal
*/
sortTable.compareRow = function(RowA, RowB) {
var valA, valB;
if ('function' != typeof sortTable[sortTable.sortFunc]) {
sortTable.sortFunc = 'string';
}
valA = sortTable[sortTable.sortFunc](RowA.cells[sortTable.sortCol]);
valB = sortTable[sortTable.sortFunc](RowB.cells[sortTable.sortCol]);
return valA == valB ? 0 : sortTable.sortDir * (valA > valB ? 1 : -1);
};
/**
* Strip all HTML, no exceptions
* @param html
* @returns {string}
*/
sortTable.stripTags = function(html) {
return html.replace(/<\/?[a-z][a-z0-9]*\b[^>]*>/gi, '');
};
/**
* Helper function that converts a table cell (TD) to a comparable value
* Converts innerHTML to a timestamp, 0 for invalid dates
*
* @param Cell A TD DOM object
* @returns {Number}
*/
sortTable.date = function(Cell) {
// If okDate library is available, Use it for advanced Date processing
if (typeof okDate !== 'undefined') {
var kDate = okDate(sortTable.stripTags(Cell.innerHTML));
return kDate ? kDate.getTime() : 0;
} else {
return (new Date(sortTable.stripTags(Cell.innerHTML))).getTime() || 0;
}
};
/**
* Helper function that converts a table cell (TD) to a comparable value
* Converts innerHTML to a JS Number object
*
* @param Cell A TD DOM object
* @returns {Number}
*/
sortTable.number = function(Cell) {
return Number(sortTable.stripTags(Cell.innerHTML).replace(/[^-\d.]/g, ''));
};
/**
* Helper function that converts a table cell (TD) to a comparable value
* Converts innerHTML to a lower case string for insensitive compare
*
* @param Cell A TD DOM object
* @returns {String}
*/
sortTable.string = function(Cell) {
return sortTable.stripTags(Cell.innerHTML).toLowerCase();
};
/**
* Helper function that converts a table cell (TD) to a comparable value
*
* @param Cell A TD DOM object
* @returns {String}
*/
sortTable.raw = function(Cell) {
return Cell.innerHTML;
};
/**
* Helper function that converts a table cell (TD) to a comparable value
* Captures the last space-delimited token from innerHTML
*
* @param Cell A TD DOM object
* @returns {String}
*/
sortTable.last = function(Cell) {
return sortTable.stripTags(Cell.innerHTML).split(' ').pop().toLowerCase();
};
/**
* Helper function that converts a table cell (TD) to a comparable value
* Captures the value of the first childNode
*
* @param Cell A TD DOM object
* @returns {String}
*/
sortTable.input = function(Cell) {
for (var i = 0; i < Cell.children.length; i++) {
if ('object' == typeof Cell.children[i] &&
'undefined' != typeof Cell.children[i].value
) {
return Cell.children[i].value.toLowerCase();
}
}
return sortTable.string(Cell);
};
/**
* Helper function that prevents sorting by always returning null
*
* @param Cell A TD DOM object
* @returns null
*/
sortTable.none = function(Cell) {
return null;
};
/**
* Return the click handler appropriate to the specified Table and column
*
* @param Table Table to sort
* @param col Column to sort by
* @returns {Function} Click Handler
*/
sortTable.getClickHandler = function(Table, col) {
return function() {
sortTable(Table, col);
};
};
/**
* Attach sortTable() calls to table header cells' onclick events
* If the table(s) do not have a THead node, one will be created around the
* first row
*/
sortTable.init = function() {
var THead, Tables, Handler;
if (document.querySelectorAll) {
Tables = document.querySelectorAll('table.js-sort-table');
} else {
Tables = document.getElementsByTagName('table');
}
for (var i = 0; i < Tables.length; i++) {
// Because IE<8 doesn't support querySelectorAll, skip unclassed tables
if (!document.querySelectorAll && null === Tables[i].className.match(/\bjs-sort-table\b/)) {
continue;
}
// Prevent repeat processing
if (Tables[i].attributes['data-js-sort-table']) {
continue;
}
// Ensure table has a tHead element
if (!Tables[i].tHead) {
THead = document.createElement('thead');
THead.appendChild(Tables[i].rows[0]);
Tables[i].insertBefore(THead, Tables[i].children[0]);
} else {
THead = Tables[i].tHead;
}
// Attach click events to table header
for (var rowNum = 0; rowNum < THead.rows.length; rowNum++) {
for (var cellNum = 0, colNum = 0; cellNum < THead.rows[rowNum].cells.length; cellNum++) {
// Skip headers marked "js-sort-none"
if (THead.rows[rowNum].cells[cellNum].className.match(/\bjs-sort-none\b/)) {
continue;
}
// Define which column the header should invoke sorting for
THead.rows[rowNum].cells[cellNum].setAttribute('data-js-sort-colNum', colNum);
Handler = sortTable.getClickHandler(Tables[i], colNum);
window.addEventListener ?
THead.rows[rowNum].cells[cellNum].addEventListener('click', Handler) :
window.attachEvent && THead.rows[rowNum].cells[cellNum].attachEvent('onclick', Handler);
colNum += THead.rows[rowNum].cells[cellNum].colSpan;
}
}
// Mark table as processed
Tables[i].setAttribute('data-js-sort-table', 'true')
}
// Add default styles as the first style in head so they can be easily overwritten by user styles
var element = document.createElement('style');
document.head.insertBefore(element, document.head.childNodes[0]);
var sheet = element.sheet;
sheet.insertRule('table.js-sort-table.js-sort-asc thead tr > .js-sort-active:not(.js-sort-none):after {content: "\\25b2";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 0);
sheet.insertRule('table.js-sort-table.js-sort-desc thead tr > .js-sort-active:not(.js-sort-none):after {content: "\\25bc";font-size: 0.7em;padding-left: 3px;line-height: 0.7em;}', 0);
};
// removed for autosort:
// Run sortTable.init() when the page loads
// window.addEventListener ?
// window.addEventListener('load', sortTable.init, true) :
// window.attachEvent && window.attachEvent('onload', sortTable.init);
// :end removed
window.onload = function() {
var mySpans, tables, table;
tables = document.getElementsByTagName("table");
mySpans = document.getElementsByTagName('th');
// sortTable(document.getElementById('my_Table'), 0);
for (var g = 0; g < tables.length; g++) {
tables[g].className += " js-sort-table";
}
for (var i = 0; i < mySpans.length; i++) {
if (mySpans[i].innerHTML.match('[dD]ate')) {
mySpans[i].className += " js-sort-date";
}
}
// modified original code, removed their onLoad sortTable.init in order to autosort tables:
sortTable.init();
for (var g = 0; g < tables.length; g++) {
sortTable(tables[g], 0, 1);
}
}
// Shim for IE11's lack of NodeList.prototype.forEach
if (typeof NodeList.prototype.forEach !== "function") {
NodeList.prototype.forEach = Array.prototype.forEach;
}

BIN
sorting-filtering-pagination-fancytable.zip

Binary file not shown.

227
src/fancyTable.js

@ -0,0 +1,227 @@
/*!
* jQuery fancyTable plugin
* https://github.com/myspace-nu
*
* Copyright 2018 Johan Johansson
* Released under the MIT license
*/
(function($) {
$.fn.fancyTable = function(options) {
var settings = $.extend({
inputStyle: "",
inputPlaceholder: "Search...",
pagination: false,
paginationClass: "btn btn-light",
paginationClassActive: "active",
pagClosest: 3,
perPage: 10,
sortable: true,
searchable: true,
onInit: function(){ },
onUpdate: function(){ },
testing: false
}, options);
var instance = this;
this.settings = settings;
this.tableUpdate = function (elm) {
elm.fancyTable.matches = 0;
$(elm).find("tbody tr").each(function() {
var n=0;
var match = true;
var globalMatch = false;
$(this).find("td").each(function() {
if(!settings.globalSearch && elm.fancyTable.searchArr[n] && !(new RegExp(elm.fancyTable.searchArr[n],"i").test($(this).html()))){
match = false;
} else if(settings.globalSearch && (!elm.fancyTable.search || (new RegExp(elm.fancyTable.search,"i").test($(this).html())))){
if(!Array.isArray(settings.globalSearchExcludeColumns) || !settings.globalSearchExcludeColumns.includes(n+1)){
globalMatch = true;
}
}
n++;
});
if((settings.globalSearch && globalMatch) || (!settings.globalSearch && match)){
elm.fancyTable.matches++
if(!settings.pagination || (elm.fancyTable.matches>(elm.fancyTable.perPage*(elm.fancyTable.page-1)) && elm.fancyTable.matches<=(elm.fancyTable.perPage*elm.fancyTable.page))){
$(this).show();
} else {
$(this).hide();
}
} else {
$(this).hide();
}
});
elm.fancyTable.pages = Math.ceil(elm.fancyTable.matches/elm.fancyTable.perPage);
if(settings.pagination){
var paginationElement = (elm.fancyTable.paginationElement) ? $(elm.fancyTable.paginationElement) : $(elm).find(".pag");
paginationElement.empty();
for(var n=1; n<=elm.fancyTable.pages; n++){
if(n==1 || (n>(elm.fancyTable.page-(settings.pagClosest+1)) && n<(elm.fancyTable.page+(settings.pagClosest+1))) || n==elm.fancyTable.pages){
var a = $("<a>",{
html:n,
"data-n": n,
style:"margin:0.2em",
class:settings.paginationClass+" "+((n==elm.fancyTable.page)?settings.paginationClassActive:"")
}).css("cursor","pointer").bind("click",function(){
elm.fancyTable.page = $(this).data("n");
instance.tableUpdate(elm);
});
if(n==elm.fancyTable.pages && elm.fancyTable.page<(elm.fancyTable.pages-settings.pagClosest-1)){
paginationElement.append($("<span>...</span>"));
}
paginationElement.append(a);
if(n==1 && elm.fancyTable.page>settings.pagClosest+2){
paginationElement.append($("<span>...</span>"));
}
}
}
}
settings.onUpdate.call(this,elm);
};
this.reinit = function(elm){
$(this).each(function(){
$(this).find("th a").contents().unwrap();
$(this).find("tr.fancySearchRow").remove();
});
$(this).fancyTable(this.settings);
};
this.tableSort = function (elm) {
if(typeof elm.fancyTable.sortColumn !== "undefined" && elm.fancyTable.sortColumn < elm.fancyTable.nColumns){
$(elm).find("thead th div.sortArrow").each(function(){
$(this).remove();
});
var sortArrow = $("<div>",{"class":"sortArrow"}).css({"margin":"0.1em","display":"inline-block","width":0,"height":0,"border-left":"0.4em solid transparent","border-right":"0.4em solid transparent"});
sortArrow.css(
(elm.fancyTable.sortOrder>0) ?
{"border-top":"0.4em solid #000"} :
{"border-bottom":"0.4em solid #000"}
);
$(elm).find("thead th a").eq(elm.fancyTable.sortColumn).append(sortArrow);
var rows = $(elm).find("tbody tr").toArray().sort(
function(a, b) {
var elma = $(a).find("td").eq(elm.fancyTable.sortColumn);
var elmb = $(b).find("td").eq(elm.fancyTable.sortColumn);
var cmpa = $(elma).data("sortvalue") ? $(elma).data("sortvalue") : elma.html();
var cmpb = $(elmb).data("sortvalue") ? $(elmb).data("sortvalue") : elmb.html();
if(elm.fancyTable.sortAs[elm.fancyTable.sortColumn] == 'case-insensitive') {
cmpa = cmpa.toLowerCase();
cmpb = cmpb.toLowerCase();
}
if(elm.fancyTable.sortAs[elm.fancyTable.sortColumn] == 'numeric'){
return((elm.fancyTable.sortOrder>0) ? parseFloat(cmpa)-parseFloat(cmpb) : parseFloat(cmpb)-parseFloat(cmpa));
} else {
return((cmpa<cmpb)?-elm.fancyTable.sortOrder:(cmpa>cmpb)?elm.fancyTable.sortOrder:0);
}
}
);
$(elm).find("tbody").empty().append(rows);
}
};
this.each(function() {
if($(this).prop("tagName")!=="TABLE"){
console.warn("fancyTable: Element is not a table.");
return true;
}
var elm = this;
elm.fancyTable = {
nColumns: $(elm).find("td").first().parent().find("td").length,
nRows : $(this).find("tbody tr").length,
perPage : settings.perPage,
page : 1,
pages : 0,
matches : 0,
searchArr : [],
search : "",
sortColumn : settings.sortColumn,
sortOrder : (typeof settings.sortOrder === "undefined") ? 1 : (new RegExp("desc","i").test(settings.sortOrder) || settings.sortOrder == -1) ? -1 : 1,
sortAs:[], // null, numeric or case-insensitive
paginationElement : settings.paginationElement
};
if($(elm).find("tbody").length==0){
var content = $(elm).html();
$(elm).empty();
$(elm).append("<tbody>").append($(content));
}
if($(elm).find("thead").length==0){
$(elm).prepend($("<thead>"));
// Maybe add generated headers at some point
//var c=$(elm).find("tr").first().find("td").length;
//for(var n=0; n<c; n++){
// $(elm).find("thead").append($("<th></th>"));
//}
}
if(settings.sortable){
var n=0;
$(elm).find("thead th").each(function() {
elm.fancyTable.sortAs.push(
($(this).data('sortas')=='numeric') ? 'numeric' :
($(this).data('sortas')=='case-insensitive') ? 'case-insensitive' :
null
);
var content = $(this).html();
var a = $("<a>",{
html:content,
"data-n": n,
class:""
}).css("cursor","pointer").bind("click",function(){
if(elm.fancyTable.sortColumn == $(this).data("n")){
elm.fancyTable.sortOrder=-elm.fancyTable.sortOrder;
} else {
elm.fancyTable.sortOrder=1;
}
elm.fancyTable.sortColumn = $(this).data("n");
instance.tableSort(elm);
instance.tableUpdate(elm);
});
$(this).empty();
$(this).append(a);
n++;
});
}
if(settings.searchable){
var searchHeader = $("<tr>").addClass("fancySearchRow");
if(settings.globalSearch){
var searchField = $("<input>",{
"placeholder": settings.inputPlaceholder,
style:"width:100%;"+settings.inputStyle
}).bind("change paste keyup",function(){
elm.fancyTable.search = $(this).val();
elm.fancyTable.page = 1;
instance.tableUpdate(elm);
});
var th = $("<th>",{ style:"padding:2px;" }).attr("colspan",elm.fancyTable.nColumns);
$(searchField).appendTo($(th));
$(th).appendTo($(searchHeader));
} else {
var n=0;
$(elm).find("td").first().parent().find("td").each(function() {
elm.fancyTable.searchArr.push("");
var searchField = $("<input>",{
"data-n": n,
"placeholder": settings.inputPlaceholder,
style:"width:100%;"+settings.inputStyle
}).bind("change paste keyup",function(){
elm.fancyTable.searchArr[$(this).data("n")] = $(this).val();
elm.fancyTable.page = 1;
instance.tableUpdate(elm);
});
var th = $("<th>",{ style:"padding:2px;" });
$(searchField).appendTo($(th));
$(th).appendTo($(searchHeader));
n++;
});
}
searchHeader.appendTo($(elm).find("thead"));
}
// Sort
instance.tableSort(elm);
if(settings.pagination && !settings.paginationElement){
$(elm).find("tfoot").remove();
$(elm).append($("<tfoot><tr></tr></tfoot>"));
$(elm).find("tfoot tr").append($("<td class='pag'></td>",{ }).attr("colspan",elm.fancyTable.nColumns));
}
instance.tableUpdate(elm);
settings.onInit.call(this,elm);
});
return this;
};
}(jQuery));

67
table_sort.css

@ -0,0 +1,67 @@
* {
-moz-box-sizing: border-box;
-o-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
color: #333;
font-size: 1em;
}
a:link,
a:visited,
a:hover,
a:active {
color: #000;
text-decoration: none;
}
.container {
margin: 50px auto;
padding: 0 50px;
max-width: 960px;
}
table {
background: #FFF;
border-collapse: collapse;
/* width: 100%; */
}
td,
th {
padding: 4px;
border: 1px solid #CCC;
overflow: hidden;
text-align: left;
vertical-align: middle;
}
th {
background-color: #DDD;
font-weight: 400;
}
th a,
td a {
display: block;
/* width: 100%; */
}
th a.sort-by {
padding-right: 18px;
position: relative;
}
a.sort-by:before,
a.sort-by:after {
border: 4px solid transparent;
content: "";
display: block;
height: 0;
right: 5px;
top: 50%;
position: absolute;
width: 0;
}
a.sort-by:before {
border-bottom-color: #666;
margin-top: -9px;
}
a.sort-by:after {
border-top-color: #666;
margin-top: 1px;
}

30
table_sort.js

@ -0,0 +1,30 @@
window.onload = function() {
var arrows, headers, header;
headers = document.getElementsByTagName("th");
for (var g = 0; g < headers.length; g++) {
arrows = document.createElement('a');
arrows.href = "#";
arrows.className = "sort-by";
headers[g].appendChild(arrows);
headers[g].onclick = sortTable(g);
headers[g].onkeypress = sortTable(g);
}
}
function sortTable(n) {
const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;
const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
// do the work...
document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
const table = th.closest('table');
Array.from(table.querySelectorAll('tr:nth-child(n+2)'))
.sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
.forEach(tr => table.appendChild(tr));
})));
}

10
test.html

@ -0,0 +1,10 @@
<table class="table table-bordered" data-darkreader-inline-border-bottom="" data-darkreader-inline-border-left="" data-darkreader-inline-border-right="" data-darkreader-inline-border-top="" style="border: 1px solid rgb(221, 221, 221); --darkreader-inline-border-top:#3a3e41; --darkreader-inline-border-right:#3a3e41; --darkreader-inline-border-bottom:#3a3e41; --darkreader-inline-border-left:#3a3e41;">
<tbody>
<tr>
<td class="ck_border" data-darkreader-inline-border-bottom="" data-darkreader-inline-border-left="" data-darkreader-inline-border-right="" data-darkreader-inline-border-top="" style="border: 1px solid rgb(221, 221, 221); --darkreader-inline-border-top:#3a3e41; --darkreader-inline-border-right:#3a3e41; --darkreader-inline-border-bottom:#3a3e41; --darkreader-inline-border-left:#3a3e41;">Name;</td>
<td class="ck_border" data-darkreader-inline-border-bottom="" data-darkreader-inline-border-left="" data-darkreader-inline-border-right="" data-darkreader-inline-border-top="" style="border: 1px solid rgb(221, 221, 221); --darkreader-inline-border-top:#3a3e41; --darkreader-inline-border-right:#3a3e41; --darkreader-inline-border-bottom:#3a3e41; --darkreader-inline-border-left:#3a3e41;">Date</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
Loading…
Cancel
Save