copying files to public repo
This commit is contained in:
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
.vscode
|
12
.travis.yml
Normal file
12
.travis.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 14
|
||||
|
||||
sudo: false
|
||||
|
||||
install:
|
||||
- npm install
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
22
Gruntfile.js
Normal file
22
Gruntfile.js
Normal file
@@ -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
Normal file
21
LICENSE
Normal file
@@ -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
Normal file
160
README.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# jQuery.fancyTable
|
||||
|
||||
A jQuery plugin for making html tables searchable and sortable with pagination.
|
||||
|
||||
[](https://travis-ci.com/myspace-nu/jquery.fancyTable)
|
||||
[](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 <input>
|
||||
|
||||
inputPlaceholder: 'Sök...'
|
||||
|
||||
*Default: 'Search...'*
|
||||
|
||||
**inputStyle** - Style attributes to use for <input>
|
||||
|
||||
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
Normal file
9
dist/fancyTable.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
200
example/index.html
Normal file
200
example/index.html
Normal file
@@ -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
Normal file
487
gs_sortable.js
Normal file
@@ -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(/\ /, ' ');
|
||||
}
|
||||
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
Normal file
56
index.html
Normal file
@@ -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
Normal file
33
package.json
Normal file
@@ -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
Normal file
327
sort-table.js
Normal file
@@ -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
Normal file
BIN
sorting-filtering-pagination-fancytable.zip
Normal file
Binary file not shown.
227
src/fancyTable.js
Normal file
227
src/fancyTable.js
Normal file
@@ -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
Normal file
67
table_sort.css
Normal file
@@ -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
Normal file
30
table_sort.js
Normal file
@@ -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
Normal file
10
test.html
Normal file
@@ -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> </p>
|
Reference in New Issue
Block a user