/*
 * jQuery UI Slider 1.8.9.rtl.1
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function ($, undefined) {

// number of pages in a slider
// (how many times can you page up/down to go through the whole range)
    var numPages = 5;

    $.widget("ui.slider", $.ui.mouse, {

        widgetEventPrefix: "slide",

        options: {
            animate: false,
            distance: 0,
            max: 96,
            min: 0,
            orientation: "horizontal",
            isRTL: false, // RTL
            range: false,
            step: 1,
            value: 0,
            values: null
        },

        _create: function () {
            var self = this,
                o = this.options;

            this._keySliding = false;
            this._mouseSliding = false;
            this._animateOff = true;
            this._handleIndex = null;
            this._detectOrientation();
            this._mouseInit();

            this.element
                .addClass("ui-slider" +
                    " ui-slider-" + this.orientation +
                    ( o.isRTL ? " ui-slider-rtl" : "" ) + // RTL
                    " ui-widget" +
                    " ui-widget-content" +
                    " ui-corner-all");

            if (o.disabled) {
                this.element.addClass("ui-slider-disabled ui-disabled");
            }

            this.range = $([]);

            if (o.range) {
                if (o.range === true) {
                    this.range = $("<div></div>");
                    if (!o.values) {
                        o.values = [this._valueMin(), this._valueMin()];
                    }
                    if (o.values.length && o.values.length !== 2) {
                        o.values = [o.values[0], o.values[0]];
                    }
                } else {
                    this.range = $("<div></div>");
                }

                this.range
                    .appendTo(this.element)
                    .addClass("ui-slider-range");

                if (o.range === "min" || o.range === "max") {
                    this.range.addClass("ui-slider-range-" + o.range);
                }

                // note: this isn't the most fittingly semantic framework class for this element,
                // but worked best visually with a variety of themes
                this.range.addClass("ui-widget-header");
            }

            if ($(".ui-slider-handle", this.element).length === 0) {
                $("<a href='#'></a>")
                    .appendTo(this.element)
                    .addClass("ui-slider-handle");
            }

            if (o.values && o.values.length) {
                while ($(".ui-slider-handle", this.element).length < o.values.length) {
                    $("<a href='#'></a>")
                        .appendTo(this.element)
                        .addClass("ui-slider-handle");
                }
            }

            this.handles = $(".ui-slider-handle", this.element)
                .addClass("ui-state-default" +
                    " ui-corner-all");

            this.handle = this.handles.eq(0);

            this.handles.add(this.range).filter("a")
                .click(function (event) {
                    event.preventDefault();
                })
                .hover(function () {
                    if (!o.disabled) {
                        $(this).addClass("ui-state-hover");
                    }
                }, function () {
                    $(this).removeClass("ui-state-hover");
                })
                .focus(function () {
                    if (!o.disabled) {
                        $(".ui-slider .ui-state-focus").removeClass("ui-state-focus");
                        $(this).addClass("ui-state-focus");
                    } else {
                        $(this).blur();
                    }
                })
                .blur(function () {
                    $(this).removeClass("ui-state-focus");
                });

            this.handles.each(function (i) {
                $(this).data("index.ui-slider-handle", i);
            });

            this.handles
                .keydown(function (event) {
                    var ret = true,
                        index = $(this).data("index.ui-slider-handle"),
                        allowed,
                        curVal,
                        newVal,
                        step;

                    if (self.options.disabled) {
                        return;
                    }

                    switch (event.keyCode) {
                        case $.ui.keyCode.HOME:
                        case $.ui.keyCode.END:
                        case $.ui.keyCode.PAGE_UP:
                        case $.ui.keyCode.PAGE_DOWN:
                        case $.ui.keyCode.UP:
                        case $.ui.keyCode.RIGHT:
                        case $.ui.keyCode.DOWN:
                        case $.ui.keyCode.LEFT:
                            ret = false;
                            if (!self._keySliding) {
                                self._keySliding = true;
                                $(this).addClass("ui-state-active");
                                allowed = self._start(event, index);
                                if (allowed === false) {
                                    return;
                                }
                            }
                            break;
                    }

                    step = self.options.step;
                    if (self.options.values && self.options.values.length) {
                        curVal = newVal = self.values(index);
                    } else {
                        curVal = newVal = self.value();
                    }

                    var adjust = function (minMax, offset) { // RTL
                        if (curVal === minMax) {
                            return;
                        }
                        newVal = self._trimAlignValue(curVal + offset);
                    };
                    switch (event.keyCode) {
                        case $.ui.keyCode.HOME:
                            newVal = self._valueMin();
                            break;
                        case $.ui.keyCode.END:
                            newVal = self._valueMax();
                            break;
                        case $.ui.keyCode.PAGE_UP:
                            newVal = self._trimAlignValue(curVal + ( (self._valueMax() - self._valueMin()) / numPages ));
                            break;
                        case $.ui.keyCode.PAGE_DOWN:
                            newVal = self._trimAlignValue(curVal - ( (self._valueMax() - self._valueMin()) / numPages ));
                            break;
                        case $.ui.keyCode.UP:
                            adjust(self._valueMax(), step); // RTL
                            break;
                        case $.ui.keyCode.RIGHT:
                            adjust(self._valueMax(), self.options.isRTL ? -step : step); // RTL
                            break;
                        case $.ui.keyCode.DOWN:
                            adjust(self._valueMin(), -step); // RTL
                            break;
                        case $.ui.keyCode.LEFT:
                            adjust(self._valueMin(), self.options.isRTL ? step : -step); // RTL
                            break;
                    }

                    self._slide(event, index, newVal);

                    return ret;

                })
                .keyup(function (event) {
                    var index = $(this).data("index.ui-slider-handle");

                    if (self._keySliding) {
                        self._keySliding = false;
                        self._stop(event, index);
                        self._change(event, index);
                        $(this).removeClass("ui-state-active");
                    }

                });

            this._refreshValue();

            this._animateOff = false;
        },

        destroy: function () {
            this.handles.remove();
            this.range.remove();

            this.element
                .removeClass("ui-slider" +
                    " ui-slider-horizontal" +
                    " ui-slider-vertical" +
                    " ui-slider-disabled" +
                    " ui-widget" +
                    " ui-widget-content" +
                    " ui-corner-all")
                .removeData("slider")
                .unbind(".slider");

            this._mouseDestroy();

            return this;
        },

        _mouseCapture: function (event) {
            var o = this.options,
                position,
                normValue,
                distance,
                closestHandle,
                self,
                index,
                allowed,
                offset,
                mouseOverHandle;

            if (o.disabled) {
                return false;
            }

            this.elementSize = {
                width: this.element.outerWidth(),
                height: this.element.outerHeight()
            };
            this.elementOffset = this.element.offset();

            position = {x: event.pageX, y: event.pageY};
            normValue = this._normValueFromMouse(position);
            distance = this._valueMax() - this._valueMin() + 1;
            self = this;
            this.handles.each(function (i) {
                var thisDistance = Math.abs(normValue - self.values(i));
                if (distance > thisDistance) {
                    distance = thisDistance;
                    closestHandle = $(this);
                    index = i;
                }
            });

            // workaround for bug #3736 (if both handles of a range are at 0,
            // the first is always used as the one with least distance,
            // and moving it is obviously prevented by preventing negative ranges)
            if (o.range === true && this.values(1) === o.min) {
                index += 1;
                closestHandle = $(this.handles[index]);
            }

            allowed = this._start(event, index);
            if (allowed === false) {
                return false;
            }
            this._mouseSliding = true;

            self._handleIndex = index;

            closestHandle
                .addClass("ui-state-active")
                .focus();

            offset = closestHandle.offset();
            mouseOverHandle = !$(event.target).parents().andSelf().is(".ui-slider-handle");
            this._clickOffset = mouseOverHandle ? {left: 0, top: 0} : {
                left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
                top: event.pageY - offset.top -
                ( closestHandle.height() / 2 ) -
                ( parseInt(closestHandle.css("borderTopWidth"), 10) || 0 ) -
                ( parseInt(closestHandle.css("borderBottomWidth"), 10) || 0) +
                ( parseInt(closestHandle.css("marginTop"), 10) || 0)
            };

            if (!this.handles.hasClass("ui-state-hover")) {
                this._slide(event, index, normValue);
            }
            this._animateOff = true;
            return true;
        },

        _mouseStart: function (event) {
            return true;
        },

        _mouseDrag: function (event) {
            var position = {x: event.pageX, y: event.pageY},
                normValue = this._normValueFromMouse(position);

            this._slide(event, this._handleIndex, normValue);

            return false;
        },

        _mouseStop: function (event) {
            this.handles.removeClass("ui-state-active");
            this._mouseSliding = false;

            this._stop(event, this._handleIndex);
            this._change(event, this._handleIndex);

            this._handleIndex = null;
            this._clickOffset = null;
            this._animateOff = false;

            return false;
        },

        _detectOrientation: function () {
            this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
        },

        _normValueFromMouse: function (position) {
            var pixelTotal,
                pixelMouse,
                percentMouse,
                valueTotal,
                valueMouse;

            if (this.orientation === "horizontal") {
                pixelTotal = this.elementSize.width;
                pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
            } else {
                pixelTotal = this.elementSize.height;
                pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
            }

            percentMouse = ( pixelMouse / pixelTotal );
            if (percentMouse > 1) {
                percentMouse = 1;
            }
            if (percentMouse < 0) {
                percentMouse = 0;
            }
            if (this.orientation === "vertical") {
                percentMouse = 1 - percentMouse;
            }
            if (this.options.isRTL) { // RTL
                percentMouse = 1 - percentMouse;
            }

            valueTotal = this._valueMax() - this._valueMin();
            valueMouse = this._valueMin() + percentMouse * valueTotal;

            return this._trimAlignValue(valueMouse);
        },

        _start: function (event, index) {
            var uiHash = {
                handle: this.handles[index],
                value: this.value()
            };
            if (this.options.values && this.options.values.length) {
                uiHash.value = this.values(index);
                uiHash.values = this.values();
            }
            return this._trigger("start", event, uiHash);
        },

        _slide: function (event, index, newVal) {
            var otherVal,
                newValues,
                allowed;

            if (this.options.values && this.options.values.length) {
                otherVal = this.values(index ? 0 : 1);

                if (( this.options.values.length === 2 && this.options.range === true ) &&
                    ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
                ) {
                    newVal = otherVal;
                }

                if (newVal !== this.values(index)) {
                    newValues = this.values();
                    newValues[index] = newVal;
                    // A slide can be canceled by returning false from the slide callback
                    allowed = this._trigger("slide", event, {
                        handle: this.handles[index],
                        value: newVal,
                        values: newValues
                    });
                    otherVal = this.values(index ? 0 : 1);
                    if (allowed !== false) {
                        this.values(index, newVal, true);
                    }
                }
            } else {
                if (newVal !== this.value()) {
                    // A slide can be canceled by returning false from the slide callback
                    allowed = this._trigger("slide", event, {
                        handle: this.handles[index],
                        value: newVal
                    });
                    if (allowed !== false) {
                        this.value(newVal);
                    }
                }
            }
        },

        _stop: function (event, index) {
            var uiHash = {
                handle: this.handles[index],
                value: this.value()
            };
            if (this.options.values && this.options.values.length) {
                uiHash.value = this.values(index);
                uiHash.values = this.values();
            }

            this._trigger("stop", event, uiHash);
        },

        _change: function (event, index) {
            if (!this._keySliding && !this._mouseSliding) {
                var uiHash = {
                    handle: this.handles[index],
                    value: this.value()
                };
                if (this.options.values && this.options.values.length) {
                    uiHash.value = this.values(index);
                    uiHash.values = this.values();
                }

                this._trigger("change", event, uiHash);
            }
        },

        value: function (newValue) {
            if (arguments.length) {
                this.options.value = this._trimAlignValue(newValue);
                this._refreshValue();
                this._change(null, 0);
            }

            return this._value();
        },

        values: function (index, newValue) {
            var vals,
                newValues,
                i;

            if (arguments.length > 1) {
                this.options.values[index] = this._trimAlignValue(newValue);
                this._refreshValue();
                this._change(null, index);
            }

            if (arguments.length) {
                if ($.isArray(arguments[0])) {
                    vals = this.options.values;
                    newValues = arguments[0];
                    for (i = 0; i < vals.length; i += 1) {
                        vals[i] = this._trimAlignValue(newValues[i]);
                        this._change(null, i);
                    }
                    this._refreshValue();
                } else {
                    if (this.options.values && this.options.values.length) {
                        return this._values(index);
                    } else {
                        return this.value();
                    }
                }
            } else {
                return this._values();
            }
        },

        _setOption: function (key, value) {
            var i,
                valsLength = 0;

            if ($.isArray(this.options.values)) {
                valsLength = this.options.values.length;
            }

            $.Widget.prototype._setOption.apply(this, arguments);

            switch (key) {
                case "disabled":
                    if (value) {
                        this.handles.filter(".ui-state-focus").blur();
                        this.handles.removeClass("ui-state-hover");
                        this.handles.attr("disabled", "disabled");
                        this.element.addClass("ui-disabled");
                    } else {
                        this.handles.removeAttr("disabled");
                        this.element.removeClass("ui-disabled");
                    }
                    break;
                case "orientation":
                    this._detectOrientation();
                    this.element
                        .removeClass("ui-slider-horizontal ui-slider-vertical")
                        .addClass("ui-slider-" + this.orientation);
                    this._refreshValue();
                    break;
                case "isRTL": // RTL
                    this.element.toggleClass("ui-slider-rtl", value);
                    this._refreshValue();
                    break;
                case "value":
                    this._animateOff = true;
                    this._refreshValue();
                    this._change(null, 0);
                    this._animateOff = false;
                    break;
                case "values":
                    this._animateOff = true;
                    this._refreshValue();
                    for (i = 0; i < valsLength; i += 1) {
                        this._change(null, i);
                    }
                    this._animateOff = false;
                    break;
            }
        },

        //internal value getter
        // _value() returns value trimmed by min and max, aligned by step
        _value: function () {
            var val = this.options.value;
            val = this._trimAlignValue(val);

            return val;
        },

        //internal values getter
        // _values() returns array of values trimmed by min and max, aligned by step
        // _values( index ) returns single value trimmed by min and max, aligned by step
        _values: function (index) {
            var val,
                vals,
                i;

            if (arguments.length) {
                val = this.options.values[index];
                val = this._trimAlignValue(val);

                return val;
            } else {
                // .slice() creates a copy of the array
                // this copy gets trimmed by min and max and then returned
                vals = this.options.values.slice();
                for (i = 0; i < vals.length; i += 1) {
                    vals[i] = this._trimAlignValue(vals[i]);
                }

                return vals;
            }
        },

        // returns the step-aligned value that val is closest to, between (inclusive) min and max
        _trimAlignValue: function (val) {
            if (val <= this._valueMin()) {
                return this._valueMin();
            }
            if (val >= this._valueMax()) {
                return this._valueMax();
            }
            var step = ( this.options.step > 0 ) ? this.options.step : 1,
                valModStep = (val - this._valueMin()) % step;
            alignValue = val - valModStep;

            if (Math.abs(valModStep) * 2 >= step) {
                alignValue += ( valModStep > 0 ) ? step : ( -step );
            }

            // Since JavaScript has problems with large floats, round
            // the final value to 5 digits after the decimal point (see #4124)
            return parseFloat(alignValue.toFixed(5));
        },

        _valueMin: function () {
            return this.options.min;
        },

        _valueMax: function () {
            return this.options.max;
        },

        _refreshValue: function () {
            var oRange = this.options.range,
                o = this.options,
                self = this,
                animate = ( !this._animateOff ) ? o.animate : false,
                valPercent,
                _set = {},
                lastValPercent,
                value,
                valueMin,
                valueMax;

            if (this.options.values && this.options.values.length) {
                this.handles.each(function (i, j) {
                    valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 96;
                    valPercent = ( self.options.isRTL ? 96 - valPercent : valPercent ); // RTL
                    _set[self.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
                    $(this).stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);
                    if (self.options.range === true) {
                        if (self.orientation === "horizontal") {
                            if (i === 0) {
                                self.range.stop(1, 1)[animate ? "animate" : "css"](
                                    self.options.isRTL ? {right: ( 96 - valPercent ) + "%"} : // RTL
                                    {left: valPercent + "%"}, o.animate);
                            }
                            if (i === 1) {
                                self.range[animate ? "animate" : "css"]({
                                        width: ( ( self.options.isRTL ? -1 : +1 ) * ( valPercent - lastValPercent ) ) + "%"
                                    }, // RTL
                                    {queue: false, duration: o.animate});
                            }
                        } else {
                            if (i === 0) {
                                self.range.stop(1, 1)[animate ? "animate" : "css"](
                                    self.options.isRTL ? {top: ( 96 - valPercent ) + "%"} : // RTL
                                    {bottom: ( valPercent ) + "%"}, o.animate);
                            }
                            if (i === 1) {
                                self.range[animate ? "animate" : "css"]({
                                        height: ( ( self.options.isRTL ? -1 : +1 ) * ( valPercent - lastValPercent ) ) + "%"
                                    }, // RTL
                                    {queue: false, duration: o.animate});
                            }
                        }
                    }
                    lastValPercent = valPercent;
                });
            } else {
                value = this.value();
                valueMin = this._valueMin();
                valueMax = this._valueMax();
                valPercent = ( valueMax !== valueMin ) ?
                ( value - valueMin ) / ( valueMax - valueMin ) * 96 :
                    0;
                valPercent = ( self.options.isRTL ? 96 - valPercent : valPercent ); // RTL
                _set[self.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
                this.handle.stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);

                if (oRange === "min" && this.orientation === "horizontal") {
                    this.range.stop(1, 1)[animate ? "animate" : "css"](
                        {width: ( self.options.isRTL ? 96 - valPercent : valPercent ) + "%"}, o.animate); // RTL
                }
                if (oRange === "max" && this.orientation === "horizontal") {
                    this.range[animate ? "animate" : "css"]({
                            width: ( self.options.isRTL ? valPercent : 96 - valPercent ) + "%"
                        }, // RTL
                        {queue: false, duration: o.animate});
                }
                if (oRange === "min" && this.orientation === "vertical") {
                    this.range.stop(1, 1)[animate ? "animate" : "css"](
                        {height: ( self.options.isRTL ? 96 - valPercent : valPercent ) + "%"}, o.animate); // RTL
                }
                if (oRange === "max" && this.orientation === "vertical") {
                    this.range[animate ? "animate" : "css"](
                        {height: ( self.options.isRTL ? valPercent : 96 - valPercent ) + "%"}, // RTL
                        {queue: false, duration: o.animate});
                }
            }
        }

    });

    $.extend($.ui.slider, {
        version: "1.9.1"
    });

}(jQuery));
