Website page slider using left arrow and right arrow

What I have at the moment, is a row of buttons and a website that slides left to right, the buttons make the slider move as below:


<span><a id="link1" href="#" title="Home">&nbsp;home&nbsp;</a></span>
<span><a id="link2" href="#" title="Profile">&nbsp;profile&nbsp;</a></span>
<span><a id="link3" href="#" title="Gallery">&nbsp;gallery&nbsp;</a></span>
<span><a id="link4" href="#" title="Contact">&nbsp;contact&nbsp;</a></span>

And here is the jscript:


$('link1').addEvent('click', function(event){
	event = new Event(event).stop();
	scroll.toElement('content1');
});

$('link2').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content2');
});

$('link3').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content3');
});

$('link4').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content4');
});

So what the “customer” now wants is to have a left pointing arrow to the left of the buttons and a right pointing arrow to the right, so that they think the user will be happy to use them as they give the user more feedback.

So I’m guessing that i will need to have a count function that when it relates to a certain number it calls one of the right functions above to make it move.

All that up there works perfect so will keep that, just need a bit of help with the 2 buttons.

So i would have something like this:


<span><a id="?" href="#">Left Button Image</a></span>
<span><a id="link1" href="#" title="Home">&nbsp;home&nbsp;</a></span>
<span><a id="link2" href="#" title="Profile">&nbsp;profile&nbsp;</a></span>
<span><a id="link3" href="#" title="Gallery">&nbsp;gallery&nbsp;</a></span>
<span><a id="link4" href="#" title="Contact">&nbsp;contact&nbsp;</a></span>
<span><a id="?" href="#">Right Button Image</a></span>


Give the arrows an appropriate id


<span><a id="left" href="#">Left Button Image</a></span>
...
<span><a id="right" href="#">Right Button Image</a></span>

and have each trigger an event handler that takes care of moving left or right.
Also make sure to place the scripting at the end of the body, just before the </body> tag.


document.getElementById('left').onclick = function () {
    // do left moving stuff
    ...
    return false;
};
document.getElementById('right').onclick = function () {
    // do right moving stuff
    ...
    return false;
};

When you move, you’ll want to keep track of an index number that indicates which one needs to be gone to.
To prevent issues with global variables, we’ll also wrap this code in its own self-executing function.


(function () {
    var index = 0;
    document.getElementById('left').onclick = function () {
        index -= 1;

        return false;
    };
    document.getElementById('right').onclick = function () {
        index += 1;

        return false;
    };
}());


Now all we need is a list that the left and right events can get information from, and to loop to the other end if they attempt to go too far.

For the sake of this example, I’m going to assume that the links are contained within an identified element. For example, “nav”.


<div [color="green"]id="nav"[/color]>
    <span><a id="left" href="#">Left Button Image</a></span>
    ...
    <span><a id="right" href="#">Right Button Image</a></span>
</div>

Let’s now get all of the links within that “nav” area, then remove the first and last ones (left/right).


(function () {
    var index = 0,
        nav = document.getElementById('nav'),
        links = nav.getElementsByTagName('a');

    // change the links from a live nodeList to an array
    links = Array.prototype.slice.call(links);
    links.shift(); // remove the first link - the left arrow
    links.pop(); // remove the last link - the right arrow

    ...
}());

We now have an index that goes up and down, and we now also have a list of links. The only thing to do now is to perform some bounds checking, and to trigger the appropriate link.


document.getElementById('left').onclick = function () {
    index -= 1;
    if (index < 0) {
        index = links.length - 1;
    }
    links[index].click();

    return false;
};
document.getElementById('right').onclick = function () {
    index += 1;
    if (index >= links.length) {
        index = 0;
    }
    links[index].click();

    return false;
};

That’s how it’s done with JavaScript. Here’s the full script:


(function () {
    var index = 0,
        nav = document.getElementById('nav'),
        links = nav.getElementsByTagName('a');

    // change the links from a live nodeList to an array
    links = Array.prototype.slice.call(links);
    links.shift(); // remove the first link - the left arrow
    links.pop(); // remove the last link - left arrow

    document.getElementById('left').onclick = function () {
        index -= 1;
        if (index < 0) {
            index = links.length - 1;
        }
        links[index].click();

        return false;
    };
    document.getElementById('right').onclick = function () {
        index += 1;
        if (index >= links.length) {
            index = 0;
        }
        links[index].click();

        return false;
    };
}());

There may-well be parts of mootools that can simplify the above, but someone who’s proficient with mootools would want to provide some further advice about making use of some of the built-in mootools methods that might help to condense some things there.

Hi Paul,

So sorry I havent been back to you sooner, I sudeenyl came down with the flu and it knocked me side ways.

I’ve lost my thread a bit with this now and in honesty Im struggling a bit, I have used what you put and I dont seem to be able to get it working.

This is what I got, and would you mind advising me a bit further, its very comprehensive but a bit of a step up especially in jscript for me.

Here is the link to the site:

http://www.c6512511.myzen.co.uk/index2.php

