在交互式 flowchart/tree 图表中隐藏未选择的选项

Hiding unselected options in an interactive flowchart/tree diagram

我正在寻求一些 Javascript 代码的帮助,我正试图从另一个网站改编这些代码,但我无法让它执行我想要它执行的操作。

我想在 HTML 代码中完全使用 CSS 和 javascript 来完成此操作。我是一个完整的 javascript 初学者。

在下面的 HTML 代码中,您可以单击一个复选框,它会显示下一级选项。

但是,我希望发生的事情是,例如,选择 'Option 1',然后隐藏 'Option 2' 和 'Option 3'。目前,它们保留在视图中,可以点击。

,然后选择选项1.2,然后隐藏'Option 1.1'的其他两个选项。

本质上,我希望用户能够向下导航一棵树,但一次只能导航一个分支,并且在他们做出选择后,同一级别中未选择的选项消失。

当然,反之亦然,如果他们在更高级别清除了一个选项,那么整个菜单就会在该级别重新显示。

我尝试了多种不同的编码,但它们要么隐藏所有内容,要么使所有复选框都没有响应!此处显示我缺乏 javascript 语法知识,但我认为解决方案包括将同一级别中未勾选的框转到 'hide' 的 class,同时保留已勾选的框勾选并显示 class of 'active'

<!DOCTYPE html>
<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    ul,
    #myUL {
      list-style-type: none;
    }
    
    #myUL {
      margin: 0;
      padding: 0;
    }
    
    .box {
      cursor: pointer;
      -webkit-user-select: none;
      /* Safari 3.1+ */
      -moz-user-select: none;
      /* Firefox 2+ */
      -ms-user-select: none;
      /* IE 10+ */
      user-select: none;
    }
    
    .box::before {
      content: "10";
      color: black;
      display: inline-block;
      margin-right: 6px;
    }
    
    .check-box::before {
      content: "11";
      color: dodgerblue;
    }
    
    .nested {
      display: none;
    }
    
    .active {
      display: block;
    }
    
    .hide {
      display: none;
    }
  </style>
</head>

<body>

  <h2>Interactive Decision Tree</h2>

  <ul id="myUL">
    <li><span class="box">Option 1</span>
      <ul class="nested">
        <li><span class="box">Option 1.1</span>
          <ul class="nested">
            <li><span class="box">Option 1.1.1</span></li>
            <li><span class="box">Option 1.1.2</span></li>
            <li><span class="box">Option 1.1.3</span></li>
          </ul>
        </li>
        <li><span class="box">Option 1.2</span>
          <ul class="nested">
            <li><span class="box">Option 1.2.1</span></li>
            <li><span class="box">Option 1.2.2</span></li>
            <li><span class="box">Option 1.2.3</span></li>
          </ul>
        </li>
        <li><span class="box">Option 1.3</span>
          <ul class="nested">
            <li><span class="box">Option 1.3.1</span></li>
            <li><span class="box">Option 1.3.2</span></li>
            <li><span class="box">Option 1.3.3</span></li>
          </ul>
        </li>
      </ul>

      <li><span class="box">Option 2</span>
        <ul class="nested">
          <li><span class="box">Option 2.1</span>
            <ul class="nested">
              <li><span class="box">Option 2.1.1</span></li>
              <li><span class="box">Option 2.1.2</span></li>
              <li><span class="box">Option 2.1.3</span></li>
            </ul>
          </li>
          <li><span class="box">Option 2.2</span>
            <ul class="nested">
              <li><span class="box">Option 2.2.1</span></li>
              <li><span class="box">Option 2.2.2</span></li>
              <li><span class="box">Option 2.2.3</span></li>
            </ul>
          </li>
          <li><span class="box">Option 2.3</span>
            <ul class="nested">
              <li><span class="box">Option 2.3.1</span></li>
              <li><span class="box">Option 2.3.2</span></li>
              <li><span class="box">Option 2.3.3</span></li>
            </ul>
          </li>
        </ul>

        <li><span class="box">Option 3</span>
          <ul class="nested">
            <li><span class="box">Option 3.1</span>
              <ul class="nested">
                <li><span class="box">Option 3.1.1</span></li>
                <li><span class="box">Option 3.1.2</span></li>
                <li><span class="box">Option 3.1.3</span></li>
              </ul>
            </li>
            <li><span class="box">Option 3.2</span>
              <ul class="nested">
                <li><span class="box">Option 3.2.1</span></li>
                <li><span class="box">Option 3.2.2</span></li>
                <li><span class="box">Option 3.2.3</span></li>
              </ul>
            </li>
            <li><span class="box">Option 3.3</span>
              <ul class="nested">
                <li><span class="box">Option 3.3.1</span></li>
                <li><span class="box">Option 3.3.2</span></li>
                <li><span class="box">Option 3.3.3</span></li>
              </ul>
            </li>
          </ul>
        </li>
  </ul>


  <script>
    var toggler = document.getElementsByClassName("box");
    var i;

    for (i = 0; i < toggler.length; i++) {
      toggler[i].addEventListener("click", function() {
        this.parentElement.querySelector(".nested").classList.toggle("active");
        this.classList.toggle("check-box");
      });
    }
  </script>

</body>

</html>

感谢您提供使其按预期工作所需的补充。

