View Full Version : Sidescrolling Image Gallery trouble

06-24-2009, 06:44 AM
Hi guys, new to these forums, let's see if I can sculpt this post so that I include everything I'm supposed to.

So, I'm interested in making a side scrolling gallery that implements some smooth scrolling. An arrow would be on each side, where the "right" arrow would have the image slide off to the left of the screen, and the next image slide in from the right. Basically like Hulu.com (http://hulu.com) 's front page.

Trying to adapt smooth scrolling code from HERE (http://www.itnewb.com/v/Creating-the-Smooth-Scroll-Effect-with-JavaScript). This code works for vertical scrolling, trying to apply it horizontally and inside my divs.

The buttons aren't yet equipped to automatically jump to the next image. I'm trying to get any scrolling at all, so jumping between div 1 and 6 is all I'm trying to get working.

Obviously, it's not working right now, here's what I have so far. Would appreciate the help!

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Side Scrolling Gallery</title>

<style type="text/css">
html, body { margin: 0px; padding: 0px; }
#scroller { overflow: hidden; }
#gallery { white-space: nowrap; display:table; }
* html #gallery { display:inline; }
#gallery div.box { width:380px; padding:10px; border:1px dotted #666; display:table-cell; }
* html #gallery div.box { display:inline-block; width:380px; }
img { }
h4 { margin:0; text-align:center; }

<script type="text/javascript">

function currentXPosition() {
if (getElementById("scroller").pageXOffset)
return getElementById("scroller").pageXOffset;
if (document.getElementById("scroller") && document.getElementById("scroller").scrollLeft)
return document.getElementById("scroller").scrollLeft;
if (document.body.scrollLeft)
return document.getElementById("scroller").scrollLeft;
return 0;
function elmXPosition(eID) {
var elm = document.getElementById(eID);
var x = elm.offsetLeft;
var node = elm;
while (node.offsetParent && node.offsetParent != document.body) {
node = node.offsetParent;
x += node.offsetLeft;
} return x;
function smoothScroll(eID) {
var startX = currentXPosition();
var stopX = elmXPosition(eID);
var distance = stopX > startX ? stopX - startX : startX - stopX;
if (distance < 100) {
getElementById("scroller").scrollTo(stopX,0); return;
var speed = Math.round(distance / 100);
var step = Math.round(distance / 25);
var leapX = stopX > startX ? startX + step : startX - step;
var timer = 0;
if (stopX > startX) {
for ( var i=startX; i<stopX; i+=step ) {
setTimeout("getElementById("scroller").scrollTo("+leapX+",0)", timer * speed);
leapX += step; if (leapX > stopX) leapX = stopX; timer++;
} return;
for ( var i=startX; i>stopX; i-=step ) {
setTimeout("getElementById("scroller").scrollTo("+leapX+",0)", timer * speed);
leapX -= step; if (leapX < stopX) leapX = stopX; timer++;



<!-- Buttons for Testing -->
<input type="button" value="1" onClick="smoothScroll('1');">
<input type="button" value="6" onClick="smoothScroll('6');">

<!-- Can't get links to work either -->
<a href="#" onclick="smoothScroll('1'); return false">Jump to 1</a>
<a href="#" onclick="smoothScroll('6'); return false">Jump to 6</a>

<div id="scroller" name="scroller">
<div id="gallery" name="gallery">

<div class="box" id="0">
<img src="/images/someimage.jpg" width="380" height="495" /><br />

<div class="box" id="1">
<img src="/images/anotherimage.jpg" width="380" height="495" /><br />
<h4>another caption</h4></div>

<div class="box" id="2">
<img src="/images/dfgh.jpg" width="380" height="495" /><br />
<h4>what what</h4></div>

<div class="box" id="3">
<img src="/images/img.jpg" width="380" height="495" /><br />

<div class="box" id="4">
<img src="/images/something.jpg" width="380" height="495" /><br />

<div class="box" id="5">
<img src="/images/blah.jpg" width="380" height="495" /><br />

<div class="box" id="6">
<img src="/images/sky.jpg" width="380" height="495" /><br />

<div class="box" id="7">
<img src="/images/fghjk.jpg" width="380" height="495" /><br />



06-24-2009, 07:30 AM
I'm still trying to figure it out... but I think the code I gave is butchered.

Sounds like I can't use scrollTo in my div, have to use scrollLeft instead, but I'm not quite sure how.

And I'm not even sure I'm finding positions correctly. Not sure if I should be finding the position relative to the div scroller container or the entire page.

06-24-2009, 01:48 PM
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<style type="text/css">
#tst {
position:relative;overflow:hidden;width:500px;height:300px;border:solid black 1px;

#tst .frame {

#tst .pages {

#tst .page {
position:relative;width:40px;height:20px;background-Color:#FFCC66;border:solid black 1px;;float:left;margin-Left:5px;

.pageon {
position:relative;width:40px;height:20px;background-Color:#FF3333;border:solid black 1px;;float:left;margin-Left:5px;

#tst .button {
position:absolute;z-Index:2;left:10px;top:100px;width:30px;height:40px;background-Color:#CCFFFF;border:solid black 1px;
<script type="text/javascript">
// Basic Element Animator (14-May-2009)
// by Vic Phillips http://www.vicsjavascripts.org.uk

// To progressively change the Left, Top, Width, Height or Opacity of an element over a specified period of time.
// With the ability to scale the effect time on specified minimum/maximum values
// and with three types of progression 'sin' and 'cos' and liner and an optional 'Bounce'.

// **** Application Notes

// **** The HTML Code
// when moving an element the inline or class rule style position of the element should be assigned as
// 'position:relative;' or 'position:absolute;'.
// The element would normally be assigned a unique ID name.

// **** Executing the Effect(Script)
// The effect is executed by an event call to function 'zxcBAnimator('width#',document.getElementById('tst'),10,800,5000,[10,800],'sin');'
// where:
// parameter 0 = the mode(see Note 2). (string)
// parameter 1 = the unique ID name or element object. (string or element object)
// parameter 2 = the start position of the effect. (digits, for opacity minimum 0, maximum 100)
// parameter 3 = the finish position of the effect. (digits, for opacity minimum 0, maximum 100)
// parameter 4 = (optional) period of time between the start and finish of the effect in milliseconds. (digits or defaults to 2000 milliSeconds)
// parameter 5 = (optional) to scale the effect time on a specified minimum/maximum. (array, see Note 5)
// field 0 the minimum. (digits)
// field 1 the maximum. (digits)
// parameter 6 = (optional) the type of progression, 'sin', 'cos' or 'liner'. (string, default = 'liner')
// 'sin' progression starts fast and ends slow.
// 'cos' progression starts slow and ends fast.
// Note 1: The default units(excepting opacity) are 'px'.
// Note 2: Examples modes: 'left', 'top', 'width', 'height', 'opacity.
// For hyphenated modes, the first character after the hyphen must be upper case, all others lower case.
// Note 3: To 'toggle' the effect include '#' in parameter 0.
// The first call will set the toggle parameters.
// Subsequent calls with '#' in parameter 0 and the same start and finish parameters will 'toggle' the effect.
// Note 4: The function may be re-executed with a different set of parameters (start/finish time or period)
// whenever required, say from an onclick/mouseover/out event.
// The period parameter will be retained unless re-specified.
// Note 5: parameter 5 is of particular use when re-calling the effect
// in mid travel to retain an constant rate of progression.
// Note 6: parameters 2 and 3 must be different values to execute the script.

// **** Advanced Applications
// Calling function 'zxcBAnimator' returns the instance of the script,
// this may be assigned to a variable and used to access the current value of the effect or to control the effect.
// alternatively the script instance by elementobject[mode.replace(/\W/g,'')+'oop'];
// where mode is parameter 0 of the initial call.
// An array storing the current, start and finish values of the element effect may be accessed
// from the element [instance].data as fields 0, 1 and 2 respectively where [instance] is the instance of the script.
// Once initialised the effect may be updated by calling function
// [instance].update([100,200])
// where:
// parameter 0 = an array defining the start and finish values. (array)
// field[0] =the start position of the effect. (digits, for opacity minimum 0, maximum 100)
// field[0] = the finish position of the effect. (digits, for opacity minimum 0, maximum 100)
// parameter 1 = (optional) period of time between the start and finish of the effect in milliseconds. (digits or defaults to 2000 milliSeconds)
// parameter 2 = (optional) to scale the effect time on a specified minimum/maximum. (array, see Note 5)
// field 0 the minimum. (digits)
// field 1 the maximum. (digits)
// parameter 3 = (optional) the type of progression, 'sin', 'cos' or 'liner'. (string, default = 'liner')
// 'sin' progression starts fast and ends slow.
// 'cos' progression starts slow and ends fast.
// ** Bounce
// A 'bounce' effect may be applied by assigning the script instance property 'Bounce' an array
// defining the 'bounce' properties.
// e.g.
// [instance].Bounce=[100,90,4,200];
// where:
// field[0] = the 'bounce' maximum. (digits)
// field[1] = the 'bounce' minimum. (digits)
// field[2] = the number of bounces. (digits)
// field[3] = the 'bounce' duration. (digits)

// **** General
// Function names are prefixed with 'zxc' to minimise conflicts with other JavaScripts.
// These characters may be changed to characters of choice using global find and replace.
// The Functional Code, about 2.41K with 'bounce' and 'opacity' or 1.97K without is best as an External JavaScript.
// Tested with IE7 and Mozilla FireFox on a PC.

// **** Functional Code - NO NEED to Change

function zxcBAnimator(mde,obj,srt,fin,ms,scale,curve){
if (typeof(obj)=='string'){ obj=document.getElementById(obj); }
if (!obj) return;
var oop=obj[mde.replace(/\W/g,'')+'oop'];
if (oop){
if (oop.srtfin[0]==srt&&oop.srtfin[1]==fin&&mde.match('#')) oop.update([oop.data[0],(oop.srtfin[0]==oop.data[2])?fin:srt],ms,scale,curve);
else oop.update([srt,fin],ms,scale,curve);
else oop=obj[mde.replace(/\W/g,'')+'oop']=new zxcBAnimatorOOP(mde,obj,srt,fin,ms,scale,curve);
return oop;

function zxcBAnimatorOOP(mde,obj,srt,fin,ms,scale,curve){

this.srttime=new Date().getTime();

this.ms=new Date().getTime()-this.srttime;
if (this.ms<this.mS) this.to=setTimeout(function(oop){return function(){oop.cng();}}(this),10);
else {
if (this.Bounce&&this.Bounce[2]>0) this.bounce();

if (isFinite(this.data[0])){
if (this.mde!='left'&&this.mde!='top'&&this.data[0]<0) this.data[0]=0;
if (this.mde!='opacity') this.obj.style[this.mde]=this.data[0]+'px';
else zxcOpacity(this.obj,this.data[0]);

if (this.Bounce[2]%2==0)

function zxcOpacity(obj,opc){
if (opc<0||opc>100) return;


<script type="text/javascript">

function zxcSlider(id,fcls,bcls,pcls,oncls,ms){
var obj=document.getElementById(id),frames=zxcByClassName(fcls,obj),pages=zxcByClassName(pcls,obj),buts= zxcByClassName(bcls,obj);
for (var z0=0;z0<frames.length;z0++){
if (pages[0]&&z0>0) zxcES(pages[0].cloneNode(true),{},pages[0].parentNode);
for (var z1=0;z1<pages.length;z1++){
if (this.frames[0][1]) this.frames[0][1].className=this.pagecls[1];
for (var z2=0;z2<buts.length;z2++){

if (nu!=this.cnt&&this.frames[this.cnt][0].data[0]==this.mmm[0]){
if (this.frames[this.cnt][1]) this.frames[this.cnt][1].className=this.pagecls[0];
if (this.frames[nu][1]) this.frames[nu][1].className=this.pagecls[1];

if (this.frames[this.cnt][0].data[0]==this.mmm[0]){
var nu=this.cnt+ud;

var oop=this;
if (o.addEventListener) o.addEventListener(t,function(e){ return oop[f](p);}, false);
else if (o.attachEvent) o.attachEvent('on'+t,function(e){ return oop[f](p); });
else {
var prev=o['on'+t];
if (prev) o['on'+t]=function(e){ prev(e); oop[f](p); };
else o['on'+t]=o[f];

function zxcES(ele,style,par,txt){
if (typeof(ele)=='string') ele=document.createElement(ele);
for (key in style) ele.style[key]=style[key];
if (par) par.appendChild(ele);
if (txt) ele.appendChild(document.createTextNode(txt));
return ele;

function zxcByClassName(nme,el,tag){
if (typeof(el)=='string') el=document.getElementById(el);
for (var tag=tag||'*',reg=new RegExp('\\b'+nme+'\\b'),els=el.getElementsByTagName(tag),ary=[],z0=0; z0<els.length;z0++){
if(reg.test(els[z0].className)) ary.push(els[z0]);
return ary;


<body onload="S=new zxcSlider('tst','frame','button','page','pageon',1000);" >
<div id="tst">

<div class="frame">0</div>
<div class="frame">1</div>
<div class="frame">2</div>

<div class="pages">
<div class="page"></div>

<div class="button"></div>
<div class="button" style="left:460px;" ></div>




06-24-2009, 03:59 PM
That's fantastic, thanks!

06-24-2009, 05:28 PM
Any chance you could step through the zxcSlider function and explain what's going on?