通过标签获取最近的前一个兄弟
Get nearest previous sibling by tag
我有 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
});
});
这确实适用于我目前在我的应用程序中的 mark-up,但是
我想让代码在遍历 parent 复选框时更加健壮。具体来说 - .filter('ul').prev('label').prev('input:checkbox')
表示输入必须紧接在标签之前,标签必须紧接在输入之前。
我想要的是像 closest
这样的命令,它遍历兄弟姐妹而不是祖先,所以我可以写出像 .filter('ul').prevNearest('input:checkbox')
这样的命令
编辑 - 警告
对于遇到此问题并希望在复选框层次结构中使用代码的任何人,请当心。我的逻辑有问题。 Grandparent 必须检查他们所有的 children。此代码不执行此操作。
jQuery 的 .prevAll() returns 之前的所有元素(可选地匹配 selector)。它 returns 它们按顺序排列,从最近到最远的元素。
由于您只需要第一个匹配项,因此您只需要 select 找到的第一个元素:
$source
.parentsUntil(".tristate")
.filter('ul')
.prevAll('input:checkbox')[0]
您还可以添加一个 .length > 0
条件来检查前面的元素是否与您的 selector.
匹配
我们可以试试下面的代码来循环遍历所有的 ul 元素并找到最近的复选框..
var ulCol = $(this).parentsUntil(".tristate").filter('ul');
ulCol.each(function(){
$(this).prevAll('input:checkbox:first').prop({
indeterminate: indeterminate,
checked: checked && !indeterminate
});
});
我有 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
});
});
这确实适用于我目前在我的应用程序中的 mark-up,但是
我想让代码在遍历 parent 复选框时更加健壮。具体来说 - .filter('ul').prev('label').prev('input:checkbox')
表示输入必须紧接在标签之前,标签必须紧接在输入之前。
我想要的是像 closest
这样的命令,它遍历兄弟姐妹而不是祖先,所以我可以写出像 .filter('ul').prevNearest('input:checkbox')
编辑 - 警告 对于遇到此问题并希望在复选框层次结构中使用代码的任何人,请当心。我的逻辑有问题。 Grandparent 必须检查他们所有的 children。此代码不执行此操作。
jQuery 的 .prevAll() returns 之前的所有元素(可选地匹配 selector)。它 returns 它们按顺序排列,从最近到最远的元素。
由于您只需要第一个匹配项,因此您只需要 select 找到的第一个元素:
$source
.parentsUntil(".tristate")
.filter('ul')
.prevAll('input:checkbox')[0]
您还可以添加一个 .length > 0
条件来检查前面的元素是否与您的 selector.
我们可以试试下面的代码来循环遍历所有的 ul 元素并找到最近的复选框..
var ulCol = $(this).parentsUntil(".tristate").filter('ul');
ulCol.each(function(){
$(this).prevAll('input:checkbox:first').prop({
indeterminate: indeterminate,
checked: checked && !indeterminate
});
});