// measure page width and height (the viewable canvas area)

function getViewport()
{
    if (document.documentElement && document.documentElement.scrollLeft) this.scrollX = document.documentElement.scrollLeft;
    else if (document.body && document.body.scrollLeft) this.scrollX = document.body.scrollLeft;
    else if (window.scrollX) this.scrollX = window.scrollX;
    else if (window.pageXOffset) this.scrollX = window.pageXOffset;
    else this.scrollX = 0;
    if (document.documentElement && document.documentElement.scrollTop) this.scrollY = document.documentElement.scrollTop;
    else if (document.body && document.body.scrollTop) this.scrollY = document.body.scrollTop;
    else if (window.scrollY) this.scrollY = window.scrollY;
    else if (window.pageYOffset) this.scrollY = window.pageYOffset;
    else this.scrollY = 0;
    if (document.documentElement && document.documentElement.clientWidth) this.width = document.documentElement.clientWidth;
    else if (document.body && document.body.clientWidth) this.width = document.body.clientWidth;
    else if (window.innerWidth) this.width = window.innerWidth;
    else this.width = 0;
    if (document.documentElement && document.documentElement.clientHeight) this.height = document.documentElement.clientHeight;
    else if (document.body && document.body.clientHeight) this.height = document.body.clientHeight;
    else if (window.innerHeight) this.height = window.innerHeight;
    else this.height = 0;
    return this;
}

// event listeners
// object      = the object to attach the event handler to
// eventType    = the type of event to listen for
// functionName = the handler function to execute when the event is fired
// capture      = use event capture?
function addEvent(object, eventType, functionName, capture)
{
    if (object.addEventListener)
    {
        object.addEventListener(eventType, functionName, capture);
        return true;
    }
    else if (object.attachEvent)
    {
        var ae = object.attachEvent("on" + eventType, functionName);
        return ae;
    }
    else { object["on" + eventType] = functionName; }
}

function removeEvent(object, eventType, functionName, capture)
{
    if (object.removeEventListener)
    {
        object.removeEventListener(eventType, functionName, capture);
        return true;
    }
    else if (object.detachEvent)
    {
        var re = object.detachEvent("on" + eventType, functionName);
        return re;
    }
    else { object["on" + eventType] = null; }
}

function fixEvent(e, currentTarget)
{
    if (!e) e = event;
    if (!e.target) e.target = e.srcElement;
    if (!e.currentTarget) e.currentTarget = currentTarget;
    if (typeof e.layerX == "undefined") e.layerX = e.offsetX;
    if (typeof e.layerY == "undefined") e.layerY = e.offsetY;
    if (typeof e.clientX == "undefined") e.clientX = e.pageX;
    if (typeof e.clientY == "undefined") e.clientY = e.pageY;
    if (!e.stopPropagation) e.stopPropagation = function() { this.cancelBubble = true; }
    if (!e.preventDefault) e.preventDefault = function() { this.returnValue = false; }
    return e;
}

// browser check
function browserCheck()
{
    this.ua = navigator.userAgent.toLowerCase();
    this.dom = document.getElementById ? 1 : 0;
    this.op7 = (this.dom && this.ua.indexOf("opera 7") > -1 || this.ua.indexOf("opera/7") > -1) ? 1 : 0;
    this.ie5 = (this.dom && this.ua.indexOf("msie 5") > -1) ? 1 : 0;
    this.ie6 = (this.dom && this.ua.indexOf("msie 6") > -1) ? 1 : 0;
    this.moz = (this.dom && this.ua.indexOf("mozilla") > -1 && this.ua.indexOf("gecko") > -1) ? 1 : 0;
    return this;
}

// browser check variable
var bw = browserCheck();

// returns a random number between x and y (integers)
function rand(x, y) { return (Math.round(Math.random() * (y - x)) + x); }

//basic
// object constructor
function createObjectById(id)
{
    this.el = document.getElementById ? document.getElementById(id) : null;
    if (!this.el) throw new Error("Element with " + id + " id not found.");
    this.css = this.el.style;
    this.i = createObjectById.registry.length;
    createObjectById.registry[this.i] = this;
    this.w = this.el.offsetWidth ? this.el.offsetWidth : 0;
    this.h = this.el.offsetHeight ? this.el.offsetHeight : 0;
    this.x = this.el.offsetLeft ? this.el.offsetLeft : 0;
    this.y = this.el.offsetTop ? this.el.offsetTop : 0;
    this.o = 100;
}

