javascriptjqueryclassnextuntil

Automatically increment adding a class tag [class-(+1)] between two sets of sibling divs


I was wondering if there was a way to automate/condense adding the specific classes ".header-child-accordion .header-child-accordion-set-(incrementing number)" to sibling divs that exist between two controlling sibling divs that contain the class ".mv-header-menu-accordion-(incrementing number)" as opposed to manually dictating the classes from one controlling sibling div to another.

I have done this one by one through identifying if there is, for example, a div that contains ".mv-header-menu-accordion-11" nextUntil ".mv-header-menu-accordion-12".

Is there a way to: $('.mv-header-menu-accordion- + (i+1)').nextUntil('.mv-header-menu-accordion-+ ((i+1)+1)').addClass("header-child-accordion header-child-accordion-set-+ (i+1)");

$(document).ready(function() {
  $(".header-menu-nav-folder-content").each(function() {
    $(this).find('.mv-header-menu-accordion').each(function() {
      $('.mv-header-menu-accordion-1').nextUntil('.mv-header-menu-accordion-2').addClass("header-child-accordion header-child-accordion-set-1");
      $('.mv-header-menu-accordion-2').nextUntil('.mv-header-menu-accordion-3').addClass("header-child-accordion header-child-accordion-set-2");
      $('.mv-header-menu-accordion-3').nextUntil('.mv-header-menu-accordion-4').addClass("header-child-accordion header-child-accordion-set-3");
      $('.mv-header-menu-accordion-4').nextUntil('.mv-header-menu-accordion-5').addClass("header-child-accordion header-child-accordion-set-4");
      $('.mv-header-menu-accordion-5').nextUntil('.mv-header-menu-accordion-6').addClass("header-child-accordion header-child-accordion-set-5");
      $('.mv-header-menu-accordion-6').nextUntil('.mv-header-menu-accordion-7').addClass("header-child-accordion header-child-accordion-set-6");
      $('.mv-header-menu-accordion-7').nextUntil('.mv-header-menu-accordion-8').addClass("header-child-accordion header-child-accordion-set-7");
      $('.mv-header-menu-accordion-8').nextUntil('.mv-header-menu-accordion-9').addClass("header-child-accordion header-child-accordion-set-8");
      $('.mv-header-menu-accordion-9').nextUntil('.mv-header-menu-accordion-10').addClass("header-child-accordion header-child-accordion-set-9");
      $('.mv-header-menu-accordion-10').nextUntil('.mv-header-menu-accordion-11').addClass("header-child-accordion header-child-accordion-set-10");
      $('.mv-header-menu-accordion-11').nextUntil('.mv-header-menu-accordion-12').addClass("header-child-accordion header-child-accordion-set-11");
    });
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="header-menu-nav-folder-content">
  <div class="mv-header-menu-accordion-1 mv-header-menu-accordion">
    <p>Parent 1</p>
  </div>
  <div class="">
    <p>Child 1</p>
  </div>
  <div class="">
    <p>Child 2</p>
  </div>
  <div class="">
    <p>Child 3</p>
  </div>
  <div class="mv-header-menu-accordion-2 mv-header-menu-accordion">
    <p>Parent 2</p>
  </div>
  <div class="">
    <p>Child 1</p>
  </div>
  <div class="">
    <p>Child 2</p>
  </div>
  <div class="">
    <p>Child 3</p>
  </div>
  <div class="mv-header-menu-accordion-3 mv-header-menu-accordion">
    <p>Parent 3</p>
  </div>
  <div class="">
    <p>Child 1</p>
  </div>
  <div class="">
    <p>Child 2</p>
  </div>
  <div class="">
    <p>Child 3</p>
  </div>
  <div class="mv-header-menu-accordion-4 mv-header-menu-accordion">
    <p>Parent 4</p>
  </div>
  <div class="">
    <p>Child 1</p>
  </div>
  <div class="">
    <p>Child 2</p>
  </div>
  <div class="">
    <p>Child 3</p>
  </div>
</div>


Solution

  • The first step towards condensing the code would be to use constant variables in place of long, repeated strings like the class names. Next your nested loop already goes through all the headers so you only need to use this and one call to nextUntil() in each iteration. You already have the set number in this.className you can use a regex to capture that number, whatever it happens to be.

    In the following snippet I have added some styles for easy visual confirmation.

    const hmaClass = 'mv-header-menu-accordion'
    const hcaClass = 'header-child-accordion'
    const setNClass = n => `${hcaClass}-set-${n}`
    $(document).ready(function() {
      $(".header-menu-nav-folder-content").each(function() {
    
        $(this).find(`.${hmaClass}`).each(function() {
          // get this set number from this.className
          const setNum = this.className.match(/mv-header-menu-accordion-(\d+)/)[1]
          // .match() returns array with index 1 holding the captured digits (\d+)
    
          $(this).nextUntil(`.${hmaClass}`) // until the next with the header class
            .addClass(hcaClass)
            .addClass(setNClass(setNum))
    
        });
    
      });
    });
    .mv-header-menu-accordion * {
      color: black;
      font-weight: bolder;
    }
    
    .header-child-accordion {
      border: 1px solid blue;
    }
    
    [class$=set-27] {
      color: skyblue;
    }
    
    [class$=set-1] {
      color: blue;
    }
    
    [class$=set-2] {
      color: green;
    }
    
    [class$=set-3] {
      color: orange;
    }
    
    [class$=set-4] {
      color: red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="header-menu-nav-folder-content">
      <div class="mv-header-menu-accordion-1 mv-header-menu-accordion">
        <p>Parent 1</p>
      </div>
      <div class="">
        <p>Child 1</p>
      </div>
      <div class="">
        <p>Child 2</p>
      </div>
      <div class="">
        <p>Child 3</p>
      </div>
      <div class="mv-header-menu-accordion-2 mv-header-menu-accordion">
        <p>Parent 2</p>
      </div>
      <div class="">
        <p>Child 1</p>
      </div>
      <div class="">
        <p>Child 2</p>
      </div>
      <div class="">
        <p>Child 3</p>
      </div>
      <div class="mv-header-menu-accordion-3 mv-header-menu-accordion">
        <p>Parent 3</p>
      </div>
      <div class="">
        <p>Child 1</p>
      </div>
      <div class="">
        <p>Child 2</p>
      </div>
      <div class="">
        <p>Child 3</p>
      </div>
      <div class="mv-header-menu-accordion-4 mv-header-menu-accordion">
        <p>Parent 4</p>
      </div>
      <div class="">
        <p>Child 1</p>
      </div>
      <div class="">
        <p>Child 2</p>
      </div>
      <div class="">
        <p>Child 3</p>
      </div>
      <div class="mv-header-menu-accordion-27 mv-header-menu-accordion">
        <p>Parent 27</p>
      </div>
      <div class="">
        <p>Child 1</p>
      </div>
      <div class="">
        <p>Child 2</p>
      </div>
      <div class="">
        <p>Child 3</p>
      </div>
    </div>