Search code examples
jquerynews-ticker

jQuery News Ticker: .remove() dom effect


I'm trying to make a news ticker (without any plug-in). I use jQuery UI's animate method to make the news move from right to left.

I'm removing the first news (li) and attaching it to the end of the list (ul) and readjusting the margin-left. This is not to get a long white space every after cycle.

Problem is... when I .remove() the first news, it's causing an undesirable UI glitch (at least for me). This part:

leftMargin = leftMargin + $('.news-ticker-display li:first').width() - 2;
$('.news-ticker-display li:first').remove();

Here's my jsFiddle link:

Any help/suggestion/comment/alternative will be greatly appreciated. Sorry I can't think a constructive title for this. lol


Solution

  • Your code is waiting fo the next animate cycle to update the left margin, which happens a few frames later. You need to set it immediately (on the same frame as the remove()) to avoid visual glitches.

    var leftMargin, scrollSpeed;
    var playScroll = true;
    
    scrollSpeed = 5;
    leftMargin = 0;
    
    function autoPlay() {
        if (playScroll) {
            $('.news-ticker-display').animate({ marginLeft: --leftMargin }, scrollSpeed, "linear", function () {
                var $first = $('.news-ticker-display li:first');
                var width = $first.outerWidth();
                if (leftMargin < -width) {
                    $first.clone().appendTo('.news-ticker-display ul');
                    leftMargin = leftMargin + width;
                    $first.remove();
                    $(this).css({marginLeft: --leftMargin});
                }
                autoPlay();
            });
        }
    }
    
    autoPlay();
    

    JSFiddle: https://jsfiddle.net/TrueBlueAussie/8djw6qen/8/

    Notes:

    • You will see I have simplified the code using temp vars. It is good practice to not repeat jQuery selectors.
    • You also need to use outerWidth(), rather than try to compensate for the border.
    • I sped up the animation for the testing (taking too long to see the glitches otherwise) :) Just set it back to your own value.
    • You can reduce the first selector using a context. e.g. var $first = $('li:first', this);
    • .first() is traditionally faster than using :first in a selector, but that really does not matter here :)