// global reference to the dhtml object
createObjectById.registry = [];

// update object values
createObjectById.prototype.update = function()
{
    this.w = this.el.offsetWidth ? this.el.offsetWidth : 0;
    this.h = this.el.offsetHeight ? this.el.offsetHeight : 0;
    this.x = this.el.offsetLeft ? this.el.offsetLeft : 0;
    this.y = this.el.offsetTop ? this.el.offsetTop : 0;
}

// visibility
createObjectById.prototype.show = function() { this.css.visibility = "visible"; }
createObjectById.prototype.hide = function() { this.css.visibility = "hidden"; }

// display
createObjectById.prototype.display = function(d) { this.css.display = d; }

// colors
createObjectById.prototype.fg = function(f) { this.css.color = f; }
createObjectById.prototype.bg = function(b) { this.css.backgroundColor = b; }

// set layer opacity (in percent, between 0 and 100)
createObjectById.prototype.setOpacity = function(o)
{
    if (typeof this.css.MozOpacity != "undefined") { this.css.MozOpacity = (o / 100); this.o = o; }
    else if (this.el.filters) { this.css.filter = "alpha(opacity=" + o + ")"; this.o = o; }
}

// moves a layer to (x, y) pixels
createObjectById.prototype.moveTo = function(x, y)
{
    if (x != null && typeof x == "number")
    {
        x = Math.round(x);
        this.x = x;
        this.css.left = x + "px";
    }
    if (y != null && typeof y == "number")
    {
        y = Math.round(y);
        this.y = y;
        this.css.top = y + "px";
    }
}

// resize layer to (width, height) pixels
createObjectById.prototype.setSize = function(w, h)
{
    if (w != null && typeof w == "number")
    {
        if (w < 0) w = 0;
        w = Math.round(w);
        this.css.width = w + "px";
    }
    if (h != null && typeof h == "number")
    {
        if (h < 0) h = 0;
        h = Math.round(h);
        this.css.height = h + "px";
    }
    this.update();
}

// clips layer to specific dimensions; (top, right, bottom, left) in pixels
createObjectById.prototype.clipTo = function(t, r, b, l)
{
    if (t < 0) t = 0; if (r < 0) r = 0; if (b < 0) b = 0; if (l < 0) l = 0;
    this.css.clip = "rect(" + t + "px, " + r + "px, " + b + "px, " + l + "px)";
}

// write content to layer
createObjectById.prototype.write = function(text)
{
    if (typeof this.el.innerHTML != "undefined")
    {
        this.el.innerHTML = text;
        this.update();
    }
}

