mirror of
https://github.com/Mottie/tablesorter.git
synced 2025-01-12 15:24:21 +00:00
data fixes & performance improvements
This commit is contained in:
parent
0b1a411894
commit
83ccdb2bde
BIN
README.markdown
BIN
README.markdown
Binary file not shown.
@ -25,9 +25,9 @@
|
||||
|
||||
// or to change the format for specific columns, add the dateFormat to the headers option:
|
||||
headers: {
|
||||
0: { sorter: "shortDate" }, // dateFormat will parsed as the default above
|
||||
1: { sorter: "shortDate", dateFormat: "ddmmyyyy" }, // set day first format
|
||||
2: { sorter: "shortDate", dateFormat: "yyyymmdd" } // set year first format
|
||||
0: { sorter: "shortDate" } //, dateFormat will parsed as the default above
|
||||
// 1: { sorter: "shortDate", dateFormat: "ddmmyyyy" }, // set day first format; set using class names
|
||||
// 2: { sorter: "shortDate", dateFormat: "yyyymmdd" } // set year first format; set using data attributes (jQuery data)
|
||||
}
|
||||
|
||||
});
|
||||
@ -49,6 +49,15 @@
|
||||
<li>The dateFormat option will ONLY work with the <code class="hilight">shortDate</code> parser.</li>
|
||||
<li>The date can be separated by any of the following: slash, dash, period, comma, space(s) or tab (/-., ).</li>
|
||||
<li>This date format parser will only work with a four digit year. You can <a href="example-parsers.html">write your own</a> if you need a two digit year parser.</a>
|
||||
<li>In versions 2.3+, columns can be disabled using any of the following methods, in order of priority:
|
||||
<ul>
|
||||
<li>jQuery data <code class="hilight">data-sorter="false"</code> (see the Javascript block below on how to set it directly).</li>
|
||||
<li>metadata <code class="hilight">class="{ sorter: false }"</code>. This requires the metadata plugin.</li>
|
||||
<li>headers option <code class="hilight">headers : { 0 : { sorter: false } }</code>.</li>
|
||||
<li>header class name <code class="hilight">class="sorter-false"</code>.</li>
|
||||
<li>overall <code class="hilight">dateFormat</code> option setting.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
@ -57,8 +66,8 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date MMDDYYYY</th>
|
||||
<th>Date DDMMYYYY</th>
|
||||
<th>Date YYYYMMDD</th>
|
||||
<th class="sorter-shortDate dateFormat-ddmmyyyy">Date DDMMYYYY</th>
|
||||
<th data-sorter="shortDate" data-date-format="yyyymmdd">Date YYYYMMDD</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery plugin: Tablesorter 2.0 - Lock sort order using header options</title>
|
||||
<title>jQuery plugin: Tablesorter 2.0 - Lock sort order</title>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
|
||||
@ -24,10 +24,6 @@
|
||||
0: {
|
||||
// lock the sort order of the first column to ascending (always Bruce to Peter when sorting on that column)
|
||||
lockedOrder: 'asc'
|
||||
},
|
||||
2: {
|
||||
// lock the sort order of the third column to descending (always 45 to 18 when sorting on that column)
|
||||
lockedOrder: 'desc'
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -36,27 +32,37 @@
|
||||
<body>
|
||||
<div id="banner">
|
||||
<h1>table<em>sorter</em></h1>
|
||||
<h2>Lock sort order using header options</h2>
|
||||
<h2>Lock sort order</h2>
|
||||
<h3>Flexible client-side table sorting</h3>
|
||||
<a href="index.html">Back to documentation</a>
|
||||
</div>
|
||||
<div id="main">
|
||||
|
||||
<p class="tip">
|
||||
<em>TIP!</em> Sort the first and third columns to see how the sort is locked. Override this by using the multisort key (shift) while clicking on the header.<br>
|
||||
<em>NOTE!</em> This option was part of the original plugin, but it was broken.
|
||||
<em>NOTE!</em>
|
||||
<ul>
|
||||
<li>This option was part of the original plugin, but it was broken.</li>
|
||||
<li>Sort the first, third and fifth columns to see how the sort is locked.</li>
|
||||
<li>Columns can be locked using any of the following methods, in order of priority (v2.3+):
|
||||
<ul>
|
||||
<li>jQuery data <code class="hilight">data-lockedorder="asc"</code>. (equivalent to <code class="hilight">data-locked-order="asc"</code>).</li>
|
||||
<li>metadata <code class="hilight">class="{ lockedOrder: 'asc'}"</code>. This requires the metadata plugin.</li>
|
||||
<li>headers option <code class="hilight">headers : { 0 : { lockedOrder: 'asc' } }</code>.</li>
|
||||
<li>header class name <code class="hilight">class="lockedOrder-asc"</code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<h1>Demo</h1>
|
||||
<div id="demo"><table class="tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Age</th>
|
||||
<th data-lockedOrder="desc">Age</th> <!-- added as data-lockedOrder, but the DOM changes it to data-lockedorder -->
|
||||
<th>Total</th>
|
||||
<th>Discount</th>
|
||||
<th class="lockedOrder-desc">Discount</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery plugin: Tablesorter 2.0 - Set initial sort order using header options</title>
|
||||
<title>jQuery plugin: Tablesorter 2.0 - Set initial sort order</title>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
|
||||
@ -26,9 +26,7 @@
|
||||
// pass the headers argument and passing a object
|
||||
headers: {
|
||||
// set initial sort order by column, this headers option setting overrides the sortInitialOrder option
|
||||
0: { sortInitialOrder: 'desc' },
|
||||
2: { sortInitialOrder: 'desc' },
|
||||
4: { sortInitialOrder: 'desc' }
|
||||
0: { sortInitialOrder: 'desc' }
|
||||
}
|
||||
|
||||
});
|
||||
@ -37,14 +35,26 @@
|
||||
<body>
|
||||
<div id="banner">
|
||||
<h1>table<em>sorter</em></h1>
|
||||
<h2>Set initial sort order using header options</h2>
|
||||
<h2>Set initial sort order</h2>
|
||||
<h3>Flexible client-side table sorting</h3>
|
||||
<a href="index.html">Back to documentation</a>
|
||||
</div>
|
||||
<div id="main">
|
||||
|
||||
<p class="tip">
|
||||
<em>NOTE!</em> The functionality to add a "sortInitialOrder" inside of the "headers" option was added in version 2.0.8 (not part of the original plugin).
|
||||
<em>NOTE!</em>
|
||||
<ul>
|
||||
<li>Adding "sortInitialOrder" inside of the "headers" option was added in version 2.0.8 (not part of the original plugin).</li>
|
||||
<li>In versions 2.3+, the initial sort order of the columns can be set using any of the following methods, in order of priority:
|
||||
<ul>
|
||||
<li>jQuery data <code class="hilight">data-sort-initial-order="desc"</code> (equivalent to <code class="hilight">data-sortinitialorder="desc"</code>).</li>
|
||||
<li>metadata <code class="hilight">class="{ sortInitialOrder: "desc" }"</code>. This requires the metadata plugin.</li>
|
||||
<li>headers option <code class="hilight">headers : { 0 : { sortInitialOrder: "desc" } }</code>.</li>
|
||||
<li>header class name <code class="hilight">class="sortInitialOrder-desc"</code>.</li>
|
||||
<li>overall <code class="hilight">sortInitialOrder</code> option setting.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h1>Demo</h1>
|
||||
@ -53,9 +63,9 @@
|
||||
<tr>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Age</th>
|
||||
<th class="sortInitialOrder-desc">Age</th>
|
||||
<th>Total</th>
|
||||
<th>Discount</th>
|
||||
<th data-sortinitialorder="desc">Discount</th> <!-- equivalent to data-sortInitialOrder="desc" or data-sort-initialorder="desc" -->
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>jQuery plugin: Tablesorter 2.0 - Disable sort using headers options</title>
|
||||
<title>jQuery plugin: Tablesorter 2.0 - Disable sort</title>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
|
||||
@ -18,16 +18,15 @@
|
||||
<script src="../js/jquery.tablesorter.js"></script>
|
||||
|
||||
<script id="js">$(function(){
|
||||
|
||||
// BONUS TIP: disable a column using jQuery data directly
|
||||
// but do it before the table initializes
|
||||
$("table thead th:eq(5)").data("sorter", false);
|
||||
|
||||
$("table").tablesorter({
|
||||
// pass the headers argument and passing a object
|
||||
headers: {
|
||||
// assign the secound column (we start counting zero)
|
||||
1: {
|
||||
// disable it by setting the property sorter to false
|
||||
sorter: false
|
||||
},
|
||||
// assign the third column (we start counting zero)
|
||||
2: {
|
||||
// disable sorting of the first column (we start counting at zero)
|
||||
0: {
|
||||
// disable it by setting the property sorter to false
|
||||
sorter: false
|
||||
}
|
||||
@ -38,20 +37,36 @@
|
||||
<body>
|
||||
<div id="banner">
|
||||
<h1>table<em>sorter</em></h1>
|
||||
<h2>Disable sort using headers options</h2>
|
||||
<h2>Disable sort</h2>
|
||||
<h3>Flexible client-side table sorting</h3>
|
||||
<a href="index.html">Back to documentation</a>
|
||||
</div>
|
||||
<div id="main">
|
||||
|
||||
<p class="tip">
|
||||
<em>NOTE!</em>
|
||||
<ul>
|
||||
<li>In tablesorter v2.0.5 and older, only the metadata and headers options methods were available.</li>
|
||||
<li>In versions 2.3+, columns can be disabled using any of the following methods, in order of priority:
|
||||
<ul>
|
||||
<li>jQuery data <code class="hilight">data-sorter="false"</code> (see the Javascript block below on how to set it directly).</li>
|
||||
<li>metadata <code class="hilight">class="{ sorter: false }"</code>. This requires the metadata plugin.</li>
|
||||
<li>headers option <code class="hilight">headers : { 0 : { sorter: false } }</code>.</li>
|
||||
<li>header class name <code class="hilight">class="sorter-false"</code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h1>Demo</h1>
|
||||
<div id="demo"><table class="tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Age</th>
|
||||
<th data-sorter="false">Age</th>
|
||||
<th>Total</th>
|
||||
<th>Discount</th>
|
||||
<th class="sorter-false">Discount</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -31,7 +31,19 @@
|
||||
<div id="main">
|
||||
|
||||
<p class="tip">
|
||||
<em>NOTE!</em> This functionality was added in version 2.0.11 (it is not part of the original plugin).
|
||||
<em>NOTE!</em>
|
||||
<ul>
|
||||
<li>In tablesorter version 2.0.5 and older, only the metadata and headers options methods were available to set the parsers.</li>
|
||||
<li>In versions 2.0.11+, parsers could be set using class names.</li>
|
||||
<li>Currently (versions 2.3+), parsers can be set using any of the following methods, in order of priority:
|
||||
<ul>
|
||||
<li>jQuery data <code class="hilight">data-sorter="text"</code> (see the Javascript block below on how to set it directly).</li>
|
||||
<li>metadata <code class="hilight">class="{ sorter: "text" }"</code>. This requires the metadata plugin.</li>
|
||||
<li>headers option <code class="hilight">headers : { 0 : { sorter: "text" } }</code>.</li>
|
||||
<li>header class name <code class="hilight">class="sorter-text"</code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h1>Demo</h1>
|
||||
|
@ -80,10 +80,16 @@ $(function(){
|
||||
<p class="tip">
|
||||
<em>NOTE!</em>
|
||||
<ul>
|
||||
<li>This widget can be applied to the original plugin. The code is in the "jquery.tablesorter.widgets.js" file.</li>
|
||||
<li>Added filter header option and class name to allow disabling the filter in a specific column in v2.0.19.1.</li>
|
||||
<li>The Discount column has the "filter-false" class added to the header - see the HTML on how to add this ability.</li>
|
||||
<li>The Date column has the "headers" option applied to disable the sort and the filter - see the table options in the javascript for this example.</li>
|
||||
<li>As of tablesorter version 2.3, this widget <strong>can no longer be applied to the original plugin</strong>. Get the "jquery.tablesorter.widgets.js" file from a version prior to 2.3 to get a widget that works with the original plugin.</li>
|
||||
<li>In version 2.0.19.1, a filter header option and header class name check was added to allow disabling the filter in a specific column.</li>
|
||||
<li>In versions 2.3+, the filter widget can be disabled using any of the following methods, in order of priority:
|
||||
<ul>
|
||||
<li>jQuery data <code class="hilight">data-filter="false"</code>.</li>
|
||||
<li>metadata <code class="hilight">class="{ filter: false }"</code>. This requires the metadata plugin.</li>
|
||||
<li>headers option <code class="hilight">headers : { 0 : { filter: false } }</code>.</li>
|
||||
<li>header class name <code class="hilight">class="filter-false"</code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Replaced <code class="hilight">widgetFilterChildRows</code> option with <code class="hilight">widgetOptions.filter_childRows</code>. <span class="tip"><em>New! v2.1</em></span></li>
|
||||
<li>Added <code class="hilight">widgetOptions.filter_startsWith</code> option, which when <code class="hilight">true</code>, allows you to search the table from the starting of the table cell text. Use the toggle button to see the difference, and that it can be dynamically changed! <span class="tip"><em>New! v2.1</em></span></li>
|
||||
<li>Added <code class="hilight">widgetOptions.filter_cssFilter</code> option, which allows you to defined the css class applied to the filter row and each search input. <span class="tip"><em>New! v2.1</em></span></li>
|
||||
|
@ -259,9 +259,9 @@
|
||||
<li><a href="example-child-rows.html">Child rows; how to add rows that sort with their parent row</a></li>
|
||||
<li><a href="example-child-rows-filtered.html">Child rows + filter widget; how they work together</a></li>
|
||||
<li><a href="example-option-sort-order.html">Direction of initial sort</a></li>
|
||||
<li><a href="example-options-headers.html">Disable sort using headers options</a></li>
|
||||
<li><a href="example-options-headers-locked.html">Lock sort order using header options</a></li>
|
||||
<li><a href="example-options-headers-order.html">Set initial sort order using header options</a></li>
|
||||
<li><a href="example-options-headers.html">Disable sort</a></li>
|
||||
<li><a href="example-options-headers-locked.html">Lock sort order</a></li>
|
||||
<li><a href="example-options-headers-order.html">Set initial sort order</a></li>
|
||||
<li><a href="example-option-sortreset-sortrestart.html">Using sortReset & sortRestart options</a></li>
|
||||
<li><a href="example-option-sort-empty.html">Sorting empty cells</a> (v2.1.11)</li>
|
||||
<li><a href="example-option-sort-key.html">Change the default multi-sorting key</a></li>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* TableSorter 2.3.2 - Client-side table sorting with ease!
|
||||
* TableSorter 2.3.3 - Client-side table sorting with ease!
|
||||
* @requires jQuery v1.2.6+
|
||||
*
|
||||
* Copyright (c) 2007 Christian Bach
|
||||
@ -18,7 +18,7 @@
|
||||
$.extend({
|
||||
tablesorter: new function() {
|
||||
|
||||
this.version = "2.3.2";
|
||||
this.version = "2.3.3";
|
||||
|
||||
var parsers = [], widgets = [];
|
||||
this.defaults = {
|
||||
@ -275,7 +275,7 @@
|
||||
var c = table.config,
|
||||
b = table.tBodies,
|
||||
rows = [],
|
||||
r, n, totalRows, checkCell,
|
||||
r, n, totalRows, checkCell, c2 = c.cache,
|
||||
f, i, j, k, l, pos, appendTime;
|
||||
if (c.debug) {
|
||||
appendTime = new Date();
|
||||
@ -283,8 +283,8 @@
|
||||
for (k = 0; k < b.length; k++) {
|
||||
if (!$(b[k]).hasClass(c.cssInfoBlock)){
|
||||
f = document.createDocumentFragment();
|
||||
r = c.cache[k].row;
|
||||
n = c.cache[k].normalized;
|
||||
r = c2[k].row;
|
||||
n = c2[k].normalized;
|
||||
totalRows = n.length;
|
||||
checkCell = totalRows ? (n[0].length - 1) : 0;
|
||||
for (i = 0; i < totalRows; i++) {
|
||||
@ -602,6 +602,8 @@
|
||||
this.config = {};
|
||||
// merge and extend.
|
||||
c = config = $.extend(true, this.config, $.tablesorter.defaults, settings);
|
||||
|
||||
if (c.debug) { $.data( this, 'startoveralltimer', new Date()); }
|
||||
// store common expression for speed
|
||||
$this = $(this).addClass(c.tableClass);
|
||||
// save the settings where they read
|
||||
@ -805,6 +807,9 @@
|
||||
|
||||
// initialized
|
||||
this.hasInitialized = true;
|
||||
if (c.debug) {
|
||||
$.tablesorter.benchmark("Overall initialization time", $.data( this, 'startoveralltimer'));
|
||||
}
|
||||
$this.trigger('tablesorter-initialized', this);
|
||||
if (typeof c.initialized === 'function') { c.initialized(this); }
|
||||
});
|
||||
@ -903,18 +908,20 @@
|
||||
// metadata, header option or header class name ("sorter-false")
|
||||
// priority = jQuery data > meta > headers option > header class name
|
||||
this.getData = function(h, ch, key) {
|
||||
var val = '',
|
||||
m = $.metadata ? h.metadata() : false,
|
||||
cl = (h.length) ? h.attr('class') || '' : '';
|
||||
if (h.length && h.data() && typeof h.data(key) !== 'undefined'){
|
||||
val += h.data(key);
|
||||
var val = '', $h = $(h),
|
||||
m = $.metadata ? $h.metadata() : false,
|
||||
cl = ' ' + ($h.length ? $h.attr('class') || '' : '');
|
||||
if ($h.length && $h.data() && ( typeof $h.data(key) !== 'undefined' || typeof $h.data(key.toLowerCase()) !== 'undefined') ){
|
||||
// "data-lockedOrder" is assigned to "lockedorder"; but "data-locked-order" is assigned to "lockedOrder"
|
||||
// "data-sort-initial-order" is assigned to "sortInitialOrder"
|
||||
val += $h.data(key) || $h.data(key.toLowerCase());
|
||||
} else if (m && typeof m[key] !== 'undefined') {
|
||||
val += m[key];
|
||||
} else if (ch && typeof ch[key] !== 'undefined') {
|
||||
val += ch[key];
|
||||
} else if (cl && cl.match(key + '-')) {
|
||||
} else if (cl && cl.match(' ' + key + '-')) {
|
||||
// include sorter class name "sorter-text", etc
|
||||
val = cl.match( new RegExp(key + '-(\\w+)') )[1] || '';
|
||||
val = cl.match( new RegExp(' ' + key + '-(\\w+)') )[1] || '';
|
||||
}
|
||||
return $.trim(val);
|
||||
};
|
||||
@ -1032,8 +1039,12 @@
|
||||
return (/\d{1,4}[\/\-\,\.\s+]\d{1,4}[\/\-\.\,\s+]\d{1,4}/).test(s);
|
||||
},
|
||||
format: function(s, table, cell, cellIndex) {
|
||||
var c = table.config,
|
||||
format = ts.getData($(cell), c.headers[cellIndex], 'dateFormat') || c.dateFormat;
|
||||
var c = table.config, ci = c.headerList[cellIndex],
|
||||
format = ci.shortDateFormat;
|
||||
if (typeof format === 'undefined') {
|
||||
// cache header formatting so it doesn't getData for every cell in the column
|
||||
format = ci.shortDateFormat = ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat;
|
||||
}
|
||||
s = s.replace(/\s+/g," ").replace(/[\-|\.|\,]/g, "/");
|
||||
if (format === "mmddyyyy") {
|
||||
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
|
||||
@ -1086,9 +1097,9 @@
|
||||
ts.addWidget({
|
||||
id: "zebra",
|
||||
format: function(table) {
|
||||
var $tr, $r, row, even, time, k,
|
||||
var $tb, $tr, $f, row, even, time, k, j, l, n,
|
||||
c = table.config,
|
||||
child = c.cssChildRow,
|
||||
child = new RegExp(c.cssChildRow, 'i'),
|
||||
b = $(table).children('tbody:not(.' + c.cssInfoBlock + ')'),
|
||||
css = [ "even", "odd" ];
|
||||
// maintain backwards compatibility
|
||||
@ -1100,18 +1111,22 @@
|
||||
for (k = 0; k < b.length; k++ ) {
|
||||
row = 0;
|
||||
// loop through the visible rows
|
||||
$tr = $(b[k]).children('tr:visible');
|
||||
if ($tr.length > 1) {
|
||||
$tr.each(function() {
|
||||
$r = $(this);
|
||||
// style children rows the same way the parent row was styled
|
||||
if (!$r.hasClass(child)) { row++; }
|
||||
even = (row % 2 === 0);
|
||||
$r
|
||||
.removeClass(css[even ? 1 : 0])
|
||||
.addClass(css[even ? 0 : 1]);
|
||||
});
|
||||
$tb = $(b[k]);
|
||||
l = $tb.children('tr').length;
|
||||
if (l > 1) {
|
||||
$f = $(document.createDocumentFragment());
|
||||
$tr = $tb.children('tr').appendTo($f);
|
||||
for (j = 0; j < l; j++) {
|
||||
if ($tr[j].style.display !== 'none') {
|
||||
n = $tr[j].className;
|
||||
// style children rows the same way the parent row was styled
|
||||
if (!child.test(n)) { row++; }
|
||||
even = (row % 2 === 0);
|
||||
$tr[j].className = n.replace(/\s+/g,'').replace(css[0],'').replace(css[1],'') + ' ' + css[even ? 0 : 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
$tb.append($tr);
|
||||
}
|
||||
if (c.debug) {
|
||||
ts.benchmark("Applying Zebra widget", time);
|
||||
|
4
js/jquery.tablesorter.min.js
vendored
4
js/jquery.tablesorter.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,8 +1,8 @@
|
||||
/*! tableSorter 2.3 widgets - updated 5/11/2012
|
||||
/*! tableSorter 2.3 widgets - updated 5/19/2012
|
||||
*
|
||||
* jQuery UI Theme
|
||||
* Column Styles
|
||||
* Column Filters
|
||||
* Column Filters (not compatible with tablesorter v2.0.5)
|
||||
* Sticky Header
|
||||
* Column Resizing
|
||||
* Save Sort
|
||||
@ -125,7 +125,7 @@ $.tablesorter.addWidget({
|
||||
$.tablesorter.addWidget({
|
||||
id: "columns",
|
||||
format: function(table) {
|
||||
var $tr, $td, time, last, rmv, k,
|
||||
var $tb, $tr, $td, $f, time, last, rmv, i, j, k, l,
|
||||
c = table.config,
|
||||
b = $(table).children('tbody:not(.' + c.cssInfoBlock + ')'),
|
||||
list = c.sortList,
|
||||
@ -142,23 +142,33 @@ $.tablesorter.addWidget({
|
||||
// check if there is a sort (on initialization there may not be one)
|
||||
if (list && list[0]) {
|
||||
for (k = 0; k < b.length; k++ ) {
|
||||
$tb = $(b[k]);
|
||||
$f = $(document.createDocumentFragment());
|
||||
$tr = $tb.children('tr').appendTo($f);
|
||||
l = $tr.length;
|
||||
// loop through the visible rows
|
||||
$tr = $(b[k]).children('tr:visible');
|
||||
$tr.each(function(i) {
|
||||
$td = $(this).children().removeClass(rmv);
|
||||
for (j = 0; j < l; j++) {
|
||||
$td = $tr.eq(j).children().removeClass(rmv);
|
||||
// primary sort column class
|
||||
$td.eq(list[0][0]).addClass(css[0]);
|
||||
if (len > 1) {
|
||||
for (i=1; i<len; i++){
|
||||
for (i = 1; i < len; i++){
|
||||
// secondary, tertiary, etc sort column classes
|
||||
$td.eq(list[i][0]).addClass( css[i] || css[last] );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$tb.append($tr);
|
||||
}
|
||||
} else {
|
||||
// remove all column classes if sort is cleared (sortReset)
|
||||
$(table).find('td').removeClass(rmv);
|
||||
// $(table).find('td').removeClass(rmv); slow
|
||||
$td = $(table).find('td');
|
||||
len = $td.length;
|
||||
rmv = new RegExp('(' + css.join('|') + ')');
|
||||
for (i = 0; i < len; i++){
|
||||
$td[i].className = $td[i].className.replace(rmv, '');
|
||||
}
|
||||
}
|
||||
if (c.debug) {
|
||||
$.tablesorter.benchmark("Applying Columns widget", time);
|
||||
@ -186,7 +196,13 @@ $.tablesorter.addWidget({
|
||||
for (i=0; i < cols; i++){
|
||||
fr += '<td><input type="search" data-col="' + i + '" class="' + css;
|
||||
// use header option - headers: { 1: { filter: false } } OR add class="filter-false"
|
||||
fr += $.tablesorter.getData(c.headerList[i], c.headers[i], 'filter') === 'false' ? ' disabled" disabled' : '"';
|
||||
if ($.tablesorter.getData) {
|
||||
// get data from jQuery data, metadata, headers option or header class name
|
||||
fr += $.tablesorter.getData(c.headerList[i], c.headers[i], 'filter') === 'false' ? ' disabled" disabled' : '"';
|
||||
} else {
|
||||
// only class names and header options - keep this for compatibility with tablesorter v2.0.5
|
||||
fr += ((c.headers[i] && c.headers[i].hasOwnProperty('filter') && c.headers[i].filter === false) || $(c.headerList[i]).is('.filter-false') ) ? ' disabled" disabled' : '"';
|
||||
}
|
||||
fr += '></td>';
|
||||
}
|
||||
$t
|
||||
@ -196,6 +212,7 @@ $.tablesorter.addWidget({
|
||||
if (v.join('') === '') {
|
||||
$t.find('tr').show();
|
||||
} else {
|
||||
// *** to do *** optimize this to work better with very large tables
|
||||
$t.children('tbody:not(.' + c.cssInfoBlock + ')').children('tr:not(.' + c.cssChildRow + ')').each(function(){
|
||||
r = true;
|
||||
cr = $(this).nextUntil('tr:not(.' + c.cssChildRow + ')');
|
||||
|
16
js/jquery.tablesorter.widgets.min.js
vendored
16
js/jquery.tablesorter.widgets.min.js
vendored
@ -1,10 +1,10 @@
|
||||
/*! tableSorter 2.3 widgets - updated 5/11/2012 */
|
||||
/*! tableSorter 2.3 widgets - updated 5/19/2012 */
|
||||
;(function(b){
|
||||
b.tablesorter.storage=function(a,f,d){var c,g=!1;c={};var i=a.id||b(".tablesorter").index(b(a)),e=window.location.pathname;try{g=!!localStorage.getItem}catch(h){}b.parseJSON&&(g?c=b.parseJSON(localStorage[f])||{}:(c=document.cookie.split(/[;\s|=]/),a=b.inArray(f,c)+1,c=0!==a?b.parseJSON(c[a])||{}:{}));if(d&&JSON&&JSON.hasOwnProperty("stringify")){if(!c[e]||!c[e][i])c[e]||(c[e]={});c[e][i]=d;g?localStorage[f]=JSON.stringify(c):(a=new Date,a.setTime(a.getTime()+31536E6),document.cookie= f+"="+JSON.stringify(c).replace(/\"/g,'"')+"; expires="+a.toGMTString()+"; path=/")}else return c&&c.hasOwnProperty(e)&&c[e].hasOwnProperty(i)?c[e][i]:{}};
|
||||
b.tablesorter.addWidget({id:"uitheme",format:function(a){var f,d,c,g,i,e=b(a),h=a.config,j=h.widgetOptions,k=["ui-icon-arrowthick-2-n-s","ui-icon-arrowthick-1-s","ui-icon-arrowthick-1-n"],k=h.widgetUitheme&&h.widgetUitheme.hasOwnProperty("css")?h.widgetUitheme.css||k:j&&j.hasOwnProperty("uitheme")?j.uitheme:k;c=k.join(" ");h.debug&&(f=new Date); e.hasClass("ui-theme")||(e.addClass("ui-widget ui-widget-content ui-corner-all ui-theme"),b.each(h.headerList,function(){b(this).addClass("ui-widget-header ui-corner-all ui-state-default").append('<span class="ui-icon"/>').wrapInner('<div class="tablesorter-inner"/>').hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")})}));b.each(h.headerList,function(a){g=b(this);if(this.sortDisabled)g.find("span.ui-icon").removeClass(c+" ui-icon");else{d=g.hasClass(h.cssAsc)? k[1]:g.hasClass(h.cssDesc)?k[2]:g.hasClass(h.cssHeader)?k[0]:"";i=e.hasClass("hasStickyHeaders")?e.find("tr."+(j.stickyHeaders||"tablesorter-stickyHeader")).find("th").eq(a).add(g):g;i[d===k[0]?"removeClass":"addClass"]("ui-state-active").find("span.ui-icon").removeClass(c).addClass(d)}});h.debug&&b.tablesorter.benchmark("Applying uitheme widget",f)}});
|
||||
b.tablesorter.addWidget({id:"columns",format:function(a){var f,d,c,g,i,e=a.config,h=b(a).children("tbody:not(."+e.cssInfoBlock+")"),j=e.sortList,k= j.length,l=["primary","secondary","tertiary"],l=e.widgetColumns&&e.widgetColumns.hasOwnProperty("css")?e.widgetColumns.css||l:e.widgetOptions&&e.widgetOptions.hasOwnProperty("columns")?e.widgetOptions.columns||l:l;c=l.length-1;g=l.join(" ");e.debug&&(d=new Date);if(j&&j[0])for(i=0;i<h.length;i++)a=b(h[i]).children("tr:visible"),a.each(function(a){f=b(this).children().removeClass(g);f.eq(j[0][0]).addClass(l[0]);if(1<k)for(a=1;a<k;a++)f.eq(j[a][0]).addClass(l[a]||l[c])});else b(a).find("td").removeClass(g); e.debug&&b.tablesorter.benchmark("Applying Columns widget",d)}});
|
||||
b.tablesorter.addWidget({id:"filter",format:function(a){if(!b(a).hasClass("hasFilters")){var f,d,c,g,i,e,h,j=a.config,k=j.widgetOptions,l=k.filter_cssFilter||"tablesorter-filter",m=b(a).addClass("hasFilters"),n=j.parsers.length,a='<tr class="'+l+'">',o;j.debug&&(o=new Date);for(f=0;f<n;f++)a+='<td><input type="search" data-col="'+f+'" class="'+l,a+="false"===b.tablesorter.getData(j.headerList[f],j.headers[f],"filter")?' disabled" disabled': '"',a+="></td>";m.find("thead").eq(0).append(a+="</tr>").find("input."+l).bind("keyup search",function(){d=m.find("thead").eq(0).children("tr").find("input."+l).map(function(){return(b(this).val()||"").toLowerCase()}).get();""===d.join("")?m.find("tr").show():m.children("tbody:not(."+j.cssInfoBlock+")").children("tr:not(."+j.cssChildRow+")").each(function(){c=!0;e=b(this).nextUntil("tr:not(."+j.cssChildRow+")");g=e.length&&(k&&k.hasOwnProperty("filter_childRows")&&"undefined"!==typeof k.filter_childRows? k.filter_childRows:1)?e.text():"";h=b(this).children("td");for(f=0;f<n;f++)i=b.trim(h.eq(f).text()+g).toLowerCase().indexOf(d[f]),""!==d[f]&&(!k.filter_startsWith&&0<=i||k.filter_startsWith&&0===i)?c=c?!0:!1:""!==d[f]&&(c=!1);b(this)[c?"show":"hide"]();if(e.length)e[c?"show":"hide"]()});m.trigger("applyWidgets")});j.debug&&b.tablesorter.benchmark("Applying Filter widget",o)}}});
|
||||
b.tablesorter.addWidget({id:"stickyHeaders",format:function(a){if(!b(a).hasClass("hasStickyHeaders")){var f=b(a).addClass("hasStickyHeaders"), d=a.config.widgetOptions,c=b(window),g=b(a).children("thead"),i=g.children("tr:not(.sticky-false)").children(),e=d.stickyHeaders||"tablesorter-stickyHeader",h=i.eq(0),j=f.find("tfoot"),k=g.find("tr.tablesorter-header:not(.sticky-false)").clone().removeClass("tablesorter-header").addClass(e).css({width:g.outerWidth(!0),position:"fixed",left:h.offset().left,margin:0,top:0,visibility:"hidden",zIndex:10}),l=k.children(),m="";f.bind("sortEnd",function(a,c){var d=b(c).find("thead tr"),f=d.filter("."+e).children(); d.filter(":not(."+e+")").children().each(function(a){f.eq(a).attr("class",b(this).attr("class"))})}).bind("pagerComplete",function(){c.resize()});i.each(function(a){var c=b(this);l.eq(a).bind("click",function(a){c.trigger(a)}).bind("mousedown",function(){this.onselectstart=function(){return!1};return!1}).find(".tablesorter-header-inner").width(c.find(".tablesorter-header-inner").width())});g.prepend(k);c.scroll(function(){var a=h.offset(),b=c.scrollTop(),d=f.height()-(h.height()+(j.height()||0)), b=b>a.top&&b<a.top+d?"visible":"hidden";k.css({left:a.left-c.scrollLeft(),visibility:b});b!==m&&(c.resize(),m=b)}).resize(function(){var a=0;k.css({left:h.offset().left-c.scrollLeft(),width:g.outerWidth()}).each(function(c){b(this).css("top",a);a+=g.find("tr").eq(c).outerHeight()});l.find(".tablesorter-header-inner").each(function(a){b(this).width(i.eq(a).find(".tablesorter-header-inner").width())})})}}});
|
||||
b.tablesorter.addWidget({id:"resizable",format:function(a){if(!b(a).hasClass("hasResizable")){b(a).addClass("hasResizable"); var f,d,c=a.config,g=b(c.headerList).filter(":gt(0)"),i=0,e=null,h=null,j=function(){i=0;e=h=null;b(window).trigger("resize")};if(d=b.tablesorter.storage?b.tablesorter.storage(a,"tablesorter-resizable"):"")for(f in d)!isNaN(f)&&f<c.headerList.length&&b(c.headerList[f]).width(d[f]);g.each(function(){b(this).append('<div class="tablesorter-resizer" style="cursor:w-resize;position:absolute;height:100%;width:20px;left:-20px;top:0;z-index:1;"></div>').wrapInner('<div style="position:relative;height:100%;width:100%"></div>')}).bind("mousemove", function(a){if(0!==i&&e){var b=a.pageX-i;e.width()<-b||h&&h.width()<=b||(h.width(h.width()+b),i=a.pageX)}}).bind("mouseup",function(){d&&(b.tablesorter.storage&&e)&&(d[h.index()]=h.width(),b.tablesorter.storage(a,"tablesorter-resizable",d));j();return!1}).find(".tablesorter-resizer").bind("mousedown",function(a){e=b(a.target).closest("th");h=e.prev();i=a.pageX});b(a).find("thead").bind("mouseup mouseleave",function(){j()})}}});
|
||||
b.tablesorter.addWidget({id:"saveSort",init:function(a,b,d){d.format(a, !0)},format:function(a,f){var d,c,g=a.config;d={sortList:g.sortList};g.debug&&(c=new Date);b(a).hasClass("hasSaveSort")?a.hasInitialized&&b.tablesorter.storage&&(b.tablesorter.storage(a,"tablesorter-savesort",d),g.debug&&b.tablesorter.benchmark("saveSort widget: Saving last sort: "+g.sortList,c)):(b(a).addClass("hasSaveSort"),d="",b.tablesorter.storage&&(d=(d=b.tablesorter.storage(a,"tablesorter-savesort"))&&d.hasOwnProperty("sortList")&&b.isArray(d.sortList)?d.sortList:"",g.debug&&b.tablesorter.benchmark("saveSort: Last sort loaded: "+ d,c)),f&&d&&0<d.length?g.sortList=d:a.hasInitialized&&(d&&0<d.length)&&b(a).trigger("sorton",[d]))}})
|
||||
b.tablesorter.storage=function(a,e,c){var d,h=!1;d={};var j=a.id||b(".tablesorter").index(b(a)),f=window.location.pathname;try{h=!!localStorage.getItem}catch(g){}b.parseJSON&&(h?d=b.parseJSON(localStorage[e])||{}:(d=document.cookie.split(/[;\s|=]/),a=b.inArray(e,d)+1,d=0!==a?b.parseJSON(d[a])||{}:{}));if(c&&JSON&&JSON.hasOwnProperty("stringify")){if(!d[f]||!d[f][j])d[f]||(d[f]={});d[f][j]=c;h?localStorage[e]=JSON.stringify(d):(a=new Date,a.setTime(a.getTime()+31536E6),document.cookie= e+"="+JSON.stringify(d).replace(/\"/g,'"')+"; expires="+a.toGMTString()+"; path=/")}else return d&&d.hasOwnProperty(f)&&d[f].hasOwnProperty(j)?d[f][j]:{}};
|
||||
b.tablesorter.addWidget({id:"uitheme",format:function(a){var e,c,d,h,j,f=b(a),g=a.config,i=g.widgetOptions,k=["ui-icon-arrowthick-2-n-s","ui-icon-arrowthick-1-s","ui-icon-arrowthick-1-n"],k=g.widgetUitheme&&g.widgetUitheme.hasOwnProperty("css")?g.widgetUitheme.css||k:i&&i.hasOwnProperty("uitheme")?i.uitheme:k;d=k.join(" ");g.debug&&(e=new Date); f.hasClass("ui-theme")||(f.addClass("ui-widget ui-widget-content ui-corner-all ui-theme"),b.each(g.headerList,function(){b(this).addClass("ui-widget-header ui-corner-all ui-state-default").append('<span class="ui-icon"/>').wrapInner('<div class="tablesorter-inner"/>').hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")})}));b.each(g.headerList,function(a){h=b(this);if(this.sortDisabled)h.find("span.ui-icon").removeClass(d+" ui-icon");else{c=h.hasClass(g.cssAsc)? k[1]:h.hasClass(g.cssDesc)?k[2]:h.hasClass(g.cssHeader)?k[0]:"";j=f.hasClass("hasStickyHeaders")?f.find("tr."+(i.stickyHeaders||"tablesorter-stickyHeader")).find("th").eq(a).add(h):h;j[c===k[0]?"removeClass":"addClass"]("ui-state-active").find("span.ui-icon").removeClass(d).addClass(c)}});g.debug&&b.tablesorter.benchmark("Applying uitheme widget",e)}});
|
||||
b.tablesorter.addWidget({id:"columns",format:function(a){var e,c,d,h,j,f,g,i,k,l=a.config,m=b(a).children("tbody:not(."+l.cssInfoBlock+")"),o=l.sortList, p=o.length,n=["primary","secondary","tertiary"],n=l.widgetColumns&&l.widgetColumns.hasOwnProperty("css")?l.widgetColumns.css||n:l.widgetOptions&&l.widgetOptions.hasOwnProperty("columns")?l.widgetOptions.columns||n:n;h=n.length-1;j=n.join(" ");l.debug&&(d=new Date);if(o&&o[0])for(i=0;i<m.length;i++){a=b(m[i]);e=b(document.createDocumentFragment());e=a.children("tr").appendTo(e);k=e.length;for(g=0;g<k;g++)if(c=e.eq(g).children().removeClass(j),c.eq(o[0][0]).addClass(n[0]),1<p)for(f=1;f<p;f++)c.eq(o[f][0]).addClass(n[f]|| n[h]);a.append(e)}else{c=b(a).find("td");p=c.length;j=RegExp("("+n.join("|")+")");for(f=0;f<p;f++)c[f].className=c[f].className.replace(j,"")}l.debug&&b.tablesorter.benchmark("Applying Columns widget",d)}});
|
||||
b.tablesorter.addWidget({id:"filter",format:function(a){if(!b(a).hasClass("hasFilters")){var e,c,d,h,j,f,g,i=a.config,k=i.widgetOptions,l=k.filter_cssFilter||"tablesorter-filter",m=b(a).addClass("hasFilters"),o=i.parsers.length,a='<tr class="'+l+'">',p;i.debug&&(p=new Date);for(e=0;e<o;e++)a+= '<td><input type="search" data-col="'+e+'" class="'+l,a=b.tablesorter.getData?a+("false"===b.tablesorter.getData(i.headerList[e],i.headers[e],"filter")?' disabled" disabled':'"'):a+(i.headers[e]&&i.headers[e].hasOwnProperty("filter")&&!1===i.headers[e].filter||b(i.headerList[e]).is(".filter-false")?' disabled" disabled':'"'),a+="></td>";m.find("thead").eq(0).append(a+="</tr>").find("input."+l).bind("keyup search",function(){c=m.find("thead").eq(0).children("tr").find("input."+l).map(function(){return(b(this).val()|| "").toLowerCase()}).get();""===c.join("")?m.find("tr").show():m.children("tbody:not(."+i.cssInfoBlock+")").children("tr:not(."+i.cssChildRow+")").each(function(){d=!0;f=b(this).nextUntil("tr:not(."+i.cssChildRow+")");h=f.length&&(k&&k.hasOwnProperty("filter_childRows")&&"undefined"!==typeof k.filter_childRows?k.filter_childRows:1)?f.text():"";g=b(this).children("td");for(e=0;e<o;e++)j=b.trim(g.eq(e).text()+h).toLowerCase().indexOf(c[e]),""!==c[e]&&(!k.filter_startsWith&&0<=j||k.filter_startsWith&& 0===j)?d=d?!0:!1:""!==c[e]&&(d=!1);b(this)[d?"show":"hide"]();if(f.length)f[d?"show":"hide"]()});m.trigger("applyWidgets")});i.debug&&b.tablesorter.benchmark("Applying Filter widget",p)}}});
|
||||
b.tablesorter.addWidget({id:"stickyHeaders",format:function(a){if(!b(a).hasClass("hasStickyHeaders")){var e=b(a).addClass("hasStickyHeaders"),c=a.config.widgetOptions,d=b(window),h=b(a).children("thead"),j=h.children("tr:not(.sticky-false)").children(),f=c.stickyHeaders||"tablesorter-stickyHeader",g=j.eq(0),i= e.find("tfoot"),k=h.find("tr.tablesorter-header:not(.sticky-false)").clone().removeClass("tablesorter-header").addClass(f).css({width:h.outerWidth(!0),position:"fixed",left:g.offset().left,margin:0,top:0,visibility:"hidden",zIndex:10}),l=k.children(),m="";e.bind("sortEnd",function(a,c){var d=b(c).find("thead tr"),e=d.filter("."+f).children();d.filter(":not(."+f+")").children().each(function(a){e.eq(a).attr("class",b(this).attr("class"))})}).bind("pagerComplete",function(){d.resize()});j.each(function(a){var c= b(this);l.eq(a).bind("click",function(b){c.trigger(b)}).bind("mousedown",function(){this.onselectstart=function(){return!1};return!1}).find(".tablesorter-header-inner").width(c.find(".tablesorter-header-inner").width())});h.prepend(k);d.scroll(function(){var b=g.offset(),a=d.scrollTop(),c=e.height()-(g.height()+(i.height()||0)),a=a>b.top&&a<b.top+c?"visible":"hidden";k.css({left:b.left-d.scrollLeft(),visibility:a});a!==m&&(d.resize(),m=a)}).resize(function(){var a=0;k.css({left:g.offset().left-d.scrollLeft(), width:h.outerWidth()}).each(function(c){b(this).css("top",a);a+=h.find("tr").eq(c).outerHeight()});l.find(".tablesorter-header-inner").each(function(a){b(this).width(j.eq(a).find(".tablesorter-header-inner").width())})})}}});
|
||||
b.tablesorter.addWidget({id:"resizable",format:function(a){if(!b(a).hasClass("hasResizable")){b(a).addClass("hasResizable");var e,c,d=a.config,h=b(d.headerList).filter(":gt(0)"),j=0,f=null,g=null,i=function(){j=0;f=g=null;b(window).trigger("resize")};if(c=b.tablesorter.storage? b.tablesorter.storage(a,"tablesorter-resizable"):"")for(e in c)!isNaN(e)&&e<d.headerList.length&&b(d.headerList[e]).width(c[e]);h.each(function(){b(this).append('<div class="tablesorter-resizer" style="cursor:w-resize;position:absolute;height:100%;width:20px;left:-20px;top:0;z-index:1;"></div>').wrapInner('<div style="position:relative;height:100%;width:100%"></div>')}).bind("mousemove",function(a){if(0!==j&&f){var b=a.pageX-j;f.width()<-b||g&&g.width()<=b||(g.width(g.width()+b),j=a.pageX)}}).bind("mouseup", function(){c&&(b.tablesorter.storage&&f)&&(c[g.index()]=g.width(),b.tablesorter.storage(a,"tablesorter-resizable",c));i();return!1}).find(".tablesorter-resizer").bind("mousedown",function(a){f=b(a.target).closest("th");g=f.prev();j=a.pageX});b(a).find("thead").bind("mouseup mouseleave",function(){i()})}}});
|
||||
b.tablesorter.addWidget({id:"saveSort",init:function(a,b,c){c.format(a,!0)},format:function(a,e){var c,d,h=a.config;c={sortList:h.sortList};h.debug&&(d=new Date);b(a).hasClass("hasSaveSort")?a.hasInitialized&& b.tablesorter.storage&&(b.tablesorter.storage(a,"tablesorter-savesort",c),h.debug&&b.tablesorter.benchmark("saveSort widget: Saving last sort: "+h.sortList,d)):(b(a).addClass("hasSaveSort"),c="",b.tablesorter.storage&&(c=(c=b.tablesorter.storage(a,"tablesorter-savesort"))&&c.hasOwnProperty("sortList")&&b.isArray(c.sortList)?c.sortList:"",h.debug&&b.tablesorter.benchmark("saveSort: Last sort loaded: "+c,d)),e&&c&&0<c.length?h.sortList=c:a.hasInitialized&&(c&&0<c.length)&&b(a).trigger("sorton",[c]))}})
|
||||
})(jQuery);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tablesorter",
|
||||
"version": "2.3.2",
|
||||
"version": "2.3.3",
|
||||
"title": "tablesorter",
|
||||
"author": {
|
||||
"name": "Christian Bach",
|
||||
|
Loading…
Reference in New Issue
Block a user