From 96d50fd6981c15b85a01b5cde72cddaf1ae24915 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 30 Mar 2022 09:19:32 -0500 Subject: [PATCH] copying files to public repo --- .gitattributes | 2 + .gitignore | 2 + .travis.yml | 12 + Gruntfile.js | 22 + LICENSE | 21 + README.md | 160 +++++++ dist/fancyTable.min.js | 9 + example/index.html | 200 ++++++++ gs_sortable.js | 487 ++++++++++++++++++++ index.html | 56 +++ package.json | 33 ++ sort-table.js | 327 +++++++++++++ sorting-filtering-pagination-fancytable.zip | Bin 0 -> 12165 bytes src/fancyTable.js | 227 +++++++++ table_sort.css | 67 +++ table_sort.js | 30 ++ test.html | 10 + 17 files changed, 1665 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Gruntfile.js create mode 100644 LICENSE create mode 100644 README.md create mode 100644 dist/fancyTable.min.js create mode 100644 example/index.html create mode 100644 gs_sortable.js create mode 100644 index.html create mode 100644 package.json create mode 100644 sort-table.js create mode 100644 sorting-filtering-pagination-fancytable.zip create mode 100644 src/fancyTable.js create mode 100644 table_sort.css create mode 100644 table_sort.js create mode 100644 test.html diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18566ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +.vscode \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..47a6aa6 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: node_js +node_js: + - 14 + +sudo: false + +install: + - npm install + +cache: + directories: + - node_modules diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..54b6afb --- /dev/null +++ b/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']); +}; \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a8c0a54 --- /dev/null +++ b/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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..cdffcbe --- /dev/null +++ b/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 + + + +Or manually by including the script *after* the jQuery library + + + +## Usage + + + +## 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 to define that values in the column should be sorted in numerical order (..., 8, 9, 10, 10.1, 12, ...) + + + +**data-sortas="case-insensitive"** - Used in the table header element to define that values in the column should be sorted case insensitive (a, B, c, D, ...) + + + +**data-sortvalue="``"** - Used in the table data element to define an alternate value to be used when sorting + + 1 + Two + 3 + + Ghost + The Fox and the Hound + I Know What You Did Last Summer + + +### Author: [Johan Johansson](https://github.com/myspace-nu) + +### This library has been modified/used to meet the needs of Brookens Library \ No newline at end of file diff --git a/dist/fancyTable.min.js b/dist/fancyTable.min.js new file mode 100644 index 0000000..f6fa61d --- /dev/null +++ b/dist/fancyTable.min.js @@ -0,0 +1,9 @@ +/*! + * jQuery fancyTable plugin v1.0.20 + * https://github.com/myspace-nu + * + * Copyright 2018 Johan Johansson + * Released under the MIT license + */ + +!function(i){i.fn.fancyTable=function(a){var l=i.extend({inputStyle:"",inputPlaceholder:"Search...",pagination:!1,paginationClass:"btn btn-light",paginationClassActive:"active",pagClosest:3,perPage:10,sortable:!0,searchable:!0,onInit:function(){},onUpdate:function(){},testing:!1},a),r=this;return this.settings=l,this.tableUpdate=function(n){if(n.fancyTable.matches=0,i(n).find("tbody tr").each(function(){var a=0,e=!0,t=!1;i(this).find("td").each(function(){l.globalSearch||!n.fancyTable.searchArr[a]||new RegExp(n.fancyTable.searchArr[a],"i").test(i(this).html())?!l.globalSearch||n.fancyTable.search&&!new RegExp(n.fancyTable.search,"i").test(i(this).html())||Array.isArray(l.globalSearchExcludeColumns)&&l.globalSearchExcludeColumns.includes(a+1)||(t=!0):e=!1,a++}),l.globalSearch&&t||!l.globalSearch&&e?(n.fancyTable.matches++,!l.pagination||n.fancyTable.matches>n.fancyTable.perPage*(n.fancyTable.page-1)&&n.fancyTable.matches<=n.fancyTable.perPage*n.fancyTable.page?i(this).show():i(this).hide()):i(this).hide()}),n.fancyTable.pages=Math.ceil(n.fancyTable.matches/n.fancyTable.perPage),l.pagination){var a=n.fancyTable.paginationElement?i(n.fancyTable.paginationElement):i(n).find(".pag");a.empty();for(var e,t=1;t<=n.fancyTable.pages;t++)(1==t||t>n.fancyTable.page-(l.pagClosest+1)&&t",{html:t,"data-n":t,style:"margin:0.2em",class:l.paginationClass+" "+(t==n.fancyTable.page?l.paginationClassActive:"")}).css("cursor","pointer").bind("click",function(){n.fancyTable.page=i(this).data("n"),r.tableUpdate(n)}),t==n.fancyTable.pages&&n.fancyTable.page...")),a.append(e),1==t&&n.fancyTable.page>l.pagClosest+2&&a.append(i("...")))}l.onUpdate.call(this,n)},this.reinit=function(a){i(this).each(function(){i(this).find("th a").contents().unwrap(),i(this).find("tr.fancySearchRow").remove()}),i(this).fancyTable(this.settings)},this.tableSort=function(t){var a;void 0!==t.fancyTable.sortColumn&&t.fancyTable.sortColumn",{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"})).css(0").append(i(e))),0==i(s).find("thead").length&&i(s).prepend(i("")),l.sortable&&(n=0,i(s).find("thead th").each(function(){s.fancyTable.sortAs.push("numeric"==i(this).data("sortas")?"numeric":"case-insensitive"==i(this).data("sortas")?"case-insensitive":null);var a=i(this).html(),a=i("",{html:a,"data-n":n,class:""}).css("cursor","pointer").bind("click",function(){s.fancyTable.sortColumn==i(this).data("n")?s.fancyTable.sortOrder=-s.fancyTable.sortOrder:s.fancyTable.sortOrder=1,s.fancyTable.sortColumn=i(this).data("n"),r.tableSort(s),r.tableUpdate(s)});i(this).empty(),i(this).append(a),n++})),l.searchable&&(t=i("").addClass("fancySearchRow"),l.globalSearch?(a=i("",{placeholder:l.inputPlaceholder,style:"width:100%;"+l.inputStyle}).bind("change paste keyup",function(){s.fancyTable.search=i(this).val(),s.fancyTable.page=1,r.tableUpdate(s)}),e=i("",{style:"padding:2px;"}).attr("colspan",s.fancyTable.nColumns),i(a).appendTo(i(e)),i(e).appendTo(i(t))):(n=0,i(s).find("td").first().parent().find("td").each(function(){s.fancyTable.searchArr.push("");var a=i("",{"data-n":n,placeholder:l.inputPlaceholder,style:"width:100%;"+l.inputStyle}).bind("change paste keyup",function(){s.fancyTable.searchArr[i(this).data("n")]=i(this).val(),s.fancyTable.page=1,r.tableUpdate(s)}),e=i("",{style:"padding:2px;"});i(a).appendTo(i(e)),i(e).appendTo(i(t)),n++})),t.appendTo(i(s).find("thead"))),r.tableSort(s),l.pagination&&!l.paginationElement&&(i(s).find("tfoot").remove(),i(s).append(i("")),i(s).find("tfoot tr").append(i("",{}).attr("colspan",s.fancyTable.nColumns))),r.tableUpdate(s),l.onInit.call(this,s)}),this}}(jQuery); \ No newline at end of file diff --git a/example/index.html b/example/index.html new file mode 100644 index 0000000..aca696d --- /dev/null +++ b/example/index.html @@ -0,0 +1,200 @@ + + + + + + Sample + + + +
+

