7

I'm getting the following error in my Firefox console, accompanied by jittery animations:

This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning;

I checked out Firefox's support post, but I didn't see any examples relevant to my scenario.

I have an anchor-based navigation menu which indicates where on the page the visitor currently is. Here is the jQuery I'm using to handle this:

$(window).scroll(function(){

    var scrollpos   = $(this).scrollTop();
    var pad         = $('.panel_header').outerHeight();

    $('.form_group').not('.sub_group').each(function(i){

        if(scrollpos + $(window).height() == $(document).height()){

            $('ul.tabs li').removeClass('active_tab');
            $('ul.tabs li:last-child').addClass('active_tab');

            return false;

        } else if(scrollpos+pad < $(this).position().top+($(this).height()/2)){

            var id  = $(this).attr('id').replace('-table','-tab');
            var tab = $('#'+id);

            if(tab.length > 0){

                $('ul.tabs li').removeClass('active_tab');
                tab.addClass('active_tab');
            }
            return false;
        }
    });
});

Basically, I'm checking the scroll position against the position of the anchor, and toggling a CSS class if the anchor is nearby. The CSS handles the transition effect.

Is there another way to achieve this that doesn't require a scroll-linked positioning effect and result in jittery scrolling?

Tony Hinkle
  • 4,706
  • 7
  • 23
  • 35
