Introduction
I'm basically in the marketing business, and Display Advertising is key to marketing success. What's even better is being able to squeeze
in 5 to 10 display ads or marketing messages in the same amount of space and change them every 5 seconds or so, and replay it over and over,
or just run it in a loop until the user says no more.
So if you are a programmer and you are trying to make a slideshow or something
to show several items of content in the same place, then you are participating in some form of marketing.
Background
I took over a website project for a customer and spent days fixing all the errors. I ran across this jQuery script for a slideshow in the project, but it had issues with timing and looping. I guess the previous vendor just copied and pasted the code from a Wordpress plug-in into the project without knowing how it operated.
After spending a couple of hours trying to fix it, I thought maybe I would just look for something already written just to get by with, but really found nothing that was easy to setup and deploy. So I started from scratch and wrote my own.
The biggest issue is being easy to setup, controlling the timing of animations, and how to detect when the animation was really finished, to start again. I did some research on the jQuery website on the
.animation()
call, and ended up running various tests for about an hour to test the complete callback function. Other slideshow scripts used a loop counter to track each slide, but when JavaScript runs, it goes full bore until complete, making the counter completely useless because it finished before all the delay times completed.
So the question is, how do we determine when all the animations are complete? Do we use elapsed time?
No, because the script would stop running before the elapsed time was complete.
We can't use the counter in the loop because that would complete as well before the animations are finished running. So we'll use the length of the total amount of elements in the container then. When we reach the calculated length of the combined total of element widths, that's the end, so reverse or loop.
Do something. This value will always be available because it's written to the DOM. One way to look at it is that
JavaScript alters the DOM but the DOM holds the values until its changed again by
JavaScript.
The code takes all the div elements in the master film container and reorganizes them in the DOM, creating a long filmstrip of cells, just like film. It then programs all the CSS needed, so no CSS file is required, and trashes the code on the webpage and inserts the new code. Then the loop function just runs the film left to right, 1 frame at a time, and rewinds the film and starts again.
This is the horizontal version, I suppose I could make it go vertical as well, but let's see how this works first.
Using the code
Make a reference to jQuery, I used version 1.8.2 but I think
earlier versions should work fine. Then make a new file, register it on your webpage in the header element, and copy the code below to the file. The
HTML code block below is just a simple div container, with five more div elements inside it.
You can create new HTML content now, or just use my content and replace the image files with something in your project, to make sure it works first.
Then you can go back and edit the child elements.
The example content below is a container that is 980px by 250px, with images that are the same size.
This is an explanation of the var
s in the run script.
// Some Preset Values,
This is the width, height of the filmstrip. The other two are the ease time and view time.
function run_DisplayAdvertising_Horizontal(obj, cW, vW, cC, vT, eT) {
Don't mess or modify the code above unless your really good at jQuery. They are abbreviated for a reason, but the values are as follows:
-
obj
- Filmstrip container cW
- filmstrip total length-
vW
- cell or frame width cC
- total amount of framesvT
- view time eT
- ease time -
fsRewind
- is a calculation that auto sets the rewind time, to product a smooth result.
$(document).ready(function () {
load_DisplayAdvertising_Horizontal();
});
function load_DisplayAdvertising_Horizontal() {
var view_Width = 980;
var view_Height = 250;
var view_Time = 4000;
var ease_Time = 1400;
var child_Count = parseInt($('[id*="_slide_container"]').children().length);
$('[id*="_slide_container"]').css({
"position": "relative",
"width": view_Width + "px",
"height": view_Height + "px",
"overflow": "hidden"
});
var fsWidth = 0;
var fsHeight = 0;
$('[id*="_slide_container"]').find("._slide_child").css({
"display": "inline",
"position": "relative",
"float": "left",
"top": "0px",
"left": "0px"
}).each(function (index) {
fsWidth = fsWidth + parseInt($(this).css("width"));
if (fsHeight > parseInt($(this).css("height"))) {
fsHeight = parseInt($(this).css("height"));
}
})
var div_filmStrip = document.createElement("div");
div_filmStrip.style.textAlign = "left";
div_filmStrip.style.width = fsWidth + "px";
div_filmStrip.style.height = fsHeight + "px";
div_filmStrip.style.position = "relative";
div_filmStrip.style.left = "0px";
div_filmStrip.style.top = "0px";
var temp_InnerHTML = $('[id*="_slide_container"]').html();
div_filmStrip.innerHTML = temp_InnerHTML;
$('[id*="_slide_container"]').empty();
$('[id*="_slide_container"]').append(div_filmStrip);
run_DisplayAdvertising_Horizontal(
div_filmStrip,
fsWidth,
view_Width,
child_Count,
view_Time,
ease_Time
);
}
function run_DisplayAdvertising_Horizontal(obj, cW, vW, cC, vT, eT) {
if (cC > 0)
{
var fsWidth = parseInt(cW - vW);
var fsRewind = parseInt(vT / cC);
for (var i = 0; i < cC-1; i++)
{
$(obj).delay(vT).animate({
left: '-=' + vW
}, eT, "linear", function () {
var fsPosition = parseInt($(obj).css("left"));
if (fsPosition == -fsWidth) {
$(obj).delay(vT).animate({
left: '0px'
}, fsRewind, "linear", function () {
run_DisplayAdvertising_Horizontal(obj, cW, vW, cC, vT, eT);
});
}
});
}
}
}
function displayAdvertising_Collapse() {
var slideState = $('[id*="_slide_container"]').css("display");
if (slideState == "block")
{
$('[id*="_slide_container"]').slideUp('fast');
$('[id*="_lbl_SS_Collapse"]').text("show display advertising");
}
else
{
$('[id*="_slide_container"]').slideDown('fast');
$('[id*="_lbl_SS_Collapse"]').text("hide display advertising");
}
}
This is the HTML part of the program. The master container has an ID of _slide_container
which is needed so the script can detect the container. The child container has a class called
_slide_child
. This is needed so the child elements can be picked up and modified by the script.
Other than that, you can place anything you want in the child container.
You can create a stylesheet and a class called
_slide_child
if your prefer to style over there instead of direct styling on the web form. Right now I just have an image file in the film cell
"_slide_child
". You can write more complex HTML and place in the film cell. The images should show up for testing to make sure it works,
before you modify the contents with your messages.
<div id="_slide_container"
style="width: 980px; height: 254px; text-align: center; margin: 0px auto; display: block;">
<div id="slideChild_0" class="_slide_child" style="width: 980px; height: 250px; display: block;">
<asp:Image ID="img_slideshow_child_0" runat="server"
ImageUrl="http://www.redcopper.net/EN-US/images/SlideShows/SS_StrategyPlanning_980x250.png" />
</div>
<div id="slideChild_1" class="_slide_child" style="width: 980px; height: 250px; display: none;">
<asp:Image ID="img_slideshow_child_1" runat="server"
ImageUrl="http://www.redcopper.net/EN-US/images/SlideShows/SS_WebDesign_980x250.png" />
</div>
<div id="slideChild_2" class="_slide_child" style="width: 980px; height: 250px; display: none;">
<asp:Image ID="img_slideshow_child_2" runat="server"
ImageUrl="http://www.redcopper.net/EN-US/images/SlideShows/SS_WebDevelopment_980x250.png" />
</div>
<div id="slideChild_3" class="_slide_child" style="width: 980px; height: 250px; display: none;">
<asp:Image ID="img_slideshow_child_3" runat="server"
ImageUrl="http://www.redcopper.net/EN-US/images/SlideShows/SS_HKB_Project_2_980x250.png" />
</div>
<div id="slideChild_4" class="_slide_child" style="width: 980px; height: 250px; display: none;">
<asp:Image ID="img_slideshow_child_4" runat="server"
ImageUrl="http://www.redcopper.net/EN-US/images/SlideShows/SS_InternetCommerceEngine-5_980x250.png" />
</div>
</div>
Points of Interest
There is no fixed relationship between the variable your declare in
JavaScript for tracking versus the total amount of time that animations are set to ease or animate.
The only real way to measure or check animations results are to go back to the DOM and check the updated value. So if you
are depending on a loop counter to determine when
the animation is complete, the loop counter will finish in about 1 second, while the animation can take up to 30 seconds. That's why you have to take a measurement
to something in the DOM, and compare it to your calculated end result from your
JavaScript.
I'm curious about adding the jQuery.UI to the script to do some real fancy easing or transitions, in
between Display Ads.
History
This is the first time I've written one of these from scratch. I wrote something similar in ActionScript 3 for Flash. I like the rewind feature that moves the strip back
to 0 really fast, instead of just looping clean from the start.
Download the Zip Example
I have added a zipped asp.net project for you to download, and quickly run to see how it works. You should be able to quickly see how simplistic it is, and how easy it is to implement in your project.
Remember, you not limited to images, technically, you should be able to put any HTML you want in the containers, just remember to keep the height and width consistent.