英文:
jQuery next input in DOM for different parent
问题
我有一组角色输入和每个角色的最大注册输入。我试图找到一种优雅的方法,只选择DOM中的下一个输入,不管其父元素如何。我的最终目标是仅在匹配的角色输入处'checked'时将max_registrations[]输入设置为禁用,但我在jQuery中无法匹配该元素。
代码:
@foreach ($roles as $role)
<div class="row">
<div class="col">
<input type="checkbox" name="roles[]" value="{{ $role->id }}"
onchange="console.log($(this).parent().siblings().first().children('input').attr('name'))"
> {{ $role->name }}
</div>
<div class="col input-group input-group mb-2">
<div class="input-group-prepend">
<span class="input-group-text">Max Registrations:</span>
</div>
<input type="number" name="max_registrations[]" value="" class="form-control">
</div>
</div>
@endforeach
解释:
roles[]是一个复选框。max_registrations[]是一个数字输入。我有几个这样的行。当第一个roles[]被选中时,第一个max_registrations[]应该被禁用/启用。
我使用Laravel Blade作为我的模板语言,Bootstrap作为我的前端模板,并希望使用内联jQuery来实现这一目标。
我尝试过:
next('input').......仅适用于兄弟元素
nextAll('input')....看起来应该可以工作,但我搞不清楚如何使用
closest('input')....也不确定为什么这不起作用。
目前,我选择使用parent..siblings..first..children('input')方法,但感觉不太美观。
感谢任何建议。
英文:
I have a set of role inputs and max registration inputs for each individual role. I'm trying to find an elegant way of just selecting the next input in the DOM, no matter the parent. My end goal will be to set the max_registrations[] input to disabled only when its matching role input is 'checked', but I'm having trouble matching that element in jQuery.
Code:
@foreach ($roles as $role)
<div class="row">
<div class="col">
<input type="checkbox" name="roles[]" value="{{ $role->id }}"
onchange="console.log($(this).parent().siblings().first().children('input').attr('name'))"
>&nbsp;{{ $role->name }}
</div>
<div class="col input-group input-group mb-2">
<div class="input-group-prepend">
<span class="input-group-text">Max Registrations:</span>
</div>
<input type="number" name="max_registrations[]" value="" class="form-control" >
</div>
</div>
@endforeach
Explanation:
roles[] is a checkbox. max_registrations[] is a number input. I have several of each of these laid out in rows. When the first roles[] is checked, the first max_registrations[] should be disabled/enabled.
I'm using Laravel Blade as my templating language, Bootstrap as my frontend template, and would like to achieve this using inline jQuery.
I've tried:
next('input').......Only works with siblings
nextAll('input')....This seems that it should work, but I can't figure out how
closest('input')....Also not sure why this doesn't work.
For right now I'm opting for the parent..siblings..first..children('input') method, but it feels ugly.
Thanks for any input.
答案1
得分: 1
你可以编写自己的jQuery函数来选择下一个DOM元素。
为什么其他建议不起作用:
closest()
将选择第一个匹配的父元素。next()
确实会选择下一个同级元素。nextAll()
将选择所有后续同级元素。
在目标是选择器的一部分时有效
此函数将选择下一个与jQuery选择中的每个对象匹配的给定选择器的元素。
如果要使其适用于任何选择器,请查看第二个代码片段。
jQuery.fn.nextInDom = function(selector){
//创建一个空的返回对象
var $returnCollection = $([]);
//循环遍历jQuery对象中的元素
this.each(function(){
//查找与给定选择器匹配的元素,并循环遍历它们
$targetCollection = selector ? $(selector) : $('*');
$targetCollection.each((i, el) => {
//当在选择器中找到目标时,选择下一个元素并将其添加到返回集合中
if(el === this) {
if($targetCollection.length > i) {
$returnCollection = $returnCollection.add($targetCollection.eq(i+1));
}
}
//退出循环以提高性能的jQuery版本
return;
});
});
return $returnCollection;
}
$('.target').nextInDom('input').css('background-color', 'yellow');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input value="target1" class="target">
</div>
<div>
<input value="should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="target2" class="target">
</div>
<div>
<input value="should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
适用于任何选择器
以下代码应该在目标不是选择器的一部分时也能工作。但是,在大型DOM上可能导致性能问题,因为它会循环遍历DOM中的所有元素。谨慎使用!
jQuery.fn.nextInDom = function(selector){
//创建一个空的返回对象
var $returnCollection = $([]);
//循环遍历jQuery对象中的元素
this.each(function(){
//获取DOM中的所有元素并循环遍历它们
var $dom = $('*');
$dom.each((i, el) => {
var $elementsAfter;
//当找到目标时,筛选只包含当前元素后面元素的DOM集合
if(el === this) {
$elementsAfter = $dom.filter((j) => {
return j > i;
});
//如果定义了选择器,则再次使用给定选择器进行筛选
if(selector) {
$returnCollection = $returnCollection.add($elementsAfter.filter(selector).first());
}
else {
$returnCollection = $returnCollection.add($elementsAfter.first());
}
}
//退出循环以提高性能的jQuery版本
return;
});
});
return $returnCollection;
}
$('.target').nextInDom('div').css('background-color', 'yellow');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input value="target1" class="target">
</div>
<div>
<input value="div should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="target2" class="target">
</div>
<div>
<input value="div should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
英文:
You can write your own jQuery function that selects the next DOM element.
Why your other suggestions don't work:
closest()
will select the first matching parent.next()
will indeed select the next sibling.nextAll()
will select all next siblings.
Works when target is part of the selector
This function will select the next element that matches the given selector for each object in the jQuery selection.
If you want it to work with any selector then check the second snippet.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
jQuery.fn.nextInDom = function(selector){
//create an empty return object
var $returnCollection = $([]);
//loop over the elements in the jQuery object
this.each(function(){
//find elements that match the given selector and loop over those
$targetCollection = selector ? $(selector) : $('*');
$targetCollection.each((i, el) => {
//when the target is found in the selector select the next element and add it to the return collection
if(el === this) {
if($targetCollection.length > i) {
$returnCollection = $returnCollection.add($targetCollection.eq(i+1));
}
}
//jQuery version of continue to exit the each loop for better performance
return;
});
});
return $returnCollection;
}
$('.target').nextInDom('input').css('background-color', 'yellow');
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input value="target1" class=target>
</div>
<div>
<input value="should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="target2" class=target>
</div>
<div>
<input value="should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
<!-- end snippet -->
Works with any selector
The following should work even if the target is not part of the selector. However it might cause bad performance on big doms because it loops over all elements in the DOM. Use with caution!
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
jQuery.fn.nextInDom = function(selector){
//create an empty return object
var $returnCollection = $([]);
//loop over the elements in the jQuery object
this.each(function(){
//get all elements in the dom and loop over them
var $dom = $('*');
$dom.each((i, el) => {
var $elementsAfter;
//when target is found filter the dom collection on only elements after current one
if(el === this) {
$elementsAfter = $dom.filter((j) => {
return j > i;
});
//filter another time with the given selector if defined
if(selector) {
$returnCollection = $returnCollection.add($elementsAfter.filter(selector).first());
}
else {
$returnCollection = $returnCollection.add($elementsAfter.first());
}
}
//jQuery version of continue to exit the each loop for better performance
return;
});
});
return $returnCollection;
}
$('.target').nextInDom('div').css('background-color', 'yellow');
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input value="target1" class=target>
</div>
<div>
<input value="div should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="target2" class=target>
</div>
<div>
<input value="div should become yellow (next)">
</div>
<div>
<input value="no change">
</div>
<div>
<input value="no change">
</div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论