Home > Back-end >  Is it possible to select a specific number of closest siblings
Is it possible to select a specific number of closest siblings

Time:08-31

I have an amount of div elements, i would like to target a specific number of the closet elements, in this case the closest 2 either side of itself and add a class.

$(document).ready(function() {
  var dot = $('.dot3');
  if (dot.length > 5) {
    var activeDot = $('.dot3.active');
    var closestDots = $(activeDot).siblings(3);
    $(closestDots).css('background-color', '#ff0000');
    $(activeDot).css('background-color', '#ff0000');
  }
});
.dot3 {
  background-color: #000;
  height: 10px;
  width: 10px;
  border-radius: 100%;
  display: inline-block;
  margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>

CodePudding user response:

To do what you require you can use prevAll()/nextAll() to get the preceding/following dot elements, then slice() to limit the selection to the 2 nearest in each direction. Then you can apply a CSS class to them to add the required syling.

$(document).ready(function() {
  let $dots = $('.dot3');
  if ($dots.length > 5) {
    var $activeDot = $('.dot3.active');
    let $prev2 = $activeDot.prevAll().slice(0, 2);
    let $next2 = $activeDot.nextAll().slice(0, 2);
    $prev2.add($next2).addClass('active');
  }
});
.dot3 {
  background-color: #000;
  height: 10px;
  width: 10px;
  border-radius: 100%;
  display: inline-block;
  margin: 5px;
}
.dot3.active {
  background-color: #F00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>

CodePudding user response:

To get the elements on either side of the target element you could use the .next() and .prev() methods:

$(document).ready(function() {
  var dot = $('.dot3');
  if (dot.length > 5) {
    var activeDot = $('.dot3.active');
    var closestDots = $() // use add to make a collection 
      .add(activeDot.prev())
      .add(activeDot.next());
    $(closestDots).css('background-color', '#ff0000');
    $(activeDot).css('background-color', '#ff0000');
  }
});
.dot3 {
  background-color: #000;
  height: 10px;
  width: 10px;
  border-radius: 100%;
  display: inline-block;
  margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>

Since the active dot and its siblings are all getting the same treatment, you could arguably keep things clearer by combining them all into a single collection before altering the CSS:

$(document).ready(function() {
  var dot = $('.dot3');
  if (dot.length > 5) {
    var activeDot = $('.dot3.active');
    var targetElements = $() // use add to make a collection 
      .add(activeDot)
      .add(activeDot.prev())
      .add(activeDot.next());
    $(targetElements).css('background-color', '#ff0000');
  }
});
.dot3 {
  background-color: #000;
  height: 10px;
  width: 10px;
  border-radius: 100%;
  display: inline-block;
  margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>

If you need to support an arbitrary number of previous and next siblings, you can define your own methods called nextN and prevN that take an integer-- this is a rudimentary start without any error handling or checking for out of bounds:

$.fn.nextN = function (n) {
  let newCollection = $();
  let cachedElement = this;
  for (let i = 0; i < n; i  = 1) {
    const nextElement = cachedElement.next();
    newCollection = newCollection.add(nextElement);
    cachedElement = nextElement;
  }
  return newCollection;
}

$.fn.prevN = function (n) {
  let newCollection = $();
  let cachedElement = this;
  for (let i = 0; i < n; i  = 1) {
    const nextElement = cachedElement.prev();
    newCollection = newCollection.add(nextElement);
    cachedElement = nextElement;
  }
  return newCollection;
}


$(document).ready(function() {
  var dot = $('.dot3');
  if (dot.length > 5) {
    var activeDot = $('.dot3.active');
    var prevElements = activeDot.prevN(2);
    var nextElements = activeDot.nextN(2);
    $(activeDot).css('background-color', '#ff0000');
    $(prevElements).css('background-color', '#ff0000');
    $(nextElements).css('background-color', '#ff0000');
  }
});
.dot3 {
  background-color: #000;
  height: 10px;
  width: 10px;
  border-radius: 100%;
  display: inline-block;
  margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>

UPDATE based on Rory's answer, I have improved the helper methods to take advantage of nextAll() and prevAll() in lieu of looping:

$.fn.nextN = function (n) {
  return this.nextAll().slice(0, n);
}

$.fn.prevN = function (n) {
  return this.prevAll().slice(0, n);
}


$(document).ready(function() {
  var dot = $('.dot3');
  if (dot.length > 5) {
    var activeDot = $('.dot3.active');
    var prevElements = activeDot.prevN(2);
    var nextElements = activeDot.nextN(2);
    $(activeDot).css('background-color', '#ff0000');
    $(prevElements).css('background-color', '#ff0000');
    $(nextElements).css('background-color', '#ff0000');
  }
});
.dot3 {
  background-color: #000;
  height: 10px;
  width: 10px;
  border-radius: 100%;
  display: inline-block;
  margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>
<div >
</div>

CodePudding user response:

$( document ).ready(function() {
      var dot = $('.dot3');
      if( dot.length > 5 ) {
          var activeDot = $('.dot3.active');
          var $active = activeDot.filter('.active');
            var $prev = $active.prev();
            activeDot.removeClass('prev_slide').removeClass('next_slide');
            if (!$prev.length) {
                $prev = activeDot.last();
            }else{
                $prev.addClass('prev_div')
                $active.prev().prev().addClass('prev_div')
            }
    
            var $next = $active.next();
            if (!$next.length) {
                $next = activeDot.first();
            }else{
                $next.addClass('next_div')
                $active.next().next().addClass('next_div')
            }
            
          $('.next_div, .prev_div').css('background-color','#ff0000');
          $(activeDot).css('background-color','#ff0000');
      }
    });
    

.dot3 {
          background-color: #000;
          height: 10px;
          width: 10px;
          border-radius: 100%;
          display: inline-block;
          margin: 5px;
        }
    
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
    </div>
    <div >
    </div>
    <div >
    </div>
    <div >
    </div>
    <div >
    </div>
    <div >
    </div>
    <div >
    </div>

You can use the below jquery to add before and after class which is active div.

    $( document ).ready(function() {
      var dot = $('.dot3');
      if( dot.length > 5 ) {
          var activeDot = $('.dot3.active');
          var $active = activeDot.filter('.active');
            var $prev = $active.prev();
            activeDot.removeClass('prev_slide').removeClass('next_slide');
            if (!$prev.length) {
                $prev = activeDot.last();
            }else{
                $prev.addClass('prev_div')
                $active.prev().prev().addClass('prev_div')
            }
    
            var $next = $active.next();
            if (!$next.length) {
                $next = activeDot.first();
            }else{
                $next.addClass('next_div')
                $active.next().next().addClass('next_div')
            }
            
          $('.next_div, .prev_div').css('background-color','#ff0000');
          $(activeDot).css('background-color','#ff0000');
      }
    });
  • Related