使用 Javascript 隐藏 HTML table 的元素时的意外行为

unexpected behaviour when using Javascript to hide elements of an HTML table

我在使用 Javascript 隐藏 HTML table 的部分时观察到奇怪的行为,这取决于我使用的浏览器。我已使 HTML 可在此站点上访问

https://auditrecordit.com/SO_demo/MSc.html

并将其包含在下面,但我认为该网站非常方便,可以让您自己快速查看行为。

如您所见,该页面显示了学位结构。如果我 select 在 Firefox 中切换“证书”,我会得到预期的行为 - 第二学期消失,第一学期的中间模块也消失(第一学期底部行的选择扩展)。

再次在 Firefox 中,如果我然后 select“MSc”切换,我会得到预期的反向行为 - 隐藏的 table 元素重新出现。

但是,如果我 select 切换“文凭”,不适用的 table 元素中的文本会消失(好),但它们的背景颜色不会(坏)。

现在有一个超级奇怪的地方 - 如果我然后交换浏览器选项卡并再次返回(或切换应用程序并再次返回),背景颜色会固定,即消失!

事实上,我什至不需要离开window。如果我打开 Web Developer 控制台,我只需要将鼠标指针移到 window 的显示部分之外(甚至只是将鼠标悬停在滚动条上),背景颜色就会消失。

所以我猜当我这样做时发生了一些事件,提示 Firefox 进行某种小型刷新。

考虑到这一点,我尝试添加

window.self.blur();
window.self.focus();

到我的函数结束时进行调整,但无济于事。

更令人困惑的是,我在上面描述的意外行为并没有发生在 Chrome 中。 Chrome 弄错并保持错误(即背景颜色在不应该保留的情况下仍然存在)。当然,可能是我出了问题,但我不知道是什么,而 Firefox 最终会按照我的意图进行,所以我现在要怪 Chrome。

如果您检查 Javascript,您会发现我试图通过在设置可见性时将 class 'tdNoBG' 分配给单元格来摆脱不需要的背景颜色到 'collapsed',我可以通过 Inspector 看到 class 已经更改,但背景颜色仍然显示。

知道触发什么事件让 Firefox 改变主意,以及对 Chrome 的修复建议吗?

