The context of the example is a news scroller so we’ll be working with plain text, but we should be able to put whatever we wanted into the underlying mark-up; images, or links, or whatever. We’ll be using jQuery as the underlying JS library, and a little HTML and CSS. Let’s make a start.
The Underlying HTML
In a new page in your text editor add the following code:
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <link rel="stylesheet" type="text/css" href="simpleTicker.css">
- <dl id="ticker">
- <dt>This is a news title!</dt>
- <dd>This is a snippet of the news. It could be the whole news item or it could link to another page containing...</dd>
- <dt>News Heading 2</dt>
- <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</dd>
- <dt>News Heading 3</dt>
- <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</dd>
- <dt>News Heading 4</dt>
- <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</dd>
- <dt class="heading">This item is long!</dt>
- <dd class="text">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</dd>
- </dl>
- <script type="text/javascript" src="jquery-1.3.2.js"></script>
- <script type="text/javascript">
- </script>
The code is minimal and highly accessible; browsers, mobile devices and screen-readers should all have no difficulty interpreting and rendering it. With no styling however, it does look pretty shocking:
Providing Default Styling
Let’s add some basic styling; even with JavaScript switched off, no one
wants to see the list as it is at the moment. In a new file in your text
editor add the following code:
- #ticker {
- width:180px; height:300px; overflow:auto; border:1px solid #aaaaaa;
- }
- #ticker dt {
- font:normal 14px Georgia; padding:0 10px 5px 10px;
- background-color:#e5e5e5; padding-top:10px; border:1px solid #ffffff;
- border-bottom:none; border-right:none;
- }
- #ticker dd {
- margin-left:0; font:normal 11px Verdana; padding:0 10px 10px 10px;
- border-bottom:1px solid #aaaaaa; background-color:#e5e5e5;
- border-left:1px solid #ffffff;
- }
- #ticker dd.last { border-bottom:1px solid #ffffff;
However minimal we choose to make it, it’s a big improvement on the default rendering; it would quite happily fit into a sidebar or column now; it’s an acceptable fallback from the finished widget and a great foundation from which to progressively enhance.
Progressively Enhancing the Ticker
Now we can move on to the fun part – adding the JavaScript that will
turn this from a simple list into an automatic ticker; in the empty
<script> element at the bottom of the page add the following code:
- $(function() {
- //cache the ticker
- var ticker = $("#ticker");
- //wrap dt:dd pairs in divs
- ticker.children().filter("dt").each(function() {
- var dt = $(this),
- container = $("
- <div>");
- dt.next().appendTo(container);
- dt.prependTo(container);
- container.appendTo(ticker);
- });
- //hide the scrollbar
- ticker.css("overflow", "hidden");
- //animator function
- function animator(currentItem) {
- //work out new anim duration
- var distance = currentItem.height(),
- duration = (distance - Math.abs(parseInt(currentItem.css("marginTop")))) / 0.025;
- //animate the first child of the ticker
- currentItem.animate({ marginTop: -distance }, duration, "linear", function() {
- //move current item to the bottom currentItem.appendTo(currentItem.parent()).css("marginTop", 0);
- //recurse
- animator(currentItem.parent().children(":first"));
- });
- };
- //start the ticker
- animator(ticker.children(":first"));
- });
- </div>
The underlying definition list contains both definition term and definition description elements, all of which could potentially be of varying sizes. To make things a little easier in our script we next wrap each <dt> and <dd> pair in a containing <div> element; this allows us to group the different elements logically and smooth out the animations. It also means that we can use whatever margins and padding on the *lt;dt> and
elements without needing to take these into consideration in our animation calculations.
Once all of the <dt> and <dd> pairs have been wrapped in <div> elements we then change the ticker’s overflow CSS property to hidden so that the scrollbar is removed. This is part of the accessibility strategy and ensures that only visitors with JavaScript enabled get to see the enhanced ticker.
Next we define our animator function, which is where we’ll set the animation which causes the ticker to begin scrolling and then keep scrolling indefinitely. This is a regular JavaScript function which accepts a single parameter; when we call this function we’ll pass in the first container element within the ticker.
The first thing we do within this function is work out the distance that the selected element has to travel and the duration of the animation. The distance part is easy; it’s just the height of the current container element.
The duration is a little more complex; it’s the total distance to travel minus the distance already traveled, divided by a baseline speed that I’ve arbitrarily set at 0.025. The height will already be an integer but the css method will return a string representing the margin-top of the element being animated so we need to use JavaScript’s parseInt() function to convert it to a number. It will also be a negative number so we use the Math.abs() JavaScript function to convert it from a negative to an absolute (positive) number.
The baseline speed that we divide the remaining distance to travel by is pretty slow in my opinion; I’ve seen tickers before (built with Java) and they’ve been approximately the same speed and I didn’t get motion sickness or suffer any ill effects. If you feel that the animation is too fast (or even too slow) feel free to change this figure. It needs to be a really small number though; anything in the range of 0.01 to 0.09 is probably going to be ok.
Once we have these figures we can then create the animation using jQuery’s animate method. The first parameter for this method is the actual animation itself; we want the first of the container elements in the ticker to be moved upwards until it is completely hidden in the overflow, but we also want to drag the rest of the container elements up by the same distance as well so we use adjust the marginTop of the element.
The second argument of the animate method is the duration which we worked out a moment ago. The third argument is the easing method; custom jQuery animations automatically get two types of easing – swing and linear. Swing causes the animation to speed up and slow down, while linear makes it sooth and continuous, so this is the option for us in this situation.
The final argument is an anonymous callback function that will be executed when the animation ends. Within this function we move the element that has just been animated to the end of the set of containers, reset its marginTop back to 0, and then recursively call the animator function again, passing in the new first-child of the ticker.
Finally, we need to call the animator function once to start off the whole process. When we view this page in a browser, the ticker should smoothly scroll through each of the elements in the list repeatedly:
Starting and Stopping
- //set mouseenter
- ticker.mouseenter(function() {
- //stop current animation
- ticker.children().stop();
- });
- //set mouseleave
- ticker.mouseleave(function() {
- //resume animation
- animator(ticker.children(":first"));
- });
Fixing IE
We have one problem left to solve, and fortunately it’s an easy one. Running the page as it is in IE (tested in version 8) throws an error as soon as it is loaded. The error is caused because the very first time the animator function runs the first container <div> will have its margin-top set to auto by the browser. Other browsers will interpret the margin-top as 0. Which browser is correct is debatable, although I’ll let you draw your own conclusion about the fact that IE is the only browser that causes the problem. All we need to do to fix it is explicitly set the margin-top of the container elements. We can do this by adding the following line of code to the style sheet:- #ticker div { margin-top:0; }
Summary
This now brings us to the end of the tutorial, we should now have a simple but effective news ticker that can be put to use in a variety of ways. When using text, like in this example, defining the headings and associated content sections within a definition list makes sense from a semantics perspective, and it’s easy to add any additional elements we may need as we go.- Follow us on Twitter, or subscribe to the Nettuts+ RSS Feed for more daily web development tuts and articles.
0 nhận xét:
Đăng nhận xét