This blog has moved here: woorkup.com | FOLLOW ME ON TWITTER @woork
Monday, July 28, 2008

News ticker with horizontal scrolling using Mootools

Make your site more attractive! Add this horizontal news ticker scroller to enanche your home page.
This tutorial is another version of my News Ticker with Mootools I published yesterday. I want to reply to all that wrote me asking for information about how to implement a news ticker with horizontal scrolling. Don't panic, it's very simple to implement and reuse in your projects. The result is something like this:



Use the following links to download the full source code ready to use in your web projects or take a look at the live preview of this tutorial.

Download source code Live Preview


Step 1: Introduction
In this tutorial I used the same structure I used in the previous post. I changed only CSS code:


...each news is contained into a <li> element and <ul> list is contained into the layer #NewsHorizontal with overflow property set to hidden and position set to relative.

Step 2: HTML code
How I said, HTML code is equal to the code I used in the previous post. First of all, add a link to mootools framework in the <head> tag of your page:

<script language="javascript" src="mootools/mootools.svn.js" type="text/javascript"></script>


... and add this code into the tag <body>:

<div id="NewsTicker">
<h1>What's news?</h1>
<div id="NewsHorizontal">
<ul id="TickerHorizontal">
<!-- Each News into a LI element
Use PHP or another language
to get dinamically your news. -->
<li>
<img src="img/img1.png" border="0" class="NewsImg"/>
<span class="NewsTitle">
<a href="link.html">News Title</a>
</span>
Some text here, it's your news summary...
<span class="NewsFooter"><strong>Published July 25</strong> - 324 comments</span>
</li>
<!-- If you can't use a server side
language to get your news add
manually your news into LI element
-->
</ul>
</div>
</div>


How you can see, in the code above I just added the main HTML elements. You can add your news manually adding <li> elements to the previous code or, if you use PHP (or another server side language such as ASP, Coldfusion, Js...) you can get your news dinamically from a database table. Take a look at the previous tutorial from an example using PHP.

Step 3: CSS code
Take a look at the step 3 of my previous tutorial for an explanation about CSS elements I used in this tutorial (I changed only the style).

Step 4: Javascript function to enable vertical scroller
Last step is adding this JavaScript function to enable vertical scrolling provided from Capitol Media. I didn't add the code in this page but you can find it downloading the source code of this tutorial.



You have just to copy and paste JavaScript code without changing nothing. If you want, you can set the speed and delay (in milliseconds) for news transition at the end of the function changing these parameters:

var hor = new Ticker('TickerHorizontal',{speed:1000,delay:4000, direction:'horizontal'});



It's all! Add your comment for some suggests or interesting uses of this tutorial :)


Download source code Live Preview


Related Post
Fantastic News Ticker Newsvine-like using Mootools

blog comments powered by Disqus
Milo said...

Thanks! I was waiting for this!!! :))

Paco said...

I like your html syntax!
Thanks!

Jackson said...

I like this one too. Hope to see a future tutorial on how the user can pause each headline onMouseOver to add more interactivity.

Ryan said...

Excellent post Antonio, both today's article and yesterday's vertical scroll. I've just bookmarked your site, and I'll check back often. Any plans to publish a tutorial re a scroll using an RSS news feed, or simply pulling from an XML file?

Dave Bowker said...

Might be nice to include an option where when you hover over a news item, the ticker pauses and won't resume until the mouse pointer leaves the item.

Any chance of an update to include this?

Nice article anyhow.

Wez said...

Good Post.

tamuir said...

How can we add button like we would like it have a button option too if we would like to goto specific news like a pagination.

Thanks.

Shane said...

To pause/resume on enter/exit use the following:

Add a variable for the timer.

var mytimer = null;

Add the following functions:

pause: function() {
$clear(mytimer);
mytimer = null;},
resume: function() {
if (mytimer == null) {
this.next();}},

