jquery prev-next visible selector

Viewed 115

I want to select prev or next visible element, jumping over hidden ones.

So click on the first title shoud write c in console, but it doesn't work.

$('.atitle').on('click', function(){
  console.log($(this).next(':visible').text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='atitle'>a</div>
<div class='atitle' hidden>b</div>
<div class='atitle'>c</div>
<div class='atitle'>d</div>

3 Answers

You can try with nextAll(':visible:first') and prevAll(':visible:first'):

$('.atitle').on('click', function(){
  console.clear();
  console.log($(this).nextAll(':visible:first').text() + ':Next');
  console.log($(this).prevAll(':visible:first').text() + ':Prevoius');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='atitle'>a</div>
<div class='atitle' hidden>b</div>
<div class='atitle'>c</div>
<div class='atitle'>d</div>

$('.atitle').on('click', function(){ 
  if($(this)[0] == $('.atitle:last')[0]){ // for some reason $(this).is(':last') not working
    console.log("EOL");
    return null;
  }
  var atitle = findNext($(this).next('.atitle'));
  if(atitle) console.log(atitle.text());
});

function findNext(elem){
  if($(this)[0] == $('.atitle:last')[0]){
    console.log("EOL");
    return null;
  } 
  if(elem.is(":visible")) 
    return elem;
  else 
    return findNext(elem.next('.atitle'));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='atitle'>a</div>
<div class='atitle' style="display:none">b</div>
<div class='atitle'>c</div>
<div class='atitle'>d</div>

Well, as you stated that you want to select the next or the prev visible element, I'm assuming that you want only one of them and it should be the closest one between both. To achieve this, one solution is to select the next visible one, the previous visible one and compare between them which one is the closest. So, taking into account the next layout:

<div class='atitle'>a</div>
<div class='atitle' hidden>b</div>
<div class='atitle'>c</div>
<div class='atitle'>d</div>
<div class='atitle' hidden>e</div>
<div class='atitle'>f</div>
<div class='atitle' hidden>g</div>
<div class='atitle'>h</div>

Clicking on each element should return:

┌─────────────┬───────────────┐
│ Clicking on │ Should return │
├─────────────┼───────────────┤
│ a           │ c             │
│ c           │ d             │
│ d           │ c             │
│ f           │ d or h*       │
│ h           │ f             │
└─────────────┴───────────────┘

* As d and h are at the same distance from f, if the later is clicked, you should decide which one of the first ones you are going to select if you want only one, in this example, I'm selecting both.

$('.atitle').on('click', function() {

  var $this = $(this);

  // Select the closest prev and next visible elements
  var $prev = $this.prevAll('.atitle:visible:eq(0)');
  var $next = $this.nextAll('.atitle:visible:eq(0)');

  // Check the indexes of each one
  var prevDiff = $prev.index() < 0 ? NaN : Math.abs($this.index() - $prev.index());
  var nextDiff = $next.index() < 0 ? NaN : Math.abs($this.index() - $next.index());

  // Decide which one should be selected
  if (isNaN(prevDiff) || nextDiff < prevDiff) {
    console.log( $next.text() );
  } else if (isNaN(nextDiff) || prevDiff < nextDiff) {
    console.log( $prev.text() );
  } else if (nextDiff === prevDiff) {
    console.log($prev.text(), $next.text());
  } else {
    console.log('no element');
  }
  
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class='atitle'>a</div>
<div class='atitle' hidden>b</div>
<div class='atitle'>c</div>
<div class='atitle'>d</div>
<div class='atitle' hidden>e</div>
<div class='atitle'>f</div>
<div class='atitle' hidden>g</div>
<div class='atitle'>h</div>

Related