转换脚本以独立处理多个表 [英] Convert script to handle multiple tables independently

查看:125
本文介绍了转换脚本以独立处理多个表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当页面包含一个表格时,我有两个脚本可以很好地工作。但是,现在我需要在支持相同功能的同一页面上放置多个表格。




$ b $我需要一些帮助,将这两个脚本转换为与同一页面上的多个表一起工作,同时保持相同的功能。 b

第一个脚本叫做TABLE DATA STATES。
第二个脚本叫做SORT TABLE DATA。



当前JSBin:
https://jsbin.com/noyoluhasa/1/edit?html,js,output

  // ================================= ================================== 
// ========== =========表数据状态=============================
// === ================================================== ==============

//回答我在Stackoverflow上的问题:
// http://stackoverflow.com/questions/33128718/change -data-attribute-on-click-of-html-elements
// JsFiddle:http://jsfiddle.net/pya9jzxm/14

//获取数组中的所有行< thead> row
var tbody = document.querySelector('tbody');
var trs = tbody.querySelectorAll('tr');
var tr,index = 0,length = trs.length;
//开始循环
用于(; index< length; index ++){
tr = trs [index];
//将属性设置为默认状态
tr.setAttribute('data-state','enabled');
tr.setAttribute('data-display','collapsed');
tr.addEventListener('click',
function(){
//如果它的行字母标签,跳过
if(this.classList.contains('alphabet -label')){
return;
}
//点击离开突出显示的行后重置行的条件逻辑
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 ++){
//将所有行设为禁用单击任意行
trs [trIndex] .setAttribute('data-state',state);
//重置所有行的显示
trs [trIndex] .setAttribute('data-display','colla如果(!hasExpanded){
//将点击行设置为活动高亮状态
this.setAttribute('data-state','enabled');

if );
this.setAttribute('data-display','expanded');
}
}
);
}


// =============================== ====================================
// ======== ===========排序表数据===============================
/ / ================================================= ==================
//作为参考:
// this.setAttribute('data-state',this.getAttribute('data-状态')。contains ===enabled?disabled:enabled);

//添加图标点击< th>
// VanillaJS版本 - 由于灵活性和易用性,选择了jquery.tablesorter插件
var thsort = document.querySelectorAll('th')
//console.log(thsort);
var sort,sortIndex = 0,sortlength = thsort.length; (; sortIndex< sortlength; sortIndex ++){
sort = thsort [sortIndex];

//console.log(sort);
//点击排序表列,执行:
sort.addEventListener('click',
function(){
var rm,rmIndex = 0;
为(; rmIndex< sortlength; rmIndex ++){
rmsort = thsort [rmIndex];
//从其他元素中移除排序图标
rmsort.classList.remove(' sort-key');
//将排序图标添加到此
this.classList.add('sort-key');
//console.log(rmsort) ;


//有条件逻辑切换asc desc label
var state ='asc',prevState ='desc',hasAsc,prevState;
if .classList.contains('asc')){
hasAsc = true;
state ='desc';
prevState ='asc';

// console .log(prevState);

}
//将所有行设置为禁用单击任何行
this.classList.add(state);
this.classList.remove(prevState);

// if(hasAsc){
// //将点击的行设置为活动高亮状态
// this.setAttribute('class',state);
//}
}
}
);



$ b

我尝试在代码中包装我的代码,除了替换 tbody thisTable ,但是这些脚本只能用于表的最后一次出现:

  var alltables = document.querySelectorAll('tbody')
console.log(alltables);
var thisTable,sortIndex = 0,sortlength = alltables.length; (; sortIndex< sortlength; sortIndex ++){
thisTable = alltables [sortIndex];

//在这里的原始代码
}


解决方案

所以这实际上只是一个范围问题。您在事件处理程序中引用了 tbody trs 这个NodeList,但是这些值随着时间的推移而变化,因为有多个表。当这些处理程序被调用,它看到 tbody 它首先检查该变量是否是其当前作用域的一部分,而不是。所以它检查下一个范围,直到找到它。但是它发现的是变量的最后一个值随着时间的推移而变化。

解决这个问题的最简单的方法就是将你原来的代码块包围在一个函数中,给它的范围,当它的调用,并调用该函数传递当前表的每个表。那么这个函数在它的范围内唯一的东西就是我们关心的表格,而且我们在这个函数中创建的每个变量,比如 trs ,都只在这个特定的函数调用。



看看下面的代码,看看小提琴,让我知道如果你有任何问题。你可以看到我使用了所有表的循环的原始思想,只有我发现基于类的表,查询表的 tbody 并将其传递给我们的 configureTable 函数。 $ b

小提琴: https://jsfiddle.net/rbpc5vfu/

ConfigureTable函数:

