How to Make a Graphical News Slider in jQuery



Join the Fan Club!

You are currently viewing a premium “Member’s Only” post from the Web Design Fan Club. To continue viewing this awesome content after June 16, you can become a member for the heavily discounted of $36/year or join us on a monthly basis for $9/month after June 16.

Did you read that right? Yes, yes you did. $36 for the year (8 months free) if you become a yearly subscriber before June 16. Seems kind of foolish to pass something like that up, eh?

Joining the Web Design Fan Club grants you access to all the incredible resources and knowledge you need to become an expert web designer. From WordPress themes to premium icon sets and vectors, advanced tutorials to educational resources and files, the Web Design Fan Club delivers. Not only that, but you gain access to interviews with some of the best web designers and developers working today.

moneyback


How to Make a Graphical News Slider in jQuery

  1. Introduction
  2. The HTML
  3. The CSS
  4. The Object and Important Variables
  5. The Object Call
  6. Creating and Styling the Elements
  7. Changing Slides Event Listener
  8. The Fade Algorithm
  9. The Slide Algorithm
    1. The Diagonal Algorithm
    2. The Horizontal and Vertical Algorithm
  10. Conclusion

Introduction

The graphical news slider: something used so often in so many places for so many different purposes. I had made one ages ago as one of my first jQuery projects. I figured I could write a tutorial to share that code with WebDesignFan’s readers, but was taken aback when I reviewed the code I had made so long ago. It was not bad formatting or compatibility or any such thing, as I would never allow such problems to be a part of my programs. However, it wasn’t very extensible as I feel all public code should be. It was merely designed to support the features I needed at the time. Having spent the last few days revising the code, namely to allow custom image dimensions, I am happy to share with you the revised code.

In a nutshell, this program will take images and associated text/HTML, put them in a navigation bar, and periodically scroll through the images. A picture is worth a thousand words, so of course I’ll offer an example. The navigation bar below is set to be hidden until you put your mouse over the news slider. The slides are set to change automatically every 7.5 seconds, or when you click on a slide from the navigation bar.

Example

Graphic Slider in Javascript Demo

The HTML

Just like with the previous image magnifier tutorial, I’ll explain the DOM structure before getting into the algorithms involved, as the algorithms are entirely dependant on the DOM.

{code type=html}
<div class=”news-slider” id=”news-slider-#”>
<div class=”padding”>
<div class=”background2″></div>
<div class=”background”></div>
<div class=”navigation bar”></div>
<div class=”navigation icons”>
<img alt=”…” class=”image#” src=”…” title=”” />
<img alt=”…” class=”image#” src=”…” title=”” />
<img alt=”…” class=”image#” src=”…” title=”” />
</div>
<div class=”text”>
<div>…</div>
</div>
</div>
</div>
{/code}

