Question

I have n equally sized boxes in an absolutely positioned container of boxWidth * n width. This resides in a relatively positioned container with a hidden overflow. There are multiple rows. On a left or right swipe the horizontal position of the box container will add or subtract 1 boxWidth from the containers left position in the swiped direction without exceeding its max positions (0, 0) and ((boxWidth * n), 0)

example

http://jsfiddle.net/rTe8U/8/

This is a simple version of what I am currently rolling with, and it works, however, if two swipes are made before the css transition is completed then the wrong 'current' position is being referenced. What can I do about this?

HTML

<div class="widget a">
    <div class="overflow">
        <div class="box">1</div>
        <div class="box">2</div>
        <div class="box">3</div>
        <div class="box">4</div>
    </div>
</div>
<div class="widget b">
    <div class="overflow">
        <div class="box">1</div>
        <div class="box">2</div>
        <div class="box">3</div>
        <div class="box">4</div>
        <div class="box">5</div>
    </div>
</div>
<div class="widget c">
    <div class="overflow">
        <div class="box">1</div>
        <div class="box">2</div>
    </div>
</div>
<div class="widget d">
    <div class="overflow">
        <div class="box">1</div>
        <div class="box">2</div>
        <div class="box">3</div>
        <div class="box">4</div>
    </div>
</div>

CSS

* {
    margin:0;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}
.widget {
    width: 200px;
    position: relative;
    height: 100px;
    overflow: hidden;
}
.overflow {
    transition: all 0.5s ease-out;
    -o-transition: all 0.5s ease-out;
    -moz-transition: all 0.5s ease-out;
    -webkit-transition: all 0.5s ease-out;
    height: 100px;
    position:absolute;
    left: 0;
}
.box {
    user-select: none;
    -o-user-select: none;
    -moz-user-select: none;
    -webkit-user-select: none;
    float: left;
    text-align:center;
    line-height: 100px;
    width: 200px;
    height: 100px;
    border: 1px solid #000;
}
.box:hover{
    cursor:pointer;
}

JS

var fullbox = '200',
    overflows = [$('.a .overflow'),$('.b .overflow'),$('.c .overflow'),$('.d .overflow')];

// Set Widths of Overflow Boxes
for (var i=0; i < 4; i++){
    overflows[i].width(overflows[i].children().length * fullbox);   
}

// Swipe Handlers
$('.overflow').on({
    swipeleft: function () {
        if ($(this).position().left != '-' + ($(this).children().length - 1) * fullbox) {
            $(this).css('left', '-=' + fullbox);
        }
    },
    swiperight: function () {
        if ($(this).position().left !== 0) {
            $(this).css('left', '+=' + fullbox);
        }
    }
});
Was it helpful?

Solution

You probably don't want to stop the gesture while the boxes are in transition. From a user experience stand point if I swiped twice I'll probably expect the boxes to move twice as far. One method you could use is instead of detecting the boxes positions and moving relative to the position is to keep tab of which index the user is in. Either keep track in a var or in the DOM itself:

<div class="overflow" data-index="0">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
    <div class="box">5</div>
</div>

Then I change the swipe gestures to track the index as such:

$('.overflow').on({
  swipeleft: function () {
    var currentPosition = parseInt($(this).attr('data-index'));
    var totalBoxes = $(this).children('.box').length - 1;

    // Calculate the next position and ensure it doesn't pass the last box.
    var nextPosition = currentPosition + 1;
    if (nextPosition >= totalBoxes) {
        nextPosition = totalBoxes;
    }

    moveBox($(this), nextPosition);
  },
  swiperight: function () {
    var currentPosition = parseInt($(this).attr('data-index'));

    // Calculate the next position and ensure it doesn't pass the first box.
    var nextPosition = currentPosition - 1;
    if (nextPosition < 0) {
        nextPosition = 0;
    }

    moveBox($(this), nextPosition);
  }
});

The moveBox function:

function moveBox($ele, position) {
    var movePosition = parseInt(fullbox) * position;

    $ele
        .attr('data-index', position)
        .css('left', '-' + movePosition + 'px');
}

http://jsfiddle.net/rTe8U/11/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top