HWD
  • 1,547
  • 7
  • 36
  • 72
  • Consider share a code snippet with error reproduced... – shramee Jun 26 '16 at 07:15
  • @ShrameeSrivastav I think you find an code snippet in the [this](http://stackoverflow.com/questions/38042789/change-navigation-active-class-on-page-scroll-with-pure-css) post... – wittich Jun 26 '16 at 21:38
  • How many elements are returned by `$('.form_group').not('.sub_group')`? I.e., is it jittery because it requires too much processing? – Tony Hinkle Jun 27 '16 at 20:24
  • @TonyHinkle Maybe about 10 or 15 max. – HWD Jun 27 '16 at 23:58
  • It's really difficult to come up with a workaround without having a full working sample. Can you create an example on jsfiddle.net? Off the top of my head, I could only ask if using the `scrollStop` event would be adequate, or just running this constantly on a one or two second interval. That certainly would not a great solution, but might be a workaround to get it functional if it doesn't use too many resources. When you use the scroll event, it just fires so rapidly... – Tony Hinkle Jun 28 '16 at 13:47
  • If you store all the selectors on variables outside of the "on scroll" function (eg: `var $formGroup = $('.form_group').not('.sub_group')`, etc), then use only variables inside the "on scroll" function (eg: `$formGroup.each(function(){...})`), you'll get a very noticeable performance improvement! – Fisnik Tahiri Jun 30 '16 at 20:09

1 Answers1

0

Here is an attempt to approximate your aim (Demo). The code is inspired by Bootstrap ScrollSpy is modified to meet your requirements. Please let me now if this works for you:

var ScrollSpy = function() {

  var pad = 10;
  var offsets = [];
  var targets = [];
  var activeTarget = null;
  
  function init() {      
    $(document.body).find(".form_group").not(".sub_group").map(function () {    
      var $el   = $(this);
      var id  = $(this).attr('id').replace('-table','-tab');
      var $li = $('#'+id);
      
      return  [[$el.offset().top, $li[0]]];
    }).sort(function (a, b) { return a[0] - b[0] }).each(function () {
      offsets.push(this[0])
      targets.push(this[1])
    });
  };
  
  function activate(target) {
   activeTarget = target;
    clear();
   $(target).addClass('active_tab');
  };
  
  function clear() {
    $('ul.tabs li').removeClass('active_tab'); 
  };
  
  function getScrollHeight() {
    return window.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
  };
  
  function spy()  {  
    var scrollTop = $(window).scrollTop() + pad;
    var scrollHeight = getScrollHeight();
    var maxScroll = pad + scrollHeight - $(window).height();
    
    if (scrollTop >= maxScroll) {
      return activeTarget != (i = targets[targets.length - 1]) && activate(i);
    }
    
    if (activeTarget && scrollTop < offsets[0]) {
      activeTarget = null;
      return clear();
    }
    
  for (i = offsets.length; i--;) {
      activeTarget != targets[i]
        && scrollTop >= offsets[i]
        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
        && activate(targets[i]);
    }
  };
  
  $(window).scroll(spy);
  init();
  spy();
};

jQuery(function($) {
 ScrollSpy();
});
body, html {
  padding:0;
  margin:0;
  position: relative;
}
.panel_header {
  background-color:#ccc;
  padding:5px;
}

.tabs {
  padding:0;
  list-style:none;
  position:fixed;
  margin-left:-125px;
  left:50%;
  top:10px;
}
.tabs li {
  float:left;
  margin-left:4px;
}
.tabs li a {
  padding:4px 10px;
  background-color:white;
  border:1px solid #ccc;
}
.tabs li.active_tab a {
  background-color:red;
}

.form_group {
  border:1px solid #ccc;
  min-height:500px;
  padding:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<header style="height:120px"></header>
<ul class="tabs">
  <li id="1-tab"><a href="#">Tab 1</a></li>
  <li id="2-tab"><a href="#">Tab 2</a></li>
  <li id="3-tab"><a href="#">Tab 3</a></li>
  <li id="4-tab"><a href="#">Tab 4</a></li>
</ul>

<div class="form_group" id="1-table">
  <h3 class="panel_header">Form_group 1 </h3>
  <p>Sodales velit. Aliquam libero duis duis nam, pariatur etiam neque ridiculus nisl libero, quis dis enim. Justo natoque, suscipit quam leo elit mauris tortor venenatis, morbi libero magna lorem enim. Sociis sed eu auctor inceptos nec, commodo quis nostra pretium turpis, semper sapien amet pretium aliquam, mauris faucibus euismod. Sed justo odio justo aliquet, natoque duis, tristique ultricies eget sodales tempus vitae.</p>
  
</div>
<div class="form_group" id="2-table">
  <h3 class="panel_header">Form_group 2 </h3>
  <p>Sodales velit. Aliquam libero duis duis nam, pariatur etiam neque ridiculus nisl libero, quis dis enim. Justo natoque, suscipit quam leo elit mauris tortor venenatis, morbi libero magna lorem enim. Sociis sed eu auctor inceptos nec, commodo quis nostra pretium turpis, semper sapien amet pretium aliquam, mauris faucibus euismod. Sed justo odio justo aliquet, natoque duis, tristique ultricies eget sodales tempus vitae.</p>
</div>
<div class="form_group" id="3-table">
  <h3 class="panel_header">Form_group 3 </h3>
  <p>Sodales velit. Aliquam libero duis duis nam, pariatur etiam neque ridiculus nisl libero, quis dis enim. Justo natoque, suscipit quam leo elit mauris tortor venenatis, morbi libero magna lorem enim. Sociis sed eu auctor inceptos nec, commodo quis nostra pretium turpis, semper sapien amet pretium aliquam, mauris faucibus euismod. Sed justo odio justo aliquet, natoque duis, tristique ultricies eget sodales tempus vitae.</p>
</div>
<div class="form_group" id="4-table">
  <h3 class="panel_header">Form_group 4 </h3>
  <p>Sodales velit. Aliquam libero duis duis nam, pariatur etiam neque ridiculus nisl libero, quis dis enim. Justo natoque, suscipit quam leo elit mauris tortor venenatis, morbi libero magna lorem enim. Sociis sed eu auctor inceptos nec, commodo quis nostra pretium turpis, semper sapien amet pretium aliquam, mauris faucibus euismod. Sed justo odio justo aliquet, natoque duis, tristique ultricies eget sodales tempus vitae.</p>
</div>

For better experience please run the snippet in full page mode.

Ismail RBOUH
  • 10,292
  • 2
  • 24
  • 36
  • Thanks, let me give this a test in my environment and see if it solves the problem. It seems to follow @Fisnik's comment about storing the selectors outside of the "on scroll" function. – HWD Jul 01 '16 at 18:33