Blame | Letzte Änderung | Log anzeigen | RSS feed
/*!jQuery Knob*//*** Downward compatible, touchable dial** Version: 1.2.8* Requires: jQuery v1.7+** Copyright (c) 2012 Anthony Terrien* Under MIT License (http://www.opensource.org/licenses/mit-license.php)** Thanks to vor, eskimoblood, spiffistan, FabrizioC*/(function($) {/*** Kontrol library*/"use strict";/*** Definition of globals and core*/var k = {}, // kontrolmax = Math.max,min = Math.min;k.c = {};k.c.d = $(document);k.c.t = function (e) {return e.originalEvent.touches.length - 1;};/*** Kontrol Object** Definition of an abstract UI control** Each concrete component must call this one.* <code>* k.o.call(this);* </code>*/k.o = function () {var s = this;this.o = null; // array of optionsthis.$ = null; // jQuery wrapped elementthis.i = null; // mixed HTMLInputElement or array of HTMLInputElementthis.g = null; // deprecated 2D graphics context for 'pre-rendering'this.v = null; // value ; mixed array or integerthis.cv = null; // change value ; not commited valuethis.x = 0; // canvas x positionthis.y = 0; // canvas y positionthis.w = 0; // canvas widththis.h = 0; // canvas heightthis.$c = null; // jQuery canvas elementthis.c = null; // rendered canvas contextthis.t = 0; // touches indexthis.isInit = false;this.fgColor = null; // main colorthis.pColor = null; // previous colorthis.dH = null; // draw hookthis.cH = null; // change hookthis.eH = null; // cancel hookthis.rH = null; // release hookthis.scale = 1; // scale factorthis.relative = false;this.relativeWidth = false;this.relativeHeight = false;this.$div = null; // component divthis.run = function () {var cf = function (e, conf) {var k;for (k in conf) {s.o[k] = conf[k];}s._carve().init();s._configure()._draw();};if(this.$.data('kontroled')) return;this.$.data('kontroled', true);this.extend();this.o = $.extend({// Configmin : this.$.data('min') !== undefined ? this.$.data('min') : 0,max : this.$.data('max') !== undefined ? this.$.data('max') : 100,stopper : true,readOnly : this.$.data('readonly') || (this.$.attr('readonly') === 'readonly'),// UIcursor : (this.$.data('cursor') === true && 30) ||this.$.data('cursor') || 0,thickness : (this.$.data('thickness') &&Math.max(Math.min(this.$.data('thickness'), 1), 0.01)) || 0.35,lineCap : this.$.data('linecap') || 'butt',width : this.$.data('width') || 200,height : this.$.data('height') || 200,displayInput : this.$.data('displayinput') == null || this.$.data('displayinput'),displayPrevious : this.$.data('displayprevious'),fgColor : this.$.data('fgcolor') || '#87CEEB',inputColor: this.$.data('inputcolor'),font: this.$.data('font') || 'Arial',fontWeight: this.$.data('font-weight') || 'bold',inline : false,step : this.$.data('step') || 1,rotation: this.$.data('rotation'),// Hooksdraw : null, // function () {}change : null, // function (value) {}cancel : null, // function () {}release : null, // function (value) {}// Output formatting, allows to add unit: %, ms ...format: function(v) {return v;},parse: function (v) {return parseFloat(v);}}, this.o);// finalize optionsthis.o.flip = this.o.rotation === 'anticlockwise' || this.o.rotation === 'acw';if(!this.o.inputColor) {this.o.inputColor = this.o.fgColor;}// routing valueif(this.$.is('fieldset')) {// fieldset = array of integerthis.v = {};this.i = this.$.find('input');this.i.each(function(k) {var $this = $(this);s.i[k] = $this;s.v[k] = s.o.parse($this.val());$this.bind('change blur', function () {var val = {};val[k] = $this.val();s.val(val);});});this.$.find('legend').remove();} else {// input = integerthis.i = this.$;this.v = this.o.parse(this.$.val());(this.v === '') && (this.v = this.o.min);this.$.bind('change blur', function () {s.val(s._validate(s.o.parse(s.$.val())));});}(!this.o.displayInput) && this.$.hide();// adds needed DOM elements (canvas, div)this.$c = $(document.createElement('canvas')).attr({width: this.o.width,height: this.o.height});// wraps all elements in a div// add to DOM before Canvas init is triggeredthis.$div = $('<div style="'+ (this.o.inline ? 'display:inline;' : '')+ 'width:' + this.o.width + 'px;height:' + this.o.height + 'px;'+ '"></div>');this.$.wrap(this.$div).before(this.$c);this.$div = this.$.parent();if (typeof G_vmlCanvasManager !== 'undefined') {G_vmlCanvasManager.initElement(this.$c[0]);}this.c = this.$c[0].getContext ? this.$c[0].getContext('2d') : null;if (!this.c) {throw {name: "CanvasNotSupportedException",message: "Canvas not supported. Please use excanvas on IE8.0.",toString: function(){return this.name + ": " + this.message}}}// hdpi supportthis.scale = (window.devicePixelRatio || 1) /(this.c.webkitBackingStorePixelRatio ||this.c.mozBackingStorePixelRatio ||this.c.msBackingStorePixelRatio ||this.c.oBackingStorePixelRatio ||this.c.backingStorePixelRatio || 1);// detects relative width / heightthis.relativeWidth = ((this.o.width % 1 !== 0) &&this.o.width.indexOf('%'));this.relativeHeight = ((this.o.height % 1 !== 0) &&this.o.height.indexOf('%'));this.relative = (this.relativeWidth || this.relativeHeight);// computes size and carves the componentthis._carve();// prepares props for transactionif (this.v instanceof Object) {this.cv = {};this.copy(this.v, this.cv);} else {this.cv = this.v;}// binds configure eventthis.$.bind("configure", cf).parent().bind("configure", cf);// finalize initthis._listen()._configure()._xy().init();this.isInit = true;this.$.val(this.o.format(this.v));this._draw();return this;};this._carve = function() {if(this.relative) {var w = this.relativeWidth ?this.$div.parent().width() *parseInt(this.o.width) / 100 :this.$div.parent().width(),h = this.relativeHeight ?this.$div.parent().height() *parseInt(this.o.height) / 100 :this.$div.parent().height();// apply relativethis.w = this.h = Math.min(w, h);} else {this.w = this.o.width;this.h = this.o.height;}// finalize divthis.$div.css({'width': this.w + 'px','height': this.h + 'px'});// finalize canvas with computed widththis.$c.attr({width: this.w,height: this.h});// scalingif (this.scale !== 1) {this.$c[0].width = this.$c[0].width * this.scale;this.$c[0].height = this.$c[0].height * this.scale;this.$c.width(this.w);this.$c.height(this.h);}return this;}this._draw = function () {// canvas pre-renderingvar d = true;s.g = s.c;s.clear();s.dH&& (d = s.dH());(d !== false) && s.draw();};this._touch = function (e) {var touchMove = function (e) {var v = s.xy2val(e.originalEvent.touches[s.t].pageX,e.originalEvent.touches[s.t].pageY);if (v == s.cv) return;if (s.cH && (s.cH(v) === false)) return;s.change(s._validate(v));s._draw();};// get touches indexthis.t = k.c.t(e);// First touchtouchMove(e);// Touch events listenersk.c.d.bind("touchmove.k", touchMove).bind("touchend.k", function () {k.c.d.unbind('touchmove.k touchend.k');s.val(s.cv);});return this;};this._mouse = function (e) {var mouseMove = function (e) {var v = s.xy2val(e.pageX, e.pageY);if (v == s.cv) return;if (s.cH && (s.cH(v) === false)) return;s.change(s._validate(v));s._draw();};// First clickmouseMove(e);// Mouse events listenersk.c.d.bind("mousemove.k", mouseMove).bind(// Escape key cancel current change"keyup.k", function (e) {if (e.keyCode === 27) {k.c.d.unbind("mouseup.k mousemove.k keyup.k");if (s.eH&& (s.eH() === false)) return;s.cancel();}}).bind("mouseup.k", function (e) {k.c.d.unbind('mousemove.k mouseup.k keyup.k');s.val(s.cv);});return this;};this._xy = function () {var o = this.$c.offset();this.x = o.left;this.y = o.top;return this;};this._listen = function () {if (!this.o.readOnly) {this.$c.bind("mousedown", function (e) {e.preventDefault();s._xy()._mouse(e);}).bind("touchstart", function (e) {e.preventDefault();s._xy()._touch(e);});this.listen();} else {this.$.attr('readonly', 'readonly');}if(this.relative) {$(window).resize(function() {s._carve().init();s._draw();});}return this;};this._configure = function () {// Hooksif (this.o.draw) this.dH = this.o.draw;if (this.o.change) this.cH = this.o.change;if (this.o.cancel) this.eH = this.o.cancel;if (this.o.release) this.rH = this.o.release;if (this.o.displayPrevious) {this.pColor = this.h2rgba(this.o.fgColor, "0.4");this.fgColor = this.h2rgba(this.o.fgColor, "0.6");} else {this.fgColor = this.o.fgColor;}return this;};this._clear = function () {this.$c[0].width = this.$c[0].width;};this._validate = function(v) {return (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step;};// Abstract methodsthis.listen = function () {}; // on start, one timethis.extend = function () {}; // each time configure triggeredthis.init = function () {}; // each time configure triggeredthis.change = function (v) {}; // on changethis.val = function (v) {}; // on releasethis.xy2val = function (x, y) {}; //this.draw = function () {}; // on change / on releasethis.clear = function () { this._clear(); };// Utilsthis.h2rgba = function (h, a) {var rgb;h = h.substring(1,7)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] + "," + a + ")";};this.copy = function (f, t) {for (var i in f) { t[i] = f[i]; }};};/*** k.Dial*/k.Dial = function () {k.o.call(this);this.startAngle = null;this.xy = null;this.radius = null;this.lineWidth = null;this.cursorExt = null;this.w2 = null;this.PI2 = 2*Math.PI;this.extend = function () {this.o = $.extend({bgColor : this.$.data('bgcolor') || '#EEEEEE',angleOffset : this.$.data('angleoffset') || 0,angleArc : this.$.data('anglearc') || 360,inline : true}, this.o);};this.val = function (v, triggerRelease) {if (null != v) {// reverse formatv = this.o.parse(v);if (triggerRelease !== false && (v != this.v) && this.rH &&(this.rH(v) === false)) return;this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v;this.v = this.cv;this.$.val(this.o.format(this.v));this._draw();} else {return this.v;}};this.xy2val = function (x, y) {var a, ret;a = Math.atan2(x - (this.x + this.w2), - (y - this.y - this.w2)) - this.angleOffset;if (this.o.flip) {a = this.angleArc - a - this.PI2;}if(this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) {// if isset angleArc option, set to min if .5 under mina = 0;} else if (a < 0) {a += this.PI2;}ret = ~~ (0.5 + (a * (this.o.max - this.o.min) / this.angleArc))+ this.o.min;this.o.stopper && (ret = max(min(ret, this.o.max), this.o.min));return ret;};this.listen = function () {// bind MouseWheelvar s = this, mwTimerStop, mwTimerRelease,mw = function (e) {e.preventDefault();var ori = e.originalEvent,deltaX = ori.detail || ori.wheelDeltaX,deltaY = ori.detail || ori.wheelDeltaY,v = s._validate(s.o.parse(s.$.val()))+ (deltaX>0 || deltaY>0 ? s.o.step : deltaX<0 || deltaY<0 ? -s.o.step : 0);v = max(min(v, s.o.max), s.o.min);s.val(v, false);if(s.rH) {// Handle mousewheel stopclearTimeout(mwTimerStop);mwTimerStop = setTimeout(function() {s.rH(v);mwTimerStop = null;}, 100);// Handle mousewheel releasesif(!mwTimerRelease) {mwTimerRelease = setTimeout(function() {if(mwTimerStop) s.rH(v);mwTimerRelease = null;}, 200);}}}, kval, to, m = 1, kv = {37:-s.o.step, 38:s.o.step, 39:s.o.step, 40:-s.o.step};this.$.bind("keydown",function (e) {var kc = e.keyCode;// numpad supportif(kc >= 96 && kc <= 105) {kc = e.keyCode = kc - 48;}kval = parseInt(String.fromCharCode(kc));if (isNaN(kval)) {(kc !== 13) // enter&& (kc !== 8) // bs&& (kc !== 9) // tab&& (kc !== 189) // -&& (kc !== 190 || s.$.val().match(/\./)) // . only allowed once&& e.preventDefault();// arrowsif ($.inArray(kc,[37,38,39,40]) > -1) {e.preventDefault();var v = s.o.parse(s.$.val()) + kv[kc] * m;s.o.stopper && (v = max(min(v, s.o.max), s.o.min));s.change(v);s._draw();// long time keydown speed-upto = window.setTimeout(function () { m *= 2; }, 30);}}}).bind("keyup",function (e) {if (isNaN(kval)) {if (to) {window.clearTimeout(to);to = null;m = 1;s.val(s.$.val());}} else {// kval postcond(s.$.val() > s.o.max && s.$.val(s.o.max))|| (s.$.val() < s.o.min && s.$.val(s.o.min));}});//this.$c.bind("mousewheel DOMMouseScroll", mw);//this.$.bind("mousewheel DOMMouseScroll", mw)};this.init = function () {if (this.v < this.o.min|| this.v > this.o.max) this.v = this.o.min;this.$.val(this.v);this.w2 = this.w / 2;this.cursorExt = this.o.cursor / 100;this.xy = this.w2 * this.scale;this.lineWidth = this.xy * this.o.thickness;this.lineCap = this.o.lineCap;this.radius = this.xy - this.lineWidth / 2;this.o.angleOffset&& (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset);this.o.angleArc&& (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc);// deg to radthis.angleOffset = this.o.angleOffset * Math.PI / 180;this.angleArc = this.o.angleArc * Math.PI / 180;// compute start and end anglesthis.startAngle = 1.5 * Math.PI + this.angleOffset;this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc;var s = max(String(Math.abs(this.o.max)).length, String(Math.abs(this.o.min)).length, 2) + 2;this.o.displayInput&& this.i.css({'width' : ((this.w / 2 + 4) >> 0) + 'px','height' : ((this.w / 3) >> 0) + 'px','position' : 'absolute','vertical-align' : 'middle','margin-top' : ((this.w / 3) >> 0) + 'px','margin-left' : '-' + ((this.w * 3 / 4 + 2) >> 0) + 'px','border' : 0,'background' : 'none','font' : this.o.fontWeight + ' ' + ((this.w / s) >> 0) + 'px ' + this.o.font,'text-align' : 'center','color' : this.o.inputColor || this.o.fgColor,'padding' : '0px','-webkit-appearance': 'none'})|| this.i.css({'width' : '0px','visibility' : 'hidden'});};this.change = function (v) {this.cv = v;this.$.val(this.o.format(v));};this.angle = function (v) {return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min);};this.arc = function (v) {var sa, ea;v = this.angle(v);if (this.o.flip) {sa = this.endAngle + 0.00001;ea = sa - v - 0.00001;} else {sa = this.startAngle - 0.00001;ea = sa + v + 0.00001;}this.o.cursor&& (sa = ea - this.cursorExt)&& (ea = ea + this.cursorExt);return {s: sa,e: ea,d: this.o.flip && !this.o.cursor};};this.draw = function () {var c = this.g, // contexta = this.arc(this.cv) // Arc, pa // Previous arc, r = 1;c.lineWidth = this.lineWidth;c.lineCap = this.lineCap;c.beginPath();c.strokeStyle = this.o.bgColor;c.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true);c.stroke();if (this.o.displayPrevious) {pa = this.arc(this.v);c.beginPath();c.strokeStyle = this.pColor;c.arc(this.xy, this.xy, this.radius, pa.s, pa.e, pa.d);c.stroke();r = (this.cv == this.v);}c.beginPath();c.strokeStyle = r ? this.o.fgColor : this.fgColor ;c.arc(this.xy, this.xy, this.radius, a.s, a.e, a.d);c.stroke();};this.cancel = function () {this.val(this.v);};};$.fn.dial = $.fn.knob = function (o) {return this.each(function () {var d = new k.Dial();d.o = o;d.$ = $(this);d.run();}).parent();};})(jQuery);