/*! * jQuery UI Slider 1.8.23 * * Copyright 2012, 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: 100, min: 0, orientation: "horizontal", range: false, step: 1, value: 0, values: null }, _create: function () { var self = this, o = this.options, existingHandles = this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"), handle = "", handleCount = (o.values && o.values.length) || 1, handles = []; 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 + " ui-widget" + " ui-widget-content" + " ui-corner-all" + (o.disabled ? " ui-slider-disabled ui-disabled" : "")); this.range = $([]); if (o.range) { if (o.range === true) { 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]]; } } this.range = $("
") .appendTo(this.element) .addClass("ui-slider-range" + // note: this isn't the most fittingly semantic framework class for this element, // but worked best visually with a variety of themes " ui-widget-header" + ((o.range === "min" || o.range === "max") ? " ui-slider-range-" + o.range : "")); } for (var i = existingHandles.length; i < handleCount; i += 1) { handles.push(handle); } this.handles = existingHandles.add($(handles.join("")).appendTo(self.element)); 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 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: event.preventDefault(); 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(); } 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: case $.ui.keyCode.RIGHT: if (curVal === self._valueMax()) { return; } newVal = self._trimAlignValue(curVal + step); break; case $.ui.keyCode.DOWN: case $.ui.keyCode.LEFT: if (curVal === self._valueMin()) { return; } newVal = self._trimAlignValue(curVal - step); break; } self._slide(event, index, newVal); }) .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; } 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; } 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); return; } 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.propAttr("disabled", true); this.element.addClass("ui-disabled"); } else { this.handles.propAttr("disabled", false); 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 "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()) * 100; _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"]({left: valPercent + "%"}, o.animate); } if (i === 1) { self.range[animate ? "animate" : "css"]({width: (valPercent - lastValPercent) + "%"}, { queue: false, duration: o.animate }); } } else { if (i === 0) { self.range.stop(1, 1)[animate ? "animate" : "css"]({bottom: (valPercent) + "%"}, o.animate); } if (i === 1) { self.range[animate ? "animate" : "css"]({height: (valPercent - lastValPercent) + "%"}, { queue: false, duration: o.animate }); } } } lastValPercent = valPercent; }); } else { value = this.value(); valueMin = this._valueMin(); valueMax = this._valueMax(); valPercent = (valueMax !== valueMin) ? (value - valueMin) / (valueMax - valueMin) * 100 : 0; _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: valPercent + "%"}, o.animate); } if (oRange === "max" && this.orientation === "horizontal") { this.range[animate ? "animate" : "css"]({width: (100 - valPercent) + "%"}, { queue: false, duration: o.animate }); } if (oRange === "min" && this.orientation === "vertical") { this.range.stop(1, 1)[animate ? "animate" : "css"]({height: valPercent + "%"}, o.animate); } if (oRange === "max" && this.orientation === "vertical") { this.range[animate ? "animate" : "css"]({height: (100 - valPercent) + "%"}, { queue: false, duration: o.animate }); } } } }); $.extend($.ui.slider, { version: "1.8.23" }); }(jQuery));