Ecommerce Developer
 
 

Code

Develop a Scrolling 'Merchandiser' Like Gardener's Supply Company

 

Multi-channel merchant Gardener's Supply Company uses an Adobe-Flash-based scrolling ticker to merchandise to site visitors. But in this post, I’ll demonstrate how to get a similar—if not identical—effect using JavaScript and CSS.

Gardener's scrolling "merchandiser," as I am calling it, is positioned at the top of every page on the site, smoothly offering shoppers links to gardening tips, catalog request forms, and specific products that can be added directly to the "shopping basket."

shows the merchandiser at the top of the Gardener's page

The merchandiser also exhibits two specific behaviors that I want to emulate.

First, it is circular, meaning that it does not simply display a list of items and then slide all the way back to the top and start over again like the carriage return on an old-fashioned typewriter. Rather, it seems to move through an endless, albeit repetitive, list, never cycling back to the top.

Second, as the merchandiser slides up and out of view, more of each image is shown. Specifically, notice in the screen capture below that we see only a portion of the catalog graphic in the merchandiser.

shows an example of the merchandiser

When the merchandiser slides up, the bottom portion of the catalog graphic becomes visible as seen in the screen capture below.

shows a detail of the merchandiser including the bottom of the catalog image

As I mentioned above, I want my example to behave the same way as the Gardener's merchandiser.

Merchandiser Video

Step No. 1: HTML

As always, I need to start with some basic HTML markup. In this case, I am going to imagine that I am selling accessories to the awesome Icon CJSB, which is a new take on the classic Willys Jeep. As such, I have an unordered list containing several images promoting possible Icon add-ons.

I have also created an image to serve as my header, since like the Gardener's Supply Company example, I want my merchandiser to reside at the top of the page.

<!doctype html>
<html lang="en">
<head>
	<title>The Scrolling Merchandiser</title>
	<link type="text/css" rel="stylesheet" href="style.css">
	<link rel="icon" type="image/png" href="favicon.png">
</head>
<body>
	<div id="wrapper">	
		<div id="merchandiser">
			<ul id="merch-cont">
				<li id="1"><a href="#"><img src="merch-1-bumper-sticker.png" alt="Bumper Stickers" /></a></li>
				<li id="2"><a href="#"><img src="merch-2-mirror-danglies.png" alt="Mirror Danglies" /></a></li>
				<li id="3"><a href="#"><img src="merch-3-cia-gps.png" alt="CIA GPS" /></a></li>
				<li id="4"><a href="#"><img src="merch-4-m60.png" alt="Rear Mounted M60s" /></a></li>
			</ul>
		</div>
		<div id="header">
			<img src="header-graphic.png" alt="header graphic"/>
		</div>
	
		<p>This is an <em>Ecommerce Developer</em> article DEMO. The Icon image is used under the auspice of fair editorial use.</p>
	</div><!--end wrapper-->
	<script src="js.js"></script>
</body>
</html>

Before adding style to hide a portion of the merchandising all four banners can be seen above the header.

In the HTML, note two id attributes.

The first of these is "merch-cont." It is associated with the ul tag that contains the images I will be manipulating. This id will be very important when it comes to writing my JavaScript.

Next, notice that I have given each list item a numerical id value. This is in no way required, but if you watch the video associated with this tutorial, you will see that I used them to help explain how a particular JavaScript function (appendChild()) works.

Step No. 2: CSS

I also wrote a relatively short cascading style sheet that manages three important tasks associated with building my merchandiser.

First, it removes all of the associated elements' margins and padding so that my merchandiser images will fit snuggly against the top of the page and the header graphic.

Second, the style sheet limits the "merchandiser" div to a height of 45px, somewhat less than the 75px height of each image. This way, there will be a little more of the image that shows as it slides up, just like Gardener's catalog graphic described above.

Third, the style sheet also sets the unordered list's position to relative so that I can more easily reposition it.

body {margin: 0;}
#wrapper {margin: 0 auto; padding: 0; width: 960px;}
#merchandiser { height: 45px; overflow: hidden;}
#merchandiser ul {position: relative; top: 0; margin: 0; padding: 0; list-style: none;}
#merchandiser li {margin: 0; padding: 0; height: 75px;}
#merchandiser li img {margin: 0; padding: 0; border: none;}

With the style sheet applied, a little more than half of the first image shows.

Step No. 3: Identify "merch-cont"

The JavaScript for my merchandiser is going to manipulate the unordered list in two ways. First, repositioning it on the page and then reordering the list items. For both of these tasks, it will need to get the <ul>, which has an id of "merch-cont," so I start by creating a variable to hold "merch-cont."

