twitter-bootstrap 嵌套的父/子复选框 - 工作解决方案需要 Bootstrap 的调整帮助

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20355375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 19:23:12  来源:igfitidea点击:

Nested parent/child checkboxes - working solution need adjustment help for Bootstrap

javascriptjquerytwitter-bootstrapcheckboxparent-child

提问by Sam

I have been looking for a 'complete' solution to nesting parent child checkboxes that change state correctly based on a hierarchy.

我一直在寻找一种“完整”的解决方案来嵌套根据层次结构正确更改状态的父子复选框。

Most 'solutions' do not work or only work to one level. They also require you to name the checkboxes in a particular way.

大多数“解决方案”不起作用或仅适用于一个级别。它们还要求您以特定方式命名复选框。

ThisStack Overflow discussion covers the main points but also provide a good solution discovered by Rory here.

这个Stack Overflow 讨论涵盖了要点,但也提供了 Rory在这里发现的一个很好的解决方案。

I have tested it within my development project and it works perfectly standalone. However, I am using Bootstrap 2.x and for checkboxes

我已经在我的开发项目中对其进行了测试,并且它可以完全独立运行。但是,我使用的是 Bootstrap 2.x 和复选框

I have a JSFiddlewhich shows the working example code, then my version with a disabled parent checkbox and then the bootsrap code version which does not work.

我有一个JSFiddle,它显示了工作示例代码,然后是禁用父复选框的版本,然后是不起作用的引导程序代码版本。

<!DOCTYPE html>
<body>
<!-- Raw working example from site http://css-tricks.com/indeterminate-checkboxes/ -->

<b>Raw working example</b>
<p>
<ul>
    <li>
        <input type="checkbox" name="tall" id="tall">
        <label for="tall">Tall Things</label>
        <ul>
            <li>
                <input type="checkbox" name="tall-1" id="tall-1">
                <label for="tall-1">Buildings</label>
            </li>
            <li>
                <input type="checkbox" name="tall-2" id="tall-2">
                <label for="tall-2">Giants</label>
                <ul>
                    <li>
                        <input type="checkbox" name="tall-2-1" id="tall-2-1">
                        <label for="tall-2-1">Andre</label>
                    </li>
                    <li>
                        <input type="checkbox" name="tall-2-2" id="tall-2-2">
                        <label for="tall-2-2">Paul Bunyan</label>
                        <ul>
                            <li>
                                <input type="checkbox" name="tall-2-2-1" id="tall-2-2-1">
                                <label for="tall-2-2-1">Son</label>
                            </li>
                            <li>
                                <input type="checkbox" name="tall-2-2-2" id="tall-2-2-2">
                                <label for="tall-2-2-2">Daughter</label>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>
                <input type="checkbox" name="tall-3" id="tall-3">
                <label for="tall-3">Two sandwiches</label>
            </li>
        </ul>
    </li>
    <li>
        <input type="checkbox" name="short" id="short">
        <label for="short">Short Things</label>
        <ul>
            <li>
                <input type="checkbox" name="short-1" id="short-1">
                <label for="short-1">Smurfs</label>
            </li>
            <li>
                <input type="checkbox" name="short-2" id="short-2">
                <label for="short-2">Mushrooms</label>
            </li>
            <li>
                <input type="checkbox" name="short-3" id="short-3">
                <label for="short-3">One Sandwich</label>
            </li>
        </ul>
    </li>
</ul>

<hr>

<!-- Non Bootstrap Example -->
<b>My initial code example - Is Working</b>
<p>
<ul>
    <li>

        <input type="checkbox" name="" value="" disabled><strong>Ford</strong>

        <ul>
            <li>

                <input type="checkbox" name="" value="">Fiesta</label>
            </li>
            <li>

                <input type="checkbox" name="" value="">Focus</label>
            </li>
            <li>

                <input type="checkbox" name="" value="">Mondeo</label>
            </li>
        </ul>
    </li>
    <li>

        <input type="checkbox" name="" value="" disabled><strong>Vauxhall</strong>


        <ul>
            <li>

                    <input type="checkbox" name="" value="">Corsa</label>
            </li>
            <li>

                    <input type="checkbox" name="" value="">Astra</label>
            </li>
            <li>

                    <input type="checkbox" name="" value="">Vectra</label>
            </li>
        </ul>
    </li>