In the next function, set the mytimer var to the delay timer.

mytimer = this.next.bind(this).delay(this.options.delay+this.options.speed);

In your domready, add two events for the NewsTicker div.

$('NewsTicker').addEvent('mouseenter', function() {hor.pause();});

$('NewsTicker').addEvent('mouseleave', function() {hor.resume();});

I also added some CSS so that a pause button appears over the NewsTicker div just to let people know it's paused on the mouseover.

Dave Bowker said...

Nice comment Shane. ;) Exactly what I was thinking of.

Rob said...

This is really nice. Thanks so much for sharing. You can see our usage at http://www.NeatoStuff.com/

Thanks again!

Andrea said...

How can i change scrolling direction? I mean... in the case of horizontal scrolling i would like to have the scrolling from left to right instead of right to left.
Thanks!

Shane said...

@Andrea: I haven't actually tested to make sure it works but this should do the trick... Change these lines in the "next" function of the original code.


this.current--;
if (this.current < 0 ) this.current = this.items.length;


That would decrement the var called "current" which identifies the current article being shown. If "current" is less than zero then it is set to a number equal to the number of articles, thus starting back at the end.

Federico said...

thanks a lot, your blog is brilliant!

johla29 said...

This works only with mootools 1.1, if you want to use mootools 1.2 you need to change to this (i added shanes pause/resume function):

//script tag here
window.addEvent('domready', function(){
//In your domready, add two events for the NewsTicker div.
$('NewsTicker').addEvent('mouseenter', function() {vert.pause();});
$('NewsTicker').addEvent('mouseleave', function() {vert.resume();});
});
// end script tag here

//script tag here
var mytimer = null;
var Ticker = new Class({
setOptions: function(options) {
this.options = Object.extend({
speed: 1500,
delay: 5000,
direction: 'vertical',
onComplete: Class.empty,
onStart: Class.empty
}, options || {});
},
initialize: function(el,options){
this.setOptions(options);
this.el = $(el);
this.items = this.el.getElements('li');
var w = 0;
var h = 0;
if(this.options.direction.toLowerCase()=='horizontal') {
h = this.el.getSize().y;
this.items.each(function(li,index) {
w += li.getSize().x;
});
} else {
w = this.el.getSize().x;
this.items.each(function(li,index) {
h += li.getSize().y;
});
}
this.el.setStyles({
position: 'absolute',
top: 0,
left: 0,
width: w,
height: h
});
this.fx = new Fx.Morph(this.el,{duration:this.options.speed,onComplete:function() {
var i = (this.current==0)?this.items.length:this.current;
this.items[i-1].injectInside(this.el);
this.el.setStyles({
left:0,
top:0
});
}.bind(this)});
this.current = 0;
this.next();
},
next: function() {
this.current++;
if (this.current >= this.items.length) this.current = 0;
var pos = this.items[this.current];
this.fx.start({
top: -pos.offsetTop,
left: -pos.offsetLeft
});
//this.next.bind(this).delay(this.options.delay+this.options.speed);
//In the next function, set the mytimer var to the delay timer.
mytimer = this.next.bind(this).delay(this.options.delay+this.options.speed);
},

pause: function() {
$clear(mytimer);
mytimer = null;
},
resume: function() {
if (mytimer == null) {
this.next();
}
}

});

var vert = new Ticker('TickerVertical',{speed:1000,delay:2000,direction:'vertical'});
// end script tag here

Son Nguyen said...

I have a problem with version 1.1 when I used the method e.stop(). Firebug display error e.stop() is not a function

Is There many different between version 1.1 and 1.2?

johla29 said...

I just tested the code and the pause/resume works but If you trigger the mouseenter and mouseleave event really fast, it scrolls and jumps like crazy. So to check (the easy way)that no mouseleave or mouseenter event would fire when its actually scrolling you could add a control variable such as var con = 0; then in the Fx.Morph oncomplete function just change it to con = 1; in the next function add con = 0, then add some if:s on the pause and resume function.Then the next() wont fire if its scrolling if you hover over it.