var merchCont = document.getElementById('merch-cont');

Because this variable was created outside of a function, it is global in scope and any function that I write may use it.

Step No. 4: Establish a "top" Attribute

Even though I set a "top" style attribute for the unordered list in my style sheet, that attribute is not recognized in the document object model (DOM), so if I stated my first function by trying to manipulate "top," I would throw an error saying that "top" is undefined. To avoid this error, I simply check to learn if "top" exists yet. If it doesn't, I establish it.

function merchandiser()
{
	if(!merchCont.style.top) merchCont.style.top = 0;	

Step No. 5: Establish the List's Current and Target Positions

Next, I need to know where on the page the list is now, and I need to know where I want it to end up, so I have my function check for the current position, and then take the current position and subtract 75, which is the height of each merchandising image in pixels. Finally, it passes the target position to another function named "merchSlide."

	var topNow = parseInt(merchCont.style.top);
	var topTarg = topNow - 75;
	merchSlide(topTarg);	
	
}

Step No. 6: Incrementally Slide the List Upward

In order for merchSlide() to reposition the list, it needs to do a quick test for the list's position. Since merchSlide() will run about 75 times for every time that merchandiser() is run, I do not want to use the "current" position captured in the last step.

Notice, that thanks to a timer, merchSlide() incrementally adds a single pixel to the unordered list's "top" style attribute until the integer value of "top" is the same as the target position calculated in the last step. Finally, remember that "topTarg" from the last step is now held in the variable "targ."

function merchSlide(targ)
{
	var currentTop = parseInt(merchCont.style.top);
	if(currentTop > targ)
	{
		merchCont.style.top = (currentTop - 1) + 'px';		
		var slideTimer = setTimeout(function(){merchSlide(targ)}, 10);
		
	}

If we ran the JavaScript now, the images would gracefully slide up the page one spot. If I kept running it they would each move up and out of view. Unfortunately, they wouldn't stop when the last image moved out of view, rather they would continue creeping into imaginary space above the browser forever. From the user's perspective, four images would have been displayed and then nothing. So I need to do something more. I need to make the list circular.

Step No. 7: Make the List Circular

When an image moves up and out of view, the integer value of its "current" position will be exactly equal to the target position I established for it. So when it reaches that moment of unity, I ask my function to take the image that just vanished from view and add it to the bottom of list, effectively making the list infinite and circular.

Of course in JavaScript this procedure takes a couple of steps. I must identify the various list items, store them as a variable ("merchList"), and then literally reorder the list so that the first item becomes the last. Finally, I must also add 75 to the list's "top" attribute to compensate for the item I repositioned.

The heavy lifting in this part of the function is done with appendChild(), which when used with a value of the first child, effectively reorders the list—the first becomes last.

else if(currentTop == targ)
	{
		var merchList = merchCont.children;
		var merchAdd = merchList[0];
		merchCont.appendChild(merchAdd);
		var topNow = parseInt(merchCont.style.top);
		merchCont.style.top = (topNow + 75) + 'px';
		
	}
	
}

Step No. 8: Do It All Again

As is, this JavaScript would run once and quit, so I establish an interval timer that starts the entire process every 3,000 milliseconds.

setInterval('merchandiser()', 3000);

Summing Up

That's it. I now have a merchandiser that functions exactly like the Gardener's merchandiser. I am going to give you a look at the complete JavaScript, so that you can see how everything came together. You can also check out the online demo.

As is often the case with a JavaScript, there may be way to refactor it to improve performance. If you come up with a suggestion, I would love to see it in the comments below.

var merchCont = document.getElementById('merch-cont');

function merchandiser()
{
	if(!merchCont.style.top) merchCont.style.top = 0;	
	var topNow = parseInt(merchCont.style.top);
	var topTarg = topNow - 75;
	merchSlide(topTarg);	
	
}

function merchSlide(targ)
{
	var currentTop = parseInt(merchCont.style.top);
	if(currentTop > targ)
	{
		merchCont.style.top = (currentTop - 1) + 'px';		
		var slideTimer = setTimeout(function(){merchSlide(targ)}, 10);
		
	}
	else if(currentTop == targ)
	{
		var merchList = merchCont.children;
		var merchAdd = merchList[0];
		merchCont.appendChild(merchAdd);
		var topNow = parseInt(merchCont.style.top);
		merchCont.style.top = (topNow + 75) + 'px';
		
	}
	
}

setInterval('merchandiser()', 3000);

Related Articles

2 Comments

Rss-sm