PageSourceSearch

https://familienzentrum-oldesloe.de/js/custom/jquery.knob.js

js familienzentrum-oldesloe.de collected 2026-10-06 17:58:44 UTC 24,209 bytes, 760 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.