Scroll tabs with animation - Stop setInterval immediately on mouseup

743 views Asked by At

I've make scroll buttons , and while I'm pressing, the tabs are scrolling.

When I scroll to right and back to the begin, the tabs overflow area. How not to let this happen?

Problem

Code:

jQuery(document).ready(function($) {

    var hidWidth;
    var scrollBarWidths = $('#page-tabs .scroller-right').width() + $('#page-tabs .scroller-left').width();

    var widthOfList = function() {
        var itemsWidth = 0;
        $('#page-tabs .list li').each(function() {
            var itemWidth = $(this).outerWidth();
            itemsWidth += itemWidth;
        });
        return itemsWidth;
    };

    var widthOfHidden = function() {
        return (($('#page-tabs .wrapper').outerWidth()) - widthOfList() - getLeftPosi()) - scrollBarWidths;
    };

    var getLeftPosi = function() {
        return $('#page-tabs .list').position().left;
    };

    var timeout;
    $list = $('#page-tabs .list');
    $('#page-tabs .scroller-right').on('mousedown', function(event) {
        event.preventDefault();
        timeout = setInterval(function() {
            move = widthOfHidden();
            move = move < -10 ? -10 : move;

            if (move >= 0) {
                clearInterval(timeout);
                return false;
            } else {
                $list.animate({
                    left: "+=" + move + "px"
                }, 10, 'linear');
            }
        }, 10);
    }).on('mouseup mouseleave', function(event) {
        event.preventDefault();
        clearInterval(timeout);
    });

    $('#page-tabs .scroller-left').on('mousedown', function(event) {
        event.preventDefault();
        timeout = setInterval(function() {
            move = getLeftPosi();
            move = move < -10 ? -10 : move;

            if (move >= 0) {
                clearInterval(timeout);
                //$list.animate({left:"0px"},300, 'linear');
                return false;
            } else {
                $list.animate({
                    left: "-=" + move + "px"
                }, 10, 'linear');
            }

        }, 10);

    }).on('mouseup mouseleave', function(event) {
        event.preventDefault();
        clearInterval(timeout);
    });
});
#page-tabs {
    position: relative;
    width: 100%;
    margin-top: 50px;
}

.scroller {
    width: 30px;
    height: 30px;
    position: absolute;
    top: 0;
}

.scroller-left {
    left: 0;
}

.scroller-right {
    right: 0;
}

.wrapper {
    position: relative;
    margin: 0 34px;
    overflow: hidden;
    height: 30px;
    background: #454545;
}

ul {
    position: absolute;
    margin: 0;
    padding: 0;
    list-style: none;
    min-width: 3000px;
}

li {
    display: inline-block;
    margin: 0;
    padding: 10px;
    background: #CCC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="page-tabs">
    <div class="wrapper">
        <ul class="list">
            <li>Aba nº 1</li>
            <li>Aba nº 2</li>
            <li>Aba nº 3</li>
            <li>Aba nº 4</li>
            <li>Aba nº 5</li>
            <li>Aba nº 6</li>
            <li>Aba nº 7</li>
            <li>Aba nº 8</li>
            <li>Aba nº 9</li>
            <li>Aba nº 10</li>
            <li>Aba nº 11</li>
            <li>Aba nº 12</li>
            <li>Aba nº 13</li>
            <li>Aba nº 14</li>
            <li>Aba nº 15</li>
            <li>Aba nº 16</li>
            <li>Aba nº 17</li>
            <li>Aba nº 18</li>
            <li>Aba nº 19</li>
            <li>Aba nº 20</li>
        </ul>
    </div>
    <button class="scroller scroller-left">&larr;</button>
    <button class="scroller scroller-right">&rarr;</button>
</div>

JsFiddle

Sorry, my English is not very good.

2

There are 2 answers

0
Carlos On BEST ANSWER

I've fixed changing the code:

timeout = setInterval(function() {
    move = getLeftPosi();
    move = move < -10 ? -10 : move;

    if (move >= 0) {
        clearInterval(timeout);
        return false;
    } else {
        $list.animate({
            left: "-=" + move + "px"
        }, 10, 'linear');
    }

}, 10);

To:

timeout = setInterval(function(){
    move = getLeftPosi();
    move = move < -100 ? -100 : move;

    if (move < 0)
        $list.animate({left:"-="+move+"px"},100, 'linear');

    if (move > -100){
        clearInterval(timeout);
        $list.stop(true, true);
        return false;
    }

}, 100);

Result:

   var hidWidth;
   var scrollBarWidths = $('#page-tabs .scroller-right').width() + $('#page-tabs .scroller-left').width();

   var widthOfList = function(){
      var itemsWidth = 0;
      $('#page-tabs .list li').each(function(){
         var itemWidth = $(this).outerWidth();
         itemsWidth+=itemWidth;
      });
      return itemsWidth;
   };

   var widthOfHidden = function(){
      return (($('#page-tabs .wrapper').outerWidth())-widthOfList()-getLeftPosi())-scrollBarWidths;
   };

   var getLeftPosi = function(){
      return $('#page-tabs .list').position().left;
   };

   var timeout;
   $list = $('#page-tabs .list');
   $('#page-tabs .scroller-right').on('mousedown', function(event) {
      event.preventDefault();
      timeout = setInterval(function(){
         move = widthOfHidden();
         move = move < -100 ? -100 : move;

         if (move < 0)
             $list.animate({left:"+="+move+"px"},100, 'linear');

         if (move > -100){
            clearInterval(timeout);
            $list.stop(true, true);
            return false;
         }
      }, 100);
   }).on('mouseup mouseleave', function(event){
      event.preventDefault();
      clearInterval(timeout);
   });

   $('#page-tabs .scroller-left').on('mousedown', function(event) {
      event.preventDefault();
      timeout = setInterval(function(){
         move = getLeftPosi();
         move = move < -100 ? -100 : move;

         if (move < 0)
             $list.animate({left:"-="+move+"px"},100, 'linear');
         
         if (move > -100){
            clearInterval(timeout);
            $list.stop(true, true);
            return false;
         }

      }, 100);

   }).on('mouseup mouseleave', function(event){
      event.preventDefault();
      clearInterval(timeout);
   });
#page-tabs {
    position: relative;
    width: 100%;
    margin-top: 50px;
}

