Search code examples
javascriptjqueryhtmlparent

Rearranging js to accommodate more flexibility


How can I make this js affect only the child elements of the original hovered element without giving all of the individual .g_scroll or .left/.right tags id's?

function loopRight(){
      $('.g_scroll').stop().animate({scrollLeft:'+=20'}, 'fast', 'linear', loopRight);
  }

  function loopLeft(){
      $('.g_scroll').stop().animate({scrollLeft:'-=20'}, 'fast', 'linear', loopLeft);
  }

  function stop(){
      $('.g_scroll').stop();
  }


  $('#right').hover(function () {
     loopRight().children();
  },function () {
     stop();
  });

  $('#left').hover(function () {
     loopLeft();
  },function () {
     stop();
  });

JSfiddle for (confusing, but necessary) html structure: https://jsfiddle.net/6rbn18cL/

To demonstrate how it would have to be renamed: https://jsfiddle.net/z9u3azqy/


Solution

  • So here, I "merged" both arrow handlers.
    Then, there is a calculation needed to determine the "scroll" speed, based on width to be scrolled, which may no always be 100% of the element's width.

    This script allows you to easily determine a speed for 100% scrolling.
    Then, it calculates the speed if there is already a distance scrolled.

    $(document).ready(function(){
    
      function moveit(arrow){
    
        // Adjust you delay here
        var delay = 2000; // delay to scroll 100%
        var animationDelay;
    
        var slider = arrow.siblings(".g_scroll");
        var distance = slider.width();
        var scrolled = slider.scrollLeft()+1; // +1 is to avoid infinity in the math below
    
        if(arrow.hasClass("scroller_l")){
          distance = -distance;
          animationDelay = -distance * (-distance/delay)*(-distance+scrolled);
        }else{
          animationDelay = distance * (distance/delay)*(distance-scrolled);
        }
    
        slider.stop().animate({scrollLeft:distance}, animationDelay, 'linear');
      }
    
      function stop(arrow){
        arrow.siblings(".g_scroll").stop();
      }
    
    
      $('.scroller_l, .scroller_r').hover(function(){
        moveit($(this));
      },function() {
        stop($(this));
      });
    
    }); // ready
    

    CodePen




    --First answer--

    First, you can't use the same id more than once.
    So I removed id="left" and id="right" from your HTML.

    Now the trick is to pass which arrow is hovered to your functions, using $(this).
    And find the .g_scroll element which is a sibling of it.

    $(document).ready(function(){
    
    
      function loopRight(arrow){
        arrow.siblings(".g_scroll").stop().animate({scrollLeft:'+=20'}, 'fast', 'linear', loopRight);
      }
    
      function loopLeft(arrow){
        arrow.siblings(".g_scroll").stop().animate({scrollLeft:'-=20'}, 'fast', 'linear', loopLeft);
      }
    
      function stop(arrow){
        arrow.siblings(".g_scroll").stop();
      }
    
    
      $('.scroller_r').hover(function(){
        loopRight($(this));
      },function() {
        stop($(this));
      });
    
      $('.scroller_l').hover(function(){
        loopLeft($(this));
      },function() {
        stop($(this));
      });
    
    });
    

    CodePen