P.S。如果有人甚至只是确认他们观察到我所描述的行为,我会很高兴!

    <!DOCTYPE html><html><head>
        <meta charset='utf-8' />  
        <style type='text/css'>
    body { font-family: Tahoma; }
    label {
        white-space:nowrap;
    }
    
    td { 
        padding: 20px;
    }
    td:nth-child(2), td:nth-child(7){text-align:center;}
    
    table { 
        border-spacing: 2px;
        border-collapse: separate;
      width: 100%;
    }
    
    .clsSemester { font-size: xx-large; background-color: blue; color: white; font-weight: bold;  width: 35%; }
    
    .tdThinDivider { background-color: white; width: 1%; }
    
    .clsVA { vertical-align: top; }
    
    .trBG { background-color: #e6ffff; }
    
    .tdNoBG { background-color: #ffffff; }
    
    .tdModuleTitle { background-color: powderblue; font-weight: bold; }
    
    .tdPathway  { background-color: #fafafa; }
    
    </style>
    
    <script type='text/javascript'>  
           
    function getModuleName(strModuleCode) {
        var arr = new Map([
        ['MPE5003','PE and Sport and the Social Sciences'],
        ['MPE5004','Cognitive Development and Pedagogy Through PE and Sport'],
        ['MPE5005','Psychology: Culture, Coaching and Young People'],
        ['MPE5006','Dissertation: Consultancy-based Project'],
        ['MPE5007','Dissertation: Academic Research Project'],
        ]);
        return arr.get(strModuleCode);
    }
    
    function setPathway() {
        var table = document.getElementById("tblMSc");
        for (var i = 0, row; row = table.rows[i]; i++) {
           for (var j = 0, cell; cell = row.cells[j]; j++) {
             cell.style.height = i == 0 ? '20px' : (i%2 == 0 ? '200px' : '2px');
           }  
        }
        var table = document.getElementById("tblMSc");
        for (var i = 0, row; row = table.rows[i]; i++) {
           row.style.visibility = document.querySelector('input[name="rdoPathway"]:checked').value == 'Certificate' && (i == 4 || i == 5) ? 'collapse' : 'visible' ;
           
           for (var j = 0, cell; cell = row.cells[j]; j++) {
             cell.style.height = i == 0 ? '20px' : (i%2 == 0 ? '200px' : '2px');
             var strPathway = document.querySelector('input[name="rdoPathway"]:checked').value;
             cell.style.visibility = strPathway == 'Certificate' && (j > 3 || i > 1 && j > 2) || strPathway == 'Diploma' && i > 2 && j > 2 ? 'collapse' : 'visible' ;
        //console.log(i + ';' + j + ';' + cell.style.visibility + '#');
        //console.log(i + ';' + j + '#');
           }  
        }
        window.self.blur();
        window.self.focus();
        /*
        for (var i = 0, row; row = table.rows[i]; i++) {
           for (var j = 0, cell; cell = row.cells[j]; j++) {
             cell.style.visibility = 'visible';
           }  
        }
        var strPathway = document.querySelector('input[name="rdoPathway"]:checked').value;
        if (strPathway != 'MSc') {
            var arrCellsToHide = strPathway == 'Diploma' ? ['r3c5','r3c6','r4c5','r4c6'] : ['r3c0','r3c1','r3c2','r3c3','r3c4','r3c5','r3c6','r4c0','r4c1','r4c2','r4c3','r4c4','r4c5','r4c6'];
            var arrayLength = arrCellsToHide.length;
            for (var i = 0; i < arrayLength; i++) {
              document.getElementById(arrCellsToHide[i]).style.visibility = 'collapse';
              document.getElementById(arrCellsToHide[i]).className = document.getElementById(arrCellsToHide[i]).style.visibility == 'collapse' ? 'tdNoBG' : 'tdBG';
            }
        }
        */
    }
    
    </script>
    
     </head>
    
    <body onload="document.getElementById('divSem1Choice').innerHTML = getModuleName(document.querySelector('input[name=&quot;rdoSem1Choice&quot;]:checked').value);
              document.getElementById('divSem2Choice').innerHTML = getModuleName(document.querySelector('input[name=&quot;rdoSem2Choice&quot;]:checked').value);
    setPathway();
             "> 
    
    <table id='tblMSc'>
        <tr id='r0' class="trBG">
            <td id='r0c0' class="tdNoBG">
    
            </td>
            <td id='r0c1' class="clsSemester">
    SEMESTER 1
            </td>
            <td id='r0c2' class="tdThinDivider">
    
            </td>
            <td id='r0c3' class="tdPathway clsVA" >
    
    <label><input type="radio" name="rdoPathway" value="MSc" class="bcsradio" checked = "checked" onclick="setPathway();">MSc<label><br/>
    <label><input type="radio" name="rdoPathway" value="Diploma" class="bcsradio" onclick="setPathway();">Diploma<label><br/>
    <label><input type="radio" name="rdoPathway" value="Certificate" class="bcsradio" onclick="setPathway();">Certificate<label>
    
            </td>
            <td id='r0c4' class="tdThinDivider">
    
            </td>
            <td id='r0c5' class="tdNoBG">
    
            </td>
            <td id='r0c6' class="clsSemester">
    SEMESTER 2
            </td>
        </tr>
    
        <tr id='r1'  class="trBG">
            <td id='r1c0' class="tdNoBG">
    
            </td>
            <td id='r1c1' class="tdBG">
    
    
            </td>
            <td id='r1c2' class="tdThinDivider">
    
            </td>
            <td id='r1c3' class="tdNoBG">
    
            </td>
            <td id='r1c4' class="tdThinDivider">
    
            </td>
            <td id='r1c5' class="tdNoBG">
    
            </td>
            <td id='r1c6' class="tdBG">
    
            </td>
        </tr>
    
        <tr id='r2'  class="trBG">
            <td id='r2c0' class="tdBG">
    MPE5001
            </td>
            <td id='r2c1'  class="tdModuleTitle">
    Leadership and Professional Development<br/>in PE and Sport working with and for Young People
            </td>
            <td id='r2c2' class="tdThinDivider">
    
            </td>
            <td id='r2c3' class="tdNoBG">
    
            </td>
            <td  id='r2c4' class="tdThinDivider">
    
            </td>
            <td  id='r2c5' id='tdMPE5002' class="tdBG">
    MPE5002
            </td>
            <td  id='r2c6' class="tdModuleTitle">
    Research Methods in PE and Sport<br/>working with and for Young People
            </td>
        </tr>
    
        <tr id='r3'  class="trBG">
            <td id='r3c0' class="tdBG">
    
            </td>
            <td id='r3c1' class="tdBG">
    
            </td>
            <td id='r3c2' class="tdThinDivider">
    
            </td>
            <td id='r3c3' class="tdNoBG">
    
            </td>
            <td id='r3c4' class="tdThinDivider">
    
            </td>
            <td id='r3c5' class="tdBG">
    
            </td>
            <td id='r3c6' class="tdBG">
    
            </td>
        </tr>
    
        <tr id='r4'  class="trBG">
            <td id='r4c0' class="tdBG">
    MPE5004
            </td>
            <td id='r4c1' class="tdModuleTitle">
    Cognitive Development and Pedagogy Through PE and Sport
            </td>
            <td id='r4c2' class="tdThinDivider">
    
            </td>
            <td id='r4c3' class="tdNoBG">
    
            </td>
            <td id='r4c4' class="tdThinDivider">
    
            </td>
            <td id='r4c5' class="tdBG" rowspan="3">
    <label><input type="radio" name="rdoSem2Choice" value="MPE5006" class="bcsradio" checked = "checked" onclick=" document.getElementById('divSem2Choice').innerHTML = getModuleName(this.value);">MPE5006<label><br/><br/>or<br/><br/>
    <label><input type="radio" name="rdoSem2Choice" value="MPE5007" class="bcsradio" onclick=" document.getElementById('divSem2Choice').innerHTML = getModuleName(this.value);">MPE5007<label>
            </td>
            <td id='r4c6' class="tdModuleTitle" rowspan="3">
    <div id="divSem2Choice"></div>
            </td>
        </tr>
    
        <tr id='r5' class="trBG">
            <td id='r5c0' class="tdBG">
    
            </td>
            <td id='r5c1' class="tdBG">
    
            </td>
            <td id='r5c2' class="tdThinDivider">
    
            </td>
            <td id='r5c3' class="tdNoBG">
    
            </td>
        </tr>
    
        <tr id='r6'  class="trBG">
            <td id='r6c0' class="tdBG">
    <label><input type="radio" name="rdoSem1Choice" value="MPE5003" class="bcsradio" checked = "checked" onclick=" document.getElementById('divSem1Choice').innerHTML = getModuleName(this.value);">MPE5003<label><br/><br/>or<br/><br/>
    <label><input type="radio" name="rdoSem1Choice" value="MPE5005" class="bcsradio" onclick=" document.getElementById('divSem1Choice').innerHTML = getModuleName(this.value);">MPE5005<label>
    <span id='spnCertChoice'>
    <br/><br/>or<br/><br/>
    <label><input type="radio" name="rdoSem1Choice" value="MPE5004" class="bcsradio" onclick=" document.getElementById('divSem1Choice').innerHTML = getModuleName(this.value);">MPE5004<label>
    </span>
            </td>
            <td id='r6c1'  class="tdModuleTitle">
    <div id="divSem1Choice"></div>
            </td>
            <td id='r6c2'  class="tdThinDivider">
    
            </td>
            <td id='r6c3'  class="tdNoBG">
    
            </td>
        </tr>
    </table>

这真是一种时髦的行为。

我相信这与以下事实有关,即在 javascript 中,您正在设置 table 行 <tr> 可见性和 table 单元格 <td> 可见性所以有不匹配的地方。行和单元格的先前状态似乎会影响 css 类 的呈现方式。

我在下面创建了一个简单的示例,其中对此进行了演示。随机化按钮会将行和单元格可见性设置为 visiblecollapse 50% 的时间。至少在 Chrome (99.0.4844.74) 点击几次后,您会得到没有内容但背景颜色可见的单元格,以及一些内容可见但没有背景颜色的单元格。

我找不到任何确定细胞行为的可靠逻辑。

document.querySelector("#randomize-btn").addEventListener("click", function() {
        randomizeVisibilities();
      });

      function randomizeVisibilities() {
        let table = document.querySelector("#t");
        for (let row of table.rows) {
          row.style.visibility = Math.random() > 0.5 ? "visible" : "collapse";
          for (let cell of row.cells) {
            cell.style.visibility = Math.random() > 0.5 ? "visible" : "collapse";
          }
        }
      }
      td {
        width: 50px;
        height: 50px;
      }

      tr {
        background: blue;
      }
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button id="randomize-btn">Randomize</button>
    <table id="t">
      <tr>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
      </tr>
      <tr>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
      </tr>
      <tr>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
      </tr>
      <tr>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
        <td>HELLO</td>
      </tr>
    </table>
  </body>
</html>

作为一种解决方案,我建议您不要对这种布局使用 table-element。一种可能性是使用 flexboxgrid layout 来实现布局。然后您可以切换此布局中个人 div-elements 的可见性。

这里有关于这些布局的非常好的指南:

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

https://css-tricks.com/snippets/css/complete-guide-grid/