.scroller {
    width: 30px;
    height: 30px;
    position: absolute;
    top: 0;
}

.scroller-left {
    left: 0;
}

.scroller-right {
    right: 0;
}

.wrapper {
    position: relative;
    margin: 0 34px;
    overflow: hidden;
    height: 30px;
    background: #454545;
}

ul {
    position: absolute;
    margin: 0;
    padding: 0;
    list-style: none;
    min-width: 3000px;
}

li {
    display: inline-block;
    margin: 0;
    padding: 10px;
    background: #CCC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="page-tabs">
    <div class="wrapper">
        <ul class="list">
            <li>Aba nº 1</li>
            <li>Aba nº 2</li>
            <li>Aba nº 3</li>
            <li>Aba nº 4</li>
            <li>Aba nº 5</li>
            <li>Aba nº 6</li>
            <li>Aba nº 7</li>
            <li>Aba nº 8</li>
            <li>Aba nº 9</li>
            <li>Aba nº 10</li>
            <li>Aba nº 11</li>
            <li>Aba nº 12</li>
            <li>Aba nº 13</li>
            <li>Aba nº 14</li>
            <li>Aba nº 15</li>
            <li>Aba nº 16</li>
            <li>Aba nº 17</li>
            <li>Aba nº 18</li>
            <li>Aba nº 19</li>
            <li>Aba nº 20</li>
        </ul>
    </div>
    <button class="scroller scroller-left">&larr;</button>
    <button class="scroller scroller-right">&rarr;</button>
</div>

3
ps2goat On

I think you have to call .stop() on the animated jQuery element. Animations go to a queue that processes regardless of your interval code. You'll still have a little bit of lag, though.

jQuery(document).ready(function($) {

    var hidWidth;
    var scrollBarWidths = $('#page-tabs .scroller-right').width() + $('#page-tabs .scroller-left').width();

    var widthOfList = function() {
        var itemsWidth = 0;
        $('#page-tabs .list li').each(function() {
            var itemWidth = $(this).outerWidth();
            itemsWidth += itemWidth;
        });
        return itemsWidth;
    };

    var widthOfHidden = function() {
        return (($('#page-tabs .wrapper').outerWidth()) - widthOfList() - getLeftPosi()) - scrollBarWidths;
    };

    var getLeftPosi = function() {
        return $('#page-tabs .list').position().left;
    };

    var timeout;
    $list = $('#page-tabs .list');
    $('#page-tabs .scroller-right').on('mousedown', function(event) {
        event.preventDefault();
        timeout = setInterval(function() {
            move = widthOfHidden();
            move = move < -10 ? -10 : move;

            if (move >= 0) {
                clearInterval(timeout);
                return false;
            } else {
                $list.animate({
                    left: "+=" + move + "px"
                }, 10, 'linear');
            }
        }, 10);
    }).on('mouseup mouseleave', function(event) {
        event.preventDefault();
        clearInterval(timeout);
        $list.stop();
    });

    $('#page-tabs .scroller-left').on('mousedown', function(event) {
        event.preventDefault();
        timeout = setInterval(function() {
            move = getLeftPosi();
            move = move < -10 ? -10 : move;

            if (move >= 0) {
                clearInterval(timeout);
                //$list.animate({left:"0px"},300, 'linear');
                return false;
            } else {
                $list.animate({
                    left: "-=" + move + "px"
                }, 10, 'linear');
            }

        }, 10);

    }).on('mouseup mouseleave', function(event) {
        event.preventDefault();
        clearInterval(timeout);
        $list.stop();
    });
});
#page-tabs {
    position: relative;
    width: 100%;
    margin-top: 50px;
}

.scroller {
    width: 30px;
    height: 30px;
    position: absolute;
    top: 0;
}

.scroller-left {
    left: 0;
}

.scroller-right {
    right: 0;
}

.wrapper {
    position: relative;
    margin: 0 34px;
    overflow: hidden;
    height: 30px;
    background: #454545;
}

ul {
    position: absolute;
    margin: 0;
    padding: 0;
    list-style: none;
    min-width: 3000px;
}

li {
    display: inline-block;
    margin: 0;
    padding: 10px;
    background: #CCC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="page-tabs">
    <div class="wrapper">
        <ul class="list">
            <li>Aba nº 1</li>
            <li>Aba nº 2</li>
            <li>Aba nº 3</li>
            <li>Aba nº 4</li>
            <li>Aba nº 5</li>
            <li>Aba nº 6</li>
            <li>Aba nº 7</li>
            <li>Aba nº 8</li>
            <li>Aba nº 9</li>
            <li>Aba nº 10</li>
            <li>Aba nº 11</li>
            <li>Aba nº 12</li>
            <li>Aba nº 13</li>
            <li>Aba nº 14</li>
            <li>Aba nº 15</li>
            <li>Aba nº 16</li>
            <li>Aba nº 17</li>
            <li>Aba nº 18</li>
            <li>Aba nº 19</li>
            <li>Aba nº 20</li>
        </ul>
    </div>
    <button class="scroller scroller-left">&larr;</button>
    <button class="scroller scroller-right">&rarr;</button>
</div>