7

I am trying to inverse scroll two select controls. When I scroll down the first select the other one should scroll up. This is what I am currently doing

//scroll first list if second list is scrolled
$("#secondList").on("scroll", function(){    
    //alert("focused");
    $("#firstList").scrollTop($(this).scrollTop());
});

//scroll second list if first list is scrolled
$("#firstList").on("scroll", function(){
    $("#secondList").scrollTop($(this).scrollTop());
});

to start the second select box from bottom I am doing this

$("div #secondList").animate({ scrollTop: $("#2").height() }, "slow");

but it starts both selects from bottom. And my html is

<div class="container" style="margin-top: 50px;">
  <div id="1">
   <select name="color" id="firstList" size="3" class="form-control" ></select>
  </div>
  <div id="2">
    <select name="hex" size="3" id="secondList" class="form-control" style="margin-top: 50px;"></select>
  </div>
</div>

NOTE I am dynamically adding the options

$.getJSON("ColorNameMap.json", function(data){
    for (var i = 0, len = data.length; i < len; i++) {
        var color = data[i].color;
        var value = data[i].value;

        $("#firstList").append('<option value="'+value+'">'+color+'</option>');
        $("#secondList").append('<option value="'+color+'">'+value+'</option>');
    }
});

I can see the answers here but I want inverse scrolling. Please help me to proceed in right direction.

Community
  • 1
  • 1
StealthTrails
  • 2,281
  • 8
  • 43
  • 67

1 Answers1

1

One of the big challenges is getting the direction of the scroll - to get that, you need to record the current position and compare it to the last position.

Once you figure out which way the scrolling is going, you can add or subtract from the other scrollable area, depending on direction.

Below, I've assumed that $selects is always a set of two elements, and on load, I set the last one to be scrolled to the bottom (its scrollHeight). Then on scroll, I get the direction it was scrolling in (note that the first time the scroll handler is fired, we don't have a direction because we only have one data point - it's current position), and scroll the same amount in the opposite direction.

There is a slight trick (detailed in this question Updating scrollTop before scroll listener is assigned triggers a scroll event) regarding the requestAnimationFrame that I used here. Depending on your browser support you may need a polyfill.

(function() {
  // Start off scrolled to the bottom
  var $selects = $('select');
  $selects.last().scrollTop($selects.last().get(0).scrollHeight);

  var lastScroll = {
    whichEle: null,
    position: 0
  };
  
  // Wait until the scrollTop has applied itself (aka a repaint)
  window.requestAnimationFrame(function() {
    $selects.on('scroll', scrollOther);
  });
  
  function scrollOther() {
    var currPosition = $(this).scrollTop();

    if ($(this).is(lastScroll.whichEle)) {
      var positionDiff = currPosition - lastScroll.position;
     
      if(positionDiff === 0) { return; }

      var $other = $selects.not(this);
      
      $other.off('scroll'); // temporarily stop listening
      
      // Wait until the handler released itself (aka a repaint)
      window.requestAnimationFrame(function() {
        // Since scroll events happen so frequently, no need to animate (unless there's a debounce)
        $other.scrollTop($other.scrollTop() - positionDiff);
        
        // Wait until the scrollTop has applied itself (aka a repaint)
        window.requestAnimationFrame(function() {
          $other.on('scroll', scrollOther); // restart listening
        });
      });
      
      
      
      
    } else {
      // Just started scrolling a new div  
      lastScroll.whichEle = $(this);

      // Since there is no direction figured out yet, do nothing more than record for this event
    }

    lastScroll.position = currPosition;
  }
})();
select {
  width: 40%;
  margin: 0 5%;
  height: 75px;
  float: left;
  font-size: 14px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div id="1">
    <select name="color" id="firstList" size="3" class="form-control">
      <option>1 Lorem ipsum dolor</option>
      <option>2 sit amet, consectetur</option>
      <option>3 adipiscing elit</option>
      <option>4 Aenean venenatis lectus</option>
      <option>5 blandit, posuere eros ut</option>
      <option>6 condimentum nulla. Nulla facilisi</option>
      <option>7 Integer eget ex quis</option>
      <option>8 turpis ullamcorper vulputate</option>
      <option>9 eget a eros. Phasellus scelerisque</option>
    </select>
  </div>
  <div id="2">
    <select name="hex" size="3" id="secondList" class="form-control">
      <option>1 sit amet dignissim neque</option>
      <option>2 Suspendisse scelerisque</option>
      <option>3 vestibulum lacus</option>
      <option>4 eget tincidunt</option>
      <option>5 Phasellus aliquet</option>
      <option>6 leo eu purus sollicitudin</option>
      <option>7 semper quam ut ornare</option>
      <option>8 Nullam vitae mollis leo</option>
      <option>9 id hendrerit mi tristique</option>
    </select>
  </div>
</div>
Community
  • 1
  • 1
allicarn
  • 2,859
  • 2
  • 28
  • 47
  • thank you, can you please add some comments to the js script. I don't want to copy paste. – StealthTrails Dec 15 '15 at 19:28
  • I added a little bit more of an explanation, but feel free to copy/paste, I don't mind :) – allicarn Dec 15 '15 at 19:37
  • In the fiddle, you have your old code as well as mine; I believe they are running into each other - there should only be one or the other – allicarn Dec 15 '15 at 19:53
  • thank you that was the problem. but you can see now that the other div not scrolls fully, I mean if one div is fully scrolled up the other is in the middle or somewhere. What could be the possible reason for this? http://jsfiddle.net/seen123/LxsL96L7/1/ – StealthTrails Dec 15 '15 at 19:57
  • it appears to be some sort of race condition (see http://jsfiddle.net/2jvhman0/4/)... working on it – allicarn Dec 15 '15 at 21:24
  • your above fiddle have only one div – StealthTrails Dec 15 '15 at 22:40
  • I've updated the answer to address the race condition (it wasn't specific to your example, rather it was a bug with adjusting and listening to scroll position). – allicarn Dec 16 '15 at 18:52