//scrollbar
scroller = {
    scrollables: 1, // set the number of scrollable scrollContent
    step: 30, // set the timeout between each scroll
    speed: 5, // set the scroll speed
    wheelSpeed: 15, // set the scroll speed when using the mouse wheel
    wheelScrolled: false,
    timer: 0,
    contentY: 0,
    dragY: 0,
    clickY: 0,

    mouseDown: function(e)
    {
        e = fixEvent(e);
        var canvas = new getViewport();
        var mouseY = e.clientY + canvas.scrollY;
        var target = (e.target.nodeType == 3 || e.target.tagName.toLowerCase() == 'img') ? e.target.parentNode : e.target;
        scroller.wheelScrolled = false;
        for (var i = 1; i <= scroller.scrollables; i++)
        {
            if (target.id == scroller.bar[i].el.id)
            {
               scroller.bar[i].grab = true;
                scroller.clickY = mouseY - scroller.bar[i].y;
                e.preventDefault();
            }
            else if (target.id == scroller.track[i].el.id)
            {
                if (scroller.content[i].h > scroller.container[i].h)
                {
                    scroller.track[i].grab = true;
                    scroller.dragY = e.layerY - (scroller.bar[i].h / 2);
                    if (scroller.dragY < 0) scroller.dragY = 0;
                    if (scroller.dragY > scroller.track[i].h - scroller.bar[i].h) scroller.dragY = scroller.track[i].h - scroller.bar[i].h;
                    scroller.contentY = 0 - (scroller.dragY * (scroller.content[i].h - scroller.container[i].h) / Math.round(scroller.track[i].h - scroller.bar[i].h));
                    scroller.content[i].moveTo(0, scroller.contentY);
                    scroller.bar[i].moveTo(0, scroller.dragY);
                    e.preventDefault(e);
                }
            }
            else if (target.id == scroller.up[i].el.id)
            {
                scroller.up[i].grab = true;
                scroller.scroll(i, scroller.speed);
                e.preventDefault();
            }
            else if (target.id == scroller.down[i].el.id)
            {
                scroller.down[i].grab = true;
                scroller.scroll(i, -scroller.speed);
                e.preventDefault();
            }
        }
    },

    mouseUp: function(e)
    {
        for (var i = 1; i <= scroller.scrollables; i++)
        {
            scroller.bar[i].grab = false;
            scroller.track[i].grab = false;
            scroller.up[i].grab = false;
            scroller.down[i].grab = false;
        }
        clearTimeout(scroller.timer);
    },

    mouseMove: function(e)
    {
        for (var i = 1; i <= scroller.scrollables; i++)
        {
            if (scroller.bar[i].grab && scroller.content[i].h > scroller.container[i].h)
            {
                e = fixEvent(e);
                var canvas = new getViewport();
                var mouseY = e.clientY + canvas.scrollY;
                scroller.dragY = mouseY - scroller.clickY;
                if (scroller.dragY < 0) scroller.dragY = 0;
                if (scroller.dragY > scroller.track[i].h - scroller.bar[i].h) scroller.dragY = scroller.track[i].h - scroller.bar[i].h;
                scroller.contentY = 0 - (scroller.dragY * (scroller.content[i].h - scroller.container[i].h) / Math.round(scroller.track[i].h - scroller.bar[i].h));
                scroller.content[i].moveTo(0, scroller.contentY);
                scroller.bar[i].moveTo(0, scroller.dragY);
                e.preventDefault();
            }
        }
    },

    scroll: function(num, speed)
    {
        if (scroller.content[num].y < 0 || scroller.content[num].y > -scroller.content[num].h + scroller.container[num].h)
        {
            scroller.contentY = scroller.content[num].y + speed;
            if (scroller.contentY < -(scroller.content[num].h - scroller.container[num].h)) scroller.contentY = -scroller.content[num].h + scroller.container[num].h;
            else if (scroller.contentY > 0) scroller.contentY = 0;
            scroller.content[num].moveTo(0, scroller.contentY);
            scroller.dragY = 0 - (scroller.content[num].y * Math.round(scroller.track[num].h - scroller.bar[num].h) / (scroller.content[num].h - scroller.container[num].h));
            scroller.bar[num].moveTo(0, scroller.dragY);
            if (!scroller.wheelScrolled) scroller.timer = setTimeout('scroller.scroll(' + num + ', ' + speed + ')', scroller.step);
        }
    },

    wheelScroll: function(e)
    {
        e = fixEvent(e);
        var el = e.target;
        if (el.id.slice(0, el.id.length - 1) != 'scrollContent')
        {
            do el = el.parentNode;
            while (el.tagName.toLowerCase() != 'div' || el.id.slice(0, el.id.length - 1) != 'scrollContent')
        }
        var i = el.id.charAt(el.id.length - 1);
        if (window.event.wheelDelta <= -120)
        {
            scroller.wheelScrolled = true;
            scroller.scroll(i, -scroller.wheelSpeed);
        }
        else if (window.event.wheelDelta >= 120)
        {
            scroller.wheelScrolled = true;
            scroller.scroll(i, scroller.wheelSpeed);
        }
        e.preventDefault();
    },

    init: function()
    {
        scroller.container = new Array();
        scroller.content = new Array();
        scroller.bar = new Array();
        scroller.up = new Array();
        scroller.down = new Array();
        scroller.track = new Array();
        for (var i = 1; i <= scroller.scrollables; i++)
        {
            scroller.container[i] = new createObjectById('scrollContainer' + i);
            scroller.content[i] = new createObjectById('scrollContent' + i);
            scroller.bar[i] = new createObjectById('scrollBar' + i);
            scroller.bar[i].grab = false;
            scroller.track[i] = new createObjectById('scrollTrack' + i);
            scroller.track[i].grab = false;
            scroller.up[i] = new createObjectById('scrollUp' + i);
            scroller.up[i].grab = false;
            scroller.down[i] = new createObjectById('scrollDown' + i);
            scroller.down[i].grab = false;
            if (bw.ie6) addEvent(scroller.content[i].el, 'mousewheel', scroller.wheelScroll, false);
        }
        addEvent(document, 'mousemove', scroller.mouseMove, false);
        addEvent(document, 'mousedown', scroller.mouseDown, false);
        addEvent(document, 'mouseup', scroller.mouseUp, false);
    }
}