Accessible Javascript News Ticker
Views:
(Redirected from Javascript News Ticker)
A news ticker that will slowly reveal the text of the news story.
The newsTicker class (uses the Javascript Utility Class):
/**
* This object will produce a DOMElement for you to emebed in your page.
* Pass it a node list of elements containing your news items, the
* _contents_ of each node will be displayed in side the ticker.
*
* There is some CSS required to work with the elements produced by this
* object.
*
* To control the animation set the newsTicker.increment, newsTicker.interval
* and newsTicker.pause properties (see below); add a node list of news
* items (such as list items) to newsTicker.messages; call newsTicker.elements
* and add the returned DOMElement to the DOM (e.g. with .appendChild());
* Finally, call newsTicker.animate()
*
* @todo fix bug with stopping and restarting the animation when the onfocus/onblur
* events fire.
*/
newsTicker = {
/**
* timing object for the animation, returned by setInterval
*
* @var object
* @access private
*/
animation: null,
/**
* the div tag that represents the cursor
*
* @var DOMElement
* @access private
*/
cursor: null,
/**
* this is an event handler for elements inside the ticker, the handler is generated when
* the elements are created with newsTicker.elements();
*
* @var function
* @access private
*/
end: null,
/**
* the number of intervals we have been paused for - see this.pause, below
*
* @var int
* @access private
*/
hold_count: 0,
/**
* the number of pixels to increment the width of the ticker by, for each interval.
*
* @var int
* @access public
*/
increment: 2,
/**
* the item index for the list of messages. This is the next index that will be displayed
* e.g. this.messages.item(this.index);
*
* @var int
* @access private
*/
index: 0,
/**
* the number of milliseconds between each change in the ticker. The width of the ticker will
* be incremented once every <interval> milliseconds
*
* 1000 / <interval> = ~FPS
*
* @var int
* @access public
*/
interval: 50,
/**
* The element (p.message) which shows the current message
*
* @var DOMElement
* @access private
*/
message: null,
/**
* a node list of messages (or any objec that implements the "item(<index>)" method).
* the innerHTML of each item will be displayed in the ticker.
*
* @var DOMNodeList
* @access public
*/
messages: null,
/**
* a minimum width of the ticker, or could be thought of as left padding/margin
*
* @var int
* @access public
*/
offsetLeft: 20,
/**
* this is an event handler for elements inside the ticker, the handler is generated when
* the elements are created with newsTicker.elements();
*
* @var function
* @access private
*/
start: null,
/**
* once the ticker is fully expanded and the message is visible, pause this many intervals/iterations before
* starting the animation over with the next message.
*
* @var int
* @access public
*/
pause: 10,
/**
* this is the div.ticker element that will have it's width increased to create the effect of revealing the message.
*
* @var DOMElement
* @access private
*/
ticker: null,
/**
* get the next message from the list of messages. this method will return the innerHTML
* of the message.
*
* @access private
* @return string
**/
nextMessage: function () {
var message = this.messages.item(this.index);
var children = message.getElementsByTagName('*');
for (var i = 0; i < children.length; ++i)
{
children[i].onfocus = this.end;
}
this.index++;
if (this.index >= this.messages.length)
{
this.index = 0;
}
return message.innerHTML;
},
/**
* returns a graph of dom nodes ready to be inserted in to your document.
* The html will look like:
* <div class="ticker">
* <div class="message-wrapper">
* <p class="message"><a href="#">My Message</a></p>
* </div>
* <div class="cusor"></div>
* </div>
*
* @access public
* @return DOMElement
**/
elements: function () {
myself = this;
this.ticker = document.createElement('div');
this.ticker.setAttribute('class', 'ticker');
this.ticker.setAttribute('className', 'ticker');
this.end = function () {
myself.stop();
myself.ticker.style['width'] = 'auto';
myself.ticker.style['width'] = myself.message.clientWidth + myself.offsetLeft + myself.cursor.clientWidth;
myself.cursor.style['left'] = myself.ticker.offsetLeft + myself.ticker.clientWidth - myself.cursor.clientWidth + 'px';
myself.cursor.style['display'] = 'none';
};
this.start = function () {
myself.cursor.style['display'] = 'block';
myself.animate();
};
this.ticker.onmouseover = this.end;
this.ticker.onmouseout = this.start;
var wrapper = document.createElement('div');
wrapper.setAttribute('class', 'message-wrapper');
wrapper.setAttribute('className', 'message-wrapper');
this.message = document.createElement('p');
this.message.setAttribute('class', 'message');
this.message.setAttribute('className', 'message');
this.message.onfocus = this.end;
this.ticker.appendChild(wrapper);
this.cursor = document.createElement('div')
this.cursor.setAttribute('class', 'cursor');
this.cursor.setAttribute('className', 'cursor');
this.ticker.appendChild(this.cursor);
wrapper.appendChild(this.message);
if (this.messages.length)
{
this.message.innerHTML = this.nextMessage();
}
return this.ticker;
},
/**
* Call this to kick off your animation
*
* @access public
* @return void
**/
animate: function () {
myself = this;
myself.cursor.style['left'] = myself.ticker.offsetLeft + myself.ticker.clientWidth - myself.cursor.clientWidth + 'px';
myself.cursor.style['display'] = 'block';
myself.animation = setInterval(function () {
var tickerWidth = myself.ticker.clientWidth;
var newTickerWidth = false;
var messageWidth = myself.message.clientWidth;
var offsetLeft = myself.message.offsetLeft - myself.ticker.offsetLeft;
if (tickerWidth > (messageWidth + myself.offsetLeft + myself.cursor.clientWidth))
{
// Ticker has expanded enough to display the message fully
// Leave the message showing for a while, before replacing it and resetting the
// width of the ticker div.
myself.hold_count++
if (myself.hold_count > myself.pause)
{
newTickerWidth = myself.offsetLeft;
myself.hold_count = 0;
myself.message.innerHTML = myself.nextMessage();
}
}
else
{
// the ticker hasn't expanded enough to display the message, increase it's width.
newTickerWidth = tickerWidth + myself.increment;
}
if (newTickerWidth !== false)
{
// poor Webkit
if (K.isWebkit()) myself.cursor.style['display'] = 'none';
// a new width for the ticker div has been provided, so change the width
myself.ticker.style['width'] = newTickerWidth + 'px';
// also move the cursor along by the same amount.
myself.cursor.style['left'] = myself.ticker.offsetLeft + myself.ticker.clientWidth - myself.cursor.clientWidth + 1 + 'px';
// poor Webkit
if (K.isWebkit()) myself.cursor.style['display'] = 'block';
}
}, this.interval);
},
/**
* Stop the news ticker animation
*
* @access public
* @return void
**/
stop: function () {
clearInterval(this.animation);
}
}
The code to initialise the news ticker (uses Javascript Utility Class):
if (!newsTicker.messages && !K.isFirefox2())
{
var latest_news_block = document.getElementById('latest_news');
if (latest_news_block)
{
if (K.isIE6())
{
newsTicker.interval = 200;
newsTicker.increment = 5;
}
var newsTickerWrapper = document.getElementById('news_ticker_wrapper');
newsTicker.messages = latest_news_block.getElementsByTagName('li');
elements = newsTicker.elements();
newsTickerWrapper.appendChild(elements);
newsTickerWrapper.style['display'] = 'block';
newsTicker.animate();
}
}
The CSS for the news ticker:
/*****************************************************************************
* NEWS TICKER *
* the news ticker is added to the page with javascript *
* *
* The html generate will look like: *
* <div class="ticker"> *
* <div class="message-wrapper"> *
* <p class="message"><a href="#">My Message</a></p> *
* </div> *
* <div class="cusor"></div> *
* </div> *
*****************************************************************************/
div.ticker {display:none;}
@media screen,projection,tv {
/* The ticker is the animated part of the ticker, it coveres up the message inside
* and the animation slowly increases it's width */
div.ticker {
overflow:hidden;
width:0;
display:block;
margin:0;
padding:0;
}
/* The wrapper stops the message inside the ticker from collapsing, overflowing or causing the text to wrap.*/
div.ticker div.message-wrapper {
margin:0;
display:block;
}
/* The contents of your news items will be shown inside this */
div.ticker .message {
margin:0;
padding:0;
display:-mox-inline-box;
display:inline-block;
height: 20px;
}
/* The cursor will be positioned to the inside right edge of the ticker, and is animated to move right
* as the width of the ticker increases. The cursor needs to cover up the message beneath it. */
div.ticker div.cursor {
display: 'block'; /* will be set to "display: block" by the javascript */
position: absolute;
float: left;
z-index: 100;
width: 10px;
height: 20px;
background-color: white;
margin:-11px 0 0;
padding:0;
border-bottom:1px solid black;
}
}