因此,我针对自己的问题编写了一个解决方案。我意识到我发布的示例的功能不足以勾选复选框并显示项目,无论您是在选择列表中向上还是向下。因此,它需要一种不同的方法,如下所示。这对我有用,而且我在编写所有代码时完全理解它,并改编了来自各种其他来源的代码。希望这对以后的其他人有所帮助。

<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        ul,
        #myUL {
            list-style-type: none;
        }

        #myUL {
            margin: 0;
            padding: 0;
        }

        .box hide {
            cursor: pointer;
            -webkit-user-select: none;
            /* Safari 3.1+ */
            -moz-user-select: none;
            /* Firefox 2+ */
            -ms-user-select: none;
            /* IE 10+ */
            user-select: none;
        }

        .box::before {
            content: "10";
            color: black;
            display: inline-block;
            margin-right: 6px;
        }

        .check-box::before {
            content: "11";
            color: dodgerblue;
        }

        .hide {
            display: none;
        }

        .show {
            display: block;
        }

    </style>
</head>

<body>

    <h2>Interactive Decision Tree</h2>
    <p id="O" class="box">Start</p>
    <p id="O1" class="box hide">Option O1</p>
    <p id="O11" class="box hide">Option O11</p>
    <p id="O111" class="box hide">Option O111</p>
    <p id="O112" class="box hide">Option O112</p>
    <p id="O113" class="box hide">Option O113</p>
    <p id="O12" class="box hide">Option O12</p>
    <p id="O121" class="box hide">Option O121</p>
    <p id="O122" class="box hide">Option O122</p>
    <p id="O123" class="box hide">Option O123</p>
    <p id="O13" class="box hide">Option O13</p>
    <p id="O131" class="box hide">Option O131</p>
    <p id="O132" class="box hide">Option O132</p>
    <p id="O133" class="box hide">Option O133</p>
    <p id="O2" class="box hide">Option O2</p>
    <p id="O21" class="box hide">Option O21</p>
    <p id="O211" class="box hide">Option O211</p>
    <p id="O212" class="box hide">Option O212</p>
    <p id="O213" class="box hide">Option O213</p>
    <p id="O22" class="box hide">Option O22</p>
    <p id="O221" class="box hide">Option O221</p>
    <p id="O222" class="box hide">Option O222</p>
    <p id="O223" class="box hide">Option O223</p>
    <p id="O23" class="box hide">Option O23</p>
    <p id="O231" class="box hide">Option O231</p>
    <p id="O232" class="box hide">Option O232</p>
    <p id="O233" class="box hide">Option O233</p>
    <p id="O3" class="box hide">Option O3</p>
    <p id="O31" class="box hide">Option O31</p>
    <p id="O311" class="box hide">Option O311</p>
    <p id="O312" class="box hide">Option O312</p>
    <p id="O313" class="box hide">Option O313</p>
    <p id="O32" class="box hide">Option O32</p>
    <p id="O321" class="box hide">Option O321</p>
    <p id="O322" class="box hide">Option O322</p>
    <p id="O323" class="box hide">Option O323</p>
    <p id="O33" class="box hide">Option O33</p>
    <p id="O331" class="box hide">Option O331</p>
    <p id="O332" class="box hide">Option O332</p>
    <p id="O333" class="box hide">Option O333</p>


    <script>
        function getElementsStartWithId(id) {
            var children = document.body.getElementsByTagName('*');
            var elements = [],
                child;
            for (var i = 0, length = children.length; i < length; i++) {
                child = children[i];
                if (child.id.substr(0, id.length) == id)
                    elements.push(child);
            };
            return elements;
        }

        function getNextLayerDown(id) {
            var children = document.body.getElementsByTagName('*');
            var elements = [],
                child;
            for (var i = 0, length = children.length; i < length; i++) {
                child = children[i];
                if (child.id.substring(0, child.id.length - 1) == id)
                    elements.push(child);
            };
            return elements;
        }

        function getAllPreviousLayers(id) {
            var children = document.body.getElementsByTagName('*');
            var elements = [],
                child;
            var newId = id
            do {
                for (var i = 0, length = children.length; i < length; i++) {
                    child = children[i];
                    if (child.id == newId)
                        elements.push(child);
                };
                var newId = newId.substring(0, newId.length - 1);
            }
            while (newId.length > 0);
            return elements;
        }

        function updateShowItems(itemId) {
            // hide all previous shown items
            for (i = 0; i < showItems.length; i++) {
                showItems[i].classList.remove("show");
                showItems[i].classList.remove("check-box");
            };
            var checkedItems = getAllPreviousLayers(itemId)
            // add check-box to all layers picked already
            for (i = 0; i < checkedItems.length; i++) {
                checkedItems[i].classList.add("check-box");
            };
            // update show items list with latest click
            showItems = getAllPreviousLayers(itemId).concat(getNextLayerDown(itemId));
            // show all items now required
            for (i = 0; i < showItems.length; i++) {
                showItems[i].classList.add("show");
            };
        }


        // set each ID to be a trigger point
        var allItems = getElementsStartWithId("O");
        var showItems = getNextLayerDown("O");
        console.log(showItems);
        var i;
        for (i = 0; i < allItems.length; i++) {
            allItems[i].addEventListener("click", function() {
                updateShowItems(this.id);
            });
        };

    </script>

</body>

</html>