cux-test
Version:
[SB Admin](http://startbootstrap.com/template-overviews/sb-admin/) is an open source, admin dashboard template for [Bootstrap](http://getbootstrap.com/) created by [Start Bootstrap](http://startbootstrap.com/).
1,115 lines (1,055 loc) • 49.7 kB
JavaScript
/*!
* roundSlider v1.0 | (c) 2015, Soundar
* MIT license | http://roundsliderui.com/licence.html
*/
(function ($, window, undefined) {
"use strict";
/*jslint nomen: true */
var pluginName = "roundSlider";
// The plugin initialization
$.fn[pluginName] = function (options) {
return CreateRoundSlider.call(this, options, arguments);
};
RoundSlider.prototype = {
pluginName: pluginName,
version: "1.0",
// after the control initialization the updated default values
// are merged into the options
options: {},
// default properties of the plugin. while add a new property,
// that type should be included in the "_props:" for validation
defaults: {
min: 0,
max: 100,
step: 1,
value: null,
radius: 85,
width: 18,
handleSize: "+0",
startAngle: 0,
endAngle: "+360",
animation: true,
showTooltip: true,
editableTooltip: true,
readOnly: false,
disabled: false,
keyboardAction: true,
mouseScrollAction: false,
sliderType: "default",
circleShape: "full",
handleShape: "round",
// events
beforeCreate: null,
create: null,
start: null,
drag: null,
change: null,
stop: null,
tooltipFormat: null
},
_props: function () {
return {
numberType: ["min", "max", "step", "radius", "width", "startAngle"],
booleanType: ["animation", "showTooltip", "editableTooltip", "readOnly", "disabled",
"keyboardAction", "mouseScrollAction"],
stringType: ["sliderType", "circleShape", "handleShape"]
};
},
control: null,
_init: function () {
this._initialize();
this._update();
this._render();
},
_initialize: function () {
this._isBrowserSupport = this._isBrowserSupported();
if (!this._isBrowserSupport) return;
this._originalObj = this.control.clone();
this._isReadOnly = false;
this._checkDataType();
this._refreshCircleShape();
},
_render: function () {
this.container = createElement("div.rs-container");
this.innerContainer = createElement("div.rs-inner-container");
this.block = createElement("div.rs-block rs-outer rs-border");
this.container.append(this.innerContainer.append(this.block));
this.control.addClass("rs-control").empty().append(this.container);
this._setRadius();
if (this._isBrowserSupport) {
this._createLayers();
this._setProperties();
this._setValue();
this._bindControlEvents("_bind");
this._checkIE();
}
else {
var msg = createElement("div.rs-msg");
msg.html(typeof this._throwError === "function" ? this._throwError() : this._throwError);
this.control.empty().addClass("rs-error").append(msg);
}
},
_update: function () {
this._validateSliderType();
this._updateStartEnd();
this._validateStartEnd();
this._handle1 = this._handle2 = this._handleDefaults();
this._analyzeModelValue();
this._validateModelValue();
},
_createLayers: function () {
var padd = this.options.width, start = this._start, path;
path = createElement("div.rs-path rs-transition");
if (this._rangeSlider || this._showRange) {
this.block1 = path.clone().addClass("rs-range-color").rsRotate(start);
this.block2 = path.clone().addClass("rs-range-color").css("opacity", "0").rsRotate(start);
this.block3 = path.clone().addClass("rs-path-color").rsRotate(start);
this.block4 = path.addClass("rs-path-color").css({ "opacity": "1", "z-index": "1" }).rsRotate(start - 180);
this.block.append(this.block1, this.block2, this.block3, this.block4).addClass("rs-split");
}
else this.block.append(path.addClass("rs-path-color"));
this.lastBlock = createElement("span.rs-block").css({ "padding": padd });
this.innerBlock = createElement("div.rs-inner rs-bg-color rs-border");
this.lastBlock.append(this.innerBlock);
this.block.append(this.lastBlock);
this._appendHandle();
this._appendOverlay();
this._appendHiddenField();
},
_setProperties: function () {
this._prechange = this._predrag = this.options.value;
this._setHandleShape();
this._addAnimation();
this._appendTooltip();
if (!this.options.showTooltip) this._removeTooltip();
if (this.options.disabled) this.disable();
else if (this.options.readOnly) this._readOnly(true);
if (this.options.mouseScrollAction) this._bindScrollEvents("_bind");
},
_setValue: function () {
if (this._rangeSlider) {
this._setHandleValue(1);
this._setHandleValue(2);
}
else {
if (this._showRange) this._setHandleValue(1);
var index = (this.options.sliderType == "default") ? (this._active || 1) : parseFloat(this.bar.children().attr("index"));
this._setHandleValue(index);
}
},
_appendTooltip: function () {
if (this.container.children(".rs-tooltip").length !== 0) return;
this.tooltip = createElement("span.rs-tooltip rs-tooltip-text");
this.container.append(this.tooltip);
this._tooltipEditable();
this._updateTooltip();
},
_removeTooltip: function () {
if (this.container.children(".rs-tooltip").length == 0) return;
this.tooltip && this.tooltip.remove();
},
_tooltipEditable: function () {
if (!this.tooltip || !this.options.showTooltip) return;
var hook;
if (this.options.editableTooltip) {
this.tooltip.addClass("edit");
hook = "_bind";
}
else {
this.tooltip.removeClass("edit");
hook = "_unbind";
}
this[hook](this.tooltip, "click", this._editTooltip);
},
_editTooltip: function (e) {
if (!this.tooltip.hasClass("edit") || this._isReadOnly) return;
this.input = createElement("input.rs-input rs-tooltip-text").css({
height: this.tooltip.outerHeight(),
width: this.tooltip.outerWidth()
});
this.tooltip.html(this.input).removeClass("edit").addClass("hover");
this.input.val(this._getTooltipValue(true)).focus();
this._bind(this.input, "blur", this._focusOut);
this._bind(this.input, "change", this._focusOut);
},
_focusOut: function (e) {
if (e.type == "change") {
this.options.value = this.input.val().replace("-", ",");
this._analyzeModelValue();
this._validateModelValue();
this._setValue();
this.input.val(this._getTooltipValue(true));
}
else this.tooltip.addClass("edit").removeClass("hover");
this._raiseEvent("change");
},
_setHandleShape: function () {
var type = this.options.handleShape;
this._handles().removeClass("rs-handle-dot rs-handle-square");
if (type == "dot") this._handles().addClass("rs-handle-dot");
else if (type == "square") this._handles().addClass("rs-handle-square");
else this.options.handleShape = this.defaults.handleShape;
},
_setHandleValue: function (index) {
this._active = index;
var handle = this["_handle" + index];
if (this.options.sliderType != "min-range") this.bar = this._activeHandleBar();
this._changeSliderValue(handle.value, handle.angle);
},
_setAnimation: function () {
if (this.options.animation) this._addAnimation();
else this._removeAnimation();
},
_addAnimation: function () {
if (this.options.animation) this.control.addClass("rs-animation");
},
_removeAnimation: function () {
this.control.removeClass("rs-animation");
},
_setRadius: function () {
var r = this.options.radius, d = r * 2;
var circleShape = this.options.circleShape, height = d, width = d;
this.container.removeClass().addClass("rs-container");
if (circleShape.indexOf("half") === 0) {
switch (circleShape) {
case "half-top":
case "half-bottom":
height = r; width = d; break;
case "half-left":
case "half-right":
height = d; width = r; break;
}
this.container.addClass(circleShape.replace("half-", "") + " half");
}
else if (circleShape.indexOf("quarter") === 0) {
height = width = r;
var s = circleShape.split("-");
this.container.addClass(s[0] + " " + s[1] + " " + s[2]);
}
else this.container.addClass("full " + circleShape);
var style = { "height": height, "width": width };
this.control.css(style);
this.container.css(style);
},
_border: function () {
return parseFloat(this.block.css("border-top-width")) * 2;
},
_appendHandle: function () {
if (this._rangeSlider || !this._showRange) this._createHandle(1);
if (this._rangeSlider || this._showRange) this._createHandle(2);
this._startLine = this._addSeperator(this._start, "rs-start");
this._endLine = this._addSeperator(this._start + this._end, "rs-end");
},
_addSeperator: function (pos, cls) {
var line = createElement("span.rs-seperator").css({ "width": this.options.width, "margin-left": this._border() / 2 });
var lineWrap = createElement("span.rs-bar rs-transition " + cls).append(line).rsRotate(pos);
this.container.append(lineWrap);
return lineWrap;
},
_updateSeperator: function () {
this._startLine.rsRotate(this._start);
this._endLine.rsRotate(this._start + this._end);
},
_createHandle: function (index) {
var handle = createElement("div.rs-handle rs-move");
handle.attr({ "index": index, "tabIndex": "0" });
var id = this.control[0].id, id = id ? id + "_" : "";
var label = id + "handle" + (this.options.sliderType == "range" ? "_" + (index == 1 ? "start" : "end") : "");
handle.attr({ "role": "slider", "aria-label": label }); // WAI-ARIA support
var bar = createElement("div.rs-bar rs-transition").css("z-index", "4").append(handle).rsRotate(this._start);
bar.addClass(this.options.sliderType == "range" && index == 2 ? "rs-second" : "rs-first");
this.container.append(bar);
this._refreshHandle();
this.bar = bar;
this._active = index;
if (index != 1 && index != 2) this["_handle" + index] = this._handleDefaults();
this._bind(handle, "focus", this._handleFocus);
this._bind(handle, "blur", this._handleBlur);
return handle;
},
_refreshHandle: function () {
var hSize = this.options.handleSize, h, w, isSquare = true;
if (typeof hSize === "string" && isNumber(hSize)) {
if (hSize.charAt(0) === "+" || hSize.charAt(0) === "-") {
try { hSize = eval(this.options.width + hSize.charAt(0) + Math.abs(parseFloat(hSize))); }
catch (e) { console.warn(e); }
}
else if (hSize.indexOf(",")) {
var s = hSize.split(",");
if (isNumber(s[0]) && isNumber(s[1])) w = parseFloat(s[0]), h = parseFloat(s[1]), isSquare = false;
}
}
if (isSquare) h = w = isNumber(hSize) ? parseFloat(hSize) : this.options.width;
var diff = (this.options.width + this._border() - w) / 2;
this._handles().css({ height: h, width: w, "margin": -h / 2 + "px 0 0 " + diff + "px" });
},
_handleDefaults: function () {
return { angle: this._valueToAngle(this.options.min), value: this.options.min };
},
_handles: function () {
return this.container.children("div.rs-bar").find(".rs-handle");
},
_activeHandleBar: function () {
return $(this.container.children("div.rs-bar")[this._active - 1]);
},
_handleArgs: function () {
var _handle = this["_handle" + this._active];
return {
element: this._activeHandleBar().children(),
index: this._active,
value: _handle ? _handle.value : null,
angle: _handle ? _handle.angle : null
};
},
_raiseEvent: function (event) {
this._updateTooltip();
if (event == "change") this._updateHidden();
if (this["_pre" + event] !== this.options.value) {
this["_pre" + event] = this.options.value;
return this._raise(event, { value: this.options.value, "handle": this._handleArgs() });
}
},
// Events handlers
_elementDown: function (e) {
if (this._isReadOnly) return;
var $target = $(e.target);
if ($target.hasClass("rs-handle")) {
this._handleDown(e);
}
else {
var point = this._getXY(e), center = this._getCenterPoint();
var distance = getdistance(point, center);
var outerDistance = this.block.outerWidth() / 2;
var innerDistance = outerDistance - (this.options.width + this._border());
if (distance >= innerDistance && distance <= outerDistance) {
e.preventDefault();
var handle = this.control.find(".rs-handle.rs-focus");
//if (handle.length == 0)
this.control.attr("tabindex", "0").focus().removeAttr("tabindex");
var d = this._getAngleValue(point, center), angle, value;
angle = d.angle, value = d.value;
if (this._rangeSlider) {
handle = this.control.find(".rs-handle.rs-focus");
if (handle.length == 1) this._active = parseFloat(handle.attr("index"));
else this._active = (this._handle2.value - value) < (value - this._handle1.value) ? 2 : 1;
this.bar = this._activeHandleBar();
}
this._changeSliderValue(value, angle);
this._raiseEvent("change");
}
}
},
_handleDown: function (e) {
e.preventDefault();
var $target = $(e.target);
$target.focus();
this._removeAnimation();
this._bindMouseEvents("_bind");
this.bar = $target.parent();
this._active = parseFloat($target.attr("index"));
this._handles().removeClass("rs-move");
this._raise("start", { "handle": this._handleArgs() });
},
_handleMove: function (e) {
e.preventDefault();
var point = this._getXY(e), center = this._getCenterPoint();
var d = this._getAngleValue(point, center), angle, value;
angle = d.angle, value = d.value;
this._changeSliderValue(value, angle);
this._raiseEvent("drag");
},
_handleUp: function (e) {
this._handles().addClass("rs-move");
this._bindMouseEvents("_unbind");
this._addAnimation();
this._raiseEvent("change");
this._raise("stop", { "handle": this._handleArgs() });
},
_handleFocus: function (e) {
if (this._isReadOnly) return;
var $target = $(e.target);
this._handles().removeClass("rs-focus");
$target.addClass("rs-focus");
this.bar = $target.parent();
this._active = parseFloat($target.attr("index"));
if (this.options.keyboardAction) {
this._bindKeyboardEvents("_unbind");
this._bindKeyboardEvents("_bind");
}
// updates the class for change z-index
this.control.find("div.rs-bar").css("z-index", "4");
this.bar.css("z-index", "5");
},
_handleBlur: function (e) {
this._handles().removeClass("rs-focus");
if (this.options.keyboardAction) this._bindKeyboardEvents("_unbind");
},
_handleKeyDown: function (e) {
if (this._isReadOnly) return;
var key = e.keyCode;
if (key == 27) this._handles().blur();
if (!(key >= 35 && key <= 40)) return;
if (key >= 37 && key <= 40) this._removeAnimation();
var h = this["_handle" + this._active], val, ang;
e.preventDefault();
if (key == 38 || key == 37) val = this._round(this._limitValue(h.value + this.options.step)); // Up || Left Key
else if (key == 39 || key == 40) val = this._round(this._limitValue(h.value - this._getMinusStep(h.value))); // Right || Down Key
else if (key == 36) val = this._getKeyValue("Home"); // Home Key
else if (key == 35) val = this._getKeyValue("End"); // End Key
ang = this._valueToAngle(val);
this._changeSliderValue(val, ang);
this._raiseEvent("change");
},
_handleKeyUp: function (e) {
this._addAnimation();
},
_getMinusStep: function (val) {
if (val == this.options.max) {
var step = (this.options.max - this.options.min) % this.options.step;
return step == 0 ? this.options.step : step;
}
return this.options.step;
},
_getKeyValue: function (key) {
if (this._rangeSlider) {
if (key == "Home") return (this._active == 1) ? this.options.min : this._handle1.value;
else return (this._active == 1) ? this._handle2.value : this.options.max;
}
return (key == "Home") ? this.options.min : this.options.max;
},
_elementScroll: function (event) {
if (this._isReadOnly) return;
event.preventDefault();
var e = event.originalEvent || event, h, val, ang, delta;
delta = e.wheelDelta ? e.wheelDelta / 60 : (e.detail ? -e.detail / 2 : 0);
if (delta == 0) return;
this._updateActiveHandle(event);
h = this["_handle" + this._active];
val = h.value + (delta > 0 ? this.options.step : -this._getMinusStep(h.value));
val = this._limitValue(val);
ang = this._valueToAngle(val);
this._removeAnimation();
this._changeSliderValue(val, ang);
this._raiseEvent("change");
this._addAnimation();
},
_updateActiveHandle: function (e) {
var $target = $(e.target);
if ($target.hasClass("rs-handle") && $target.parent().parent()[0] == this.control[0]) {
this.bar = $target.parent();
this._active = parseFloat($target.attr("index"));
}
if (!this.bar.find(".rs-handle").hasClass("rs-focus")) this.bar.find(".rs-handle").focus();
},
// Events binding
_bindControlEvents: function (hook) {
this[hook](this.control, "mousedown", this._elementDown);
this[hook](this.control, "touchstart", this._elementDown);
},
_bindScrollEvents: function (hook) {
this[hook](this.control, "mousewheel", this._elementScroll);
this[hook](this.control, "DOMMouseScroll", this._elementScroll);
},
_bindMouseEvents: function (hook) {
this[hook]($(document), "mousemove", this._handleMove);
this[hook]($(document), "mouseup", this._handleUp);
this[hook]($(document), "mouseleave", this._handleUp);
// *** for Touch support *** //
this[hook]($(document), "touchmove", this._handleMove);
this[hook]($(document), "touchend", this._handleUp);
this[hook]($(document), "touchcancel", this._handleUp);
},
_bindKeyboardEvents: function (hook) {
this[hook]($(document), "keydown", this._handleKeyDown);
this[hook]($(document), "keyup", this._handleKeyUp);
},
// internal methods
_changeSliderValue: function (value, angle) {
var oAngle = this._oriAngle(angle), lAngle = this._limitAngle(angle);
if (!this._rangeSlider && !this._showRange) {
this["_handle" + this._active] = { angle: angle, value: value };
this.options.value = value;
this.bar.rsRotate(lAngle);
this._updateARIA(value);
}
else if ((this._active == 1 && oAngle <= this._oriAngle(this._handle2.angle)) ||
(this._active == 2 && oAngle >= this._oriAngle(this._handle1.angle))) {
this["_handle" + this._active] = { angle: angle, value: value };
this.options.value = this._rangeSlider ? this._handle1.value + "," + this._handle2.value : value;
this.bar.rsRotate(lAngle);
this._updateARIA(value);
var dAngle = this._oriAngle(this._handle2.angle) - this._oriAngle(this._handle1.angle), o2 = "1", o3 = "0";
if (dAngle <= 180) o2 = "0", o3 = "1";
this.block2.css("opacity", o2);
this.block3.css("opacity", o3);
(this._active == 1 ? this.block4 : this.block2).rsRotate(lAngle - 180);
(this._active == 1 ? this.block1 : this.block3).rsRotate(lAngle);
}
},
// WAI-ARIA support
_updateARIA: function (value) {
var min = this.options.min, max = this.options.max;
this.bar.children().attr({ "aria-valuenow": value });
if (this.options.sliderType == "range") {
var handles = this._handles();
handles.eq(0).attr({ "aria-valuemin": min });
handles.eq(1).attr({ "aria-valuemax": max });
if (this._active == 1) handles.eq(1).attr({ "aria-valuemin": value });
else handles.eq(0).attr({ "aria-valuemax": value });
}
else this.bar.children().attr({ "aria-valuemin": min, "aria-valuemax": max });
},
_getXY: function (e) {
if (e.type.indexOf("mouse") == -1) e = (e.originalEvent || e).changedTouches[0];
return { x: e.pageX, y: e.pageY };
},
_getCenterPoint: function () {
var offset = this.block.offset(), center;
center = {
x: offset.left + (this.block.outerWidth() / 2),
y: offset.top + (this.block.outerHeight() / 2)
};
return center;
},
_getAngleValue: function (point, center) {
var deg = Math.atan2(point.y - center.y, center.x - point.x);
var angle = (-deg / (Math.PI / 180));
if (angle < this._start) angle += 360;
angle = this._checkAngle(angle);
return this._processStepByAngle(angle);;
},
_checkAngle: function (angle) {
var o_angle = this._oriAngle(angle);
if (o_angle > this._end) {
var preAngle = this._oriAngle(this["_handle" + this._active].angle);
angle = this._start + (preAngle <= this._end - preAngle ? 0 : this._end);
}
return angle;
},
_processStepByAngle: function (angle) {
var value = this._angleToValue(angle);
return this._processStepByValue(value);
},
_processStepByValue: function (value) {
var step = this.options.step, remain, currVal, nextVal, preVal, val, ang;
remain = (value - this.options.min) % step;
currVal = value - remain;
nextVal = this._limitValue(currVal + step);
preVal = this._limitValue(currVal - step);
if (value >= currVal) val = (value - currVal < nextVal - value) ? currVal : nextVal;
else val = (currVal - value > value - preVal) ? currVal : preVal;
val = this._round(val), ang = this._valueToAngle(val);
return { value: val, angle: ang };
},
_round: function (val) {
var s = this.options.step.toString().split(".");
return s[1] ? parseFloat(val.toFixed(s[1].length)) : Math.round(val);
},
_oriAngle: function (angle) {
var ang = angle - this._start;
if (ang < 0) ang += 360;
return ang;
},
_limitAngle: function (angle) {
if (angle > 360 + this._start) angle -= 360;
if (angle < this._start) angle += 360;
return angle;
},
_limitValue: function (value) {
if (value < this.options.min) value = this.options.min;
if (value > this.options.max) value = this.options.max;
return value;
},
_angleToValue: function (angle) {
var m = this.options, value;
value = (this._oriAngle(angle) / this._end) * (m.max - m.min) + m.min;
return value;
},
_valueToAngle: function (value) {
var m = this.options, angle;
angle = (((value - m.min) / (m.max - m.min)) * this._end) + this._start;
return angle;
},
_appendHiddenField: function () {
this._hiddenField = createElement("input").attr({
"type": "hidden", "name": this.control[0].id || "", value: this.options.value
});
this.control.append(this._hiddenField);
},
_updateHidden: function () {
this._hiddenField.val(this.options.value);
},
_updateTooltip: function () {
if (this.tooltip && !this.tooltip.hasClass("hover"))
this.tooltip.html(this._getTooltipValue());
this._updateTooltipPos();
},
_updateTooltipPos: function () {
this.tooltip && this.tooltip.css(this._getTooltipPos());
},
_getTooltipPos: function () {
var circleShape = this.options.circleShape, pos;
if (circleShape == "full" || circleShape == "pie" || circleShape.indexOf("custom") === 0)
return {
"margin-top": -this.tooltip.outerHeight() / 2,
"margin-left": -this.tooltip.outerWidth() / 2
};
else if (circleShape.indexOf("half") != -1) {
switch (circleShape) {
case "half-top":
case "half-bottom":
pos = { "margin-left": -this.tooltip.outerWidth() / 2 }; break;
case "half-left":
case "half-right":
pos = { "margin-top": -this.tooltip.outerHeight() / 2 }; break;
}
return pos;
}
return {};
},
_getTooltipValue: function (isNormal) {
if (this._rangeSlider) {
var p = this.options.value.split(",");
if (isNormal) return p[0] + " - " + p[1];
return this._tooltipValue(p[0]) + " - " + this._tooltipValue(p[1]);
}
if (isNormal) return this.options.value;
return this._tooltipValue(this.options.value);
},
_tooltipValue: function (value) {
var val = this._raise("tooltipFormat", { value: value, "handle": this._handleArgs() });
return (val != null && typeof val !== "boolean") ? val : value;
},
_validateStartAngle: function () {
var start = this.options.startAngle;
start = (isNumber(start) ? parseFloat(start) : 0) % 360;
if (start < 0) start += 360;
this.options.startAngle = start;
return start;
},
_validateEndAngle: function () {
var end = this.options.endAngle;
if (typeof end === "string" && isNumber(end) && (end.charAt(0) === "+" || end.charAt(0) === "-")) {
try { end = eval(this.options.startAngle + end.charAt(0) + Math.abs(parseFloat(end))); }
catch (e) { console.warn(e); }
}
end = (isNumber(end) ? parseFloat(end) : 360) % 360;
if (end <= this.options.startAngle) end += 360;
return end;
},
_refreshCircleShape: function () {
var circleShape = this.options.circleShape;
var circel_shapes = ["half-top", "half-bottom", "half-left", "half-right",
"quarter-top-left", "quarter-top-right", "quarter-bottom-right", "quarter-bottom-left",
"pie", "custom-half", "custom-quarter"];
var shape_codes = ["h1", "h2", "h3", "h4", "q1", "q2", "q3", "q4", "3/4", "ch", "cq"];
if (circel_shapes.indexOf(circleShape) == -1) {
var index = shape_codes.indexOf(circleShape);
if (index != -1) circleShape = circel_shapes[index];
else if (circleShape == "half") circleShape = "half-top";
else if (circleShape == "quarter") circleShape = "quarter-top-left";
else circleShape = "full";
}
this.options.circleShape = circleShape;
},
_appendOverlay: function () {
var shape = this.options.circleShape;
if (shape == "pie")
this._checkOverlay(".rs-overlay", 270);
else if (shape == "custom-half" || shape == "custom-quarter") {
this._checkOverlay(".rs-overlay1", 180);
if (shape == "custom-quarter")
this._checkOverlay(".rs-overlay2", this._end);
}
},
_checkOverlay: function (cls, angle) {
var overlay = this.container.children(cls);
if (overlay.length == 0) {
overlay = createElement("div" + cls + " rs-transition rs-bg-color");
this.container.append(overlay);
}
overlay.rsRotate(this._start + angle);
},
_checkDataType: function () {
var m = this.options, i, prop, value, props = this._props();
// to check number datatype
for (i in props.numberType) {
prop = props.numberType[i], value = m[prop];
if (!isNumber(value)) m[prop] = this.defaults[prop];
else m[prop] = parseFloat(value);
}
// to check input string
for (i in props.booleanType) {
prop = props.booleanType[i], value = m[prop];
m[prop] = (value == "false") ? false : !!value;
}
// to check boolean datatype
for (i in props.stringType) {
prop = props.stringType[i], value = m[prop];
m[prop] = ("" + value).toLowerCase();
}
},
_validateSliderType: function () {
var type = this.options.sliderType.toLowerCase();
this._rangeSlider = this._showRange = false;
if (type == "range") this._rangeSlider = this._showRange = true;
else if (type.indexOf("min") != -1) {
this._showRange = true;
type = "min-range";
}
else type = "default";
this.options.sliderType = type;
},
_updateStartEnd: function () {
var circle = this.options.circleShape;
if (circle != "full") {
if (circle.indexOf("quarter") != -1) this.options.endAngle = "+90";
else if (circle.indexOf("half") != -1) this.options.endAngle = "+180";
else if (circle == "pie") this.options.endAngle = "+270";
if (circle == "quarter-top-left" || circle == "half-top") this.options.startAngle = 0;
else if (circle == "quarter-top-right" || circle == "half-right") this.options.startAngle = 90;
else if (circle == "quarter-bottom-right" || circle == "half-bottom") this.options.startAngle = 180;
else if (circle == "quarter-bottom-left" || circle == "half-left") this.options.startAngle = 270;
}
},
_validateStartEnd: function () {
this._start = this._validateStartAngle();
this._end = this._validateEndAngle();
var add = (this._start < this._end) ? 0 : 360;
this._end += add - this._start;
},
_analyzeModelValue: function () {
var val = this.options.value, min = this.options.min, max = this.options.max, last, t;
var parts = (typeof val == "string") ? val.split(",") : [val];
if (this._rangeSlider) {
if (typeof val == "string") {
if (parts.length >= 2) t = (isNumber(parts[0]) ? parts[0] : min) + "," +
(isNumber(parts[1]) ? parts[1] : max);
else t = isNumber(parts[0]) ? min + "," + parts[0] : min + "," + min;
}
else t = isNumber(val) ? min + "," + val : min + "," + min;
}
else {
if (typeof val == "string") last = parts.pop(), t = isNumber(last) ? parseFloat(last) : min;
else t = isNumber(val) ? parseFloat(val) : min;
}
this.options.value = t;
},
_validateModelValue: function () {
var val = this.options.value;
if (this._rangeSlider) {
var parts = val.split(","), val1 = parseFloat(parts[0]), val2 = parseFloat(parts[1]);
val1 = this._limitValue(val1);
val2 = this._limitValue(val2);
if (val1 > val2) val2 = val1;
this._handle1 = this._processStepByValue(val1);
this._handle2 = this._processStepByValue(val2);
this.options.value = this._handle1.value + "," + this._handle2.value;
}
else {
var index = this._showRange ? 2 : (this._active || 1);
this["_handle" + index] = this._processStepByValue(this._limitValue(val));
if (this._showRange) this._handle1 = this._handleDefaults();
this.options.value = this["_handle" + index].value;
}
},
// common core methods
_isBrowserSupported: function () {
var properties = ["borderRadius", "WebkitBorderRadius", "MozBorderRadius",
"OBorderRadius", "msBorderRadius", "KhtmlBorderRadius"];
for (var i = 0; i < properties.length; i++) {
if (document.body.style[properties[i]] !== undefined) return true;
}
},
_throwError: function () {
return "This browser doesn't support the border-radious property.";
},
_checkIE: function () {
var ua = window.navigator.userAgent;
if (ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0)
this.control.css({ "-ms-touch-action": "none", "touch-action": "none" });
},
_raise: function (event, args) {
var fn = this.options[event], val = true;
args = args || {};
if (fn) {
args["type"] = event;
if (typeof fn === "string") fn = window[fn];
if ($.isFunction(fn)) {
val = fn.call(this, args);
val = val === false ? false : val;
}
}
this.control.trigger($.Event ? $.Event(event, args) : event);
return val;
},
_bind: function (element, _event, handler) {
$(element).bind(_event, $proxy(handler, this));
},
_unbind: function (element, _event, handler) {
if ($.proxy) $(element).unbind(_event, $.proxy(handler, this));
else $(element).unbind(_event);
},
_getInstance: function () {
return $data(this.control[0], pluginName);
},
_removeData: function () {
var control = this.control[0];
$.removeData && $.removeData(control, pluginName);
if (control.id) delete window[control.id];
},
_destroyControl: function () {
this.control.empty().removeClass("rs-control").height("").width("");
this._removeAnimation();
this._bindControlEvents("_unbind");
},
// methods to dynamic options updation (through option)
_updateWidth: function () {
this.lastBlock.css("padding", this.options.width);
this._refreshHandle();
},
_readOnly: function (bool) {
this._isReadOnly = bool;
this.container.removeClass("rs-readonly");
if (bool) this.container.addClass("rs-readonly");
},
// get & set for the properties
_get: function (property) {
return this.options[property];
},
_set: function (property, value) {
var props = this._props();
if ($.inArray(property, props.numberType) != -1) { // to check number datatype
if (!isNumber(value)) return;
value = parseFloat(value);
}
else if ($.inArray(property, props.booleanType) != -1) { // to check boolean datatype
value = (value == "false") ? false : !!value;
}
else if ($.inArray(property, props.stringType) != -1) { // to check input string
value = value.toLowerCase();
}
if (this.options[property] == value) return;
this.options[property] = value;
switch (property) {
case "startAngle":
case "endAngle":
this._validateStartEnd();
this._updateSeperator();
this._appendOverlay();
case "min":
case "max":
case "step":
case "value":
this._analyzeModelValue();
this._validateModelValue();
this._setValue();
this._updateHidden();
this._updateTooltip();
break;
case "radius":
this._setRadius();
this._updateTooltipPos();
break;
case "width":
this._removeAnimation();
this._updateWidth();
this._updateTooltipPos();
this._addAnimation();
this.container.children().find(".rs-seperator").css({ "width": this.options.width, "margin-left": this._border() / 2 });
break;
case "handleSize":
this._refreshHandle();
break;
case "handleShape":
this._setHandleShape();
break;
case "animation":
this._setAnimation();
break;
case "showTooltip":
this.options.showTooltip ? this._appendTooltip() : this._removeTooltip();
break;
case "editableTooltip":
this._tooltipEditable();
this._updateTooltipPos();
break;
case "disabled":
this.options.disabled ? this.disable() : this.enable();
break;
case "readOnly":
this.options.readOnly ? this._readOnly(true) : (!this.options.disabled && this._readOnly(false));
break;
case "mouseScrollAction":
this._bindScrollEvents(this.options.mouseScrollAction ? "_bind" : "_unbind");
break;
case "circleShape":
this._refreshCircleShape();
if (this.options.circleShape == "full") {
this.options.startAngle = 0;
this.options.endAngle = "+360";
}
case "sliderType":
this._destroyControl();
this._init();
break;
}
return this;
},
// public methods
option: function (property, value) {
if (!this._getInstance() || !this._isBrowserSupport) return;
if ($isPlainObject(property)) {
if (property["min"] !== undefined || property["max"] !== undefined) {
if (property["min"] !== undefined) {
this.options.min = property["min"];
delete property["min"];
}
if (property["max"] !== undefined) {
this.options.max = property["max"];
delete property["max"];
}
if (property["value"] == undefined) {
this._set("value", this.options.value);
}
}
for (var prop in property) {
this._set(prop, property[prop]);
}
}
else if (property && typeof property == "string") {
if (value === undefined) return this._get(property);
this._set(property, value);
}
return this;
},
getValue: function (index) {
if (this.options.sliderType == "range" && isNumber(index)) {
var i = parseFloat(index);
if (i == 1 || i == 2)
return this["_handle" + i].value;
}
return this._get("value");
},
setValue: function (value, index) {
if (isNumber(value)) {
if (isNumber(index)) {
if (this.options.sliderType == "range") {
var i = parseFloat(index), val = parseFloat(value);
if (i == 1) value = val + "," + this._handle2.value;
else if (i == 2) value = this._handle1.value + "," + val;
}
else if (this.options.sliderType == "default") this._active = index;
}
this._set("value", value);
}
},
disable: function () {
this.options.disabled = true;
this.container.addClass("rs-disabled");
this._readOnly(true);
},
enable: function () {
this.options.disabled = false;
this.container.removeClass("rs-disabled");
if (!this.options.readOnly) this._readOnly(false);
},
destroy: function () {
if (!this._getInstance()) return;
this._destroyControl();
this._removeData();
this._originalObj.insertAfter(this.control);
this.control.remove();
}
};
$.fn.rsRotate = function (degree) {
return setTransform(this, degree);
}
if (typeof $.fn.outerHeight == "undefined") {
$.fn.outerHeight = function () { return this[0].offsetHeight; }
$.fn.outerWidth = function () { return this[0].offsetWidth; }
}
if (typeof $.fn.hasClass === "undefined") {
$.fn.hasClass = function (name) {
return this[0].className.split(" ").indexOf(name) !== -1;
}
}
if (typeof $.fn.offset === "undefined") {
$.fn.offset = function () {
return { left: this[0].offsetLeft, top: this[0].offsetTop };
}
}
function $proxy(fn, that) {
if (typeof $.proxy === "function") return $.proxy(fn, that);
return function (e) { fn.call(that, e); };
}
function $data(ele, name, data) {
if (typeof $.data === "function") return $.data(ele, name, data);
else if (!data) return $(ele).hasClass("rs-control");
}
function $isPlainObject(obj) {
if (typeof $.isPlainObject === "function") return $.isPlainObject(obj);
else {
var str = JSON.stringify(obj);
return typeof obj === "object" && obj.length === undefined &&
str.length > 2 && str.substr(0, 1) === "{" && str.substr(str.length - 1) === "}";
}
}
//core functions
function isNumber(number) {
number = parseFloat(number);
return typeof number === "number" && !isNaN(number);
}
function createElement(tag) {
var t = tag.split('.');
return $(document.createElement(t[0])).addClass(t[1] || "");
}
function getdistance(p1, p2) {
return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
function setTransform(control, value) {
control.css('-webkit-transform', "rotate(" + value + "deg)");
control.css('-moz-transform', "rotate(" + value + "deg)");
control.css('-ms-transform', "rotate(" + value + "deg)");
control.css('-o-transform', "rotate(" + value + "deg)");
control.css('transform', "rotate(" + value + "deg)");
return control;
}
// The plugin constructor
function RoundSlider(control, options) {
if (control.id) window[control.id] = this;
this.control = $(control);
// the options value holds the updated defaults value
this.options = $.extend({}, this.defaults, options);
if (this._raise("beforeCreate") !== false) {
this._init();
this._raise("create");
}
else this._removeData();
}
// The plugin wrapper, prevents multiple instantiations
function CreateRoundSlider(options, args) {
for (var i = 0; i < this.length; i++) {
var that = this[i], instance = $data(that, pluginName);
if (!instance) {
$data(that, pluginName, new RoundSlider(that, options));
}
else if ($isPlainObject(options)) {
if (typeof instance.option === "function") instance.option(options);
else if (that.id && window[that.id] && typeof window[that.id].option === "function") {
window[that.id].option(options);
}
}
else if (typeof options === "string") {
if (typeof instance[options] === "function") {
if ((options === "option" || (typeof options.startsWith === 'function' && options.startsWith("get"))) && args[2] === undefined) {
return instance[options](args[1]);
}
instance[options](args[1], args[2]);
}
}
}
return this;
}
$.fn[pluginName].prototype = RoundSlider.prototype;
})(jQuery, window);