webapp.static.js.jquery.knob.modified.js Maven / Gradle / Ivy
/**
* Knob - jQuery Plugin
* Downward compatible, touchable dial
*
* Version: 1.1.2 (22/05/2012)
* Requires: jQuery v1.7+
*
* Copyright (c) 2011 Anthony Terrien
* Under MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Thanks to vor, eskimoblood, spiffistan
*/
$(function () {
// Dial logic
var Dial = function (c, opt) {
var v = null
,ctx = c[0].getContext("2d")
,PI2 = 2 * Math.PI
,mx ,my ,x ,y
,self = this;
this.onChange = function () {};
this.onCancel = function () {};
this.onRelease = function () {};
this.val = function (nv) {
if (null != nv) {
opt.stopper && (nv = Math.max(Math.min(nv, opt.max), opt.min));
v = nv;
this.onChange(nv);
if(opt.dynamicDraw) this.dynamicDraw(nv);
else this.draw(nv);
} else {
var b, a;
b = a = Math.atan2(mx - x, -(my - y - opt.width / 2)) - opt.angleOffset;
(a < 0) && (b = a + PI2);
nv = Math.round(b * (opt.max - opt.min) / PI2) + opt.min;
return (nv > opt.max) ? opt.max : nv;
}
};
this.change = function (nv) {
opt.stopper && (nv = Math.max(Math.min(nv, opt.max), opt.min));
this.onChange(nv);
this.draw(nv);
};
this.angle = function (nv) {
return (nv - opt.min) * PI2 / (opt.max - opt.min);
};
this.draw = function (nv) {
var a = this.angle(nv) // Angle
,sa = 1.5 * Math.PI + opt.angleOffset // Previous start angle
,sat = sa // Start angle
,ea = sa + this.angle(v) // Previous end angle
,eat = sat + a // End angle
,r = opt.width / 2 // Radius
,lw = r * opt.thickness // Line width
,cgcolor = Dial.getCgColor(opt.cgColor)
,tick
;
ctx.clearRect(0, 0, opt.width, opt.width);
ctx.lineWidth = lw;
// Hook draw
if (opt.draw(a, v, opt, ctx)) { return; }
for (tick = 0; tick < opt.ticks; tick++) {
ctx.beginPath();
if (a > (((2 * Math.PI) / opt.ticks) * tick) && opt.tickColorizeValues) {
ctx.strokeStyle = opt.fgColor;
} else {
ctx.strokeStyle = opt.tickColor;
}
var tick_sa = (((2 * Math.PI) / opt.ticks) * tick) - (0.5 * Math.PI);
ctx.arc( r, r, r-lw-opt.tickLength, tick_sa, tick_sa+opt.tickWidth , false);
ctx.stroke();
}
opt.cursor
&& (sa = ea - 0.3)
&& (ea = ea + 0.3)
&& (sat = eat - 0.3)
&& (eat = eat + 0.3);
switch (opt.skin) {
case 'default' :
ctx.beginPath();
ctx.strokeStyle = opt.bgColor;
ctx.arc(r, r, r - lw / 2, 0, PI2, true);
ctx.stroke();
if (opt.displayPrevious) {
ctx.beginPath();
ctx.strokeStyle = (v == nv) ? opt.fgColor : cgcolor;
ctx.arc(r, r, r - lw / 2, sa, ea, false);
ctx.stroke();
}
ctx.beginPath();
ctx.strokeStyle = opt.fgColor;
ctx.arc(r, r, r - lw / 2, sat, eat, false);
ctx.stroke();
break;
case 'tron' :
if (opt.displayPrevious) {
ctx.beginPath();
ctx.strokeStyle = (v == nv) ? opt.fgColor : cgcolor;
ctx.arc( r, r, r - lw, sa, ea, false);
ctx.stroke();
}
ctx.beginPath();
ctx.strokeStyle = opt.fgColor;
ctx.arc( r, r, r - lw, sat, eat, false);
ctx.stroke();
ctx.lineWidth = 2;
ctx.beginPath();
ctx.strokeStyle = opt.fgColor;
ctx.arc( r, r, r - lw + 1 + lw * 2 / 3, 0, 2 * Math.PI, false);
ctx.stroke();
break;
}
};
var dynamicDrawIndex;
var dynamicDrawInterval;
this.dynamicDraw = function (nv) {
var instanceOfThis = this;
dynamicDrawIndex = opt.min;
dynamicDrawInterval = setInterval(function() {
instanceOfThis.animateDraw(nv);
}, 20);
};
this.animateDraw = function () {
if(dynamicDrawIndex > v) {
clearInterval(dynamicDrawInterval);
v = dynamicDrawIndex;
} else {
this.draw(dynamicDrawIndex);
this.change(dynamicDrawIndex);
dynamicDrawIndex++;
}
};
this.capture = function (e) {
switch (e.type) {
case 'mousemove' :
case 'mousedown' :
mx = e.pageX;
my = e.pageY;
break;
case 'touchmove' :
case 'touchstart' :
mx = e.originalEvent.touches[0].pageX;
my = e.originalEvent.touches[0].pageY;
break;
}
this.change( this.val() );
};
this.cancel = function () {
self.val(v);
self.onCancel();
};
this.startDrag = function (e) {
var p = c.offset()
,$doc = $(document);
x = p.left + (opt.width / 2);
y = p.top;
this.capture(e);
// Listen mouse and touch events
$doc.bind(
"mousemove.dial touchmove.dial"
,function (e) {
self.capture(e);
}
)
.bind(
// Escape
"keyup.dial"
,function (e) {
if(e.keyCode === 27) {
$doc.unbind("mouseup.dial mousemove.dial keyup.dial");
self.cancel();
}
}
)
.bind(
"mouseup.dial touchend.dial"
,function (e) {
$doc.unbind('mousemove.dial touchmove.dial mouseup.dial touchend.dial keyup.dial');
self.val(self.val());
self.onRelease(v);
}
);
};
};
// Dial static func
Dial.getCgColor = function (h) {
h = h.substring(1,7);
var rgb = [parseInt(h.substring(0,2),16)
,parseInt(h.substring(2,4),16)
,parseInt(h.substring(4,6),16)];
return "rgba("+rgb[0]+","+rgb[1]+","+rgb[2]+",.5)";
};
// jQuery plugin
$.fn.knob = $.fn.dial = function (gopt) {
return this.each(
function () {
var $this = $(this), opt;
if ($this.data('dialed')) { return $this; }
$this.data('dialed', true);
opt = $.extend(
{
// Config
'min' : $this.data('min') || 0
,'max' : $this.data('max') || 100
,'stopper' : true
,'readOnly' : $this.data('readonly')
// UI
,'cursor' : $this.data('cursor')
,'thickness' : $this.data('thickness') || 0.35
,'width' : $this.data('width') || 200
,'displayInput' : $this.data('displayinput') == null || $this.data('displayinput')
,'displayPrevious' : $this.data('displayprevious')
,'fgColor' : $this.data('fgcolor') || '#87CEEB'
,'cgColor' : $this.data('cgcolor') || $this.data('fgcolor') || '#87CEEB'
,'bgColor' : $this.data('bgcolor') || '#EEEEEE'
,'tickColor' : $this.data('tickColor') || $this.data('fgcolor') || '#DDDDDD'
,'ticks' : $this.data('ticks') || 0
,'tickLength' : $this.data('tickLength') || 0
,'tickWidth' : $this.data('tickWidth') || 0.02
,'tickColorizeValues' : $this.data('tickColorizeValues') || true
,'skin' : $this.data('skin') || 'default'
,'angleOffset': degreeToRadians($this.data('angleoffset'))
,'dynamicDraw': $this.data('dynamicdraw') || false
// Hooks
,'draw' :
/**
* @param int a angle
* @param int v current value
* @param array opt plugin options
* @param context ctx Canvas context 2d
* @return bool true:bypass default draw methode
*/
function (a, v, opt, ctx) {}
,'change' :
/**
* @param int v Current value
*/
function (v) {}
,'release' :
/**
* @param int v Current value
* @param jQuery ipt Input
*/
function (v, ipt) {}
}
,gopt
);
var c = $('')
,wd = $('')
,k
,vl = $this.val()
,initStyle = function () {
opt.displayInput
&& $this.css({
'width' : opt.width / 2 + 'px'
,'position' : 'absolute'
,'margin-top' : (opt.width * 5 / 14) + 'px'
,'margin-left' : '-' + (opt.width * 3 / 4) + 'px'
,'font-size' : (opt.width / 4) + 'px'
,'border' : 'none'
,'background' : 'none'
,'font-family' : 'Arial'
,'font-weight' : 'bold'
,'text-align' : 'center'
,'color' : opt.fgColor
,'padding' : '0px'
,'-webkit-appearance': 'none'
})
|| $this.css({
'width' : '0px'
,'visibility' : 'hidden'
});
};
// Canvas insert
$this.wrap(wd).before(c);
initStyle();
// Invoke dial logic
k = new Dial(c, opt);
vl || (vl = opt.min);
$this.val(vl);
k.val(vl);
k.onRelease = function (v) {
opt.release(v, $this);
};
k.onChange = function (v) {
$this.val(v);
opt.change(v);
};
// bind change on input
$this.bind(
'change'
,function (e) {
k.val($this.val());
}
);
if (!opt.readOnly) {
// canvas
c.bind(
"mousedown touchstart"
,function (e) {
e.preventDefault();
k.startDrag(e);
}
)
.bind(
"mousewheel DOMMouseScroll"
,mw = function (e) {
e.preventDefault();
var ori = e.originalEvent
,deltaX = ori.detail || ori.wheelDeltaX
,deltaY = ori.detail || ori.wheelDeltaY
,val = parseInt($this.val()) + (deltaX>0 || deltaY>0 ? 1 : deltaX<0 || deltaY<0 ? -1 : 0);
k.val(val);
}
);
// input
var kval, val, to, m = 1, kv = {37:-1, 38:1, 39:1, 40:-1};
$this
.bind(
"configure"
,function (e, aconf) {
var kconf;
for (kconf in aconf) { opt[kconf] = aconf[kconf]; }
initStyle();
k.val($this.val());
}
)
.bind(
"keydown"
,function (e) {
var kc = e.keyCode;
if (kc >= 96 && kc <= 105) kc -= 48; //numpad
kval = parseInt(String.fromCharCode(kc));
if (isNaN(kval)) {
(kc !== 13) // enter
&& (kc !== 8) // bs
&& (kc !== 9) // tab
&& (kc !== 189) // -
&& e.preventDefault();
// arrows
if ($.inArray(kc,[37,38,39,40]) > -1) {
k.change(parseInt($this.val()) + kv[kc] * m);
// long time keydown speed-up
to = window.setTimeout(
function () { m < 20 && m++; }
,50
);
e.preventDefault();
}
}
}
)
.bind(
"keyup"
,function(e) {
if (isNaN(kval)) {
if (to) {
window.clearTimeout(to);
to = null;
m = 1;
k.val($this.val());
k.onRelease($this.val(), $this);
} else {
// enter
(e.keyCode === 13)
&& k.onRelease($this.val(), $this);
}
} else {
// kval postcond
($this.val() > opt.max && $this.val(opt.max))
|| ($this.val() < opt.min && $this.val(opt.min));
}
}
)
.bind(
"mousewheel DOMMouseScroll"
,mw
);
} else {
$this.attr('readonly', 'readonly');
}
}
).parent();
};
function degreeToRadians (angle) {
return $.isNumeric(angle) ? angle * Math.PI / 180 : 0;
}
});