jQuery: sliding news viewer

jQuery: sliding news viewer

How to create a vertical sliding news viewer with jQuery.

A news viewer with a simple sliding mechanism is easy to implement with the aid of jQuery. The preparatory steps are really important in this case. We need to set the heights of the outermost and innermost containers by using the default height of each news block and the total number of blocks.

Our markup structure is simple:


<div id="news">
    <div id="news-wrapper">
      <div id="news-wrapper-inner">
        <div class="news"></div>
        <div class="news"></div>
        <div class="news"></div>
        <div class="news"></div>
        <div class="news"></div>
      </div>
    </div>
    <div id="news-nav"></div>
</div>

The outermost container, namely news-wrapper, must have the declaration overflow:hidden. The innermost container must be relatively positioned so it can slide vertically. Finally, each news block must be relatively positioned so that its vertical offset can be easily calculated:


#news-wrapper {
    overflow: hidden;
    
}

#news-wrapper-inner {
    position: relative;
}

div.news {
    padding: 1em;
    position: relative;
}

With jQuery we first need to set element's height by getting the computed height of the first block and multiply it by the total number of blocks. The first height value we get will be used to set the height of the outermost container, while the total height will be set on the innermost container.

Then we need to populate the news navigation block by looping through all blocks and getting the title of each news plus its numerical DOM index. This index will be used to create a custom data attribute that binds the current link to the corresponding news. We'll use later this index to select the current block, get its vertical offset and make the innermost container slide:


var NewsViewer = {
    fn: {
        prepare: function() {

            var $height = $('div.news', '#news-wrapper').eq(0).outerHeight();
            $('#news-wrapper').css('height', $height);
            $('#news-wrapper-inner').css('height', $height * $('div.news', '#news-wrapper').length);
            $('<ul id="news-list"/>').appendTo('#news-nav');
            var $html = '';
            $('div.news', '#news-wrapper').each(function() {
                var $div = $(this),
                    title = $('h2', $div).text();
                $html += '<li><a href="#" data-news="' + $div.index() + '">' + title + '</a></li>';




            });
            $('#news-list').html($html);
        },
        slide: function() {
            $('a', '#news-list').live('click', function(event) {
                event.preventDefault();
                var $a = $(this),
                    $news = $('div.news').eq($a.data('news'));
                $('#news-wrapper-inner').animate({
                    top: -$news.position().top
                }, 800);
            });


        }
    },

    init: function() {
        this.fn.prepare();
        this.fn.slide();
    }
};

$(function() {
    NewsViewer.init();
});​

You can see the demo on this page.