简体   繁体   中英

How to detect end of elements in div with jQuery each() on multiple div

I have several divs that have the same class .timeline-travel-steps . These divs contain elements .step that I want to select with jQuery each() Method

HTML

<div class="timeline-graphic">
  <div class="step"></div>
  <div class="step"></div>
  <div class="step"></div>
</div>

<div class="timeline-graphic">
  <div class="step"></div>
  <div class="step"></div>
  <div class="step"></div>
  <div class="step"></div>
  <div class="step"></div>
  <div class="step"></div>
</div>

JS (jQuery)

var i = 0;
$(".timeline-graphic .step").each(function(index, value) {
  $(this).css('left', i + 'px');
  i = i + 20;
});

It works but I need to know when the each() reaches the end of a div timeline-travel-steps . Currently the each() continues and run the elements contained in the other divs. It would be very simple if each divs had a different and static class but these divs are generated by a cms and I don't know how many there are.

I need something like:

if (isLastElement) {
    i = 0;
}

I've tried to play with index and .length but the each() continues to run.

Here is a snippet

 var i = 0; $(".timeline-graphic.step").each(function(index, value) { //console.log(index); var numItems = $(this).parent().length; console.log(numItems); $(this).css('left', i + 'px'); i = i + 20; });
 .timeline-graphic { height: 4px; background-color: #000; border-radius: 0.25rem; margin: 0 auto 80px auto; width: 100%; position: relative; }.step { position: absolute; top: -3px; width: 11px; height: 11px; background-color: red; border-radius: 50%; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div> <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div>

If you use each along with the index argument there is no need to use another counter variable. Just cycle all .step elements for each .timeline-graphic element

$('.timeline-graphic').each(function() {
  $('.step', this).each(function(index, v) {
     console.log(index);
     $(this).css('left', (index * 20) + 'px');
  });
})

As a side note there is no even need to use jQuery and/or position: absolute for this kind of task when you can use use only CSS , by adjusting the distance of the dots inside a Flexbox container with the gap property:

 .timeline-graphic { display: flex; align-items: center; gap: 20px; height: 2rem; background: linear-gradient(to bottom, transparent 0, transparent calc(50% - 2px), #000 0, #000 calc(50% + 2px), transparent 0 ) repeat-x; }.step { border-radius: 50%; height: 50%; aspect-ratio: 1; background: red; }
 <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div> <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div>

In case the distance of the dots were determined by JavaScript, you could still go with the CSS solution and use JS to just update a custom variable, eg

 :root { --gap: 0; }.timeline-graphic { display: flex; align-items: center; gap: var(--gap); height: 2rem; background: linear-gradient(to bottom, transparent 0, transparent calc(50% - 2px), #000 0, #000 calc(50% + 2px), transparent 0 ) repeat-x; }.step { border-radius: 50%; height: 50%; aspect-ratio: 1; background: red; }
 <label for="gap" id="gap-label">Adjust the gap via JS</label> <input type="range" id="gap" aria-labelledby="gap-label" min="0" max="40" step="1" value="0" oninput="document.documentElement.style.setProperty('--gap', this.value + 'px');" /> <hr /> <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div> <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div>

You can check if the current step is the last in the parent by using

$(this).is(":last-child")

Note: it does need to be the last element, not just the last step (without elements after). Nested each is the cleanest solution (IMO) - see other answer.

There's an experimental :nth-last-child(1 of.step) but that only works in Safari (so not recommended)

Updated snippet (without making any other changes, so this is unlikely to be the optimal/final solution)

 var i = 0; $(".timeline-graphic.step").each(function(index, value) { var numItems = $(this).parent().length; $(this).css('left', i + 'px'); i = i + 20; if ($(this).is(":last-child")) i = 0; });
 .timeline-graphic { height: 4px; background-color: #000; border-radius: 0.25rem; margin: 0 auto 80px auto; width: 100%; position: relative; }.step { position: absolute; top: -3px; width: 11px; height: 11px; background-color: red; border-radius: 50%; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div> <div class="timeline-graphic"> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> <div class="step"></div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM