Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

javascript - Selecting previous element in DOM

I'm having a hard time with some JS DOM traversal. I'm stuck with html that's something like this:

<h2>Header 1</h2>
<div class="some-content">
    <div class="inner-content">
        <h4 class="person-name">John Smith</h4>
    </div>
</div>

<h2>Header 2</h2>
<div class="some-content">
    <div class="inner-content">
        <h4 class="person-name">Emily Jones</h4>
    </div>
</div>

This is all hidden by default. I'm trying to use a text field so that if it matches an h4 person-name, it displays the some-content container, as well as the preceding h2. I can make it work for the some-content bit, but I'm having trouble targeting the h2 that's above it. I've tried various combinations of jQuery parent(), siblings(), and prev(). I do not have the ability to add additional class names.

Edit: here is the script I have for the text field event:

$('#text-field').keyup(function() {
    var nameSearch = $(this).val().toUpperCase();
    $('.person-name').each(function() {
        var x = $(this).text().toUpperCase();
        if (x.includes(nameSearch)) {
            $(this).prev('h2').show();
            $(this).closest('.some-content').show();
        }
    })
});

Edit 2:

I apologize, my code example was oversimplified. Some very good answers by the way. If for example there was a search done for Emily Jones in this bit, would there need to be something extra done?

<div class="container">
  <h2>Header 1</h2>
  <div class="some-content">
    <div class="inner-content">
      <h4 class="person-name">John Smith</h4>
    </div>
    <div class="inner-content">
      <h4 class="person-name">Emily Jones</h4>
    </div>
  </div>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If the header/content is not nested withing a wrapping div, you will need to step over every two child nodes and toggle class.

const triggerEvent = (el, eventName) => {
  var event = document.createEvent('HTMLEvents');
  event.initEvent(eventName, true, false);
  el.dispatchEvent(event);
};

const
  search = document.querySelector('.search'),
  container = document.querySelector('.container');

const onSearch = (e) => {
  const
    searchValue = e.target.value,
    nodes = container.children;
  for (let i = 0; i < nodes.length; i += 2) {
    const
      h2 = nodes[i],
      someContent = nodes[i + 1],
      matches = someContent.querySelector('.person-name').textContent === searchValue;
    h2.classList.toggle('hidden', !matches);
    someContent.classList.toggle('hidden', !matches);
  }
};

search.addEventListener('change', onSearch);
triggerEvent(search, 'change');
.hidden {
  color: #DDD; /* Replace with -: display: none */
}
<input type="text" class="search" value="Emily Jones" />
<div class="container">
  <h2>Header 1</h2>
  <div class="some-content">
    <div class="inner-content">
      <h4 class="person-name">John Smith</h4>
    </div>
  </div>
  <h2>Header 2</h2>
  <div class="some-content">
    <div class="inner-content">
      <h4 class="person-name">Emily Jones</h4>
    </div>
  </div>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...