Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
malwaredllc
GitHub Repository: malwaredllc/byob
Path: blob/master/web-gui/buildyourownbotnet/assets/js/jquery.knob.js
1292 views
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
}));
806