Creating simple pure Javascript slider on swipe for mobile devices

Viewed 1390

I want to create something similar to Google slider for images on searching on small screen sizes, Just make the browser width smaller or visit it from mobile, Then type 'image' in Google search box for example, You will see 3 images beneath Google search box that you can slide to show more images.

So there will be about 6 images next to each other, But 2 are fully shown and about half of the 3rd image, While the 3 others will be hidden.

As the user swipe to the left the 3rd image and the other 3 would become visible, The user should still can swipe to the right to show the first images if he already swiped to the left.

I tried to analyze the one on Google, But there are elements those I see for the first time, And I don't know how to find the related JS functions, If this is done with pure JS.

That's what I tried so far:

var ImageIndex = 0;

function swipe(event){
    var touch = event.targetTouches[0];
    var midpoint = Math.floor(screen.width/2);
    var px = touch.pageX;
    var items = document.getElementsByClassName('image-wrapper');
    var itemActive = items[ImageIndex]; 
    if(px < midpoint){
        itemActive.style.marginLeft = '-100%';
        itemActive.style.transition = '1s';
        if (ImageIndex < items.length) {
            ImageIndex = ImageIndex + 1;
        }else{
            ImageIndex = 0;
        }
    }else{
        itemActive.style.marginLeft = '0px';
        itemActive.style.transition = '1s';
        if (ImageIndex >= 1 ) {
            ImageIndex = ImageIndex - 1;
        }else{
            ImageIndex = 0;
        }
    }
}

CSS:

.images-gallary{
    background-color: #000;
    overflow: hidden;
    height: 73px;
    white-space: nowrap;
}

.image-wrapper{
    width: 100%;
    display: inline-block;
    text-align: center;
}

#secondItem{
    background: #fff;
}

HTML:

<div class="images-gallary" ontouchmove="swipe(event)">
    <div class="image-wrapper" id="firstItem">
        <img class="image" src="http://placehold.it/73/200">
    </div>
    <div class="image-wrapper" id="secondItem">
        <img class="image" src="http://placehold.it/73/300">
    </div>
    <div class="image-wrapper">
        <img class="image" src="http://placehold.it/73/400">
    </div>
</div> <!-- .images-gallary -->

This code just slide the first 2 images, And I get an error:

Uncaught TypeError: Cannot read property 'style' of undefined

So how to customize that code to work as mentioned at the top?

I don't want to use Jquery or any libraries, Just pure JS code.

2 Answers

So the problem in your case is in this condition if (ImageIndex < items.length) {. You have total amount of 3 elements, therefore when ImageIndex is 2, it will increment it to 3 and as you have 3 images in the html items[ImageIndex] will return undefined.

So change the condition to if (ImageIndex < items.length - 1) {.

Replace your first condition ImageIndex < items.length with ImageIndex < (items.length - 1) because total images length is 3 here and trying to access style of items[3] (undefined)

if (ImageIndex < (items.length - 1)) {
   ImageIndex = ImageIndex + 1;
}else {
   ImageIndex = 0;
}

and one more thing in 2nd condition you should have replace ImageIndex = 0; with ImageIndex = items.length - 1; in else condition because always initialising same value ImageIndex = 0; in case of px > midpoint and ImageIndex < 1

if (ImageIndex >= 1 ) {
   ImageIndex = ImageIndex - 1;
}else {
   ImageIndex = items.length-1;
}

your final code seems like below:

var ImageIndex = 0;

function swipe(event){
    var touch = event.targetTouches[0];
    var midpoint = Math.floor(screen.width/2);
    var px = touch.pageX;
    var items = document.getElementsByClassName('image-wrapper');
    var itemActive = items[ImageIndex]; 
    if(px < midpoint){
        itemActive.style.marginLeft = '-100%';
        itemActive.style.transition = '1s';
        if (ImageIndex < (items.length - 1)) {
            ImageIndex = ImageIndex + 1;
        }else{
            ImageIndex = 0;
        }
    }else{
        itemActive.style.marginLeft = '0px';
        itemActive.style.transition = '1s';
        if (ImageIndex >= 1 ) {
            ImageIndex = ImageIndex - 1;
        }else{
            ImageIndex = items.length - 1;
        }
    }
}
Related