/Main_Page

::You must have ninja focus to complete your mission::NinjaFocus::

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;
    }
}

Main Menu

Personal tools

Toolbox