Sometimes, We Write Stuff...

MooTools Content Slider Update - Numbered Nav

13 comments

So, here we are again... yet another content slider update!  By far, the most requested addition I have received is a way to 'jump' to other slides, along with a navigation for it.  I'm actually going to take that one step further, and show you how to accomplish that with a dynamically created navigation list!

Overview

This tutorial will build upon the past div slider tutorials on this site, so I'm just going to focus mainly on the creation/functionality of our new numbered nav.  (If you haven't gone over those yet, I highly recommend that you glance over them to get familiar with everything.)   In particular, I will be explaining the use of the 'element.adopt' method, the dynamic creation of html elements and their contents, and then the code to tie it all into our original slider.  I'll also add in a little code that prevents a graphical glitch that the past slider was suffering from.  (The 'stuttering' effect that was happening when the prev/next buttons were rapidly pushed.)

As always, I'll try to keep this simple – and please feel free to ask questions, call me a jackass, say thanks, etc. in the comments area!  The full code and example link are located below.

The XHTML

Our XHTML is basically identical to our last tutorial.  I have made two minor changes, though.  First, I've turned our 'controls' div into an unordered list, and assigned the buttons as anchors inside of each list:

<ul id="controls"> 
	<li id="prevbtn"><a>prev</a></li>
	<li id="playbtn"><a>pause</a></li>
	<li id="nextbtn"><a>next</a></li>
</ul>

I've also added another unordered list, with an id of 'num_nav':  (I'll give you one guess what that will be for...)

<ul id="num_nav">
	
</ul>

The CSS

Very little has been changed here.  Other than changing the CSS a bit to handle the controls being inside of list items, the only new addition is the styling/positioning for our numbered navigation.  It's just some basic styling:

#num_nav {
	width: 500px;
	height: 30px;
	position: absolute;
	top:  427px;
	left: 105px;
	list-style: none;
}

#num_nav li {
	display: block;
	float: left;
	width: 20px;
	height: 20px;
	margin: 2px;
	border: 1px solid;
	border-color: #666666;
	background-color: #333333;
}

#num_nav a {
	display: block;
	width: 20px;
	height: 20px;
	line-height: 20px;
	text-align: center;
}

The Javascript/MooTools

This is where the majority of the changes/additions are located, as you can probably imagine. 

Config Area Changes

First, I've added a few important new things to our 'config' area:

var numNav = new Array();  //create an array to hold our dynamically created number navigation
var isSliding = 0;  //will be used to prevent multiple clicking
var numNavHolder = $('num_nav');  //get element for our numbered nav
Dynamic Number Buttons Creation

Now we will dynamically create our numbered navigation items, and then insert them into the 'numNavHolder' that we just defined above.  This makes use of the native 'adopt' method of MooTools Elements, and I think you'll find it quite powerful!  We'll do this in our 'setup' area of the code, inside the setup loop for each slide.  The first thing we'll do is create the anchor element and the list item element.  As we create our anchor element, we'll also give it a class and insert content (the number) into it:

var numItem = new Element('li', {id: 'num'+index});
var numLink = new Element('a', {
	'class': 'numbtn',
	'html': (index+1)
});

Next, we'll use the 'adopt' method to insert our 'numLink' inside the 'numItem' we just created, and then we'll put this new nav item into the 'num_nav' unordered list.  (Think about those wooden Russian dolls... as that's essentially what we're doing here.)  Note that I've also used the javascript function 'push()' here to add each new anchor into an array, which we'll be using in a moment:

numItem.adopt(numLink);  //inserts link into list item
numNavHolder.adopt(numItem);  //inserts link item into the numbered nav
numNav.push(numLink); //push element into an array, for accessing later

Lastly, we'll highlight our initial active button:

var initNum = numNav[itemNum];
origColor = initNum.getStyle('color');  //get original link color
initNum.setStyles({
	'background-color': '#272727',
	'color': '#FF6600'
});
Updated Movement Function