Of course we’ll wrap all of the elements in a div.news-slider element. Since we’ll be needing timeouts in JavaScript to change the background and text periodically, we’ll need a unique identifier (div#news-slider-1, div#news-slider-2, div#news-slider-3, etc.) to refer to which slider needs to change from within the timeout.

div.padding is to prevent an error in older versions of Internet Explorer. If padding (e.g. 10px) is applied to an element that also contains a height or width (e.g. 600px), Internet Explorer would alter that element’s height or width to include the padding (e.g. 620px). In other words, the width would apply to what is inside of the padding instead of the element as a whole. By placing the padding in an element within the fixed-width, Internet Explorer is forced to render the padding inside the width instead of vice-versa, ensuring cross-browser appearance compatibility.

div.background2 is a dummy element used for transition effects. During transitions, two backgrounds are displayed: the new that is one coming into focus and the old one that is leaving. Thus, we’ll need two elements: div.background for the new background and div.background2 for the old background. Since div.background will be the new background that is in-focus, I’ve placed it after div.background2. By placing it after (and then shifting it upward via the CSS top attribute), it will appear on top of div.background2, thus hiding the old background when the new one comes into focus.

div.navigation.bar is merely a colored bar on top of which the navigation images appear. I gave it a separate element from the images themselves because it will be translucent, so the viewer is able to see the background image of div.background through it. I did not place the images inside div.navigation.bar, because I did not want the images to be translucent. Therefore, like with div.background, I placed the images in the proceeding element, then merely shifted them on top of div.navigation.bar. Since div.navigation.bar and div.navigation.icons share so many attributes (height, width, position), I gave them the common class .navigation. The separate class .bar is used for coloring the navigation bar, while .icons is unused and merely there for convenience of anyone who wants to stylize it.

img.image# are semi-unique class names that will be used in jQuery to gather information about the image, e.g. it’s src via $("news-slider-1 img.image1").attr("src"). I say semi-unique, because it is not unique to the page (therefore using class instead of ID) merely unique to the slider (each slider only has one .image1, one .image2, one .image3, etc.).

div.text is the text that will display. The div element inside of it is similar to div.padding. Oddly enough, it is not to appease Internet Explorer, but to appear jQuery. In order to position div.text toward the bottom or right of div.news-slider, we will need to know it’s width() and height() (jQuery functions). Unfortunately, jQuery does not include border or padding in its calculations of width and height, thus will not calculate the visible width and height of the element, thus not positioning div.text where we want to position it. To fix this, we merely use a div element inside of div.text for border, padding, etc. This will cause div.text to stretch and the .width() and .height() of div.text to change, incorporating the border, padding, etc. of its inner div.

The CSS

Now that you know what the elements are, we must set their default styles to position them appropriately!

{code type=css}
div.news-slider {
background-color : #f8d8d0;
border: 1px outset #e0d0c0;
height : 320px;
margin : 0 auto;
text-align : left;
width : 620px;
}

div.news-slider div.padding {
padding : 10px;
}
{/code}

The attributes of the slider itself are pretty self-explanatory. margin : 0 auto; is to center it. If you are using multiple news sliders with multiple widths, use #news-slider-1, #news-slider-2, #news-slider-3, etc. to set the height and width values.

{code type=css}
div.news-slider div.background, div.news-slider div.background2 {
background-repeat : no-repeat;
height : 300px;
margin-bottom : -300px;
width : 600px;
}
{/code}

The two backgrounds are very similar elements and thus have the same attributes. We don’t want the background to repeat so that we can see both at the same time (instead of just the one positioned on top of the other). The bottom must be set to the negative of the height. This will “pull” anything below it on top of it, essentially giving it a “height” of 0, even though it is still visible. Therefore, div.background2‘s negative margin-bottom will cause div.background to render on top of it, while div.background‘s negative margin-bottom will cause div.navigation.bar to render on top of it.

{code type=css}
div.news-slider div.navigation {
height : 300px;
position : relative;
margin-bottom : -300px;
text-align : center;
width : 142px;
}
{/code}

Here we have the shared attributes of the navigation bar and its icon wrapper. The height is the same as the background height. The position is relative so that it can be placed on the left or right of the slider. The bottom margin “pulls” div.navigation.icons on top of div.navigation.bar and div.text on top of div.navigation.icons. The centered alignment centers the images in div.navigation.icons. The width can be whatever you like. Simple.

{code type=css}
div.news-slider div.navigation.bar {
background-color : #e0d0c0;
}
{/code}

The background color of the navigation bar. You can also use a background image if you want, but keep in mind that it will translucently overlay div.background.

{code type=css}
div.news-slider div.navigation img {
border : #000000 solid 2px;
cursor : pointer;
height : 59px;
margin-top : 10px;
width : 118px;
}

div.news-slider div.navigation img:hover {
border-color : #808080;
}

div.news-slider div.navigation img.selected {
border-color : #ffffff;
}
{/code}

These are the attributes of the images in the navigation bar. The height and width are based on how many images are going to appear in the bar. This takes a bit of calculation to determine:

The height of the navigation bar is 300. The number of images is 4. The padding between the images is 10. The border width of the images is 2.

  1. Multiple the padding (10) by the number of images (4): 40.
  2. Add the padding (10) to that to include the padding at the bottom of the navigation bar: 50.If you have 4 images, you’ll want 10px above the first image (10), 10px above the second image (20), 10px above the third image (30), 10px above the fourth image (40), and 10px below the fourth image (50).That comes out to be 50 pixels of the 300 height that will be padding.
  3. Multiply the border width (2) of the images by 2: 4.If you have a border width of 2, that’s 2px on the border top and 2px on the border bottom.That comes out to be 4px total added to the vertical height of the image.
  4. Multiply that number (4) by the number of images (4): 16.
  5. Subtract that number (16) and the total padding (50) from the height (300): 234.This is how much of your navigation bar is not border or padding.i.e. This is how much of your navigation bar can actually be used for images.
  6. Divide that number (234) by the number of images (4): 58.5.
  7. Round that number (58.5) if necessary: 59.This is the height of each individual image.The width of each image can be calculated using the height-to-width ratio of the original image and this new height.

{code type=css}
div.news-slider div.text {
display : none;
float : left;
position : relative;
}

div.news-slider div.text div {
background-color : #404040;
border : #000000 solid 1px;
color : #e0d0c0;
float : left;
font-family : “Verdana”, “Tahoma”, sans-serif;
font-size : 13px;
line-height : 17px;
padding : 2px 6px;
}

div.news-slider div.text div a {
color : #e0d0c0;
}
{/code}

Lastly, these are the attributes of the text that displays with each image. By default, it is hidden, as it will become displayed when the image appears. It and its inner div are floated left so that their widths will match their text instead of being 100% and so it may be positioned (note position : relative;) from the left of the news slider to its appropriate location (e.g. the right side of the slider if the developer chooses so).

The Object and Important Variables

The news slider is placed in an object instead of a function. It requires at least two variables – one function to create the slider and one array to keep track of the timeouts used in changing slides. By using an object, we can store both of these in a single variable, while allowing the extensibility of storing other variables in the object for convenience.

{code type=javascript}
var newsSlider = {
create: function(){},
htmlSpecialChars: function(){},
specialChars: {},
timeouts: [],
total: 0
};
{/code}

newsSlider.create is simply the function used to create the slider and output the HTML. Unless you are writing custom mods, this will be the only part of the object you will ever call. An example of such a call and its parameters is explained in the following section.

newsSlider.htmlSpecialChars is a function, similar to PHP’s htmlspecialchars. It is used to store HTML in the image’s alt attribute by temporarily stripping out the HTML. newsSlider.specialChars is a variable used by newsSlider.htmlSpecialChars. For an in-depth explanation of this function and variable, give htmlspecialchars in JavaScript a read.

newsSlider.timeouts is an array of timeouts created by setTimeout. These need to be stored so that they may be cleared via clearTimeout when necessary.

newsSlider.total is merely an integer of the total news sliders on the page. It is used in the code to determine what ID should be used for the news sliders, but may also prove useful for any modification you may create: $(“#news-slider-” + newsSlider.total) will reference the last slider created.

With timeouts being an empty array, total being 0, and htmlSpecialChars and specialChars being given to you in the aforementioned tutorial, the only code left is newsSlider.create. Besides it, this object is done.

The Object Call

Before we can create newsSlider.create, we need to know what we’re working with. What is a simple interface for the developer to manipulate? How many variables with which will we be working, and what will they be called? To figure out this information, I’ve added the object call prior to the final bit of code: newsSlider.create.

{code type=javascript}
newsSlider.create({
align: “left”,
backgrounds: ["news-slider-4.jpg", "news-slider-3.jpg", "news-slider-2.jpg", "news-slider-1.jpg"],
direction: false,
effect: “random”,
hide: true,
text: ["Nintendo 3DS coming out in March 2011", '<a href="http://webdesignfan.com/how-to-design-a-stylish-business-card-in-photoshop/">How to Design a Stylish Business Card in PhotoShop<\/a>', '<a href="http://webdesignfan.com/yslow-tutorial-part-1-of-3-minimizing-file-size/">YSlow Tutorial, Part 1 of 3: Minimizing File Size<\/a>', "Ted Williams offered full-time job by Cleveland Cavaliers"],
valign: “bottom”
});
{/code}

As you can see, the parameters are all passed as an object, for simplicity reasons, as opposed to memorizing an arbitrary order of parameters.

align is the location of the navigation bar. It may be either left or right. The text will align oppose the navigation bar’s alignment. If you set this parameter to left, the navigation bar will be on the left, and the text will be on the right. If you set this parameter to right, the navigation bar will be on the right, and the text will be on the left.

backgrounds is an array of images. These are the images that will appear in the navigation bar, and the images that will appear in the background of the slide.

direction is a value used for the sliding animation. It is the direction the div.background slides as it overlaps div.background2. It can be any of eight values: top, top-right, right, bottom-right, bottom, bottom-left, left, or top-left. It may also be set to random, or false which is synonymous with random.

effect is the transitional animation. It may be either, fade, slide, or random. Again, false is synonymous with random here.

hide is a boolean for whether or not you want to hide the navigation bar. If false, the navigation bar will always appear. If true, the navigation bar will only appear when you place your mouse over the news slider.

text is the text/HTML that will display with the corresponding backgrounds. When backgrounds[0] is being displayed, text[0] will be displayed; when backgrounds[1] is being displayed, text[1] will be displayed; and so on and so forth.

valign is the vertical alignment of the text. This supports top or bottom.

Creating and Styling the Elements

Now we will tackle the foundation of the newsSlider.create function, albeit not the important algorithms yet. This section will cover the creation of variables that need to be set with JavaScript, the creation of the elements, the stylization of the elements that can only be calculated with JavaScript, and establishing the final event listener. The following code snippets go inside create: function(data) { }.

{code type=javascript}
this.total++;
{/code}

Incrementing the total will give us a new unique ID for the slider.

{code type=javascript}
this.timeouts[this.total] = null;
{/code}

Create a dummy value in the array of timeouts. This is so that clearTimeout does not generate an error if no timeout exists yet.

{code type=javascript}
data.id = this.total;
{/code}

Store the ID in the slider’s data parameter so that it may be accessed in the future. The data parameter will be stored via jQuery’s data() function.

{code type=javascript}
data.object = this;
{/code}

Store the entire object in the data parameter so that it may be accessed and manipulated in the future. When in an element’s event listener, “this” will no longer refer to the news slider object as it does here, but instead to the element itself. Because of this, we are left with no ability to reference the news slider object. (Especially if the newsSlider variable is renamed!)

div.news-slider‘s data() on the other hand, can be accessed from within event listeners. Thus by storing the object in the data, we will be able to reference it in future event listeners.

{code type=javascript}
document.write(
‘<div class=”news-slider” id=”news-slider-’ + data.id + ‘”>’ +
‘<div class=”padding”>’ +
‘<div class=”background2″><\/div>’ +
‘<div class=”background”><\/div>’ +
‘<div class=”navigation bar”><\/div>’ +
‘<div class=”navigation icons”>’
);

for (var x = 0; x < data.backgrounds.length; x++)
document.write(‘<img alt=”‘ + this.htmlSpecialChars(data.text[x]) + ‘” class=”image’ + (x + 1) + ‘” src=”‘ + data.backgrounds[x] + ‘” title=”” />’);

document.write(
‘<\/div>’ +
‘<div class=”text”><div><\/div><\/div>’ +
‘<\/div><\/div>’
);
{/code}

Output the HTML. You may want to manipulate this section to modify another element’s inner HTML instead of document.write if you plan on using this post-page-load.

The images are also written into the navigation bar. The text is stored in the images’ alt attributes to be retrieved when necessary.

{code type=javascript}
var last = $(“div#news-slider-” + data.id);
last.data(data);
{/code}

Get the newly created news slider as a jQuery object for some JavaScript-required editing.

Store the data parameter via data() for future retrieval.

{code type=javascript}
if (data.align == “right”)
{

// Note: div.navigation includes both div.navigation.bar and div.navigation.icons
var navigation = last.find(“div.navigation”);
navigation.css(“left”, (last.find(“div.background”).width() – navigation.width()) + “px”);
}
{/code}

If the navigation bar is on the right, position it as such.

The navigation bar’s position from the left is the width of the background minus the width of the navigation bar. This aligns the right side of the navigation bar with the right side of the background.

{code type=javascript}
if (data.hide)
{
last.bind({
mouseenter: function()
{
$(this).find(“div.navigation.bar”).fadeTo(333, 0.5);
$(this).find(“div.navigation.icons”).fadeTo(333, 1);
},
mouseleave: function()
{
$(this).find(“div.navigation”).fadeTo(333, 0);
}
});
last.find(“div.navigation”).fadeTo(0, 0);
}
{/code}

If the navigation bar is to be hidden by default, bind the event listeners for mouseenter and mouseleave, then hide it.

When the mouse enters the news slider, make the bar translucent and the icons opaque. When the mouse leaves the news slider, hide the navigation.

{code type=javascript}
else
last.find(“div.navigation.bar”).fadeTo(0, 0.5);
{/code}

If the navigation bar is not to be hidden, merely make the bar translucent.

Lastly, we need the event listener for changing the slides:

{code type=javascript}
last.find(“div.navigation img”).bind(“click”,
function()
{
}
);
last.find(“div.navigation img.image1″).trigger(“click”);
{/code}

When the images in the navigation bar are clicked, we’ll change the slide. To start the slider as soon as it loads, we’ll click the first image instantly using jQuery’s trigger function.

All that’s left to do is setting up the event listener for clicking images, covered in the next section.

Changing Slides Event Listener

To finish the code, we need to populate the click bind for div.navigation img. I’ll separate this into three parts: the fade algorithm, the slide algorithm, and everything else. The “everything else” is basic CSS calculations and setting timeouts and as such will be discussed first.

Being the event listener, this code will go inside the function of the click bind, i.e. inside last.find("div.navigation img").bind("click", function() { });.

{code type=javascript}
if (!$(this).is(“img.selected”))
{
}
{/code}

First things first, if the image is already selected, we don’t want to do anything at all. Thus, we wrap the entire event listener in this conditional. Nothing is outside of this conditional, because nothing at all happens if the image is already selected.

{code type=javascript}
var slider = $(this).closest(“div.news-slider”);
var data = slider.data();
{/code}

Inside of the conditional, we’ll need to get the parent div.news-slider. jQuery’s closest() function will return the first parent that matches the selector. Remember, $(this) refers to the image clicked. The closest parent div with the class .news-slider is the wrapper element. This will be used to select other elements that need to be manipulated in the slider. Also important, we will use the div.news-slider to retrieve the data() of the slider, which contains important variables like the slider’s integer ID, the newsSlider object, and the parameters passed when creating the slider.

{code type=javascript}
if (!slider.is(“div.animating”))
{
}
else
{
clearTimeout(data.object.timeouts[data.id]);
data.object.timeouts[data.id] = setTimeout(‘$(“#’ + slider.attr(“id”) + ‘”).find(“img.’ + $(this).attr(“class”) + ‘”).trigger(“click”);’, 20);
}
{/code}

.animating is a class used to determine if the slider is currently between slides. If it is, we don’t want to choppily interrupt it. Many timeouts exist to cause the animation, and there’s no way to seamlessly stop the animation to transition to a new slide. What we can do is wait for the current animation to complete, then immediately change to the slide clicked.

We have the conditional to do this. If the slider isn’t animating, change slides. Otherwise, try again every 20 milliseconds. Here is the first use of timeouts. data is the object returned by data(). object is the newsSlider object stored into data() (remember data.object = this;). timeouts is the array of timeouts. Since the animation timeouts won’t be cancelled, they are not stored in timeouts. Timeouts that may be cancelled are the clicks, such as the 20-millisecond-retry. Even though the timeout won’t exist when the click is automatically retried in 20 milliseconds, we must clear the timeout anyway in case the user manually clicks the image again.

Inside the .animating conditional:

{code type=javascript}
$(this).siblings(“img.selected”).removeClass(“selected”);
$(this).addClass(“selected”);
slider.addClass(“animating”);
{/code}

When the slider isn’t animating, remove the .selected class from the previously selected image, set the newly selected image’s class to .selected, and set the slider’s class to .animating.

{code type=javascript}
slider.find(“div.text”).fadeTo(333, 0,
function()
{
var slider = $(this).closest(“div.news-slider”);
var background = slider.find(“div.background”),
data = slider.data();
$(this).children(“div”).html(data.object.htmlSpecialChars(slider.find(“img.selected”).attr(“alt”), true));
$(this).css({
left: (data.align == “left” ? background.width() – $(this).width() – 10 : 10) + “px”,
top: (data.valign == “bottom” ? background.height() – $(this).height() – 10 : 10) + “px”
});
}
);
{/code}

The text, which is going to change, fades out. Once it has disappeared, we’ll change the contents to the selected image’s alt attribute, in which we stored the associated text when creating the image elements earlier. The second parameter of htmlSpecialChars tells the function to convert the escaped text back to HTML, i.e. convert the string <a href="http://www.charlesstover.com/">Charles Stover</a> to Charles Stover.

Once the new text has been put in the image, we must reposition it. Surely with the new text, the width is not going to be the same; if the text is long enough for it to wrap to a new line, the height won’t be either. The position of the next text is determined with a simple formula:

If the navigation bar is on the left (data.align), we must position the text on the right. To do this, we take the width of the background/slide and subtract the width of the text. Similar to a right-aligned navigation bar, this will position the right side of the text with the right side of the background. We then subtract another 10 pixels for padding. If the navigation bar is not on the left, we merely position it 10 pixels of padding from the left.

If the text is vertically aligned at the bottom (data.valign), we take the height of the background/slide and subtract the height of the text. This will position the bottom of the text with the bottom of the background. We then subtract another 10 pixels for padding. If the text is not vertically aligned at the bottom, we merely position it 10 pixels of padding from the top.

Remember, the text is still hidden. It won’t fade back in until the slide has changed, because running multiple jQuery animations at the same time causes numerous lagging issues in Internet Explorer.

{code type=javascript}
var direction = data.direction,
effect = data.effect;
{/code}

Now that the text is taken care of, we must calculate the direction and effect used. These are given their own variables because making manipulations to data.direction or data.effect will alter the object in future calls as well. That is, if data.effect is set to “random,” and the code set data.effect to “fade” for this current animation, then all future animations would be “fade” as well, as data.effect in future calls would be “fade” instead of “random.”

{code type=javascript}
if (direction == “random”)
direction = false;
if (effect == “random”)
effect = false;
{/code{

To simplify future conditionals, we replace “random” in effect and direction with the boolean value false.

{code type=javascript}
if (!effect)
effect = (Math.floor(Math.random() * (!direction ? 9 : 2)) == 1 ? “fade” : “slide”);
if (!direction)
direction = ["bottom", "bottom-left", "bottom-right", "left", "right", "top", "top-left", "top-right"][Math.floor(Math.random() * 8)];
{/code}

If there is no effect, then set one at random. The algorithm Math.floor(Math.random() * max) is fused to calculate a random number from 0 to max – 1. In this slider, there are a total of 9 different animations: fade, slide top, slide top-right, slide right, slide bottom-right, slide bottom, slide bottom-left, slide left, and slide top-left. Thus there should be a 1 in 9 chance of effect being “fade,” with the other chances of effects being “slide.” However, if a direction is set (e.g. data.direction is set to “left”), then there are only two different possible animations: fade and slide direction (e.g. fade and slide left). In our algorithm, if the direction is random (false), we create a 1 in 9 chance of the effect being fade. However, if the direction is fixed, we create only a 1 in 2 chance of the effect being fade.

We must then determine the direction if it is set to random (false). Simply give it an array of possible values, and tell it to choose one of the 8 at random. Simple enough.

The Fade Algorithm

The fade algorithm is very simple, since there is only one way to fade and eight ways to “slide.”

{code type=javascript}
if (effect == “fade”)
{
}
{/code}

The following code will go inside this conditional.

{code type=javascript}
slider.find(“div.background2″).css(“background-image”, “url(‘” + $(this).attr(“src”) + “‘)”);
{/code}

Since we are changing slides, we need to manipulate the backgrounds. In order for the previous slide (div.background) to fade into the current slide ($(this).attr("src")), the new slide will need to appear behind the old slide while the old slide fades away. div.background2, being behind div.background, must take on the background image of the soon-to-be current slide, i.e. the source of the image clicked, $(this).attr("src").

{code type=javascript}
slider.find(“div.background”).fadeTo(2000, 0,
function()
{
var slider = $(this).closest(“div.news-slider”);
var background2 = slider.find(“div.background2″),
data = slider.data();
$(this).css(“background-image”, background2.css(“background-image”));
$(this).fadeTo(0, 1);
slider.find(“div.text”).fadeTo(333, 0.75,
function()
{
var slider = $(this).closest(“div.news-slider”);
slider.removeClass(“animating”);
}
);
}
);
{/code}

Now with the background-behind-the-background set to what we want, we just need to fade div.background. Once it has faded away, three things need to be done.

  1. The element that was created to contain the current background (div.background) needs to be set appropriately. Therefore div.background takes on the background of div.background2 and is set to full opacity. The user will notice no difference, because we are overlaying an image with the exact same image. However, this needs to be done for future transitions.
  2. div.text needs to fade back in. It faded out before the slides transitioned; now that the slide has finished transitioning, it should fade back in.
  3. Once the text has faded back in, we can safely remove the .animating class from the slider.

And you’re done fading between two images! All that’s left is sliding between two images, and unfortunately the algorithm is not quite as easy.

The Slide Algorithm

The slide algorithm shall take place in the else conditional of the aforementioned if (effect == "fade") { }. I decided that each animation should take place every 10 milliseconds. Generally, 20 milliseconds is fast enough to be seamless to the eye, but I did happen to notice some choppiness, so I upped it to every 10 milliseconds. That is, every 10 milliseconds, the new background will reposition closer to its final position in the middle of the slider. Since it will take 2,000 milliseconds to complete the slide (arbitrary time that I also used in the fade transition), and there will be one animation every 10 milliseconds, that makes for 200 animations – 200 repositions of the background.

{code type=javascript}
var background = slider.find(“div.background”);
var height = background.height(),
width = background.width();
{/code}

These are merely some basic variables we’ll need to use in the slide algorithms.

{code type=javascript}
var per = {
horizontal: width / 200,
vertical: height / 200
};
{/code}

per is merely the number of pixels the background will move with each animation. If the width is 600, and there are 200 animations, that’s 3 (600 divided by 200) pixels per animation. per.horizontal is the number of pixels to move the slide horizontally per animation. per.vertical, of course, is the number of pixels to move the slide vertically with each animation.

There are two types of slide animations – basic vertical/horizontal (top, right, bottom, left) sliding and diagonal (top-right, bottom-right, bottom-left, top-left) sliding.

The Diagonal Algorithm

{code type=javascript}
if (direction.match(/\-/))
{
}
{/code}

If the direction contains a hyphen, and thus is diagonal, we apply the diagonal algorithm. The vertical and horizontal algorithm will be applied in the else conditional. The diagonal algorithm to put inside this if conditional follows.

{code type=javascript}
slider.find(“div.background2″).css(“background-image”, background.css(“background-image”));
background.css({
backgroundPosition: “-” + width + “px -” + height + “px”,
backgroundImage: “url(‘” + $(this).attr(“src”) + “‘)”
});
{/code}

We move the current slide from div.background to div.background2 so that we may cover it with the newly selected slide. We then set the background of position of div.background so that you cannot see the background image. Then, the background image of div.background is changed to the new slide. We are left with the old slide appearing in the background and the new slide out of view in the foreground. All we have to do is move the foreground image into view, and with each animation, it will further cover up the old slide.

{code type=javascript}
for (var x = 1; x <= 200; x++)
{
var shift = {
horizontal: Math.ceil(x * per.horizontal),
vertical: Math.ceil(x * per.vertical)
};
setTimeout(‘$(“#’ + slider.attr(“id”) + ‘”).find(“div.background”).css(“background-position”, “‘ + (direction.match(/left/) ? width – shift.horizontal : shift.horizontal – width) + ‘px ‘ + (direction.match(/top/) ? height – shift.vertical : shift.vertical – height) + ‘px”);’, x * 10);
}
{/code}

Now we loop for each step in the animation: all 200 of them (again, 200 steps times 10 milliseconds per step makes for a two second complete animation).

For each step, we must calculate the shift in the background, i.e. the new background position. We multiply the current step (x) by the number of pixels per step (per.horizontal and per.vertical). Thus, shift.horizontal is the new horizontal position while shift.vertical is the new vertical position.

As an example, say we move 3 pixels to the left or right per animation (per.horizontal = 3). The first animation (x = 1) will have a shift.horizontal value of 3 (x * per.horizontal = 1 * 3 = 3). The second animation (x = 2) will have a shift.horizontal value of 6 (x * per.horizontal = 2 * 3 = 6).

Now for the long timeout. The timeout will execute at x * 10 milliseconds (one step per 10 milliseconds). The first step (x = 1) will be in 10 milliseconds; the last step (x = 200) will be in 2,000 milliseconds.

In the timeout, I will break down the command: '$("#' + slider.attr("id") + '").find("div.background").css("background-position", "' + (direction.match(/left/) ? width - shift.horizontal : shift.horizontal - width) + 'px ' + (direction.match(/top/) ? height - shift.vertical : shift.vertical - height) + 'px");'

  • $("#' + slider.attr("id") + '") tells jQuery to get the slider with the same ID as the one in which the image was clicked. slider is the variable $(this).closest("div.news-slider").
  • .find("div.background"), simply enough, tells it to get the newly-created slide, so that we can position it closer to the center of the slider.
  • .css("background-position", "..."); is the reposition algorithm that moves it closer with each step.
    • (direction.match(/left/) ? width - shift.horizontal : shift.horizontal - width) constitutes the horizontal position of the background.If the direction of the slide is to move to the left, then set the new position to the width minus the horizontal shift. The position is going to start at the far right side, and for every step, it will move to the left.If the direction of the slide is to move to the right, then set the new position to the horizontal shift minus the width. An easier way to think of this may be -width + shift.horizontal. The start position is negative the width, so that it cannot be seen, and each step moves it further to the right.
    • (direction.match(/top/) ? height - shift.vertical : shift.vertical - height) constitutes the vertical position of the background.The algorithm is essentially the same as the horizontal algorithm.

This concludes the diagonal algorithm. All that’s left is the horizontal and vertical movement, which has a slight tweak.

The Horizontal and Vertical Algorithm

Unlike the diagonal algorithm, in which the new slide covers the old slide, the horizontal and vertical algorithm will have the two slides connected. In single-direction animations, the new slide gives the appearance as though it’s “pushing” the old slide out of view. This cannot be elogantly done in a diagonal slide, thus the new slide merely covers the old one in the diagonal algorithm. If you do not know the difference between the two animation types, watch them animate in the example on this page.

Since the horizontal and vertical algorithm are different than the diagonal algorithm, it is placed in the else conditional of if (direction.match(/\-/)) { }.

{code type=javascript}
slider.find(“div.background2″).css(“background-image”, “url(‘” + $(this).attr(“src”) + “‘)”);
{/code}

For this algorithm, we’ll set div.background2 to the new slide until the animation completes.

{code type=javascript}
for (var x = 1; x <= 200; x++)
{
var shift = {
horizontal: Math.ceil(x * per.horizontal),
vertical: Math.ceil(x * per.vertical)
};
setTimeout(‘$(“#’ + slider.attr(“id”) + ‘”).find(“div.background”).css(“background-position”, “‘ + (direction == “left” ? ‘-’ + shift.horizontal + ‘px’ : (direction == “right” ? shift.horizontal + ‘px’ : ’0′)) + ‘ ‘ + (direction == “top” ? ‘-’ + shift.vertical + ‘px’ : (direction == “bottom” ? shift.vertical + ‘px’ : ’0′)) + ‘”); $(“#’ + slider.attr(“id”) + ‘”).find(“div.background2″).css(“background-position”, “‘ + (direction == “left” ? (width – shift.horizontal) + ‘px’ : (direction == “right” ? (shift.horizontal – width) + ‘px’ : ’0′)) + ‘ ‘ + (direction == “top” ? (height – shift.vertical) + ‘px’ : (direction == “bottom” ? (shift.vertical – height) + ‘px’ : ’0′)) + ‘”);’, x * 10);
}
{/code}

This all functions exactly the same as the diagonal algorithm, except for the timeout. Two hundred animations, in which the shift is calculated, and a step is set to execute every 10 milliseconds.

The timeout can be split into two sections, div.background and div.background2.

  1. $("#' + slider.attr("id") + '").find("div.background").css("background-position", "..."); gets the previous slide and alters the background position as such:
    • (direction == "left" ? '-' + shift.horizontal + 'px' : (direction == "right" ? shift.horizontal + 'px' : '0'))If the direction to slide is left, move the old slide shift.horizontal pixels to the left.If the direction to slide is right, move the old side shift.horizontal pixels to the right.If the direction is neither left or right (i.e. top or bottom), don’t move it in any horizontal direction (0 pixels).
    • (direction == "top" ? '-' + shift.vertical + 'px' : (direction == "bottom" ? shift.vertical + 'px' : '0'))If the direction to slide is top, move the old slide shift.vertical pixels to the top.If the direction to slide is bottom, move the old slide shift.vertical pixels to the bottom.If the direction is neither top or bottom (i.e. left or right), don’t move it in any vertical direction (0 pixels).
  2. $("#' + slider.attr("id") + '").find("div.background2").css("background-position", "..."); gets the new slide and alters the background position in a similar way as div.background. The only difference between the two is that, while the start position of div.background is 0 pixels from the left and 0 pixels from the top, the start position of div.background2 is out-of-view.If it’s sliding from the left, its position will be negative its width (placing it out of view to the left). If it’s sliding from the right, its position will be positive its width (placing it out of view to the right). If it’s sliding from the top, its position will be negative its height (placing it out of view to the top). If it’s sliding from the bottom, its position will be positive its height (placing it out of view to the bottom).Outside of these start positions, the algorithms are precisely the same.
    • (direction == "left" ? (width - shift.horizontal) + 'px' : (direction == "right" ? (shift.horizontal - width) + 'px' : '0'))If the direction to slide is left, position the new slide at the width of the slide (start position) minus shift.horizontal pixels.If the direction to slide is right, position the new slide at shift.horizontal minus the width of the slide, i.e. negative the width of the slide (start position) plus shift.horizontal.If the direction is neither left or right (i.e. top or bottom), don’t move it in any horizontal direction (0 pixels).
    • (direction == "top" ? (height - shift.vertical) + 'px' : (direction == "bottom" ? (shift.vertical - height) + 'px' : '0'))If the direction to slide is top, position the new slide at the height of the slide (start position) minus shift.vertical pixels.If the direction to slide is bottom, position the new slide at shift.vertical pixels minus the hieght of the slide, i.e. negative the height of the slide (start position) plus shift.vertical.If the direction is neither top or bottom (i.e. left or right), don’t move it in any vertical direction (0 pixels).

Once the horizontal or vertical slide is complete (after 2,000 milliseconds), we must move the new slide from div.background2 to div.background for future transitions:

{code type=javascript}
setTimeout(‘$(“#’ + slider.attr(“id”) + ‘”).find(“div.background”).css({backgroundImage: “url(\” + $(this).attr(“src”) + ‘\’)”, backgroundPosition: “0 0″});’, 2000);
{/code}

We also reset the background-position of div.background, which was altered in the animation, to 0 0.

There is still one step left in the animation! Fear not, for it is short, and you’ve already been introduced to it in the fade algorithm. This goes for both the diagonal and horizontal/vertical algorithm (therefore goes after/outside the diagonal/horizontal/vertical else block, but still inside the else block for the slide effect).

{code type=javascript}
setTimeout(‘$(“#’ + slider.attr(“id”) + ‘”).find(“div.text”).fadeTo(333, 0.75, function() { $(“#’ + slider.attr(“id”) + ‘”).removeClass(“animating”); });’, 2000);
{/code}

After 2,000 milliseconds (after the animation has completed), have div.text fade back in. Once it has faded in, remove the animating class from the slider.

All. Done. (Almost.)

Conclusion

Last but not least there is a final tidbit of code that needs to execute for all animations (both fade and slide). Since it will execute for both, it will need to go after/outside the effect == "fade" else code; it goes inside and at the end of the if (!slider.is("div.animating")) conditional block.

{code type=javascript}
clearTimeout(data.object.timeouts[data.id]);
data.object.timeouts[data.id] = setTimeout(‘$(“#’ + slider.attr(“id”) + ‘”).find(“img.’ + ($(this).next().is(“img”) ? $(this).next().attr(“class”) : “image1″) + ‘”).trigger(“click”);’, 7500);
{/code}

Simply, we take the next image ($(this) is the current image, making $(this).next() the next image in the navigation bar). If there is no next image (i.e. the current slide is the last image in the navigation bar), then we take the first image (.image1). With this image, after 7.5 seconds, we trigger its click event. This will set the slide to automatically change every 7.5 seconds. Of course, we clearTimeout in case they manually click a slide.

Now, you’re done. This is a complete news slider script.

Due to the length of this code and the desire of WebDesignFan to have a special release of it in the future, I won’t be pasting a fully-compiled version. All of the parts of the code are in this tutorial, and those following along shall have easily been able to put them together. I’m sorry to those of you who merely scrolled to the bottom to nab it.

Thanks for reading!

Our excellent online MB7-231 training programs will lead you to success in the MB7-223 exam. We also offer latest MB6-285 with 100% success guarantee. Our 70-579 is rare in IT world.



Comments
  1. A great tutorial with a great final result! Keep up the good work. It’s not easy at all to find high quality information like yours.

  2. it’s awesome master, really cool…
    thank you…3x