Introduction
Web banners are an essential part of any web site. Advertisements, news, product announcements and any other type of information can be shown on a clickable banner. Two major "types" of banners are still-image banners (where a simple image is shown rudimentary animation can be made with GIFs) and Flash banners. First ones are simple, fast, cheap and not very nice-looking, especially when it comes to dynamically changing the banner. Flash banners are awesome when it comes to visual aspect, but are quite costly to create and (sometimes) are great traffic consumers. Both share one more disadvantage: they are quite hard to install without 3rd-party banner engines.
This article presents the "Fading Banner" script, which is a lightweight (less that 6 Kb) but quite functional ad (image + link) rotation engine, written in JavaScript. It's purposes are:
- create banner placeholders
- arrange images into "batches" - groups of images that are shown simultaneously
- perform periodic batch changes in a specified time interval
- perform these changes in a neat-looking, "fade-in, fade-out" manner
As you can see, the primary goal of this script is to aid you in rotating simple image ads on your site. The secondary goal is to overcome the dumb look and feel of image changes, which is the main annoyance of still JPGs compared to Flash. The script is perfectly compatible with all mainstream browsers: Mozilla/Firefox 2, Opera 9, MS IE 6/7.
Installation of the Fading Banner requires a casual knowledge of HTML and JavaScript; to be able to change or fine-tune this script, you must be familiar with some advanced JavaScript topics (such as closures).
Fading Banner is an open-source script distributed under the zlib/libpng license.
Setup
Follow these steps:
- At first, run the demo (banner-test.html file in the source archive) and choose the script type you wish to install. Five modifications are available:
- fb.js - all images in a batch emerge simultaneously and fade-out simultaneously, next batch shows up when previous fades out
- fb-q.js - images emerge one after another ("queued"), and fade-out simultaneously
- fb-qq.js - images emerge one after another, and fade-out one after another, in the order they emerged
- fb-qqr.js - images emerge one after another, and fade-out one after another, in the reverse order of which they emerged
- fb-c.js - all images in a batch emerge simultaneously and fade-out simultaneously, banners cross-fade.
- Include the chosen script file into your HTML page:
<html>
<head>
<script type="text/javascript" src="fb.js"></script>
...
- In the
body
of your page, create a div
element that will be the "parent" of the banner. This div
must have an id
attribute set:
<html>
...
<body>
<div id="parent1" style="..."></div>
Note: it is recommended that you place an img
element as a child to the above div
element; this image will be shown if a user has JavaScript turned off. If JavaScript is turned on, this image will be replaced by the dynamic banner.
- In the page's
head
section, create a script block that will contain a banner setup function.
<html>
<head>
<script type="text/javascript" src="fb.js"></script>
<script type="text/javascript">
</script>
- Create a banner setup function. It will look like:
<html>
<head>
<script type="text/javascript" src="fb.js"></script>
<script type="text/javascript">
function bannerSetup()
{
var fb_h = new FadingBanner("parent1", "horizontal", 390, 90,
"#FF9900", 5000);
fb_h.add(0, "h-api-competition.jpg", 130, 90,
"http://www.codeproject.com/Feature/Vista/");
fb_h.add(0, "h-vista-gadgets.jpg", 130, 90,
"http://www.codeproject.com/Feature/Gadgets/");
fb_h.add(0, "h-interview.jpg", 130, 90,
"http://www.codeproject.com/interview/mattpietrek13sep2000.asp");
fb_h.add(1, "h-codeproject.jpg", 390, 90,
"http://www.codeproject.com/");
fb_h.start();
}
</script>
- Bind your banner setup function to any desired event (for example, to
body
's onload
):
<html>
...
<body onload="bannerSetup()">
...
- All of the above assumes that you have prepared the images you wish to show as banners. Sample images are placed in the source archive.
API
FadingBanner
object (and all its modifications) has a relatively simple API:
- Constructor:
var fb = new FadingBanner("parent-id",
"horizontal",
390,
90,
"#FFF",
5000);
add
method - add image to a batch:
fb.add(0,
"image.jpg",
130,
90,
"http://link.com");
start
method - start banner operation:
fb.start();
Inner workings
FadingBanner
has the following life cycle:
- Creation is simple - a single
div
is attached to the parent:
_construct: function(width, height, bg)
{
var banner = document.createElement("DIV");
var bs = banner.style;
bs.position = "relative";
bs.top = "0px";
bs.left = "0px";
bs.width = width + "px";
bs.height = height + "px";
bs.display = "none";
bs.backgroundColor = bg || "#FFF";
this.root = this.parent.appendChild(banner);
return this;
},
- Starting banner's operation fires the
_showbatch
method, that switches the display
attribute of each image in the current batch to block
and starts the fade-in procedure:
_showbatch: function()
{
var cur = this.current, l = this.images[cur].length;
for(var i = 0; i < l; i++)
{
var img = this.images[cur][i];
img.obj.style.display = "block";
this._fade(img.obj.firstChild.id, 100, 50, 10, (i == (l - 1) ?
this._callLater(this, "_next") : null));
}
},
_fade
method is the key to image "switching":
_fade: function(id, destOp, rate, delta, callback)
{
var obj = document.getElementById(id);
if(obj.timer) clearTimeout(obj.timer);
var curOp = obj.filters ? obj.filters.alpha.opacity : (
obj.style.opacity * 100.0);
var direction = (curOp <= destOp) ? 1 : -1;
delta = Math.min(direction * (destOp - curOp), delta);
curOp += direction * delta;
if(obj.filters)
obj.filters.alpha.opacity = curOp;
else
obj.style.opacity = curOp / 100.0;
if(curOp != destOp)
obj.timer = setTimeout(function()
{ FadingBanner.prototype._fade(id, destOp, rate, delta, callback); },
rate);
else
if(callback) callback();
}
- After the current batch has appeared,
_next
method is called. It sleeps for timeout
milliseconds, then starts to switch the current batch off:
_next: function()
{
var _out = function(_obj)
{
...
var cur = _obj.current, l = _obj.images[cur].length;
for(var i = 0; i < l; i++)
{
var img = _obj.images[cur][i];
_obj._fade(img.obj.firstChild.id, 0, 50, 10, (i == (l - 1) ?
function() { _go(_obj); } : null));
}
}
setTimeout(this._callLater(null, _out, this), this.timeout);
},
- After the current batch has disappeared, the next batch is ready to be shown:
_next: function()
{
...
var _go = function(__obj)
{
var cur = __obj.current, l = __obj.images[cur].length;
for(var i = 0; i < l; i++)
__obj.images[cur][i].obj.style.display = "none";
l = __obj.batches.length;
for(i = 0; i < l; i++)
if(__obj.current == __obj.batches[i])
break;
__obj.current = (i == l - 1) ? __obj.batches[0] :
__obj.batches[i + 1];
__obj._showbatch();
}
...
},
_callLater
method, that appeared in the code above, does the magic with closures. In short, it allows us to provide parameters for methods for later execution:
_callLater: function(obj, func, param)
{
param = param || null;
return obj ? (function() { obj[func](param); }) : (function() {
func(param); });
},
Interested?
Usage of the Fading Banner is not limited to web banners; it is up to your imagination, programming and artistic skills to fit this script to any other web site application.
This project is in its infancy; it will be developed and expanded. If you wish to help - please vote for this article (and/or any other articles of mine). It is the best help I can dream of. For other means of help, please see the donate.txt file in the source archive.
Thank you.
History
- April 4th 2007: initial release;
- April 26th 2007: cross-fader script, updated article.
Dmitry Khudorozhkov began programming (and gaming) with his ZX Spectrum in 1989. Having seen and used all IBM PCs from early XT to the latest x64 machines, now Dmitry is a freelance programmer, living in Moscow, Russia. He is a graduate of the Moscow State Institute of Electronics and Mathematics (Applied Mathematics).
He is proficient in:
- C/C++ - more that 9 years of experience. Pure Win32 API/MFC desktop programming, networking (BSD/Win sockets), databases (primarily
SQLite), OpenGL;
- JavaScript - more that 6 years of experience. Client-side components, AJAX, jQuery installation and customization;
- Firefox extensions (immediatelly ready for addons.mozilla.org reviewing) and Greasemonkey scripts. As an example of extensions Dmitry made you can search for FoxyPrices or WhatBird Winged Toolbar;
- XML and it's applications (last 2 years): XSLT (+ XPath), XSD, SVG, VML;
- ASP.NET/C# (webservices mostly);
Also familiar with (= entry level):
- PHP;
- HTML/CSS slicing.
Trying to learn:
- Ruby/Ruby-on-Rails;
- Czech language.
If you wish to express your opinion, ask a question or report a bug, feel free to e-mail:
dmitrykhudorozhkov@yahoo.com. Job offers are warmly welcome.
If you wish to donate - and, by doing so, support further development - you can
send Dmitry a bonus through the Rentacoder.com service (registration is free, Paypal is supported). Russian users can donate to the Yandex.Money account 41001132298694.
-