Here is the nav as I have it:


<div id="menu">
<div id="menuNav">
<span><a id="left" href="#" title="Home">&nbsp; < &nbsp;</a></span>
<span><a id="link1" href="#" title="Home">&nbsp;home&nbsp;</a></span>
<span><a id="link2" href="#" title="Profile">&nbsp;profile&nbsp;</a></span>
<span><a id="link3" href="#" title="Gallery">&nbsp;gallery&nbsp;</a></span>
<span><a id="link4" href="#" title="Contact">&nbsp;contact&nbsp;</a></span>
<span><a id="right" href="#" title="Home">&nbsp; > &nbsp;</a></span>
</div>
</div>

And have placed the script at the bottom of the page.


(function () {
    var index = 0,
        nav = document.getElementById('menuNav'),
        links = nav.getElementsByTagName('a');

    // change the links from a live nodeList to an array
    links = Array.prototype.slice.call(links);
    links.shift(); // remove the first link - the left arrow
    links.pop(); // remove the last link - left arrow

    document.getElementById('left').onclick = function () {
        index -= 1;
        if (index < 0) {
            index = links.length - 1;
        }
        links[index].click();

        return false;
    };
    document.getElementById('right').onclick = function () {
        index += 1;
        if (index >= links.length) {
            index = 0;
        }
        links[index].click();

        return false;
    };
}());

The 4 buttons thats are there already are being made functionalo by a js file on the server called slider.js, and this is the full code:


window.addEvent("domready",function(){
	$('enviar').addEvent("click",function(e){
		e = new Event(e);
		//stop propagation
		if(!$('response').hasClass("loading")) $('response').addClass("loading");
		$('contacto').setStyle("display","none");
		$('response').setStyle("display","block");				
		var myAjax = new Ajax('mailer.php', {
		   data:$('consulta'),
		   update:$('response'),
		   onComplete:function(){
			 var desaparecer = new Fx.Style('response', 'opacity', {duration:3000});
			  if($('response').hasClass("loading")) $('response').removeClass("loading");
				 desaparecer.start(1,0).addEvent("onComplete",function(){
					 $('response').setStyle("display","none");
					 $('response').setStyle("opacity","1");
					 $('response').empty();
					 $('contacto').setStyle("display","block");
			 	 }); //margin-top is set to 10px immediately
		  	 }
		}).request();
	})
})
//Tooltips
var Tips2 = new Tips($$('.tooltip'), {
	initialize:function(){
		this.fx = new Fx.Style(this.toolTip, 'opacity', {duration: 300, wait: false}).set(0);
	},
	onShow: function(toolTip) {
		this.fx.start(1);
	},
	onHide: function(toolTip) {
		this.fx.start(0);
	}
});

// SiFR
//<![CDATA[
if(typeof sIFR == "function"){
	sIFR.replaceElement(named({sSelector:"h2", sFlashSrc:"sifr/sifr.swf", sColor:"#000000", sLinkColor:"#FFFFFF", sBgColor:"#000000", sHoverColor:"#CCCCCC", sWmode:"transparent",sFlashVars:"textalign=right"}));
};
//]]>

var scroll = new Fx.Scroll('slider', {
	wait: false,
	//duration: 2500,
	duration: 2000,
	offset: {'x': 0, 'y': 0},
	transition: Fx.Transitions.Sine.easeInOut
});

$('link1').addEvent('click', function(event){
	event = new Event(event).stop();
	scroll.toElement('content1');
});

$('link2').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content2');
});

$('link3').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content3');
});

$('link4').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content4');
});

Thanks for your help Paul, but I cant work this out sorry, and would be grateful for a little bit more help.

Things looks to be working just fine at your link of http://www.c6512511.myzen.co.uk/index2.php with the arrows to scroll from one section to another in recent Chrome, Firefox and Internet Explorer web browsers.

Can we get more details on what you are finding a problem with?

Hi Paul,

Thanks for getting back to me. Yes your right its fine in Mozilla, Safari, Opera but I seem to be having trouble with IE7 and IE 8 version 8.0.6001.

I’m sorry that I need to come back Paul, as it works perfectly in the others, which is such a frustrating thing.

Which version of IE are you using?

Is it my computer you think?

No, I think that it’s some “clever” code that I used which isn’t able to work on older web browsers. Be warned, try to stay away from clever code.

The problem code is the Array.prototype.slice.call(links) part, because even though it works on most web browsers, Internet Explorer 8 and older refuses to allow a nodelist to be treated as if it were an array.

So instead, we do it the old fashioned way, with a function to convert things to an array, which we then later on call to convert the links to an array.


