/**
 * Scroller - allows you to scroll a LIST of items within a DIV
 * Requirements:
 * <div style="width: 200px; height: 100px; overflow: hidden;">        Width, Height and Overflow MUST be specified for the wrapping DIV
 *     <ul id="scroll_me" style="position: relative;">              Only Lists are allowed on the inside
 *         <li>1 Some <a href="#">content</a></li>                     <a> links stop the scroll </a>
 *         <li>2 Some <a href="#">content</a></li>
 *         <li>3 Some <a href="#">content</a></li>
 *         <li>4 Some <a href="#">content</a></li>
 *     </ul>
 * </div>
 *
 * Usage:
 * var x = new Scroller(document.getElementById('scroller_me'), 'up', 10);
 * x.run();
 *
 * document.getElementById('')   - DOM LIST element with the scrollable items
 * 'up'                          - STRING direction of scroll (can be up, down, left, right)
 * 10                            - INT speed (10 - fastest - refresh every 1/100th of a second, 1000 - refresh every second)
 *
 * NOTE:
 * scrolling left and down are not really finished - they work but jump a bit when scroll restarts
 * If the content jumps by 1 or 2 pixels only - make sure the UL/OL has got height > 1, usually height: auto - fixes it
 */
function Scroller(target_object, mode, speed)
{
    var this_obj = this;
    var position = 0;
    var jump     = 2;
    var timer;

    this.run   = run;
    this.pause     = pause;
    this.runTimer  = runTimer;

    // constructor - copy all the children from the target_object so we easily detect when to jump to the top
    list        = target_object.cloneNode(true).getElementsByTagName('li');
    list_length = list.length;
    for (var i=0; i < list_length; i++) 
    {
        target_object.appendChild(list[0]);
    }

    // add pause events on all the links within the target_object
    var links = target_object.getElementsByTagName('a');
    for (var i=0; i < links.length; i++)
    {
        addEvent(links[i], 'mouseover', function() { this_obj.pause(); } );
        addEvent(links[i], 'mouseout',  function() { this_obj.runTimer(); });
    }

    // preset the initial position for the list if scrolling down or left
    switch(mode)
    {
        case 'down':
            position = Math.round(-target_object.offsetHeight/2); 
            break;
        case 'left':
            position = Math.round(target_object.offsetWidth);
            break;
    }

    function run()
    {
        // check if we have passed the middle of the target_element - if so then jump to the top
        scrollEnded();

        switch(mode)
        {
            case 'up':
                position = position - jump;
                target_object.style.top = position + "px";
                break;
            case 'down':
                position = position + jump;
                target_object.style.top = position + "px";
                break;
            case 'left':
                position = position - jump;
                target_object.style.left = position + "px";
                break;
            case 'right':
                position = position + jump;
                target_object.style.left = position + "px";
                break;
        }

        // run another frame after speed ms of delay
        runTimer();
    }

    function scrollEnded()
    {
        switch(mode)
        {
            case 'up':
                if (Math.abs(position) > Math.round(target_object.offsetHeight / 2))
                {
                    position = 0;
                    // target_object.scrollLeft = 0;
                    // target_object.scrollTop = 0;
                }
                break;
            case 'down':
                if (position > 0)
                {
                    position = Math.round(-target_object.offsetHeight/2);
                    // target_object.scrollLeft = 0;
                    // target_object.scrollTop = 0;
                }
                break;
            case 'left':
                if (position < 0)
                {
                    position = Math.round(target_object.offsetWidth);
                    // target_object.scrollLeft = 0;
                    // target_object.scrollTop = 0;
                }
                break;
            case 'right':
                if (target_object.offsetWidth < Math.abs(position))
                {
                    position = 0;
                    // target_object.scrollLeft = 0;
                    // target_object.scrollTop = 0;
                }
                break;
        }
    }

    function pause()
    {
        clearTimeout(timer);
    }

    function runTimer()
    {
        timer = setTimeout(function() { this_obj.run(); }, speed);
    }

    function addEvent(obj, event_type, func)
    {
        if (obj.addEventListener)
        {
            obj.addEventListener(event_type, func, false);
        }
        else if (obj.attachEvent)
        {
            obj.attachEvent("on"+event_type, func);
        }
    }
}
