1

I have a function that will jump between each instance of a class ("highlighted") every time to call gonext().

Here is the full code:

var currentPos = 0;
function gonext() {
  var pos = $(".highlighted").eq(currentPos).position();
  console.log(Math.round(pos.top));
  $(".highlighted").eq(currentPos).css("color", "red");
  currentPos++;
  $(".main").scrollTop(pos.top);
}

    
.main {
  height: 100px;
  border:1px solid grey;
  padding: 10px 20px;
  overflow: scroll;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<hr>
<button onclick="gonext()">Got to Next</button>
<hr>

<div class="main">
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
</div>
    
   

The problem is that as soon as it scrolls to the next position it scrolls up and then down.

See the console log positions for more info.

How can I fix this so that it just scrolls to the next one etc...without the up / down jump?

angel.bonev
  • 2,154
  • 3
  • 20
  • 30

4 Answers4

2

You have to add some calculation of .main top and scrollTop. Don't forget to add condition to check last .highlighted element in .main container. Otherwise it'll throw an error.

var currentPos = 0;
function gonext() {
  if($(".highlighted").eq(currentPos).length > 0){
    
    var mainTop = $(".main").position().top;
    var mainScrlTop = $(".main").scrollTop();
    
    var pos = $(".highlighted").eq(currentPos).position();
    $(".highlighted").eq(currentPos).css("color", "red");
    $(".main").scrollTop(pos.top - mainTop + mainScrlTop);
    
    currentPos++;
  }
}
    .main {
      height: 100px;
      border:1px solid grey;
      padding: 10px 20px;
      overflow: scroll;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<hr>
<button onclick="gonext()">Got to Next</button>
<hr>

<div class="main">
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
</div>
Asfan Shaikh
  • 759
  • 5
  • 9
0

So, basically the position() is not something you looking for.

From my personal experience, whenever I want to scroll to some elements, offsetTop is more accurate.

var currentPos = 0;
function gonext() {
  var pos = $(".highlighted").eq(currentPos)[0].offsetTop;
  
  $(".highlighted").eq(currentPos).css("color", "red");
  $(".main").scrollTop(pos);
  console.log(currentPos)
  console.log($(".highlighted").eq(currentPos)[0].offsetTop)
  currentPos++;
}
.main {
  height: 100px;
  border:1px solid grey;
  padding: 10px 20px;
  overflow: scroll;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<hr>
<button onclick="gonext()">Got to Next</button>
<hr>

<div class="main">
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
</div>
He Wang
  • 647
  • 7
  • 19
  • It's working well except that I can't see the current highlighted class..it's hidden. You can see that when you click the button, the currentPos changes color but I need to see it –  Oct 18 '19 at 12:13
0

You need to add the scrolled height in addition to the position or offset.

$(".main").scrollTop(pos.top + $(".main").get(0).scrollTop);

When you use overflow scrolling containers, the offset or position function tends to calculate from the relative position, not the scrolled position.

See a demo: https://jsfiddle.net/tive/e3Ls529c/

Tim Vermaelen
  • 6,869
  • 1
  • 25
  • 39
0

maybe try to walk the indexes of the list items. Like https://jsfiddle.net/vL2sayt4/15/

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<hr>
<button class="gonext">Got to Next</button>
<hr>
<div class="main">
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
    <div><span class="highlighted">a</span></div>
    <div><span class="highlighted">s</span></div>
    <div><span class="highlighted">v</span></div>
</div>
<pre class="console"></pre>
.main {
  height: 100px;
  border:1px solid grey;
  padding: 10px 20px;
  overflow: scroll;
  display:block;
}
.console {
  display:block;
  height:100px;
  border:1px solid grey;
  padding: 10px 20px;
  overflow: scroll;
}
(function($){
    var itemsLength  = $('div.main div span.highlighted').length;
    var curIndex     = 0;
    var cwindow      = $('.console');
    var button       = $('button.gonext');
    var consolelog = function(message){
        var text  = cwindow.innerHTML;
      message += "\n";
      cwindow.prepend(message);
    };
    var gonext = function(){
       consolelog('Button:click:curIndex:'+curIndex);
       consolelog('Button:click:itemLength:'+itemsLength);
       var listItem = $( "div.main div span.highlighted" ).eq( curIndex );
       // all black
       $("div.main div span.highlighted").css("color", "black");
       // current red 
       listItem.css("color", "red");
        curIndex ++;
        if(curIndex > itemsLength) curIndex = 0;
    };
    button.click(function(){
        gonext();
    });
})(jQuery)
Cianti
  • 1