jquerynextuntil

Show div if class exists later before next div of same class


I want the code to go through each div and if it has the class of "type2" or "type3", then show the div with the class of "itemheader" that is above it. It is not nested, so it's not a parent/child situation. However this code only shows the "itemheader" div if the first item is "type1" or "type2". Sometimes there will be multiple instances of "type1" either directly above or below it, or it may not be there at all.

The divs with "type1" have already been hidden with CSS.

Changing the HTML code is not an option, it is auto-generated by another program and can not be changed, I'm trying to manipulate it to show only certain text.

Existing HTML Code:

<div class="itemheader">content</div>
    <div class="itemcontent type1">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type3">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type3">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type3">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type1">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type1">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type1">content</div>
    <div class="itemcontent type1">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type3">content</div>
    <div class="itemcontent type1">content</div>

Desired results to be shown:

<div class="itemheader">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type3">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type3">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type3">content</div>
<div class="itemheader">content</div>
    <div class="itemcontent type2">content</div>
    <div class="itemcontent type3">content</div>

Existing jQuery

$(".itemheader").hide();

$(".itemheader").each(function() {
  if ($(this).next().hasClass("type2")) {
    $(this).show();
  }
  if ($(this).next().hasClass("type3")) {
    $(this).show();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class="itemheader">itemHeader</div>
<div class="itemcontent type1">content type 1</div>
<div class="itemcontent type2">content type 2</div>
<div class="itemcontent type3">content type 3</div>
<div class="itemheader">itemHeader</div>
<div class="itemcontent type3">content type 3</div>
<div class="itemheader">itemHeader</div>
<div class="itemcontent type2">content type 1</div>
<div class="itemcontent type2">content type 2</div>
<div class="itemcontent type3">content type 3</div>
<div class="itemheader">itemHeader</div>
<div class="itemcontent type1">content type 1</div>
<div class="itemheader">itemHeader</div>
<div class="itemcontent type1">content type 1</div>
<div class="itemheader">itemHeader</div>
<div class="itemcontent type1">content type 1</div>
<div class="itemcontent type1">content type 1</div>
<div class="itemcontent type2">content type 2</div>
<div class="itemcontent type3">content type 3</div>
<div class="itemcontent type1">content type 1</div>

I have tried using nextUntil() and filter(), but that will only set the style for the "itemcontent" div, not the "itemheader" div.

Example to test functionality:

$('.itemheader').nextUntil('.itemheader').filter('.type2').css('backgroundColor', 'yellow');

Solution

  • Here's a solution: first hide all $(".itemcontent.type1") and then show $(".itemheader") only if the next visible element is not a .itemheader (select using nextAll(':visible').first())

    $(".itemcontent.type1").hide();
    
    $(".itemheader").each(function() {
      if (!$(this).nextAll(':visible').first().hasClass("itemheader")) {
        $(this).show();
      } else {
        $(this).hide();
      }
    });
    .itemheader {
      font-weight: bold;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <div class="itemheader">itemHeader</div>
    <div class="itemcontent type1">content type 1</div>
    <div class="itemcontent type2">content type 2</div>
    <div class="itemcontent type3">content type 3</div>
    <div class="itemheader">itemHeader</div>
    <div class="itemcontent type3">content type 3</div>
    <div class="itemheader">itemHeader</div>
    <div class="itemcontent type2">content type 2</div>
    <div class="itemcontent type2">content type 2</div>
    <div class="itemcontent type3">content type 3</div>
    <div class="itemheader">itemHeader</div>
    <div class="itemcontent type1">content type 1</div>
    <div class="itemheader">itemHeader</div>
    <div class="itemcontent type1">content type 1</div>
    <div class="itemheader">itemHeader</div>
    <div class="itemcontent type1">content type 1</div>
    <div class="itemcontent type1">content type 1</div>
    <div class="itemcontent type2">content type 2</div>
    <div class="itemcontent type3">content type 3</div>
    <div class="itemcontent type1">content type 1</div>