</ul>

            <hr>

<!-- Bootstrap Example -->

<b>Bootstrap based code example - Not Working</b>
<p>

<ul>
    <li>
        <label class="checkbox">
            <input type="checkbox" name="" value="" disabled><strong>Ford</strong>

        </label>
        <ul>
            <li>
                <label class="checkbox">
                    <input type="checkbox" name="" value="">Fiesta</label>
            </li>
            <li>
                <label class="checkbox">
                    <input type="checkbox" name="" value="">Focus</label>
            </li>
            <li>
                <label class="checkbox">
                    <input type="checkbox" name="" value="">Mondeo</label>
            </li>
        </ul>
    </li>
    <li>
        <label class="checkbox">
            <input type="checkbox" name="" value="" disabled><strong>Vauxhall</strong>

        </label>
        <ul>
            <li>
                <label class="checkbox">
                    <input type="checkbox" name="" value="">Corsa</label>
            </li>
            <li>
                <label class="checkbox">
                    <input type="checkbox" name="" value="">Astra</label>
            </li>
            <li>
                <label class="checkbox">
                    <input type="checkbox" name="" value="">Vectra</label>
            </li>
        </ul>
    </li>
</ul>
$(function () {
  // Apparently click is better chan change? Cuz IE?
  $('input[type="checkbox"]').change(function (e) {
      var checked = $(this).prop("checked"),
          container = $(this).parent(),
          siblings = container.siblings();

      container.find('input[type="checkbox"]').prop({
          indeterminate: false,
          checked: checked
      });

      function checkSiblings(el) {
          var parent = el.parent().parent(),
              all = true;

          el.siblings().each(function () {
              return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);
          });

          if (all && checked) {
              parent.children('input[type="checkbox"]').prop({
                  indeterminate: false,
                  checked: checked
              });
              checkSiblings(parent);
          } else if (all && !checked) {
              parent.children('input[type="checkbox"]').prop("checked", checked);
              parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));
              checkSiblings(parent);
          } else {
              el.parents("li").children('input[type="checkbox"]').prop({
                  indeterminate: true,
                  checked: false
              }); 
          } 
      } 

      checkSiblings(container); 
  }); 
});

My understanding is that the code needs to be changed somewhere to use parentsor closest. Can someone who is a much better code please help identify where the change needs to happen to get the Bootstrap version working.

我的理解是代码需要在某处更改以使用parents最接近的. 代码更好的人可以帮助确定需要在何处进行更改才能使 Bootstrap 版本正常工作。

采纳答案by Matt

Take a look at the free JSTreeuser control. It is JavaScript-based, open source and allows to be configured for multiple styles of tree views, for example:

看看免费的JSTree用户控件。它是基于 JavaScript 的、开源的,并允许针对多种样式的树视图进行配置,例如:

enter image description here

在此处输入图片说明

Since the checkboxes displayed here are just images, you can replace them by radio buttons easily, and via event handling you can disallow multiple selections so they behave like radio buttons if required.

由于此处显示的复选框只是图像,因此您可以轻松地将它们替换为单选按钮,并且通过事件处理,您可以禁止进行多项选择,以便在需要时它们的行为类似于单选按钮。

This is achieved by specifying the "checkbox"plugin as follows (see the snippet I provided below for the complete working code):

这是通过"checkbox"如下指定插件来实现的(请参阅我在下面提供的完整工作代码片段):

$(function () {
    $("#demo1")
        .jstree({
        "themes": {
            "theme": "apple","dots": false,"icons": false
        },
        "plugins": ["themes", "html_data", "checkbox", "sort", "ui"]
    });
});

The corresponding HTML structure looks like this, just include it in the body of your page:

相应的 HTML 结构如下所示,只需将其包含在页面正文中即可:

<div id="demo1" class="demo" style="height:100px;">
    <ul>
        <li id="phtml_1">   <a href="#">Root node 1</a>
            <ul>
                <li id="phtml_2">   <a href="#">Child node 1</a>
                </li>
                <li id="phtml_3">   <a href="#">Child node 2</a>
                </li>
            </ul>
        </li>
        <li id="phtml_4">   <a href="#">Root node 2</a>
        </li>
    </ul>
