Touch: Promo Slider Phones

Here is another touched based slider for phones, it can be used for tablets as well. I have another touch based slider dedicated for tablets with 3D effect. But that one later.

Lets talk about this Touch Promo Slider.

PromoSlider

What it does?

You can add a set of images (static/dynamic) when the user swipes left or right the images will move left or right. I call it Promo Slider because it can be used as a homepage slider.

Download from here:
Fork Download

Example page (enable Emulate touch events in your console):
Example

The slider consists of 3 parts. CSS, JavaScript and HTML. It uses native JavaScript and no dependencies on third party libraries.

HTML:

    <div class="container">
	<div id="m-horzListing">
	    <div class="horzListing" id="horz1">
		<div class="ribbonPopular">Popular</div>
		<img src="images/1.jpg" title="" alt="" draggable="false" width="312"/>
	     </div>	
	</div>
	<div class="bullets">
	     <span class="bullet"></span>
	</div>
     </div>

The HTML has a main holder, inside an DIV element with a static id. Inside goes the Promo ribbon. Bellow you can see the bullets on which will switch based on the current image.

If you want to add multiple images depends on how you build your application you can create a loop on wich you can duplicate the div with the class horzListing. But don’t forget to iterate the id of the element horz + i. The slider moves based on those id’s.

CSS

    .container {
	background: #fff;
	border:1px solid #dadada;
	width:312px;
	height:145px;
	overflow:hidden;
	margin:0 auto;
	position:relative;
	border-radius: 4px;
	box-shadow: 0 3px 7px #dadada;
	-webkit-border-radius: 4px;
	-webkit-box-shadow: 0 3px 7px #dadada;
	-webkit-transform: perspective(0px) rotateY(0deg) translateZ(200px);
	-webkit-box-shadow: 0 3px 7px #dadada;
	margin-top: 50px;
    }
    #m-horzListing {
	width:1800px;
	-webkit-transition: -webkit-transform 0.7s ease;
	height: 100%;
    }
    .horzListing {
	padding: 5px;
	float: left;
	width: 302px;
	height: 140px;
	z-index: 4;
	margin-right: 9px;
	-webkit-backface-visibility: hidden;
	position: relative;
	overflow: hidden;
	padding-top:1px;
    }
    .ribbonPopular {
	width: 125px;
	height: 25px;
	position: absolute;
	z-index: 3;
	background-color: #b52289;
	color: #fff;
	font-size: 12px;
	-webkit-font-smoothing: antialiased;
	transform: rotate(40deg);
	-ms-transform: rotate(40deg);
	-webkit-transform: rotate(40deg);
	-o-transform: rotate(40deg);
	-moz-transform: rotate(40deg);
	text-align: center;
	line-height: 25px;
	right: -24px;
	top: 13px;
    }
    .bullets {
	position: absolute;
	bottom: 5px;
	background: rgba(0, 0, 0, 0.3);
	height: 15px;
	width: 180px;
	padding-top: 9px;
	padding-left: 120px;
	left: 5px;
	z-index: 4;
    }
    .bullets .bullet {
	float:left;
	display:block;
	width:5px;
	height:5px;
	background: #c8c8c8;
	margin-left:5px;
	border-radius:10px;
    }
    .bullets .current {
	background:#fff;
    }

I will start with .container. The CSS applied to it it’s nothing special, it has a fixed width and fixed height, because it’s a dedicated phone touch slider. I wanted to keep the width of the phones so we won’t have the overflow scroll when you swipe on your phone.

The #m-horzListing uses the CSS transition so it gives the slider an nice animation effect. You can change the width based on how many elements you have inside, but 1800px I think it should do the trick unless you have more then 20 items in your slider.

For the .horzListing there is not much “functionality” for it, the CSS it’s just plain and simple to make it look better.

The ribbon uses the transform:rotate property so it will rotate the ribbon to 45deg. I won’t go over the bullets because they are pretty straight forward. Uses position:absoulte property and are placed at the bottom of the image.