pre $函数configureTable(tbody){
var trs = tbody.querySelectorAll('tr' );
var tr,index = 0,
length = trs.length;
//开始循环
用于(; index< length; index ++){
tr = trs [index];
//将属性设置为默认状态
tr.setAttribute('data-state','enabled');
tr.setAttribute('data-display','collapsed');
tr.addEventListener('click',
function(){
//如果它的行字母标签,跳过
if(this.classList.contains('alphabet -label')){
return;
}
//有条件的逻辑,在点击离开高亮显示的行后重置行
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 ++){
//设置所有行禁用点击任何行
trs [trIndex] .setAttribute('data-state',state);
//重置所有行的显示
trs [trIndex] .setAttribute('data-display','collapsed');

if(!hasExpanded){
//将点击的行设置为活动高亮状态
this.setAttribute('data-state','enabled');
this.setAttribute('data-display','expanded');
}
}
);
}


// =============================== ====================================
// ======== ===========排序表数据===============================
/ / ================================================= ==================
//作为参考:
// this.setAttribute('data-state',this.getAttribute('data-状态')。contains ===enabled?disabled:enabled);

//添加图标点击< th>
// VanillaJS版本 - 由于灵活性和易用性,选择了jquery.tablesorter插件
var thsort = tbody.querySelectorAll('th');
//console.log(thsort);
var sort,sortIndex = 0,
sortlength = thsort.length; (; sortIndex< sortlength; sortIndex ++){
sort = thsort [sortIndex];

//console.log(sort);
//点击排序表列,执行:
sort.addEventListener('click',
function(){
var rm,rmIndex = 0;
。对于(; rmIndex< sortlength; rmIndex ++){
rmsort = thsort [rmIndex]的第i;
//从其他<删除排序图标元件
rmsort.classList.remove( sort-key');
//将排序图标添加到此
this.classList.add('sort-key');
//console.log(rmsort) ;


//有条件逻辑切换asc desc label
var state ='asc',
prevState ='desc',
hasAsc,prevState ;
if(this.classList.contains('asc')){
hasAsc = true;
state ='desc';
prevState ='asc';

//console.log(prevState);

$ b //将所有行设置为禁用单击任何行
this.classList.add(state);
this.classList.remove(prevState);

// if(hasAsc){
// //将点击的行设置为活动高亮状态
// this.setAttribute('class',state);
//}
}
}
);





$ 在加载时初始化表格

  var alltables = document.querySelectorAll('。table'); 
var thisTable,sortIndex = 0,sortlength = alltables.length; (; sortIndex< sortlength; sortIndex ++){
thisTable = alltables [sortIndex];

var tbody = thisTable.querySelector('tbody');
configureTable(tbody);





$ b

正如你所看到的,如果你看,我并没有真正改变。我只是将你的原始代码包装在一个功能块中。然后从上面偷走你的循环,找到所有的表,为每个表找到它的tbody,并调用我们的新函数将tbody传递给它。瞧。范围!


I have two scripts which work perfectly when a page contains a single table. However, now I have need to put multiple tables on the same page which support the same functions.

I need some help converting these two scripts to work with multiple tables on the same page, while maintaining the same functionality.

The first script is called "TABLE DATA STATES". The second script is called "SORT TABLE DATA".

Current JSBin: https://jsbin.com/noyoluhasa/1/edit?html,js,output

// ===================================================================
// =================== TABLE DATA STATES =============================
// ===================================================================

// Answer to my question on Stackoverflow:
// http://stackoverflow.com/questions/33128718/change-data-attribute-on-click-of-html-elements
// 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);
                //}
            }
        }
    );
}

I tried wrapping my codes in this code, in addition to replacing instances of tbody with thisTable, but then the scripts only worked for the last occurence of the 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
}

解决方案

So this is really just a scope issue. You are referencing tbody and this NodeList of trs in the event handlers but those values have changed over time because of multiple tables. When those handlers are called and it sees tbody it first checks if that variable is part of its current scope, which it isn't. So it checks the next scope up until it finds it. But what it finds is the last value of that variable as it changed over time.

The easiest way to fix this is to surround your original block of code in a function, to give it scope when its called, and call that function passing the current table to it for each table. Then the only thing that function has in its scope is the table we care about and every variable we create within that function like trs will be in the scope of only that specific function call.

Take a look at the code below and check out the fiddle and let me know if you have any questions about it. You can see I used your original idea of that loop of all tables only I found the tables based on the table class, queried the table for its tbody and passed that to our configureTable function.

Fiddle: https://jsfiddle.net/rbpc5vfu/

ConfigureTable Function:

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);
                    //}
                }
            }
        );
    }
}

Initialize tables on load:

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);
}

As you can see I didn't really change much if you look. I just wrapped your original code in a function block. Then stole your loop from above, found all the tables, for each table found its tbody and called our new function passing the tbody to it. Voila. Scope!

这篇关于转换脚本以独立处理多个表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