In order to keep this small and easy-to-understand, I condensed the animation functions into a single function called 'slideMove'  It's nearly identical to the previous 'slideForward' and 'slideBackward' functions from the earlier tutorials, except that it accepts two parameters, direction and passedID.  Direction is required, and as you may have guessed it tells our movement function 'how' to move – 0 is for backward, 1 is for forward, and 2 is for a direct jump to a number.  (Obviously, the 'passedID' parameter is only required when direction=2.)  Here's a look at the entire 'slideMove' function:

var slideMove = function(direction, passedID){ 
	
	//get item to slide out
	var curItem = items[itemNum]; 
	var curNumItem =  numNav[itemNum];
	
	//change index based on value of 'direction' parameter
	if(direction == 1){
		if(itemNum < (numItems - 1)){
			itemNum++; 
		}
		else{
			itemNum = 0;
		}
	}
	else if(direction == 0){
		if(itemNum > 0){
			itemNum--; 
		}
		else{
			itemNum = (numItems - 1);
		}
	}
	else {
		if(itemNum != passedID){
			itemNum = passedID;
		}
	}
	
	//now get item to slide in using new index
	var newItem = items[itemNum];
	var newNumItem =  numNav[itemNum];
	
	
	//set up our animation stylings for slide
	var item_in = new Fx.Morph(newItem, {
		     duration: transitionTime, 
		     transition: Fx.Transitions.Cubic.easeOut, 
		     link: 'ignore',
		     
		     //click prevention actions
		     onStart: function(){
			    isSliding = 1;  //prevents extra clicks
		     },
		     
		     onComplete: function(){ 
				isSliding = 0;  //allow clicks again
		     }
	});
	
	var item_out = new Fx.Morph(curItem, {
		     duration: transitionTime, 
		     transition: Fx.Transitions.Cubic.easeOut, 
		     link: 'ignore'
	});
	
        //number nav button effects
	var num_in = new Fx.Morph(newNumItem, {
		     duration: 100, 
		     transition: Fx.Transitions.linear, 
		     link: 'ignore'
	});
	
	var num_out = new Fx.Morph(curNumItem, {
		     duration: 100, 
		     transition: Fx.Transitions.linear, 
		     link: 'ignore'
	});
	
	//we will set a beginning value here
	//this is so that it gives the illusion of continuous motion from one direction, even after the first cycle of items
	item_in.start({
	'left': [502, 0]
	});
	
	//no beginning values needed, since we always want to push the old item out to the left
	item_out.start({
	'left': '-502'
	});
	
	num_in.start({
		'background-color': '#272727' ,
		'color': '#FF6600'
	});
	
	num_out.start({
		'background-color': '#333333' ,
		'color': origColor
	});
	
};

Take special notice of the 'onStart' and 'onComplete' events I'm making use of in the item_in animation (FX) setup above.  (These are used to set the 'isSliding' variable's value, which we will use to prevent the extra clicks glitching.)

Hooking Up the Buttons

The next/prev/play buttons are all essentially the same, except for one thing.  Through the use of an 'if' statement, I am checking the 'isSliding' variable to determine whether to perform the movement function or not.  Here's an example with the 'next' button:

nextBtn.addEvent('click', function(){
	if(isSliding == 0){
		if(isPaused == 0){
			$clear(theTimer);
			theTimer = slideMove.periodical(slideTimer, this, 1);
		}
		slideMove(1);
	}
});

The code for the new number navigation is quite similar.  The only difference is that we will be passing the index of the button into our move function, so that it knows what slide to jump to.  I've also set them to change the cursor to 'pointer' on hover, making it more like a button.  Check it out:

numNav.each(function(element, index) {
	var origColor = element.getStyle('color');
	
	element.addEvents({
		'click' : function(){
			if(isSliding == 0 && itemNum != index){
				if(isPaused == 0){
					$clear(theTimer);
					theTimer = slideMove.periodical(slideTimer, this, 1);
				}
				slideMove(2, index);
				//alert("index: " + index);
			}
		},
		'mouseenter' : function() {
			this.setStyle('cursor', 'pointer');
		}
	});

});

Conclusion

And there you have it, a timed content slider with basic controls... and now also with dynamically created slide number buttons!

Demo/Download

  • StumbleUpon It
  • del.icio.us

+ Comments

Here's a preview of your comment: