/********************************************************************
*                        Slider Class Definition                    *
*********************************************************************
* The Slider class is a OOP implemenation of a JavaScript Slider.   *
* Requires newer line of Browsers, chiefly those supported for the  *
* SoniXtream AudioTuner.                                            *                                                                 
********************************************************************/
Slider.isSupported = typeof document.createElement != "undefined" &&
    typeof document.documentElement != "undefined" &&
    typeof document.documentElement.offsetWidth == "number";

Slider.prototype.toString = function () {
    return "[object Slider]";
};

Slider.prototype.valueOf = function() {
    return this.getValue();
};

Slider.prototype.hasOwnProperty = function (name) {
    switch (name) {
        case "toString":
        case "valueOf":
            return true;
        default:
            return false;
    }
};

function Slider(oElement, sOrient) {

    this.document = oElement.ownerDocument || oElement.document;
    sOrient = (sOrient || "horizontal")

    this.element = oElement;
    this.orientation = sOrient;
    this.element.className = "slider-" + this.orientation;
    this.element.slider = this;

    // create line
    this.line = this.document.createElement("DIV");
    this.line.className = "line";
    this.line.style.visibility = "hidden";
    this.element.appendChild(this.line);
        
    // create handle
    this.handle = this.document.createElement("DIV");
    this.handle.className = "handle";
    this.element.appendChild(this.handle);
    
    this._range = new Range()

    var oThis = this;
    this._range.onchange = function () {
        oThis.redraw();
        if (typeof oThis.onchange == "function")
            oThis.onchange();
    };

    //alert("gotcha...");
    if (Slider.isSupported && oElement) {
        this.element.onmouseover = Slider.eventHandlers.onmouseover;
        this.element.onmouseout = Slider.eventHandlers.onmouseout;           
        this.element.onmousemove    = Slider.eventHandlers.onmousemove;
        this.handle.onmousedown     = Slider.eventHandlers.onmousedown;
    }

    this.redraw();
}

Slider.eventHandlers = {

    // helpers to make events a bit easier
    getEvent:   function (e, el) {
        if (!e) {
            if (el)
                e = el.document.parentWindow.event;
            else
                e = window.event;
        }
        if (!e.srcElement) {
            el = e.target;
            while (el != null && el.nodeType != 1) {
                el = el.parentNode;
            }
            e.srcElement = el;
        }
        if (typeof e.offsetX == "undefined") {
            e.offsetX = e.layerX;
            e.offsetY = e.layerY;
        }

        return e;
    },

    getSlider:      function (e) {
        var el = e.target || e.srcElement;
        while (el != null && el.slider == null) {
            el = el.parentNode;
        }
        if (el)
            return el.slider;
        return null;
    },

    onmousemove:    function (e) {
        e = Slider.eventHandlers.getEvent(e, this);

        if (Slider._beginDragData) {    // drag
            var s = Slider._beginDragData.slider;

            var boundSize = s.getMaximum() - s.getMinimum();
            var size, pos, reset;

            if (s.orientation == "horizontal") {
                size = s.element.offsetWidth - s.handle.offsetWidth;
                pos = e.screenX - Slider._beginDragData.offsetX;
            }
            else {
                size = s.element.offsetHeight - s.handle.offsetHeight;
                pos = s.element.offsetHeight - s.handle.offsetHeight -
                    (e.screenY - Slider._beginDragData.offsetY);
            }

            s.setValue(s.getMinimum() + boundSize * pos / size);
            return false;
        }
    },

    onmouseover:        function (e) {
        e = Slider.eventHandlers.getEvent(e, this);
        var s = this.slider;
        if (e.srcElement == s.handle)
                s.handle.className = "handle hover";
    },

    onmouseout: function (e) {
        e = Slider.eventHandlers.getEvent(e, this);
        var s = this.slider;
        if (e.srcElement == s.handle && !s._hasFocus && !Slider._beginDragData)
            s.handle.className = "handle";
    },  
    
    onmousedown:    function (e) {
        e = Slider.eventHandlers.getEvent(e, this);
        var s = Slider.eventHandlers.getSlider(e);
        var d = s.document;

        Slider._beginDragData = {
            offsetX:    e.screenX - s.handle.offsetLeft,
            offsetY:    e.screenY - s.handle.offsetTop,
            slider:     s
        };

        if (d.addEventListener) {
            d.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
            d.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
        } else if (d.attachEvent) {
            d.attachEvent("onmousemove", Slider.eventHandlers.onmousemove);
            d.attachEvent("onmouseup", Slider.eventHandlers.onmouseup);
            d.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
            s.handle.setCapture();
        }

    },

    onmouseup:      function (e) {
        if (!Slider._beginDragData) return;
        var s = Slider._beginDragData.slider;
        var d = s.document;
        if (d.removeEventListener) {
            d.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
            d.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
        } else if (d.detachEvent) {
            d.detachEvent("onmousemove", Slider.eventHandlers.onmousemove);
            d.detachEvent("onmouseup", Slider.eventHandlers.onmouseup);
            d.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
            if (s && s.handle)
                s.handle.releaseCapture();
        }
        s.handle.className = "handle";
        Slider._beginDragData = null;
    }
};

Slider.prototype.getInnerLine = function() {
    if (!Boolean(this.line.style.visibility))
        return true;
    return (this.line.style.visibility == "inherit")
};

Slider.prototype.setInnerLine = function(v) {
    if (Boolean(v)) {
        if (this.line.style.visibility != "inherit")
            this.line.style.visibility = "inherit";
    } else {
        if (this.line.style.visibility != "hidden")
            this.line.style.visibility = "hidden";
    }
};

Slider.prototype.setValue = function (v) {
    this._range.setValue(v);
};

Slider.prototype.getValue = function () {
    return this._range.getValue();
};

Slider.prototype.getExtent = function () {
    return this._range.getExtent();
};

Slider.prototype.getMinimum = function () {
    return this._range.getMinimum();
};

Slider.prototype.getMaximum = function () {
    return this._range.getMaximum();
};

Slider.prototype.redraw = function () {

    if (!Slider.isSupported || !this.element) return;

    var w = this.element.offsetWidth;
    var h = this.element.offsetHeight;
    var hw = this.handle.offsetWidth;
    var hh = this.handle.offsetHeight;
    var lw = this.line.offsetWidth;
    var lh = this.line.offsetHeight;

    if (this.orientation == "horizontal") {
        this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) /
            (this.getMaximum() - this.getMinimum()) + "px";
        this.handle.style.top = (h - hh) / 2 + "px";
        this.line.style.top = (h - lh) / 2 + "px";
        this.line.style.left = hw / 2 + "px";
        this.line.style.width = Math.max(0, w - hw - 2)+ "px";
    } else {
        this.handle.style.left = (w - hw) / 2 + "px";
        this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) /
            (this.getMaximum() - this.getMinimum()) + "px";
        this.line.style.left = (w - lw) / 2 + "px";
        this.line.style.top = hh / 2 + "px";
        this.line.style.height = Math.max(0, h - hh - 2) + "px";    //hard coded border width
    }

};