Matt Hough said...

keeping it Horizontal works much better, without it dying on pause.

window.addEvent('domready', function(){
//In your domready, add two events for the NewsTicker div.
$('NewsTicker').addEvent('mouseenter', function() {vert.pause();});
$('NewsTicker').addEvent('mouseleave', function() {vert.resume();});
});
// end script tag here

//script tag here
var mytimer = null;
var Ticker = new Class({
setOptions: function(options) {
this.options = Object.extend({
speed: 1500,
delay: 2000,
direction: 'horizontal',
onComplete: Class.empty,
onStart: Class.empty
}, options || {});
},
initialize: function(el,options){
this.setOptions(options);
this.el = $(el);
this.items = this.el.getElements('li');
var w = 0;
var h = 0;
if(this.options.direction.toLowerCase()=='horizontal') {
h = this.el.getSize().y;
this.items.each(function(li,index) {
w += li.getSize().x;
});
} else {
w = this.el.getSize().x;
this.items.each(function(li,index) {
h += li.getSize().y;
});
}
this.el.setStyles({
position: 'absolute',
top: 0,
left: 0,
width: w,
height: h
});
this.fx = new Fx.Morph(this.el,{transition: Fx.Transitions.Bounce.easeOut,duration:this.options.speed,onComplete:function() {
var i = (this.current==0)?this.items.length:this.current;
this.items[i-1].injectInside(this.el);
this.el.setStyles({
left:0,
top:0
});
}.bind(this)});
this.current = 0;
this.next();
},
next: function() {
this.current++;
if (this.current >= this.items.length) this.current = 0;
var pos = this.items[this.current];
this.fx.start({
top: -pos.offsetTop,
left: -pos.offsetLeft
});
//this.next.bind(this).delay(this.options.delay+this.options.speed);
//In the next function, set the mytimer var to the delay timer.
mytimer = this.next.bind(this).delay(this.options.delay+this.options.speed);
},

pause: function() {
$clear(mytimer);
mytimer = null;
},
resume: function() {
if (mytimer == null) {
this.next();
}
}

});

var vert = new Ticker('TickerVertical',{speed:1500,delay:3000,direction:'horizontal'});


but Loving it and thanks to poster for this, with the simple edit I made it is fantastic for my site, will be up in a few days with maybe too many mootools effects, but were loving it :)

Will said...

First thanks to Antonio, excellent post!


@Matt Hough

Thanks for your mouseover code - I would like to use this with the horizontal scroller but without the "Bounce" effect. How can I remove this effect?

Stefmar84 said...

Hi,
i use the newsticker with mootools 1.2 and it work correctly with 2 istance of newsscroller.
But i had created a pause script when mouse is over the div. the script is the follwing:

window.addEvent('domready', function() {
var tec = new Ticker('TickerVertical');

$('NewsTicker').addEvent('mouseenter', function() {
tec.pause();
});
$('NewsTicker').addEvent('mouseleave', function() {
tec.resume();
});


var comm = new Ticker('TickerVertical_comm');

$('NewsTicker_comm').addEvent('mouseenter', function() {
comm.pause();
});
$('NewsTicker_comm').addEvent('mouseleave', function() {
comm.resume();
});
});

it work correctly, but when in hand with muose above the div, begins to have a very strange behavior.

Please tell me how to correct rid of mice in the script?

Павел said...

I implement left-to-right scrolling by modifying the code, provided by Antonio.

Recipy by Shane doesn't works :-(

Firstly, I add new function, called `previous`, with parameter, corresponding to beginning or not autoplay.

Here it is:

