tags:

views:

177

answers:

2

see the news scroller on the top of this site

http://track.dc.gov/Agency/DH0

Any idea what library/functions this site uses to implment such a smooth scroller?

A: 

jQuery enthusiast, Remy Sharp, has his own Marquee Plugin that you can implement pretty easily. You can gather deeper details of it on his blog or by visiting the demo page.

For Mootools users, there's Mooquee.

You can also view the actual code for this example online at http://track.dc.gov/Resource/Script/ - do a search for "uiEndless" to find the target-scripting.

Jonathan Sampson
Thanks Jonathan. I look at the demo. It's not that smooth. but it's better than marquee tag though.
Vivek Chandraprakash
@Vivek: The smoothness will be determined by the options you set. If you make it fast, jumping many pixels, it will appear jerky. If you make it slow, going pixel-by-pixel, it will be smooth.
Jonathan Sampson
lemme try one real quick and see
Vivek Chandraprakash
Hi Jonathan, i used this library and tried a scroll. it's not that smooth. Thanks for the link.
Vivek Chandraprakash
+1  A: 

They have a very nicely formatted block of code you can study. Open your favorite JS debugger when you visit the site, wait for everything to get moving, and then press "Break All" or the equivalent in your debugger. You'll see something like the following:

Dashboard.UI.EndlessLine = function() {
    var me = this;
    me.jq = $(me);
    me.classNames = { CONTAINER: "uiEndless", VIEW: "uiEndlessView", CANVAS: "uiEndlessCanvas", TILE: "uiEndlessTile" };
    var canvas = null;
    var view = null;
    var tiles = null;
    var x = 0;
    var xx = 0;
    var canvasWidth = 0;
    var step = 1;
    var delay = 40;
    me.initialize = function(container, data, handler) {
        required(container, "container");
        required(data, "data");
        required(handler, "handler");
        container.addClass(me.classNames.CONTAINER);
        view = newDiv(me.classNames.VIEW);
        canvas = newDiv(me.classNames.CANVAS);
        view.append(canvas);
        container.append(view);
        x = 0;
        xx = 0;
        canvasWidth = 0;
        tiles = me.populateTiles(data, handler);
        container.click(function() {
            if (me.started()) me.stop(); else me.start();
        });
    };
    me._resize = function(size) {
    };
    var moveId = 0;
    me.start = function() {
        me.stop();
        me.tick();
    }
    me.stop = function() {
        if (moveId > 0) clearTimeout(moveId);
        moveId = 0;
    }
    me.started = function() {
        return moveId > 0;
    };
    me.tick = function() {
        var tile = tiles.current();
        var width = tile.calculatedWidth;
        if (x < width - step) {
            x += step;
        } else {
            x = 0;
            tile.css("left", canvasWidth + "px");
            if (tiles.advance()) {
                xx = 0;
                canvasWidth = 0;
                do {
                    current = tiles.current();
                    width = current.calculatedWidth;
                    current[0].style.left = canvasWidth + "px";
                    canvasWidth += width;
                } while (!tiles.advance());
            } else {
                canvasWidth += width;
            }
        }
        canvas[0].style.left = -(xx) + "px";
        xx += step;
        moveId = setTimeout(me.tick, delay);
    }
    me.populateTiles = function(data, handler) {
        var tiles = new Dashboard.Core.List();
        var viewWidth = view.contentWidth();
        var maxHeight = 0;
        each(data, function() {
            var tile = newDiv(me.classNames.TILE);
            handler.call(this, tile);
            tile.css({ left: canvasWidth + "px", top: 0 });
            canvas.append(tile);
            var width = tile.outerWidth();
            var height = tile.outerHeight();
            if (maxHeight < height) maxHeight = height;
            tile.calculatedWidth = width;
            canvasWidth += width; // getting width may only be done after the element is attached to DOM
            tiles.append(tile);
            view.height(height);
        });
        return tiles.createCycle();
    }
}

I'm impressed -- everything looks professional and nicely namespaced.

Update: If you want an explanation of how it works, focus on the tick method defined above. Glossing over all the details (cause I haven't really studied it myself), it calculates a step size, moves the message element to the left by the some amount, and schedules the next tick call for 40 milliseconds in the future.

Jonathon
very impressive. Can you tell me how to get this code easily. im using firefox with firebug. i dont see an option to break all. thanks a lot
Vivek Chandraprakash
@Vivek I actually prefer IE8 for debugging. In IE8 and Chrome, there is a built in debugger with the break all function I mentioned. In Firefox, you'll need Firebug (which you've got). Open Firebug and click on the Scripts tab. Make sure it's enabled (you should see a bunch of source code). Select the "Script" under the track.dc.gov heading under where it says "Console" (there's a drop-down menu that lets you select which script you're viewing). Then click the "||" (looks like a Pause button) to the left of "Console".
Jonathon
thanks a lot Jonathan. I see now.
Vivek Chandraprakash
hi Jonathan,I'm not able to understand this piece of code. is there any site you'd recommend to learn some advanced javascript?thanks-Vivek
Vivek Chandraprakash
@Vivek It's not simple and it would take me a while to figure out everything that's going on. There are two books I would recommend you start with: JavaScript: The Definitive Guide by David Flanagan and JavaScript: The Good Parts by Douglas Crockford. I don't know of any really good online resources for learning more advanced JS.
Jonathon