Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / pybind / mgr / dashboard / static / AdminLTE-2.3.7 / plugins / knob / jquery.knob.js
1 /*!jQuery Knob*/
2 /**
3  * Downward compatible, touchable dial
4  *
5  * Version: 1.2.11
6  * Requires: jQuery v1.7+
7  *
8  * Copyright (c) 2012 Anthony Terrien
9  * Under MIT License (http://www.opensource.org/licenses/mit-license.php)
10  *
11  * Thanks to vor, eskimoblood, spiffistan, FabrizioC
12  */
13 (function (factory) {
14     if (typeof exports === 'object') {
15         // CommonJS
16         module.exports = factory(require('jquery'));
17     } else if (typeof define === 'function' && define.amd) {
18         // AMD. Register as an anonymous module.
19         define(['jquery'], factory);
20     } else {
21         // Browser globals
22         factory(jQuery);
23     }
24 }(function ($) {
25
26     /**
27      * Kontrol library
28      */
29     "use strict";
30
31     /**
32      * Definition of globals and core
33      */
34     var k = {}, // kontrol
35         max = Math.max,
36         min = Math.min;
37
38     k.c = {};
39     k.c.d = $(document);
40     k.c.t = function (e) {
41         return e.originalEvent.touches.length - 1;
42     };
43
44     /**
45      * Kontrol Object
46      *
47      * Definition of an abstract UI control
48      *
49      * Each concrete component must call this one.
50      * <code>
51      * k.o.call(this);
52      * </code>
53      */
54     k.o = function () {
55         var s = this;
56
57         this.o = null; // array of options
58         this.$ = null; // jQuery wrapped element
59         this.i = null; // mixed HTMLInputElement or array of HTMLInputElement
60         this.g = null; // deprecated 2D graphics context for 'pre-rendering'
61         this.v = null; // value ; mixed array or integer
62         this.cv = null; // change value ; not commited value
63         this.x = 0; // canvas x position
64         this.y = 0; // canvas y position
65         this.w = 0; // canvas width
66         this.h = 0; // canvas height
67         this.$c = null; // jQuery canvas element
68         this.c = null; // rendered canvas context
69         this.t = 0; // touches index
70         this.isInit = false;
71         this.fgColor = null; // main color
72         this.pColor = null; // previous color
73         this.dH = null; // draw hook
74         this.cH = null; // change hook
75         this.eH = null; // cancel hook
76         this.rH = null; // release hook
77         this.scale = 1; // scale factor
78         this.relative = false;
79         this.relativeWidth = false;
80         this.relativeHeight = false;
81         this.$div = null; // component div
82
83         this.run = function () {
84             var cf = function (e, conf) {
85                 var k;
86                 for (k in conf) {
87                     s.o[k] = conf[k];
88                 }
89                 s._carve().init();
90                 s._configure()
91                  ._draw();
92             };
93
94             if (this.$.data('kontroled')) return;
95             this.$.data('kontroled', true);
96
97             this.extend();
98             this.o = $.extend({
99                     // Config
100                     min: this.$.data('min') !== undefined ? this.$.data('min') : 0,
101                     max: this.$.data('max') !== undefined ? this.$.data('max') : 100,
102                     stopper: true,
103                     readOnly: this.$.data('readonly') || (this.$.attr('readonly') === 'readonly'),
104
105                     // UI
106                     cursor: this.$.data('cursor') === true && 30
107                             || this.$.data('cursor') || 0,
108                     thickness: this.$.data('thickness')
109                                && Math.max(Math.min(this.$.data('thickness'), 1), 0.01)
110                                || 0.35,
111                     lineCap: this.$.data('linecap') || 'butt',
112                     width: this.$.data('width') || 200,
113                     height: this.$.data('height') || 200,
114                     displayInput: this.$.data('displayinput') == null || this.$.data('displayinput'),
115                     displayPrevious: this.$.data('displayprevious'),
116                     fgColor: this.$.data('fgcolor') || '#87CEEB',
117                     inputColor: this.$.data('inputcolor'),
118                     font: this.$.data('font') || 'Arial',
119                     fontWeight: this.$.data('font-weight') || 'bold',
120                     inline: false,
121                     step: this.$.data('step') || 1,
122                     rotation: this.$.data('rotation'),
123
124                     // Hooks
125                     draw: null, // function () {}
126                     change: null, // function (value) {}
127                     cancel: null, // function () {}
128                     release: null, // function (value) {}
129
130                     // Output formatting, allows to add unit: %, ms ...
131                     format: function(v) {
132                         return v;
133                     },
134                     parse: function (v) {
135                         return parseFloat(v);
136                     }
137                 }, this.o
138             );
139
140             // finalize options
141             this.o.flip = this.o.rotation === 'anticlockwise' || this.o.rotation === 'acw';
142             if (!this.o.inputColor) {
143                 this.o.inputColor = this.o.fgColor;
144             }
145
146             // routing value
147             if (this.$.is('fieldset')) {
148
149                 // fieldset = array of integer
150                 this.v = {};
151                 this.i = this.$.find('input');
152                 this.i.each(function(k) {
153                     var $this = $(this);
154                     s.i[k] = $this;
155                     s.v[k] = s.o.parse($this.val());
156
157                     $this.bind(
158                         'change blur',
159                         function () {
160                             var val = {};
161                             val[k] = $this.val();
162                             s.val(s._validate(val));
163                         }
164                     );
165                 });
166                 this.$.find('legend').remove();
167             } else {
168
169                 // input = integer
170                 this.i = this.$;
171                 this.v = this.o.parse(this.$.val());
172                 this.v === '' && (this.v = this.o.min);
173                 this.$.bind(
174                     'change blur',
175                     function () {
176                         s.val(s._validate(s.o.parse(s.$.val())));
177                     }
178                 );
179
180             }
181
182             !this.o.displayInput && this.$.hide();
183
184             // adds needed DOM elements (canvas, div)
185             this.$c = $(document.createElement('canvas')).attr({
186                 width: this.o.width,
187                 height: this.o.height
188             });
189
190             // wraps all elements in a div
191             // add to DOM before Canvas init is triggered
192             this.$div = $('<div style="'
193                 + (this.o.inline ? 'display:inline;' : '')
194                 + 'width:' + this.o.width + 'px;height:' + this.o.height + 'px;'
195                 + '"></div>');
196
197             this.$.wrap(this.$div).before(this.$c);
198             this.$div = this.$.parent();
199
200             if (typeof G_vmlCanvasManager !== 'undefined') {
201                 G_vmlCanvasManager.initElement(this.$c[0]);
202             }
203
204             this.c = this.$c[0].getContext ? this.$c[0].getContext('2d') : null;
205
206             if (!this.c) {
207                 throw {
208                     name:        "CanvasNotSupportedException",
209                     message:     "Canvas not supported. Please use excanvas on IE8.0.",
210                     toString:    function(){return this.name + ": " + this.message}
211                 }
212             }
213
214             // hdpi support
215             this.scale = (window.devicePixelRatio || 1) / (
216                             this.c.webkitBackingStorePixelRatio ||
217                             this.c.mozBackingStorePixelRatio ||
218                             this.c.msBackingStorePixelRatio ||
219                             this.c.oBackingStorePixelRatio ||
220                             this.c.backingStorePixelRatio || 1
221                          );
222
223             // detects relative width / height
224             this.relativeWidth =  this.o.width % 1 !== 0
225                                   && this.o.width.indexOf('%');
226             this.relativeHeight = this.o.height % 1 !== 0
227                                   && this.o.height.indexOf('%');
228             this.relative = this.relativeWidth || this.relativeHeight;
229
230             // computes size and carves the component
231             this._carve();
232
233             // prepares props for transaction
234             if (this.v instanceof Object) {
235                 this.cv = {};
236                 this.copy(this.v, this.cv);
237             } else {
238                 this.cv = this.v;
239             }
240
241             // binds configure event
242             this.$
243                 .bind("configure", cf)
244                 .parent()
245                 .bind("configure", cf);
246
247             // finalize init
248             this._listen()
249                 ._configure()
250                 ._xy()
251                 .init();
252
253             this.isInit = true;
254
255             this.$.val(this.o.format(this.v));
256             this._draw();
257
258             return this;
259         };
260
261         this._carve = function() {
262             if (this.relative) {
263                 var w = this.relativeWidth ?
264                         this.$div.parent().width() *
265                         parseInt(this.o.width) / 100
266                         : this.$div.parent().width(),
267                     h = this.relativeHeight ?
268                         this.$div.parent().height() *
269                         parseInt(this.o.height) / 100
270                         : this.$div.parent().height();
271
272                 // apply relative
273                 this.w = this.h = Math.min(w, h);
274             } else {
275                 this.w = this.o.width;
276                 this.h = this.o.height;
277             }
278
279             // finalize div
280             this.$div.css({
281                 'width': this.w + 'px',
282                 'height': this.h + 'px'
283             });
284
285             // finalize canvas with computed width
286             this.$c.attr({
287                 width: this.w,
288                 height: this.h
289             });
290
291             // scaling
292             if (this.scale !== 1) {
293                 this.$c[0].width = this.$c[0].width * this.scale;
294                 this.$c[0].height = this.$c[0].height * this.scale;
295                 this.$c.width(this.w);
296                 this.$c.height(this.h);
297             }
298
299             return this;
300         }
301
302         this._draw = function () {
303
304             // canvas pre-rendering
305             var d = true;
306
307             s.g = s.c;
308
309             s.clear();
310
311             s.dH && (d = s.dH());
312
313             d !== false && s.draw();
314         };
315
316         this._touch = function (e) {
317             var touchMove = function (e) {
318                 var v = s.xy2val(
319                             e.originalEvent.touches[s.t].pageX,
320                             e.originalEvent.touches[s.t].pageY
321                         );
322
323                 if (v == s.cv) return;
324
325                 if (s.cH && s.cH(v) === false) return;
326
327                 s.change(s._validate(v));
328                 s._draw();
329             };
330
331             // get touches index
332             this.t = k.c.t(e);
333
334             // First touch
335             touchMove(e);
336
337             // Touch events listeners
338             k.c.d
339                 .bind("touchmove.k", touchMove)
340                 .bind(
341                     "touchend.k",
342                     function () {
343                         k.c.d.unbind('touchmove.k touchend.k');
344                         s.val(s.cv);
345                     }
346                 );
347
348             return this;
349         };
350
351         this._mouse = function (e) {
352             var mouseMove = function (e) {
353                 var v = s.xy2val(e.pageX, e.pageY);
354
355                 if (v == s.cv) return;
356
357                 if (s.cH && (s.cH(v) === false)) return;
358
359                 s.change(s._validate(v));
360                 s._draw();
361             };
362
363             // First click
364             mouseMove(e);
365
366             // Mouse events listeners
367             k.c.d
368                 .bind("mousemove.k", mouseMove)
369                 .bind(
370                     // Escape key cancel current change
371                     "keyup.k",
372                     function (e) {
373                         if (e.keyCode === 27) {
374                             k.c.d.unbind("mouseup.k mousemove.k keyup.k");
375
376                             if (s.eH && s.eH() === false)
377                                 return;
378
379                             s.cancel();
380                         }
381                     }
382                 )
383                 .bind(
384                     "mouseup.k",
385                     function (e) {
386                         k.c.d.unbind('mousemove.k mouseup.k keyup.k');
387                         s.val(s.cv);
388                     }
389                 );
390
391             return this;
392         };
393
394         this._xy = function () {
395             var o = this.$c.offset();
396             this.x = o.left;
397             this.y = o.top;
398
399             return this;
400         };
401
402         this._listen = function () {
403             if (!this.o.readOnly) {
404                 this.$c
405                     .bind(
406                         "mousedown",
407                         function (e) {
408                             e.preventDefault();
409                             s._xy()._mouse(e);
410                         }
411                     )
412                     .bind(
413                         "touchstart",
414                         function (e) {
415                             e.preventDefault();
416                             s._xy()._touch(e);
417                         }
418                     );
419
420                 this.listen();
421             } else {
422                 this.$.attr('readonly', 'readonly');
423             }
424
425             if (this.relative) {
426                 $(window).resize(function() {
427                     s._carve().init();
428                     s._draw();
429                 });
430             }
431
432             return this;
433         };
434
435         this._configure = function () {
436
437             // Hooks
438             if (this.o.draw) this.dH = this.o.draw;
439             if (this.o.change) this.cH = this.o.change;
440             if (this.o.cancel) this.eH = this.o.cancel;
441             if (this.o.release) this.rH = this.o.release;
442
443             if (this.o.displayPrevious) {
444                 this.pColor = this.h2rgba(this.o.fgColor, "0.4");
445                 this.fgColor = this.h2rgba(this.o.fgColor, "0.6");
446             } else {
447                 this.fgColor = this.o.fgColor;
448             }
449
450             return this;
451         };
452
453         this._clear = function () {
454             this.$c[0].width = this.$c[0].width;
455         };
456
457         this._validate = function (v) {
458             var val = (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step;
459             return Math.round(val * 100) / 100;
460         };
461
462         // Abstract methods
463         this.listen = function () {}; // on start, one time
464         this.extend = function () {}; // each time configure triggered
465         this.init = function () {}; // each time configure triggered
466         this.change = function (v) {}; // on change
467         this.val = function (v) {}; // on release
468         this.xy2val = function (x, y) {}; //
469         this.draw = function () {}; // on change / on release
470         this.clear = function () { this._clear(); };
471
472         // Utils
473         this.h2rgba = function (h, a) {
474             var rgb;
475             h = h.substring(1,7)
476             rgb = [
477                 parseInt(h.substring(0,2), 16),
478                 parseInt(h.substring(2,4), 16),
479                 parseInt(h.substring(4,6), 16)
480             ];
481
482             return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + a + ")";
483         };
484
485         this.copy = function (f, t) {
486             for (var i in f) {
487                 t[i] = f[i];
488             }
489         };
490     };
491
492
493     /**
494      * k.Dial
495      */
496     k.Dial = function () {
497         k.o.call(this);
498
499         this.startAngle = null;
500         this.xy = null;
501         this.radius = null;
502         this.lineWidth = null;
503         this.cursorExt = null;
504         this.w2 = null;
505         this.PI2 = 2*Math.PI;
506
507         this.extend = function () {
508             this.o = $.extend({
509                 bgColor: this.$.data('bgcolor') || '#EEEEEE',
510                 angleOffset: this.$.data('angleoffset') || 0,
511                 angleArc: this.$.data('anglearc') || 360,
512                 inline: true
513             }, this.o);
514         };
515
516         this.val = function (v, triggerRelease) {
517             if (null != v) {
518
519                 // reverse format
520                 v = this.o.parse(v);
521
522                 if (triggerRelease !== false
523                     && v != this.v
524                     && this.rH
525                     && this.rH(v) === false) { return; }
526
527                 this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v;
528                 this.v = this.cv;
529                 this.$.val(this.o.format(this.v));
530                 this._draw();
531             } else {
532                 return this.v;
533             }
534         };
535
536         this.xy2val = function (x, y) {
537             var a, ret;
538
539             a = Math.atan2(
540                         x - (this.x + this.w2),
541                         - (y - this.y - this.w2)
542                     ) - this.angleOffset;
543
544             if (this.o.flip) {
545                 a = this.angleArc - a - this.PI2;
546             }
547
548             if (this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) {
549
550                 // if isset angleArc option, set to min if .5 under min
551                 a = 0;
552             } else if (a < 0) {
553                 a += this.PI2;
554             }
555
556             ret = (a * (this.o.max - this.o.min) / this.angleArc) + this.o.min;
557
558             this.o.stopper && (ret = max(min(ret, this.o.max), this.o.min));
559
560             return ret;
561         };
562
563         this.listen = function () {
564
565             // bind MouseWheel
566             var s = this, mwTimerStop,
567                 mwTimerRelease,
568                 mw = function (e) {
569                     e.preventDefault();
570
571                     var ori = e.originalEvent,
572                         deltaX = ori.detail || ori.wheelDeltaX,
573                         deltaY = ori.detail || ori.wheelDeltaY,
574                         v = s._validate(s.o.parse(s.$.val()))
575                             + (
576                                 deltaX > 0 || deltaY > 0
577                                 ? s.o.step
578                                 : deltaX < 0 || deltaY < 0 ? -s.o.step : 0
579                               );
580
581                     v = max(min(v, s.o.max), s.o.min);
582
583                     s.val(v, false);
584
585                     if (s.rH) {
586                         // Handle mousewheel stop
587                         clearTimeout(mwTimerStop);
588                         mwTimerStop = setTimeout(function () {
589                             s.rH(v);
590                             mwTimerStop = null;
591                         }, 100);
592
593                         // Handle mousewheel releases
594                         if (!mwTimerRelease) {
595                             mwTimerRelease = setTimeout(function () {
596                                 if (mwTimerStop)
597                                     s.rH(v);
598                                 mwTimerRelease = null;
599                             }, 200);
600                         }
601                     }
602                 },
603                 kval,
604                 to,
605                 m = 1,
606                 kv = {
607                     37: -s.o.step,
608                     38: s.o.step,
609                     39: s.o.step,
610                     40: -s.o.step
611                 };
612
613             this.$
614                 .bind(
615                     "keydown",
616                     function (e) {
617                         var kc = e.keyCode;
618
619                         // numpad support
620                         if (kc >= 96 && kc <= 105) {
621                             kc = e.keyCode = kc - 48;
622                         }
623
624                         kval = parseInt(String.fromCharCode(kc));
625
626                         if (isNaN(kval)) {
627                             (kc !== 13)                     // enter
628                             && kc !== 8                     // bs
629                             && kc !== 9                     // tab
630                             && kc !== 189                   // -
631                             && (kc !== 190
632                                 || s.$.val().match(/\./))   // . allowed once
633                             && e.preventDefault();
634
635                             // arrows
636                             if ($.inArray(kc,[37,38,39,40]) > -1) {
637                                 e.preventDefault();
638
639                                 var v = s.o.parse(s.$.val()) + kv[kc] * m;
640                                 s.o.stopper && (v = max(min(v, s.o.max), s.o.min));
641
642                                 s.change(s._validate(v));
643                                 s._draw();
644
645                                 // long time keydown speed-up
646                                 to = window.setTimeout(function () {
647                                     m *= 2;
648                                 }, 30);
649                             }
650                         }
651                     }
652                 )
653                 .bind(
654                     "keyup",
655                     function (e) {
656                         if (isNaN(kval)) {
657                             if (to) {
658                                 window.clearTimeout(to);
659                                 to = null;
660                                 m = 1;
661                                 s.val(s.$.val());
662                             }
663                         } else {
664                             // kval postcond
665                             (s.$.val() > s.o.max && s.$.val(s.o.max))
666                             || (s.$.val() < s.o.min && s.$.val(s.o.min));
667                         }
668                     }
669                 );
670
671             this.$c.bind("mousewheel DOMMouseScroll", mw);
672             this.$.bind("mousewheel DOMMouseScroll", mw)
673         };
674
675         this.init = function () {
676             if (this.v < this.o.min
677                 || this.v > this.o.max) { this.v = this.o.min; }
678
679             this.$.val(this.v);
680             this.w2 = this.w / 2;
681             this.cursorExt = this.o.cursor / 100;
682             this.xy = this.w2 * this.scale;
683             this.lineWidth = this.xy * this.o.thickness;
684             this.lineCap = this.o.lineCap;
685             this.radius = this.xy - this.lineWidth / 2;
686
687             this.o.angleOffset
688             && (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset);
689
690             this.o.angleArc
691             && (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc);
692
693             // deg to rad
694             this.angleOffset = this.o.angleOffset * Math.PI / 180;
695             this.angleArc = this.o.angleArc * Math.PI / 180;
696
697             // compute start and end angles
698             this.startAngle = 1.5 * Math.PI + this.angleOffset;
699             this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc;
700
701             var s = max(
702                 String(Math.abs(this.o.max)).length,
703                 String(Math.abs(this.o.min)).length,
704                 2
705             ) + 2;
706
707             this.o.displayInput
708                 && this.i.css({
709                         'width' : ((this.w / 2 + 4) >> 0) + 'px',
710                         'height' : ((this.w / 3) >> 0) + 'px',
711                         'position' : 'absolute',
712                         'vertical-align' : 'middle',
713                         'margin-top' : ((this.w / 3) >> 0) + 'px',
714                         'margin-left' : '-' + ((this.w * 3 / 4 + 2) >> 0) + 'px',
715                         'border' : 0,
716                         'background' : 'none',
717                         'font' : this.o.fontWeight + ' ' + ((this.w / s) >> 0) + 'px ' + this.o.font,
718                         'text-align' : 'center',
719                         'color' : this.o.inputColor || this.o.fgColor,
720                         'padding' : '0px',
721                         '-webkit-appearance': 'none'
722                         }) || this.i.css({
723                             'width': '0px',
724                             'visibility': 'hidden'
725                         });
726         };
727
728         this.change = function (v) {
729             this.cv = v;
730             this.$.val(this.o.format(v));
731         };
732
733         this.angle = function (v) {
734             return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min);
735         };
736
737         this.arc = function (v) {
738           var sa, ea;
739           v = this.angle(v);
740           if (this.o.flip) {
741               sa = this.endAngle + 0.00001;
742               ea = sa - v - 0.00001;
743           } else {
744               sa = this.startAngle - 0.00001;
745               ea = sa + v + 0.00001;
746           }
747           this.o.cursor
748               && (sa = ea - this.cursorExt)
749               && (ea = ea + this.cursorExt);
750
751           return {
752               s: sa,
753               e: ea,
754               d: this.o.flip && !this.o.cursor
755           };
756         };
757
758         this.draw = function () {
759             var c = this.g,                 // context
760                 a = this.arc(this.cv),      // Arc
761                 pa,                         // Previous arc
762                 r = 1;
763
764             c.lineWidth = this.lineWidth;
765             c.lineCap = this.lineCap;
766
767             if (this.o.bgColor !== "none") {
768                 c.beginPath();
769                     c.strokeStyle = this.o.bgColor;
770                     c.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true);
771                 c.stroke();
772             }
773
774             if (this.o.displayPrevious) {
775                 pa = this.arc(this.v);
776                 c.beginPath();
777                 c.strokeStyle = this.pColor;
778                 c.arc(this.xy, this.xy, this.radius, pa.s, pa.e, pa.d);
779                 c.stroke();
780                 r = this.cv == this.v;
781             }
782
783             c.beginPath();
784             c.strokeStyle = r ? this.o.fgColor : this.fgColor ;
785             c.arc(this.xy, this.xy, this.radius, a.s, a.e, a.d);
786             c.stroke();
787         };
788
789         this.cancel = function () {
790             this.val(this.v);
791         };
792     };
793
794     $.fn.dial = $.fn.knob = function (o) {
795         return this.each(
796             function () {
797                 var d = new k.Dial();
798                 d.o = o;
799                 d.$ = $(this);
800                 d.run();
801             }
802         ).parent();
803     };
804
805 }));