Table with sortable headings and global search

+ + + + + + + + + + +
Col ACol BCol C
+

+ +

+ +

Simple table with column search

+ +
+ +

Sort by nearest city

+ + + + + + + + + + + + + + + + +
CityCoordinatesDistance
Lindesberg@59.5994689,15.2132325
Tokyo@35.6708364,139.7532926
Sydney@-33.8981029,151.1612396
Stockholm@59.3275993,18.0524296
New York@40.7026091,-74.1197629
Rio de Janeiro@-22.9097071,-43.1925625
+
+ + or, find by Swedish zip code +
+ + +

Case insensitive and sort value

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Case sensitive text valuesCase insensitive text valuesNumeric values
bbbbbbTwo
AAAAAA3
DDDDDD4
cccccc1
+
+ + + + + + + + + + diff --git a/gs_sortable.js b/gs_sortable.js new file mode 100644 index 0000000..8560793 --- /dev/null +++ b/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 = "
" + node.innerHTML + + ''; + 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 + 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 + ''; + 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; +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..9c200fe --- /dev/null +++ b/index.html @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Namehere are some words in front date this is more words
Alpha12/24/1983
Bravo02/23/2014
Charlie10/09/2022
Delta04/03/1968
Echo05/26/1974
Foxtrot06/16/1997
+ \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..de70d0d --- /dev/null +++ b/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" + } +} diff --git a/sort-table.js b/sort-table.js new file mode 100644 index 0000000..a0ffeeb --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/sorting-filtering-pagination-fancytable.zip b/sorting-filtering-pagination-fancytable.zip new file mode 100644 index 0000000000000000000000000000000000000000..19f6ae2291b482b3bacabc336f219f5828564c03 GIT binary patch literal 12165 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 EANOl0ZU6uP literal 0 HcmV?d00001 diff --git a/src/fancyTable.js b/src/fancyTable.js new file mode 100644 index 0000000..710c21f --- /dev/null +++ b/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 = $("",{ + 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($("...")); + } + paginationElement.append(a); + if(n==1 && elm.fancyTable.page>settings.pagClosest+2){ + paginationElement.append($("...")); + } + } + } + } + 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 = $("
",{"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((cmpacmpb)?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("").append($(content)); + } + if($(elm).find("thead").length==0){ + $(elm).prepend($("")); + // Maybe add generated headers at some point + //var c=$(elm).find("tr").first().find("td").length; + //for(var n=0; n")); + //} + } + 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 = $("",{ + 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 = $("").addClass("fancySearchRow"); + if(settings.globalSearch){ + var searchField = $("",{ + "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 = $("",{ 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 = $("",{ + "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 = $("",{ 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($("")); + $(elm).find("tfoot tr").append($("",{ }).attr("colspan",elm.fancyTable.nColumns)); + } + instance.tableUpdate(elm); + settings.onInit.call(this,elm); + }); + return this; + }; +}(jQuery)); \ No newline at end of file diff --git a/table_sort.css b/table_sort.css new file mode 100644 index 0000000..9b1b47f --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/table_sort.js b/table_sort.js new file mode 100644 index 0000000..0e73783 --- /dev/null +++ b/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)); + }))); +} \ No newline at end of file diff --git a/test.html b/test.html new file mode 100644 index 0000000..39e393b --- /dev/null +++ b/test.html @@ -0,0 +1,10 @@ + + + + + + + +
Name;Date
+ +

 

\ No newline at end of file