I have a html list displayed in a block and I want to make the list cycle through items, i.e the first item in the list becomes the last item while the second one becomes the first, and this should continuously happen.

I wrote a small bit of jQuery to accomplish this, but the problem with this code is that is causes the block to continuously resize vertically. Does anyone know of a correction I could make to the code below to remove this glitch. Here is what I have written.

$(document).ready(function() {
    /**
     * Removes the first element of the news-ticker elements and then calls
     * addLast() to add it to the end of the list.
     */
    function removeFirst() {
        /*
         * First remove the class 'views-row-first' from the first item in the
         * list. Then since this item is to become th last item in the list we
         * add the class 'views-row-last' to it. Then we add the class
         * 'views-row-first' to the second item (obtained using the next()
         * function). Then we remove the class that defines whether this is
         * an odd or even element using a ternary operator. This information is
         * added when the item is being reinserted into the list.
         */
        $('ul#news-ticker li:first').removeClass('views-row-first')
        .addClass('views-row-last').next().addClass('views-row-first').prev()
        .hasClass('views-row-even') ?
        $('ul#news-ticker li:first').removeClass('views-row-even')
        :
        $('ul#news-ticker li:first').removeClass('views-row-odd');

        // Get the html content of the item
        first = $('ul#news-ticker li:first').html();
        //Get an array containing all the attribute of the li tag. This will be
        //needed to reconstruct the li tag later.
        attrArr = $('ul#news-ticker li:first')[0].attributes;

        // Extract the attributes into a string an reconstruct the tag.
        attributes = '';
        for(i=0 ; i < attrArr.length ; i++){
            attributes += attrArr[i].nodeName + '=" ' + attrArr[i].nodeValue + '"';
        }
        first = '<li ' + attributes + '>' + first + '</li>';

        // The animated removal of the item
        $('ul#news-ticker li:first')
        .slideUp('slow', function() {
            $(this).remove();
        });
        addLast(first);
    }

    function addLast(first){
        // Remove the 'views-row-last' tag from the last item as we are
        // appending a new item to the list.
        $('ul#news-ticker li:last').removeClass('views-row-last');
        // Find out whether the last item is odd or even, and correspondingly
        // add a class to the item we insert
        var lastParity = $('ul#news-ticker li:last').hasClass('views-row-even');
        $('ul#news-ticker').append(first);
        if(lastParity){
            $('ul#news-ticker li:last').addClass('views-row-odd');
        }
        else{
            $('ul#news-ticker li:last').addClass('views-row-even');
        }
    }

    //Calls the function every 3 seconds (3000 ms).
    ticker = setInterval(removeFirst, 3000);
});

Comments

vamega’s picture

Thanks to some help from digital-ether at the sitepoint forums I managed to find a solution to the above issue.

I thought I'd document it here so that anyone else who tries something of this sort would be able to fix it.

The solution involves setting a fixed height for the block, the height is calculated dynamically after the page has loaded. To accomplish this just add the following code to the bottom of the above script.

$(window).load(function() { 
  $('ul#news-ticker').height($('ul#news-ticker').height()).css({overflow:'hidden'});
});