JavaScript

I will split this into parts.

First it’s a self executing function. No need for dom.load event.

(function(){})();
    var sliderConf = {
        min : 1, //minimum number of images
        max : 5, //maximum number of images
        current : 1, //start image position
        currPos : 0, //custom attribute that stores current TranslateX position of each image
        imageTapStartX : 0, //get the tap start x
        imageTapEndX : 0, //tap start x end
        imageTapDistanceX : 0, //keeps the value between touch start and end
        coverFlowContainerElement : null, //the main id of the slider
        bullets : null, //the bullets holder
	moveDistance: 322 //the move distance of each image
    };

This is the main configuration object of the slider that the properites will be used later. Look at the comments in the code above to see each property what it does.

 that.init = function () {
     that.promoSlider();
  };

The main init function will be called by the window object at the end of the function. It calls the promoSlider.

   /*
    * Init Promo Slider
    */
    that.promoSlider = function() {
        //assign to the elem the slider holder
	sliderConf.coverFlowContainerElement = document.getElementById("m-horzListing");
	//set moving position for the images
        that.addAttributesToElems();
    };
    /*
    * for each child in the slider add current position attr for moveing later based on the cp
    */
    that.addAttributesToElems = function() {
        var moveDist = 0;
	//start counting from 1 and not 0
        for ( var x = 1; x &lt; sliderConf.max + 1; x++ ) {
            moveDist += sliderConf.moveDistance;
            var elems = document.getElementById("horz" + x);
            elems.setAttribute('cp', moveDist);
        }
        //the bullet for the current image add the class current
        sliderConf.bullets = document.getElementsByClassName('bullet');
        sliderConf.bullets[0].className = 'bullet current';
        that.addEventsToImageHolders();
    };

In the function addAttributesToElems each element from the slider will get a property called cp stands from Current Position. It’s the moving value distance of each element present in the slider. The cp will start with 322 which it’s defined in the sliderConf object. Why 322? Because it’s a phone slider and each image will move 322px that includes the margins as well. So the content inside the slider it’s not wider then 312px which if you look at the .container was defined.

After each elements has the current position and the bullets elem. has the active class attached. The function addEventToImageHolders it’s called.

    /*
     *   for all images in the slider add event listener touch start and end
     *   that will handle the touch not swipe on the given image
     */
    that.addEventsToImageHolders = function () {
        var imageHolders = sliderConf.coverFlowContainerElement.getElementsByClassName("horzListing"), i, imgLen;
        for ( i = 0, imgLen = imageHolders.length; i &lt; imgLen; i++ ) {
            imageHolders[i].addEventListener("touchstart", that.handleImageTapStart, false);
            //if it;s chrome running on android instead of touchend event replace it with touchcancel
            //touch end on android chrome has a different behavior then the rest of the browsers
            if ( (navigator.platform.match('Linux armv7l') &amp;&amp; navigator.userAgent.match('Chrome')) )
            {
                //works on default android 4.2.2
                //doesn't work on chrome
                imageHolders[i].addEventListener("touchend", that.handleImageTapEnd,false); //nexus 7 needs the touchend to go to detail page
                //works on chrome
               imageHolders[i].addEventListener("touchcancel", that.handleImageTapEnd,false); //nexus 7 needs the touchend to go to detail page
            } else {
                imageHolders[i].addEventListener("touchend", that.handleImageTapEnd,false);
            }
        }
    };

This one does what it says. For each div element an event listener it’s attached. The touch events. There are some challenges when it comes to default browser in Android and Chrome on Android phones.

That’s why we check for the chrome browser, this one will use the touchend and touchcancel events, by nexus tablets (I know it’s a tablet but the slider goes well on 7” tablets).

