将 jquery 脚本的范围限制为直接祖先

Limiting the scope of jquery script to immediate ancestors

我编写了这个脚本来查找 <fieldset> 标签,其中 child 包含 gfield_error,并在 class wow-error 中添加 <fieldset>.

问题是它工作得太好了,如果它在页面上的任何地方找到 gfield_error,它会将 class 添加到页面上的每个 <fieldset>,而不仅仅是带有 child 有 gfield_error.

jQuery(document).ready(function( $ ) {
$(':has(.gfield_error) > fieldset').addClass('wow-error');
});

<fieldset class="gfieldset">
    <legend class="gfieldset-legend ">Name</legend>
    <ul class="gform_fields">
        <li id="field_2_95" class="gfield gfield_error">
                <p>Some content</p>
        </li>
    </ul>
</fieldset>

我确定这是一个基本错误,谁能提供指导。

如果没有任何“真正的”标记,很难分辨...但我可以建议以下循环:

$('.gfieldset :has(.gfield_error)').each(function(){
  $(this).addClass('wow-error');
});

所以这应该遍历所有 .gfieldset 至少有一个 child 有 gfield_error.

$(this) 是目标 .gfieldset 匹配元素...

$('.gfieldset:has(.gfield_error)').each(function() {
  $(this).addClass('wow-error');
});
.wow-error {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset class="gfieldset">
  <legend class="gfieldset-legend ">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_95" class="gfield gfield_error">
      <p>Some content</p>
    </li>
  </ul>
</fieldset>
<fieldset class="gfieldset">
  <legend class="gfieldset-legend ">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_95" class="gfield"><!-- No error class here -->
      <p>Some content</p>
    </li>
  </ul>
</fieldset>

所以简而言之...:has(.gfield_error) 这是具有 child 和 gfield_error class 的所有元素的集合。这可能会导致真正目标元素的所有元素 parent 的大量集合。​​

然后你寻找一个 CHILD <fieldset> 元素,在其上添加一个 class... 遗憾的是... fieldset 是一个 parent 的匹配查找。

尽管问...因为 re-reading 我自己听起来很深奥。哈哈


编辑

另一个想法...可能更清楚。您可以从具有 .gfield_error class 的每个元素开始,然后爬升到 .closest() <fieldset> parent 以添加 .wow-error class.

$('.gfield_error').each(function() {
  $(this).closest("fieldset").addClass('wow-error');
});
.wow-error {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset class="gfieldset">
  <legend class="gfieldset-legend ">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_95" class="gfield gfield_error">
      <p>Some content</p>
    </li>
  </ul>
</fieldset>
<fieldset class="gfieldset">
  <legend class="gfieldset-legend ">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_95" class="gfield"><!-- No error class here -->
      <p>Some content</p>
    </li>
  </ul>
</fieldset>

我的第一个想法是扭转局面——找到任何 .gfield_error 然后 使用 .closest()

得到它所在的 gfieldset

$('#demo').on('click', function() {
    $('.gfield_error')
        .closest('fieldset.gfieldset')
        .addClass('wow-error');
});
fieldset {
  margin: 1em;
  border: 1px solid gray;
}
.wow-error {
  background-color: lightyellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<fieldset class="gfieldset">
  <legend class="gfieldset-legend">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_95" class="gfield gfield_error">
      <p>Some content in matching fieldset</p>
    </li>
  </ul>
</fieldset>

<fieldset class="not-gfieldset">
  <legend class="gfieldset-legend">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_96" class="gfield gfield_error">
      <p>Some content in non-matching fieldset<br>
         This is a fieldset but it's not a .gfieldset, so even though
         if contains a .gfield_error it does not get selected.</p>
    </li>
  </ul>
</fieldset>

<fieldset class="gfieldset">
  <legend class="gfieldset-legend">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_97" class="gfield not-gfield_error">
      <p>Some content in matching fieldset w/o gfield_error.<br>
         This is a .gfieldset but it does not contain a .gfield_error</p>
    </li>
  </ul>
</fieldset>

<fieldset class="gfieldset">
  <legend class="gfieldset-legend">Name</legend>
  <ul class="gform_fields">
    <li id="field_2_98" class="gfield gfield_error">
      <p>Another matching fieldset</p>
    </li>
  </ul>
</fieldset>

<button type="button" id="demo">Demonstrate</button>