</div>

To get the checked values, use this function (assuming you have created a div with id="listForDisplay"as I did in the JSFiddle example):

要获取选中的值,请使用此函数(假设您已经创建了一个 div,id="listForDisplay"就像我在 JSFiddle 示例中所做的那样):

var $listForDisplay = $("#listForDisplay");
function displayList(data) { // see: https://www.jstree.com/docs/events/
    var i, j, r = [];
    for (i = 0, j = data.selected.length; i < j; i++) {
        r.push(data.instance.get_node(data.selected[i]).text);
    }
    $listForDisplay.html('Selected: ' + r.join(', '));
}

This code can either be triggered in a click event or you can bind JSTree events like I did. Appending the following to the previous JavaScript snippet does the job:

这段代码可以在点击事件中触发,也可以像我一样绑定 JSTree 事件。将以下内容附加到前面的 JavaScript 代码段可以完成这项工作:

    $("#demo1")
    .on('loaded.jstree', function (e, data) {
            displayList(data);
        })
    .on('change_state.jstree', function (e, data) {
            displayList(data);
        });

Note:When a parent node is selected, the parent name is listed along with the childs. If only the childs are selected, the related parent(s) will not be listed.

注意:选择父节点时,父节点名称与子节点一起列出。如果只选择了孩子,则不会列出相关的父母。

You can find more about the options specifying the behaviour of this plugin here.

您可以在此处找到有关指定此插件行为的选项的更多信息。



Runnable code snippet (complete code)

可运行代码片段(完整代码)

$(function() {

  var $demo1 = $("#demo1");
  
  var $listForDisplay = $("#listForDisplay");
  function displayList(data) { // see: https://www.jstree.com/docs/events/
    var i, j, r = [];
    for (i = 0, j = data.selected.length; i < j; i++) {
      r.push(data.instance.get_node(data.selected[i]).text);
    }
    $listForDisplay.html('Selected: ' + r.join(', '));
  }

  $demo1.jstree({
    "themes": {
      "theme": "apple",
      "dots": false,
      "icons": false
    },
    "plugins": ["themes", "html_data", "checkbox", "sort", "ui"]
  });
  $demo1.on('loaded.jstree', function(e, data) {
    displayList(data);
  });
  $demo1.on('changed.jstree', function(e, data) {
    displayList(data);
  });
});
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" rel="stylesheet" />

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
</head>

<body>
  <div id="demo1" class="demo" style="height:100px;">
    <ul>
      <li id="phtml_1"> <a href="#">Root node 1</a>
        <ul>
          <li id="phtml_2"> <a href="#">Child node 1</a>
          </li>
          <li id="phtml_3"> <a href="#">Child node 2</a>
          </li>
        </ul>
      </li>
      <li id="phtml_4"> <a href="#">Root node 2</a>
      </li>
    </ul>
  </div>
  <br/>
  <div id="listForDisplay" />
</body>

回答by Abraham Uribe

you can try something like this

你可以试试这样的

  $(function () {
  $('input[type="checkbox"]').change(function (e) {
      var checked = $(this).prop("checked"),
          container = $(this).closest("li"),//get closest li instead of parent
          siblings = container.siblings();
      container.find('input[type="checkbox"]').prop({
          indeterminate: false,
          checked: checked
      });

      function checkSiblings(el) {
          var parent = el.parent().parent(),
              all = true,
              parentcheck=parent.children("label");//get the label that contains the disabled checkbox
          el.siblings().each(function () {
              return all = ($(this).find('input[type="checkbox"]').prop("checked") === checked);
          });
          //use parentcheck instead of parent to get the children checkbox
          if (all && checked) {
              parentcheck.children('input[type="checkbox"]').prop({
                  indeterminate: false,
                  checked: checked
              });
              checkSiblings(parent);
          } else if (all && !checked) {
              parentcheck.children('input[type="checkbox"]').prop("checked", checked);
              parentcheck.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));
              checkSiblings(parent);
          } else {
             parentcheck.children('input[type="checkbox"]').prop({
                  indeterminate: true,
                  checked: false
              });
          }
      }
      checkSiblings(container);
  });
});    

http://jsfiddle.net/Mvs87/2/

http://jsfiddle.net/Mvs87/2/