previous: function(play) {
if (this.options.busy == 1) return;
this.current--;
if (this.current < 0) this.current = this.items.length-1;
var i = this.current;
var j = (this.current-1<0)?this.items.length-1:this.current-1;
var pos = this.items[i];
var pos1 = this.items[j];
this.fx1.start({
top: pos.offsetTop,
left: pos.offsetLeft-pos1.offsetLeft
});
if (!play)
mytimer = this.previous.bind(this).delay(this.options.delay+this.options.speed);
}

Secondly I add new Fx method to class Ticker, named `fx1`, called by `previous` function, which implements left-to-right scrolling.

Here it is:

this.fx1 = new Fx.Styles(this.el,{duration:this.options.speed,
onComplete:function() {
this.items[this.current].inject(this.items[(this.current+1==this.items.length)?0:this.current+1],'before');
this.el.setStyles({
left:0,
top:0
});
this.options.busy = 0;
}.bind(this),
onStart:function() {
this.options.busy = 1;
}.bind(this)
});

Thirdly I modify CSS-definiton of container with UL's, add margin-left property, corresponding to the width of single LI-element with negative value (for the purpose, that when scroll from left-to-right new items from right bottom appeared after scroll).

Here my modification:

#Ticker {
width: 100%;
display: block;
list-style: none;
margin: 0;
margin-left: -270px; /*here it is */
padding: 0;
}

p.s.: I redefine classes id's for personal use, take it in care.

Thank you, Pavel Popov. E-mail: schmooser@gmail.com

Hudson said...

I, too, would me most interested if there were a simple way to pop an RSS feed in as the source text...

toomanypeople said...

Thanks, johla29, works great in 1.2.

oobox said...

Hi
I have a problem on horizontal RSS Ticker,

i would like no delay, a low horizontal speed, and mousenter = pause and mouseleave = resume

i use last version of mootols
Actually:
1° problem speed is not constant i have low and speed

2° for end li, i have a important delay for resume at begin (my while is not clean)

Thank's for your comments
Bernard

Anonymous said...

Hi
i have create a navigation bar for go next and back.

I've create a function back

back: function() {
this.current--;
if (this.current < 0) this.current = this.items.length-1;
var pos = this.items[this.current];
this.fx.start({
top: -pos.offsetTop,
left: -pos.offsetLeft
});
//this.next.bind(this).delay(this.options.delay+this.options.speed);
mytimer = this.back.bind(this).delay(this.options.delay+this.options.speed);
}

and in the thickervertical.li i've added the code with the button

but don't work and the li goes speed.
Why?

Thanks

Bencio said...

When I use it and I use lightview script too I get an error: "Class i not a constructor"
Someone get the same issue?

Federico said...

Ciao Antonio, lo script è notevole.. Hai notato che usando la versione orizzontale da errore se viene messo all'interno di una cella? torna ad essere verticale.

Ciao!
Federico.

Veronika said...

Hi! That's a great script! Only one problem... If I try using with lightbox or thickbox or similar effects it doesn't work :( Did someone fix this problem? Thanks eveybody :) Veronika ^_^

Anonymous said...

Hi! That's a great script! Only one problem... If I try using with lightbox or thickbox or similar effects it doesn't work :( Did someone fix this problem? Thanks eveybody :) Veronika ^_^

Anonymous said...

Hi, anyone managed to create previous and next functions / buttons for this great script?

If yes, please share the code, tnx!

Doodiee

Blogger hacks said...

Thanks a lot.... i was just waiting for this one !!!

Anonymous said...

Thanks for the script and great comments all, can somebody tell me where in the css or JS I can position the ticker? Mine seems to love sitting almost center when I want to position it myself.

Thanks in advance!

Chris said...

Love it!

Can't wait to use it on my next project.

Bookmarked!

  • Twitter Follow woork on Twitter
  • RSS Feed Subscribe to stay up to date
  • Podcast Coming soon...
  • 0 delicious lovers save
Share your links. Do you want to suggest any interesting link about web design or tech news? Submit your link.
Submit a News