Once the events are attached to the elements, get the end position of the touch event. The function handleImageTapEnd will move the slider left, right or the else will handle the linking event (if needed) you can add the click event on the image itself or add an a tag to send the user to the giving link.

    //handle the tap end on the image
    that.handleImageTapEnd = function(event) {
        sliderConf.imageTapEndX = event.changedTouches[0].pageX;
        sliderConf.imageTapDistanceX = sliderConf.imageTapEndX - sliderConf.imageTapStartX;
        //if the tapped distance it's smaller then 0 move right otherwize left
        if ( sliderConf.imageTapDistanceX &lt; 0) {             
               that.moveRightOne();         
        } else if (sliderConf.imageTapDistanceX &gt; 0) {
            that.moveLeftOne();
        }else { 
	    //the same image has been clicked
	    //add onclick event to the element to redirect to the giving link
            console.log('redirect the user to any page');
        }
    };

Now that we know on which direction the slider as been swiped, based on the pageX, touch value. We can calculate the distance of the image that moves. As you can see I am using imageTapEndX and imageTapStartX constants and save the value to imageTapDistanceX

The moveRightOne will crete a negative value while the moveLeftOne function will add positive value, to the div

Once we know how the slider moves left, right, we can start doing the movement of the div elements.

    //move the slider to left
    that.moveLeftOne = function() {
        if ( sliderConf.current &gt; sliderConf.min) {
            sliderConf.current--;
            if ( sliderConf.current === 1 ) {
                sliderConf.currPos = 0;
            } else {
                sliderConf.currPos = document.getElementById("horz" + ( sliderConf.current - 1)).getAttribute("cp");
            }
            for ( var i = 1; i &lt; = sliderConf.max; i++) {
                if ( i == sliderConf.current ) {
                    sliderConf.bullets[sliderConf.current -1 ].className = 'bullet current';
                } else {
                    sliderConf.bullets[sliderConf.current].className = 'bullet';
                }
            }
            sliderConf.coverFlowContainerElement.style.webkitTransform = "translateX(-" + sliderConf.currPos + "px)";
        }
    };
    //move the images in the slider to right
    that.moveRightOne = function() {
        if ( sliderConf.current &lt; sliderConf.max ) {
            if ( sliderConf.current === 1 ) {
                sliderConf.currPos = document.getElementById("horz1").getAttribute("cp");
            } else {
                sliderConf.currPos = document.getElementById("horz" + sliderConf.current).getAttribute("cp");
            }
            sliderConf.current++;
            for ( var i = 1; i &lt;= sliderConf.max; i++) {
                if ( i == ( sliderConf.current - 1 ) ) {
                    sliderConf.bullets[i].className = 'bullet current';
                } else {
                    sliderConf.bullets[sliderConf.current-2].className = 'bullet';
                }
            }
            sliderConf.coverFlowContainerElement.style.webkitTransform = "translateX(-" + sliderConf.currPos + "px)";
        }
    };

I placed both functions moveRightOne and moveLeftOne because they both uses similar logic and I will go over them both.

By default the slider uses the translateX CSS property to move the elements. It can be done with left, right CSS property as well.

Let’s see what we have above. First we check for the current image in view and compare it with the minimum value, this one will stop the slider from swipe once it reaches the end or back at the 0 position. For the moveLeftOne the starting position it’s 0, while for the moveRightOne gets the elements cp property. The one we talked that was assigned in the addAttributesToElems function.

Once the current position value it’s in place move the slider left, right with the value from cp, using translate:3d css property.

There is another for loop and if else condition. That one swiches the bullets class. Either it adds the class active to the bullet that it’s in view with the image, or removes the class active.

The disablePageScroll function it’s not currently used. But can become handy to prevent the browser to move on swipe. It can happen on older Android versions. But currently this function it’s not called anywhere. If you want to use it you can call it at the begging of the promoSlider function, above the line where we assign to coverFlowContainerElement the id of m-horzListing.

That’s pretty much it. It’s not a complex slider this one. Let me know if you find it useful, if there are improvements, fixes I can do. As well you can ask any question if something it’s unclear.

Download from here:
Fork Download

Example page:
Example

2 thoughts on “Touch: Promo Slider Phones

Leave a Reply

Your email address will not be published. Required fields are marked *