转换脚本以独立处理多个表
Convert script to handle multiple tables independently
我有两个脚本,当页面包含单个 table 时,它们可以完美地工作。但是,现在我需要在同一页面上放置多个支持相同功能的 table。
我需要一些帮助,将这两个脚本转换为与同一页面上的多个 table 一起使用,同时保持相同的功能。
第一个脚本名为 "TABLE DATA STATES"。
第二个脚本叫做 "SORT TABLE DATA".
当前 JSBin:
https://jsbin.com/noyoluhasa/1/edit?html,js,output
// ===================================================================
// =================== TABLE DATA STATES =============================
// ===================================================================
// Answer to my question on Whosebug:
//
// JsFiddle: http://jsfiddle.net/pya9jzxm/14
// Get all rows into the array except the <thead> row
var tbody = document.querySelector('tbody');
var trs = tbody.querySelectorAll('tr');
var tr, index = 0, length = trs.length;
// Start the loop
for (; index < length; index++) {
tr = trs[index];
// Set the attributes to default state
tr.setAttribute('data-state', 'enabled');
tr.setAttribute('data-display', 'collapsed');
tr.addEventListener('click',
function () {
// If its the row alphabet-label, skip it
if (this.classList.contains('alphabet-label')) {
return;
}
// Conditional logic to make the rows reset after clicking away from highlighted row
var trIndex = 0, trLength = trs.length, hasExpanded = false;
var state = 'disabled';
if (tbody.querySelectorAll('[data-display="expanded"]').length > 0) {
hasExpanded = true;
state = 'enabled';
}
for (; trIndex < trLength; trIndex++) {
// Set all rows to disabled on click of any row
trs[trIndex].setAttribute('data-state', state);
// Reset the display of all rows
trs[trIndex].setAttribute('data-display', 'collapsed');
}
if (!hasExpanded) {
// Set the clicked row to active highlighted state
this.setAttribute('data-state', 'enabled');
this.setAttribute('data-display', 'expanded');
}
}
);
}
// ===================================================================
// =================== SORT TABLE DATA ===============================
// ===================================================================
// For reference:
// this.setAttribute('data-state', this.getAttribute('data-state').contains === "enabled" ? "disabled" : "enabled");
// Adds icon to clicked <th>
// VanillaJS version - opted for jquery.tablesorter plugin due to flexibility and ease of use
var thsort = document.querySelectorAll('th')
//console.log(thsort);
var sort, sortIndex = 0, sortlength = thsort.length;
for (; sortIndex < sortlength; sortIndex++) {
sort = thsort[sortIndex];
//console.log(sort);
// On click to sort table column, do this:
sort.addEventListener('click',
function () {
var rm, rmIndex = 0;
for (; rmIndex < sortlength; rmIndex++) {
rmsort = thsort[rmIndex];
// Remove sort icon from other <th> elements
rmsort.classList.remove('sort-key');
// Add sort icon to this <th>
this.classList.add('sort-key');
//console.log(rmsort);
// Conditional logic to switch asc desc label
var state = 'asc', prevState = 'desc', hasAsc, prevState;
if (this.classList.contains('asc')) {
hasAsc = true;
state = 'desc';
prevState = 'asc';
//console.log(prevState);
}
// Set all rows to disabled on click of any row
this.classList.add(state);
this.classList.remove(prevState);
//if (hasAsc) {
// // Set the clicked row to active highlighted state
// this.setAttribute('class', state);
//}
}
}
);
}
除了将 tbody
的实例替换为 thisTable
之外,我尝试将我的代码包装在这段代码中,但是脚本仅适用于 table 的最后一次出现:
var alltables = document.querySelectorAll('tbody')
console.log(alltables);
var thisTable, sortIndex = 0, sortlength = alltables.length;
for (; sortIndex < sortlength; sortIndex++) {
thisTable = alltables[sortIndex];
// original code here
}
所以这实际上只是一个范围问题。您在事件处理程序中引用了 tbody
和这个 trs
的节点列表,但由于多个 table,这些值随时间发生了变化。当这些处理程序被调用并且它看到 tbody
时,它首先检查该变量是否是其当前范围的一部分,而事实并非如此。所以它检查下一个作用域直到找到它。但它发现的是该变量随时间变化的最后一个值。
解决此问题的最简单方法是将原始代码块包含在一个函数中,在调用时为其赋予作用域,然后调用该函数,将每个 table 的当前 table 传递给它=].然后函数在其范围内唯一的东西就是我们关心的 table 并且我们在该函数中创建的每个变量(如 trs
)将仅在该特定函数调用的范围内。
看看下面的代码并查看 fiddle 如果您对此有任何疑问,请告诉我。你可以看到我使用了所有 table 循环的原始想法,只是我根据 table
class 找到了 table,查询了 table为其 tbody
并将其传递给我们的 configureTable
函数。
Fiddle: https://jsfiddle.net/rbpc5vfu/
配置表函数:
function configureTable (tbody) {
var trs = tbody.querySelectorAll('tr');
var tr, index = 0,
length = trs.length;
// Start the loop
for (; index < length; index++) {
tr = trs[index];
// Set the attributes to default state
tr.setAttribute('data-state', 'enabled');
tr.setAttribute('data-display', 'collapsed');
tr.addEventListener('click',
function() {
// If its the row alphabet-label, skip it
if (this.classList.contains('alphabet-label')) {
return;
}
// Conditional logic to make the rows reset after clicking away from highlighted row
var trIndex = 0,
trLength = trs.length,
hasExpanded = false;
var state = 'disabled';
if (tbody.querySelectorAll('[data-display="expanded"]').length > 0) {
hasExpanded = true;
state = 'enabled';
}
for (; trIndex < trLength; trIndex++) {
// Set all rows to disabled on click of any row
trs[trIndex].setAttribute('data-state', state);
// Reset the display of all rows
trs[trIndex].setAttribute('data-display', 'collapsed');
}
if (!hasExpanded) {
// Set the clicked row to active highlighted state
this.setAttribute('data-state', 'enabled');
this.setAttribute('data-display', 'expanded');
}
}
);
}
// ===================================================================
// =================== SORT TABLE DATA ===============================
// ===================================================================
// For reference:
// this.setAttribute('data-state', this.getAttribute('data-state').contains === "enabled" ? "disabled" : "enabled");
// Adds icon to clicked <th>
// VanillaJS version - opted for jquery.tablesorter plugin due to flexibility and ease of use
var thsort = tbody.querySelectorAll('th');
//console.log(thsort);
var sort, sortIndex = 0,
sortlength = thsort.length;
for (; sortIndex < sortlength; sortIndex++) {
sort = thsort[sortIndex];
//console.log(sort);
// On click to sort table column, do this:
sort.addEventListener('click',
function() {
var rm, rmIndex = 0;
for (; rmIndex < sortlength; rmIndex++) {
rmsort = thsort[rmIndex];
// Remove sort icon from other <th> elements
rmsort.classList.remove('sort-key');
// Add sort icon to this <th>
this.classList.add('sort-key');
//console.log(rmsort);
// Conditional logic to switch asc desc label
var state = 'asc',
prevState = 'desc',
hasAsc, prevState;
if (this.classList.contains('asc')) {
hasAsc = true;
state = 'desc';
prevState = 'asc';
//console.log(prevState);
}
// Set all rows to disabled on click of any row
this.classList.add(state);
this.classList.remove(prevState);
//if (hasAsc) {
// // Set the clicked row to active highlighted state
// this.setAttribute('class', state);
//}
}
}
);
}
}
加载时初始化 tables:
var alltables = document.querySelectorAll('.table');
var thisTable, sortIndex = 0, sortlength = alltables.length;
for (; sortIndex < sortlength; sortIndex++) {
thisTable = alltables[sortIndex];
var tbody = thisTable.querySelector('tbody');
configureTable(tbody);
}
如你所见,如果你看的话,我并没有太大的改变。我只是将您的原始代码包装在一个功能块中。然后从上面窃取你的循环,找到所有 tables,每个 table 找到它的 tbody 并调用我们的新函数将 tbody 传递给它。瞧。范围!
我有两个脚本,当页面包含单个 table 时,它们可以完美地工作。但是,现在我需要在同一页面上放置多个支持相同功能的 table。
我需要一些帮助,将这两个脚本转换为与同一页面上的多个 table 一起使用,同时保持相同的功能。
第一个脚本名为 "TABLE DATA STATES"。 第二个脚本叫做 "SORT TABLE DATA".
当前 JSBin: https://jsbin.com/noyoluhasa/1/edit?html,js,output
// ===================================================================
// =================== TABLE DATA STATES =============================
// ===================================================================
// Answer to my question on Whosebug:
//
// JsFiddle: http://jsfiddle.net/pya9jzxm/14
// Get all rows into the array except the <thead> row
var tbody = document.querySelector('tbody');
var trs = tbody.querySelectorAll('tr');
var tr, index = 0, length = trs.length;
// Start the loop
for (; index < length; index++) {
tr = trs[index];
// Set the attributes to default state
tr.setAttribute('data-state', 'enabled');
tr.setAttribute('data-display', 'collapsed');
tr.addEventListener('click',
function () {
// If its the row alphabet-label, skip it
if (this.classList.contains('alphabet-label')) {
return;
}
// Conditional logic to make the rows reset after clicking away from highlighted row
var trIndex = 0, trLength = trs.length, hasExpanded = false;
var state = 'disabled';
if (tbody.querySelectorAll('[data-display="expanded"]').length > 0) {
hasExpanded = true;
state = 'enabled';
}
for (; trIndex < trLength; trIndex++) {
// Set all rows to disabled on click of any row
trs[trIndex].setAttribute('data-state', state);
// Reset the display of all rows
trs[trIndex].setAttribute('data-display', 'collapsed');
}
if (!hasExpanded) {
// Set the clicked row to active highlighted state
this.setAttribute('data-state', 'enabled');
this.setAttribute('data-display', 'expanded');
}
}
);
}
// ===================================================================
// =================== SORT TABLE DATA ===============================
// ===================================================================
// For reference:
// this.setAttribute('data-state', this.getAttribute('data-state').contains === "enabled" ? "disabled" : "enabled");
// Adds icon to clicked <th>
// VanillaJS version - opted for jquery.tablesorter plugin due to flexibility and ease of use
var thsort = document.querySelectorAll('th')
//console.log(thsort);
var sort, sortIndex = 0, sortlength = thsort.length;
for (; sortIndex < sortlength; sortIndex++) {
sort = thsort[sortIndex];
//console.log(sort);
// On click to sort table column, do this:
sort.addEventListener('click',
function () {
var rm, rmIndex = 0;
for (; rmIndex < sortlength; rmIndex++) {
rmsort = thsort[rmIndex];
// Remove sort icon from other <th> elements
rmsort.classList.remove('sort-key');
// Add sort icon to this <th>
this.classList.add('sort-key');
//console.log(rmsort);
// Conditional logic to switch asc desc label
var state = 'asc', prevState = 'desc', hasAsc, prevState;
if (this.classList.contains('asc')) {
hasAsc = true;
state = 'desc';
prevState = 'asc';
//console.log(prevState);
}
// Set all rows to disabled on click of any row
this.classList.add(state);
this.classList.remove(prevState);
//if (hasAsc) {
// // Set the clicked row to active highlighted state
// this.setAttribute('class', state);
//}
}
}
);
}
除了将 tbody
的实例替换为 thisTable
之外,我尝试将我的代码包装在这段代码中,但是脚本仅适用于 table 的最后一次出现:
var alltables = document.querySelectorAll('tbody')
console.log(alltables);
var thisTable, sortIndex = 0, sortlength = alltables.length;
for (; sortIndex < sortlength; sortIndex++) {
thisTable = alltables[sortIndex];
// original code here
}
所以这实际上只是一个范围问题。您在事件处理程序中引用了 tbody
和这个 trs
的节点列表,但由于多个 table,这些值随时间发生了变化。当这些处理程序被调用并且它看到 tbody
时,它首先检查该变量是否是其当前范围的一部分,而事实并非如此。所以它检查下一个作用域直到找到它。但它发现的是该变量随时间变化的最后一个值。
解决此问题的最简单方法是将原始代码块包含在一个函数中,在调用时为其赋予作用域,然后调用该函数,将每个 table 的当前 table 传递给它=].然后函数在其范围内唯一的东西就是我们关心的 table 并且我们在该函数中创建的每个变量(如 trs
)将仅在该特定函数调用的范围内。
看看下面的代码并查看 fiddle 如果您对此有任何疑问,请告诉我。你可以看到我使用了所有 table 循环的原始想法,只是我根据 table
class 找到了 table,查询了 table为其 tbody
并将其传递给我们的 configureTable
函数。
Fiddle: https://jsfiddle.net/rbpc5vfu/
配置表函数:
function configureTable (tbody) {
var trs = tbody.querySelectorAll('tr');
var tr, index = 0,
length = trs.length;
// Start the loop
for (; index < length; index++) {
tr = trs[index];
// Set the attributes to default state
tr.setAttribute('data-state', 'enabled');
tr.setAttribute('data-display', 'collapsed');
tr.addEventListener('click',
function() {
// If its the row alphabet-label, skip it
if (this.classList.contains('alphabet-label')) {
return;
}
// Conditional logic to make the rows reset after clicking away from highlighted row
var trIndex = 0,
trLength = trs.length,
hasExpanded = false;
var state = 'disabled';
if (tbody.querySelectorAll('[data-display="expanded"]').length > 0) {
hasExpanded = true;
state = 'enabled';
}
for (; trIndex < trLength; trIndex++) {
// Set all rows to disabled on click of any row
trs[trIndex].setAttribute('data-state', state);
// Reset the display of all rows
trs[trIndex].setAttribute('data-display', 'collapsed');
}
if (!hasExpanded) {
// Set the clicked row to active highlighted state
this.setAttribute('data-state', 'enabled');
this.setAttribute('data-display', 'expanded');
}
}
);
}
// ===================================================================
// =================== SORT TABLE DATA ===============================
// ===================================================================
// For reference:
// this.setAttribute('data-state', this.getAttribute('data-state').contains === "enabled" ? "disabled" : "enabled");
// Adds icon to clicked <th>
// VanillaJS version - opted for jquery.tablesorter plugin due to flexibility and ease of use
var thsort = tbody.querySelectorAll('th');
//console.log(thsort);
var sort, sortIndex = 0,
sortlength = thsort.length;
for (; sortIndex < sortlength; sortIndex++) {
sort = thsort[sortIndex];
//console.log(sort);
// On click to sort table column, do this:
sort.addEventListener('click',
function() {
var rm, rmIndex = 0;
for (; rmIndex < sortlength; rmIndex++) {
rmsort = thsort[rmIndex];
// Remove sort icon from other <th> elements
rmsort.classList.remove('sort-key');
// Add sort icon to this <th>
this.classList.add('sort-key');
//console.log(rmsort);
// Conditional logic to switch asc desc label
var state = 'asc',
prevState = 'desc',
hasAsc, prevState;
if (this.classList.contains('asc')) {
hasAsc = true;
state = 'desc';
prevState = 'asc';
//console.log(prevState);
}
// Set all rows to disabled on click of any row
this.classList.add(state);
this.classList.remove(prevState);
//if (hasAsc) {
// // Set the clicked row to active highlighted state
// this.setAttribute('class', state);
//}
}
}
);
}
}
加载时初始化 tables:
var alltables = document.querySelectorAll('.table');
var thisTable, sortIndex = 0, sortlength = alltables.length;
for (; sortIndex < sortlength; sortIndex++) {
thisTable = alltables[sortIndex];
var tbody = thisTable.querySelector('tbody');
configureTable(tbody);
}
如你所见,如果你看的话,我并没有太大的改变。我只是将您的原始代码包装在一个功能块中。然后从上面窃取你的循环,找到所有 tables,每个 table 找到它的 tbody 并调用我们的新函数将 tbody 传递给它。瞧。范围!