通过标记获取最近的上一个同级

Get nearest previous sibling by tag

本文关键字:上一个 最近 获取      更新时间:2023-09-26

我有jQuery用于分层复选框,看起来像这个

我的html:

<ul class='tristate'>
   <li>
      <input type='checkbox' />
      <label />
      <ul>
         <li>
            <input type='checkbox' />
            <label />
         </li>
         <li>
            <input type='checkbox' />
            <label />
            <ul>
               <li>
                   <!--can be more in the hierarchy -->
         </li>
      </ul>
   </li>
</ul>

我的jQuery:

$(document).on("click", ".tristate", function (event) {
    var $source = $(event.target);
    var checked = $source.prop("checked");
    //filter checkboxes that are checked the opposite way to the source
    var selector = checked ? ':not(:checked)' : ':checked';
    //set all descendant checkboxes to the same value as the source
    $source
        .siblings("ul")
        .find('input:checkbox')
        .filter(selector)
        .prop({
            indeterminate: false,
            checked: checked
        });
    //parents are indeterminate if there are sibling checkboxes 
    //that are checked the opposite way to the source
    var $checkboxesNextToLabel = $lis.children('input:checkbox');
    var $checkboxesInsideLabel = $lis.children('label').children('input:checkbox');
    var indeterminate = $checkboxesNextToLabel
                        .add($checkboxesInsideLabel)
                        .filter(selector).length > 0;
    //set state of parent checkboxes
    $source
        .parentsUntil(".tristate")
        .filter('ul')
        .prev('label')  //label must always be first previous
        .prev('input:checkbox') //checkbox must always be second previous
        .prop({
            indeterminate: indeterminate,
            checked: checked && !indeterminate
        });
});

这确实适用于我目前在应用程序中的标记,但是当遍历到父复选框时,我想使代码更加健壮一点。具体地说,.filter('ul').prev('label').prev('input:checkbox')意味着输入必须紧跟在标签之前,标签必须紧跟在输入之前。

我想要的是一个类似closest的命令,它遍历兄弟姐妹而不是祖先,这样我就可以编写类似.filter('ul').prevNearest('input:checkbox') 的东西

编辑-警告对于任何遇到这个问题并希望在复选框层次结构中使用代码的人,请小心。我的逻辑有缺陷。祖父母必须检查他们所有的孩子。这个代码不能做到这一点。

我们可以尝试以下代码循环遍历所有ul元素,并找到最近的复选框。。

var ulCol = $(this).parentsUntil(".tristate").filter('ul');
    ulCol.each(function(){
        $(this).prevAll('input:checkbox:first').prop({
            indeterminate: indeterminate,
            checked: checked && !indeterminate
        });
    });

jQuery的.prevAll()返回所有以前的元素(可以选择匹配选择器)。它按从最接近元素到最远的顺序返回它们。

由于你只想要第一个匹配,你只需要选择找到的第一个元素:

$source
    .parentsUntil(".tristate")
    .filter('ul')
    .prevAll('input:checkbox')[0]

您还可以添加一个.length > 0条件来检查是否有任何先前的元素与您的选择器匹配。