Tablesorter 似乎是 运行 两次用于列选择
Tablesorter appears to be running twice for column selection
多年来我一直在使用 Mottie 出色的 Tablesorter 分支。我 运行 遇到了一个我以前从未见过的问题,我不确定从哪里开始寻找这个问题。
所有功能都正常工作,但是当我单击 Column 按钮时,它显示 'auto' 两次,并拉入非列的内容。在下图中,带有红色下划线的项目不属于 headers。它们是灰色的,无法触摸。我不知道他们来自哪里。
headers 派生自动态条目集,粘贴在下面。不确定这是否相关,但我发布了代码以防它有帮助:
<tr id="sort_data" data-col="{{$col}}">
@foreach($atts as $cus_att)
@if($cus_att->attribute->visible_in_list_view)
<th class="center {{$cus_att->attribute->optional_in_list_view? 'columnSelector-false':''}}">
{{$cus_att->attribute->name}}
</th>
@endif
@endforeach
<th class="center col-1" data-filter="false" data-sorter="false">{{__("Action")}}</th>
</tr>
我不知道我是否遗漏了一些明显的东西,但是任何关于从哪里开始寻找错误的想法都将不胜感激。
谢谢!
已渲染 HTML:
<table id="table1" class="table table-bordered tablesorter tablesorter-blue tablesorterefb7ab942ea838columnselector hasResizable hasFilters hasStickyHeaders" data-sort-name="name" role="grid" aria-describedby="table1_pager_info">
<thead id="thead">
<tr id="sort_data" data-col="0" role="row" class="tablesorter-headerRow">
<th class="center tablesorter-header tablesorter-headerAsc" data-column="0" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="ascending" aria-label="Name: Ascending sort applied, activate to apply a descending sort"><div class="tablesorter-header-inner">
Name
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="1" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Owner: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Owner
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="2" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Priority: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Priority
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="3" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Data Location: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Data Location
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="4" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Category: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Category
</div></th>
<th class="center columnSelector-false tablesorter-header tablesorter-headerUnSorted" data-column="5" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Support: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Support
</div></th>
<th class="center col-1 tablesorter-header sorter-false tablesorter-headerUnSorted" data-filter="false" data-sorter="false" data-column="6" scope="col" role="columnheader" aria-disabled="true" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Action: No sort applied, sorting is disabled"><div class="tablesorter-header-inner">Action</div></th>
</tr>
<tr role="row" class="tablesorter-filter-row tablesorter-ignoreRow"><td data-column="0" class="pointer center"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="0" data-lastsearchtime="1628907240814"><span class="glyphicon glyphicon-refresh reset" style="margin-top:4px;"></span></td><td data-column="1"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="1" data-lastsearchtime="1628907240814"></td><td data-column="2"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="2" data-lastsearchtime="1628907240814"></td><td data-column="3"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="3" data-lastsearchtime="1628907240814"></td><td data-column="4"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="4" data-lastsearchtime="1628907240814"></td><td data-column="5"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="5" data-lastsearchtime="1628907240814"></td><td data-column="6"><input type="search" placeholder="" class="tablesorter-filter disabled" data-column="6" disabled="" data-lastsearchtime="1628907240814"></td></tr></thead>
<tbody class="tbodyContent reorderDiv" aria-live="polite" aria-relevant="all">
TS 初始化
$(function() {
var $table = $("table");
var sortCol = $("#sort_data").data('col');
$('button.columnSelectorButton').click(function(){
$.tablesorter.storage( $table, 'tablesorter-columnSelector', [] );
$.tablesorter.storage( $table, 'tablesorter-columnSelector-auto', {} );
// reload the page
document.location.reload();
});
/*** custom css only button popup ***/
$table.tablesorter({
theme: 'blue',
sortList: [[sortCol,0]],
widgets: ['zebra', 'filter', 'columnSelector', 'resizable', 'stickyHeaders'],
widgetOptions : {
resizable: true,
resizable_addLastColumn: true,
// Filters:
filter_columnFilters: true,
filter_placeholder: {search: 'Search...'},
filter_saveFilters: false,
filter_reset: '.reset',
{{-- number or jquery selector targeting the position:fixed element -- how far from top should header
sit, or create a class (like black_bar) that should alos be included in the sticky headaer --}}
stickyHeaders_offset : 45,
stickyHeaders : '.black_bar',
{{-- target the column selector markup --}}
columnSelector_container : $('#columnSelector'),
{{-- column status, true = display, false = hide
// disable = do not display on list --}}
columnSelector_columns : {
0: 'disable' /* set to disabled; not allowed to unselect it */
},
{{-- remember selected columns (requires $.tablesorter.storage) --}}
columnSelector_saveColumns: true,
{{-- container layout --}}
columnSelector_layout : '<label><input type="checkbox">{name}</label>',
{{-- data attribute containing column name to use in the selector container --}}
columnSelector_name : 'data-selector-name',
{{-- Responsive Media Query settings
enable/disable mediaquery breakpoints --}}
columnSelector_mediaquery: true,
{{-- toggle checkbox name --}}
columnSelector_mediaqueryName: 'Auto: ',
{{-- breakpoints checkbox initial setting --}}
columnSelector_mediaqueryState: true,
{{-- hide columnSelector false columns while in auto mode --}}
columnSelector_mediaqueryHidden: true,
{{-- responsive table hides columns with priority 1-6 at these breakpoints
// see http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/#Applyingapresetbreakpoint
// *** set to false to disable *** --}}
columnSelector_breakpoints : [ '20em', '30em', '40em', '50em', '60em', '70em' ],
{{-- data attribute containing column priority
// duplicates how jQuery mobile uses priorities:
// http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/ --}}
columnSelector_priority : 'data-priority',
{{-- class name added to checked checkboxes - this fixes an issue with Chrome not updating FontAwesome
applied icons; use this class name (input.checked) instead of input:checked --}}
columnSelector_cssChecked : 'checked'
}
})
{{-- bind to pager events
********************* --}}
.bind('pagerChange pagerComplete pagerInitialized pageMoved', function (e, c) {
var msg = '"</span> event triggered, ' + (e.type === 'pagerChange' ? 'going to' : 'now on') +
' page <span class="typ">' + (c.page + 1) + '/' + c.totalPages + '</span>';
$('#display')
.append('<li><span class="str">"' + e.type + msg + '</li>')
.find('li:first').remove();
})
{{-- initialize the pager plugin
**************************** --}}
.tablesorterPager(pagerOptions);
TS 寻呼机选项:
var pagerOptions = {
// target the pager markup - see the HTML block below
container: $(".pager"),
// use this url format "http:/mydatabase.com?page={page}&size={size}&{sortList:col}"
ajaxUrl: null,
// modify the url after all processing has been applied
customAjaxUrl: function (table, url) {
return url;
},
// ajax error callback from $.tablesorter.showError function
// ajaxError: function( config, xhr, settings, exception ){ return exception; };
// returning false will abort the error message
ajaxError: null,
// add more ajax settings here
// see http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
ajaxObject: {dataType: 'json'},
// process ajax so that the data object is returned along with the total number of rows
ajaxProcessing: null,
// Set this option to false if your table data is preloaded into the table, but you are still using ajax
processAjaxOnInit: true,
// output string - default is '{page}/{totalPages}'
// possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows}
// also {page:input} & {startRow:input} will add a modifiable input in place of the value
output: '{startRow:input} to {endRow} ({totalRows})',
// apply disabled classname (cssDisabled option) to the pager arrows when the rows
// are at either extreme is visible; default is true
updateArrows: true,
// starting page of the pager (zero based index)
page: 0,
// Number of visible rows
size: 30,
// Save pager page & size if the storage script is loaded (requires $.tablesorter.storage in jquery.tablesorter.widgets.js)
savePages: true,
// fix the column widths
widthFixed: false,
// Saves tablesorter paging to custom key if defined.
// Key parameter name used by the $.tablesorter.storage function.
// Useful if you have multiple tables defined
storageKey: 'tablesorter-pager',
// Reset pager to this page after filtering; set to desired page number (zero-based index),
// or false to not change page at filter start
pageReset: false,
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
// table row set to a height to compensate; default is false
fixedHeight: false,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
removeRows: false,
// If true, child rows will be counted towards the pager set size
countChildRows: false,
// css class names of pager arrows
cssNext: '.next', // next page arrow
cssPrev: '.prev', // previous page arrow
cssFirst: '.first', // go to first page arrow
cssLast: '.last', // go to last page arrow
cssGoto: '.gotoPage', // select dropdown to allow choosing a page
cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed
cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option
// class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
cssDisabled: 'disabled', // Note there is no period "." in front of this class name
cssErrorRow: 'tablesorter-errorRow' // ajax error information row
}
我真的很喜欢这个图书馆,它太棒了。谢谢@Mottie。
我学会了如何使用调试功能,看到了将近 100 个错误,如下所示:
Stopping initialization! No table, thead or tbody
<table class="phpdebugbar-widgets-params" style="display: table; border: 0; width: 99%">
问题 = 与 phpDebugBar 冲突,我没有意识到这一点,但显然试图在页面上创建自己的 table 并且因此 TS 也在寻找那些 headers。
测试(在 Laravel 或 php 应用中使用类似的 .env):
我通过更改 .env
以显示 APP_ENV=production
和 APP_DEBUG=false
使应用退出开发模式。这将从页面中删除 phpDebugBar,并删除问题以及 100 个调试通知。
修复:
在 Tablesorter 初始化文件的第一行,我刚刚将 jQuery 元素从通用的 'table' 更改为特定的 id:
var $table = $("#table1");
多年来我一直在使用 Mottie 出色的 Tablesorter 分支。我 运行 遇到了一个我以前从未见过的问题,我不确定从哪里开始寻找这个问题。
所有功能都正常工作,但是当我单击 Column 按钮时,它显示 'auto' 两次,并拉入非列的内容。在下图中,带有红色下划线的项目不属于 headers。它们是灰色的,无法触摸。我不知道他们来自哪里。
headers 派生自动态条目集,粘贴在下面。不确定这是否相关,但我发布了代码以防它有帮助:
<tr id="sort_data" data-col="{{$col}}">
@foreach($atts as $cus_att)
@if($cus_att->attribute->visible_in_list_view)
<th class="center {{$cus_att->attribute->optional_in_list_view? 'columnSelector-false':''}}">
{{$cus_att->attribute->name}}
</th>
@endif
@endforeach
<th class="center col-1" data-filter="false" data-sorter="false">{{__("Action")}}</th>
</tr>
我不知道我是否遗漏了一些明显的东西,但是任何关于从哪里开始寻找错误的想法都将不胜感激。
谢谢!
已渲染 HTML:
<table id="table1" class="table table-bordered tablesorter tablesorter-blue tablesorterefb7ab942ea838columnselector hasResizable hasFilters hasStickyHeaders" data-sort-name="name" role="grid" aria-describedby="table1_pager_info">
<thead id="thead">
<tr id="sort_data" data-col="0" role="row" class="tablesorter-headerRow">
<th class="center tablesorter-header tablesorter-headerAsc" data-column="0" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="ascending" aria-label="Name: Ascending sort applied, activate to apply a descending sort"><div class="tablesorter-header-inner">
Name
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="1" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Owner: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Owner
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="2" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Priority: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Priority
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="3" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Data Location: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Data Location
</div></th>
<th class="center tablesorter-header tablesorter-headerUnSorted" data-column="4" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Category: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Category
</div></th>
<th class="center columnSelector-false tablesorter-header tablesorter-headerUnSorted" data-column="5" tabindex="0" scope="col" role="columnheader" aria-disabled="false" aria-controls="table1" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Support: No sort applied, activate to apply an ascending sort"><div class="tablesorter-header-inner">
Support
</div></th>
<th class="center col-1 tablesorter-header sorter-false tablesorter-headerUnSorted" data-filter="false" data-sorter="false" data-column="6" scope="col" role="columnheader" aria-disabled="true" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="Action: No sort applied, sorting is disabled"><div class="tablesorter-header-inner">Action</div></th>
</tr>
<tr role="row" class="tablesorter-filter-row tablesorter-ignoreRow"><td data-column="0" class="pointer center"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="0" data-lastsearchtime="1628907240814"><span class="glyphicon glyphicon-refresh reset" style="margin-top:4px;"></span></td><td data-column="1"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="1" data-lastsearchtime="1628907240814"></td><td data-column="2"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="2" data-lastsearchtime="1628907240814"></td><td data-column="3"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="3" data-lastsearchtime="1628907240814"></td><td data-column="4"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="4" data-lastsearchtime="1628907240814"></td><td data-column="5"><input type="search" placeholder="Search..." class="tablesorter-filter" data-column="5" data-lastsearchtime="1628907240814"></td><td data-column="6"><input type="search" placeholder="" class="tablesorter-filter disabled" data-column="6" disabled="" data-lastsearchtime="1628907240814"></td></tr></thead>
<tbody class="tbodyContent reorderDiv" aria-live="polite" aria-relevant="all">
TS 初始化
$(function() {
var $table = $("table");
var sortCol = $("#sort_data").data('col');
$('button.columnSelectorButton').click(function(){
$.tablesorter.storage( $table, 'tablesorter-columnSelector', [] );
$.tablesorter.storage( $table, 'tablesorter-columnSelector-auto', {} );
// reload the page
document.location.reload();
});
/*** custom css only button popup ***/
$table.tablesorter({
theme: 'blue',
sortList: [[sortCol,0]],
widgets: ['zebra', 'filter', 'columnSelector', 'resizable', 'stickyHeaders'],
widgetOptions : {
resizable: true,
resizable_addLastColumn: true,
// Filters:
filter_columnFilters: true,
filter_placeholder: {search: 'Search...'},
filter_saveFilters: false,
filter_reset: '.reset',
{{-- number or jquery selector targeting the position:fixed element -- how far from top should header
sit, or create a class (like black_bar) that should alos be included in the sticky headaer --}}
stickyHeaders_offset : 45,
stickyHeaders : '.black_bar',
{{-- target the column selector markup --}}
columnSelector_container : $('#columnSelector'),
{{-- column status, true = display, false = hide
// disable = do not display on list --}}
columnSelector_columns : {
0: 'disable' /* set to disabled; not allowed to unselect it */
},
{{-- remember selected columns (requires $.tablesorter.storage) --}}
columnSelector_saveColumns: true,
{{-- container layout --}}
columnSelector_layout : '<label><input type="checkbox">{name}</label>',
{{-- data attribute containing column name to use in the selector container --}}
columnSelector_name : 'data-selector-name',
{{-- Responsive Media Query settings
enable/disable mediaquery breakpoints --}}
columnSelector_mediaquery: true,
{{-- toggle checkbox name --}}
columnSelector_mediaqueryName: 'Auto: ',
{{-- breakpoints checkbox initial setting --}}
columnSelector_mediaqueryState: true,
{{-- hide columnSelector false columns while in auto mode --}}
columnSelector_mediaqueryHidden: true,
{{-- responsive table hides columns with priority 1-6 at these breakpoints
// see http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/#Applyingapresetbreakpoint
// *** set to false to disable *** --}}
columnSelector_breakpoints : [ '20em', '30em', '40em', '50em', '60em', '70em' ],
{{-- data attribute containing column priority
// duplicates how jQuery mobile uses priorities:
// http://view.jquerymobile.com/1.3.2/dist/demos/widgets/table-column-toggle/ --}}
columnSelector_priority : 'data-priority',
{{-- class name added to checked checkboxes - this fixes an issue with Chrome not updating FontAwesome
applied icons; use this class name (input.checked) instead of input:checked --}}
columnSelector_cssChecked : 'checked'
}
})
{{-- bind to pager events
********************* --}}
.bind('pagerChange pagerComplete pagerInitialized pageMoved', function (e, c) {
var msg = '"</span> event triggered, ' + (e.type === 'pagerChange' ? 'going to' : 'now on') +
' page <span class="typ">' + (c.page + 1) + '/' + c.totalPages + '</span>';
$('#display')
.append('<li><span class="str">"' + e.type + msg + '</li>')
.find('li:first').remove();
})
{{-- initialize the pager plugin
**************************** --}}
.tablesorterPager(pagerOptions);
TS 寻呼机选项:
var pagerOptions = {
// target the pager markup - see the HTML block below
container: $(".pager"),
// use this url format "http:/mydatabase.com?page={page}&size={size}&{sortList:col}"
ajaxUrl: null,
// modify the url after all processing has been applied
customAjaxUrl: function (table, url) {
return url;
},
// ajax error callback from $.tablesorter.showError function
// ajaxError: function( config, xhr, settings, exception ){ return exception; };
// returning false will abort the error message
ajaxError: null,
// add more ajax settings here
// see http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
ajaxObject: {dataType: 'json'},
// process ajax so that the data object is returned along with the total number of rows
ajaxProcessing: null,
// Set this option to false if your table data is preloaded into the table, but you are still using ajax
processAjaxOnInit: true,
// output string - default is '{page}/{totalPages}'
// possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows}
// also {page:input} & {startRow:input} will add a modifiable input in place of the value
output: '{startRow:input} to {endRow} ({totalRows})',
// apply disabled classname (cssDisabled option) to the pager arrows when the rows
// are at either extreme is visible; default is true
updateArrows: true,
// starting page of the pager (zero based index)
page: 0,
// Number of visible rows
size: 30,
// Save pager page & size if the storage script is loaded (requires $.tablesorter.storage in jquery.tablesorter.widgets.js)
savePages: true,
// fix the column widths
widthFixed: false,
// Saves tablesorter paging to custom key if defined.
// Key parameter name used by the $.tablesorter.storage function.
// Useful if you have multiple tables defined
storageKey: 'tablesorter-pager',
// Reset pager to this page after filtering; set to desired page number (zero-based index),
// or false to not change page at filter start
pageReset: false,
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
// table row set to a height to compensate; default is false
fixedHeight: false,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
removeRows: false,
// If true, child rows will be counted towards the pager set size
countChildRows: false,
// css class names of pager arrows
cssNext: '.next', // next page arrow
cssPrev: '.prev', // previous page arrow
cssFirst: '.first', // go to first page arrow
cssLast: '.last', // go to last page arrow
cssGoto: '.gotoPage', // select dropdown to allow choosing a page
cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed
cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option
// class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
cssDisabled: 'disabled', // Note there is no period "." in front of this class name
cssErrorRow: 'tablesorter-errorRow' // ajax error information row
}
我真的很喜欢这个图书馆,它太棒了。谢谢@Mottie。
我学会了如何使用调试功能,看到了将近 100 个错误,如下所示:
Stopping initialization! No table, thead or tbody
<table class="phpdebugbar-widgets-params" style="display: table; border: 0; width: 99%">
问题 = 与 phpDebugBar 冲突,我没有意识到这一点,但显然试图在页面上创建自己的 table 并且因此 TS 也在寻找那些 headers。
测试(在 Laravel 或 php 应用中使用类似的 .env):
我通过更改 .env
以显示 APP_ENV=production
和 APP_DEBUG=false
使应用退出开发模式。这将从页面中删除 phpDebugBar,并删除问题以及 100 个调试通知。
修复:
在 Tablesorter 初始化文件的第一行,我刚刚将 jQuery 元素从通用的 'table' 更改为特定的 id:
var $table = $("#table1");