(function () {
    function convertToArray(seq) {
        var arr = new Array(seq.length),
            i;
        for (i = 0; i < seq.length; i += 1) {
            arr[i]= seq[i];
        }
        return arr;
    }

    var index = 0,
        nav = document.getElementById('menuNav'),
        links = nav.getElementsByTagName('a');
 
    // change the links from a live nodeList to an array
    links = convertToArray(links);
    links.shift(); // remove the first link - the left arrow
    links.pop(); // remove the last link - left arrow
    ...

Even with the above fix though, the page still doesn’t seem to work. So when you remove all of the scripting that I’m responsible for adding, it seems that clicking on the nav items (home, profile, gallery, contact) that there is something else with the page that is not working with IE8 either.

Hi Paul

So to swap to your code first, I change the code below:


(function () {
    var index = 0,
        nav = document.getElementById('menuNav'),
        links = nav.getElementsByTagName('a');

    // change the links from a live nodeList to an array
    links = Array.prototype.slice.call(links);
    links.shift(); // remove the first link - the left arrow
    links.pop(); // remove the last link - left arrow

To this is it.


(function () {
    function convertToArray(obj) {
        var arr = new Array(seq.length),
            i;
        for (i = 0; i < seq.length; i += 1) {
            arr[i]= seq[i];
        }
        return arr;
    }

    var index = 0,
        nav = document.getElementById('menuNav'),
        links = nav.getElementsByTagName('a');

    // change the links from a live nodeList to an array
    links = convertToArray(links);
    links.shift(); // remove the first link - the left arrow
    links.pop(); // remove the last link - left arrow

And yes by the seems your right, its saying done but with errors in the bottom left, but its not giving too much feedback to work out exactly where it is.

All I can get from it is this:

Line 2 char 2 in the code below, is one of the errors.


window.addEvent("domready",function(){
	$('enviar').addEvent("click",function(e){
		e = new Event(e);
		//stop propagation
		if(!$('response').hasClass("loading")) $('response').addClass("loading");
		$('contacto').setStyle("display","none");
		$('response').setStyle("display","block");				
		var myAjax = new Ajax('mailer.php', {
		   data:$('consulta'),
		   update:$('response'),
		   onComplete:function(){
			 var desaparecer = new Fx.Style('response', 'opacity', {duration:3000});
			  if($('response').hasClass("loading")) $('response').removeClass("loading");
				 desaparecer.start(1,0).addEvent("onComplete",function(){
					 $('response').setStyle("display","none");
					 $('response').setStyle("opacity","1");
					 $('response').empty();
					 $('contacto').setStyle("display","block");
			 	 }); //margin-top is set to 10px immediately
		  	 }
		}).request();
	})
})
//Tooltips
var Tips2 = new Tips($$('.tooltip'), {
	initialize:function(){
		this.fx = new Fx.Style(this.toolTip, 'opacity', {duration: 300, wait: false}).set(0);
	},
	onShow: function(toolTip) {
		this.fx.start(1);
	},
	onHide: function(toolTip) {
		this.fx.start(0);
	}
});

// SiFR
//<![CDATA[
if(typeof sIFR == "function"){
	sIFR.replaceElement(named({sSelector:"h2", sFlashSrc:"sifr/sifr.swf", sColor:"#000000", sLinkColor:"#FFFFFF", sBgColor:"#000000", sHoverColor:"#CCCCCC", sWmode:"transparent",sFlashVars:"textalign=right"}));
};
//]]>

var scroll = new Fx.Scroll('slider', {
	wait: false,
	//duration: 2500,
	duration: 2000,
	offset: {'x': 0, 'y': 0},
	transition: Fx.Transitions.Sine.easeInOut
});

$('link1').addEvent('click', function(event){
	event = new Event(event).stop();
	scroll.toElement('content1');
});

$('link2').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content2');
});

$('link3').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content3');
});

$('link4').addEvent('click', function(event) {
	event = new Event(event).stop();
	scroll.toElement('content4');
});

That looks like this part:

$(‘enviar’)

I changed the code you suggest (the old way) with the code thats there and it didnt work in Mozilla then either, havent checked the others yet, but it didnt work in Mozilla and IE.
I changed it to this:


function convertToArray(obj) {
        var arr = new Array(seq.length),
            i;
        for (i = 0; i < seq.length; i += 1) {
            arr[i]= seq[i];
        }
        return arr;
    }

    var index = 0,
        nav = document.getElementById('menuNav'),
        links = nav.getElementsByTagName('a');

    // change the links from a live nodeList to an array
    links = convertToArray(links);
    links.shift(); // remove the first link - the left arrow
    links.pop(); // remove the last link - left arrow

    document.getElementById('left').onclick = function () {
        index -= 1;
        if (index < 0) {
            index = links.length - 1;
        }
        links[index].click();

        return false;
    };
    document.getElementById('right').onclick = function () {
        index += 1;
        if (index >= links.length) {
            index = 0;
        }
        links[index].click();

        return false;
    };
}());

You probably knew that anyway, just wanted t bring it up just in case it makes a difference

Oh yes, there’s a silly mistake there. The function argument there should not be obj, but should be seq instead.

function convertToArray([s][color="red"]obj[/color][/s][color="green"]seq[/color]) {

I’ll update the initial post with that correction, so that others wanting to use it will have less of an issue with it too

Thank you Paul,

Thats great it works very well.

Cheers