mirror of
				https://github.com/ShaYmez/ezservermonitor-web.git
				synced 2025-10-30 20:40:23 -04:00 
			
		
		
		
	
		
			
	
	
		
			789 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			789 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /*!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 = {}, // kontrol
 | ||
|  |         max = 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 options
 | ||
|  |         this.$ = null; // jQuery wrapped element
 | ||
|  |         this.i = null; // mixed HTMLInputElement or array of HTMLInputElement
 | ||
|  |         this.g = null; // deprecated 2D graphics context for 'pre-rendering'
 | ||
|  |         this.v = null; // value ; mixed array or integer
 | ||
|  |         this.cv = null; // change value ; not commited value
 | ||
|  |         this.x = 0; // canvas x position
 | ||
|  |         this.y = 0; // canvas y position
 | ||
|  |         this.w = 0; // canvas width
 | ||
|  |         this.h = 0; // canvas height
 | ||
|  |         this.$c = null; // jQuery canvas element
 | ||
|  |         this.c = null; // rendered canvas context
 | ||
|  |         this.t = 0; // touches index
 | ||
|  |         this.isInit = false; | ||
|  |         this.fgColor = null; // main color
 | ||
|  |         this.pColor = null; // previous color
 | ||
|  |         this.dH = null; // draw hook
 | ||
|  |         this.cH = null; // change hook
 | ||
|  |         this.eH = null; // cancel hook
 | ||
|  |         this.rH = null; // release hook
 | ||
|  |         this.scale = 1; // scale factor
 | ||
|  |         this.relative = false; | ||
|  |         this.relativeWidth = false; | ||
|  |         this.relativeHeight = false; | ||
|  |         this.$div = null; // component div
 | ||
|  | 
 | ||
|  |         this.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( | ||
|  |                 { | ||
|  |                     // Config
 | ||
|  |                     min : 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'), | ||
|  | 
 | ||
|  |                     // UI
 | ||
|  |                     cursor : (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'), | ||
|  | 
 | ||
|  |                     // Hooks
 | ||
|  |                     draw : 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 options
 | ||
|  |             this.o.flip = this.o.rotation === 'anticlockwise' || this.o.rotation === 'acw'; | ||
|  |             if(!this.o.inputColor) { | ||
|  |                 this.o.inputColor = this.o.fgColor; | ||
|  |             } | ||
|  | 
 | ||
|  |             // routing value
 | ||
|  |             if(this.$.is('fieldset')) { | ||
|  | 
 | ||
|  |                 // fieldset = array of integer
 | ||
|  |                 this.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 = integer
 | ||
|  |                 this.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 triggered
 | ||
|  |             this.$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 support
 | ||
|  |             this.scale = (window.devicePixelRatio || 1) / | ||
|  |                         ( | ||
|  |                             this.c.webkitBackingStorePixelRatio || | ||
|  |                             this.c.mozBackingStorePixelRatio || | ||
|  |                             this.c.msBackingStorePixelRatio || | ||
|  |                             this.c.oBackingStorePixelRatio || | ||
|  |                             this.c.backingStorePixelRatio || 1 | ||
|  |                         ); | ||
|  | 
 | ||
|  |             // detects relative width / height
 | ||
|  |             this.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 component
 | ||
|  |             this._carve(); | ||
|  | 
 | ||
|  |             // prepares props for transaction
 | ||
|  |             if (this.v instanceof Object) { | ||
|  |                 this.cv = {}; | ||
|  |                 this.copy(this.v, this.cv); | ||
|  |             } else { | ||
|  |                 this.cv = this.v; | ||
|  |             } | ||
|  | 
 | ||
|  |             // binds configure event
 | ||
|  |             this.$ | ||
|  |                 .bind("configure", cf) | ||
|  |                 .parent() | ||
|  |                 .bind("configure", cf); | ||
|  | 
 | ||
|  |             // finalize init
 | ||
|  |             this._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 relative
 | ||
|  |                 this.w = this.h = Math.min(w, h); | ||
|  |             } else { | ||
|  |                 this.w = this.o.width; | ||
|  |                 this.h = this.o.height; | ||
|  |             } | ||
|  | 
 | ||
|  |             // finalize div
 | ||
|  |             this.$div.css({ | ||
|  |                 'width': this.w + 'px', | ||
|  |                 'height': this.h + 'px' | ||
|  |             }); | ||
|  | 
 | ||
|  |             // finalize canvas with computed width
 | ||
|  |             this.$c.attr({ | ||
|  |                 width: this.w, | ||
|  |                 height: this.h | ||
|  |             }); | ||
|  | 
 | ||
|  |             // scaling
 | ||
|  |             if (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-rendering
 | ||
|  |             var 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 index
 | ||
|  |             this.t = k.c.t(e); | ||
|  | 
 | ||
|  |             // First touch
 | ||
|  |             touchMove(e); | ||
|  | 
 | ||
|  |             // Touch events listeners
 | ||
|  |             k.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 click
 | ||
|  |             mouseMove(e); | ||
|  | 
 | ||
|  |             // Mouse events listeners
 | ||
|  |             k.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 () { | ||
|  | 
 | ||
|  |             // Hooks
 | ||
|  |             if (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 methods
 | ||
|  |         this.listen = function () {}; // on start, one time
 | ||
|  |         this.extend = function () {}; // each time configure triggered
 | ||
|  |         this.init = function () {}; // each time configure triggered
 | ||
|  |         this.change = function (v) {}; // on change
 | ||
|  |         this.val = function (v) {}; // on release
 | ||
|  |         this.xy2val = function (x, y) {}; //
 | ||
|  |         this.draw = function () {}; // on change / on release
 | ||
|  |         this.clear = function () { this._clear(); }; | ||
|  | 
 | ||
|  |         // Utils
 | ||
|  |         this.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 format
 | ||
|  |                 v = 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 min
 | ||
|  |                 a = 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 MouseWheel
 | ||
|  |             var 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 stop
 | ||
|  |                         clearTimeout(mwTimerStop); | ||
|  |                         mwTimerStop = setTimeout(function() { | ||
|  |                             s.rH(v); | ||
|  |                             mwTimerStop = null; | ||
|  |                         }, 100); | ||
|  | 
 | ||
|  |                         // Handle mousewheel releases
 | ||
|  |                         if(!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 support
 | ||
|  |                         if(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(); | ||
|  | 
 | ||
|  |                             // arrows
 | ||
|  |                             if ($.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-up
 | ||
|  |                                 to = 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 rad
 | ||
|  |             this.angleOffset = this.o.angleOffset * Math.PI / 180; | ||
|  |             this.angleArc = this.o.angleArc * Math.PI / 180; | ||
|  | 
 | ||
|  |             // compute start and end angles
 | ||
|  |             this.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,                 // context
 | ||
|  |                 a = this.arc(this.cv)       // Arc
 | ||
|  |                 , pa                        // Previous arc
 | ||
|  |                 , r = 1; | ||
|  | 
 | ||
|  |             c.lineWidth = this.lineWidth; | ||
|  |             c.lineCap = this.lineCap; | ||
|  |             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); |