PageSourceSearch

https://permiccion.de/js/jquery.bootstrap-touchspin.js

js permiccion.de collected 2026-10-08 18:46:34 UTC 19,540 bytes, 689 lines download raw bytes

1(function($) {
2  'use strict';
3
4  var _currentSpinnerId = 0;
5
6  function _scopedEventName(name, id) {
7    return name + '.touchspin_' + id;
8  }
9
10  function _scopeEventNames(names, id) {
11    return $.map(names, function(name) {
12      return _scopedEventName(name, id);
13    });
14  }
15
16  $.fn.TouchSpin = function(options) {
17
18    if (options === 'destroy') {
19      this.each(function() {
20        var originalinput = $(this),
21            originalinput_data = originalinput.data();
22        $(document).off(_scopeEventNames([
23          'mouseup',
24          'touchend',
25          'touchcancel',
26          'mousemove',
27          'touchmove',
28          'scroll',
29          'scrollstart'], originalinput_data.spinnerid).join(' '));
30      });
31      return;
32    }
33
34    var defaults = {
35      min: 0,
36      max: 100,
37      initval: '',
38      replacementval: '',
39      step: 1,
40      decimals: 0,
41      stepinterval: 100,
42      forcestepdivisibility: 'round', // none | floor | round | ceil
43      stepintervaldelay: 500,
44      verticalbuttons: false,
45      verticalupclass: 'glyphicon glyphicon-chevron-up',
46      verticaldownclass: 'glyphicon glyphicon-chevron-down',
47      prefix: '',
48      postfix: '',
49      prefix_extraclass: '',
50      postfix_extraclass: '',
51      booster: true,
52      boostat: 10,
53      maxboostedstep: false,
54      mousewheel: true,
55      buttondown_class: 'btn btn-default',
56      buttonup_class: 'btn btn-default',
57	  buttondown_txt: '-',
58	  buttonup_txt: '+'
59    };
60
61    var attributeMap = {
62      min: 'min',
63      max: 'max',
64      initval: 'init-val',
65      replacementval: 'replacement-val',
66      step: 'step',
67      decimals: 'decimals',
68      stepinterval: 'step-interval',
69      verticalbuttons: 'vertical-buttons',
70      verticalupclass: 'vertical-up-class',
71      verticaldownclass: 'vertical-down-class',
72      forcestepdivisibility: 'force-step-divisibility',
73      stepintervaldelay: 'step-interval-delay',
74      prefix: 'prefix',
75      postfix: 'postfix',
76      prefix_extraclass: 'prefix-extra-class',
77      postfix_extraclass: 'postfix-extra-class',
78      booster: 'booster',
79      boostat: 'boostat',
80      maxboostedstep: 'max-boosted-step',
81      mousewheel: 'mouse-wheel',
82      buttondown_class: 'button-down-class',
83      buttonup_class: 'button-up-class',
84	  buttondown_txt: 'button-down-txt',
85	  buttonup_txt: 'button-up-txt'
86    };
87
88    return this.each(function() {
89
90      var settings,
91          originalinput = $(this),
92          originalinput_data = originalinput.data(),
93          container,
94          elements,
95          value,
96          downSpinTimer,
97          upSpinTimer,
98          downDelayTimeout,
99          upDelayTimeout,
100          spincount = 0,
101          spinning = false;
102
103      init();
104
105
106      function init() {
107        if (originalinput.data('alreadyinitialized')) {
108          return;
109        }
110
111        originalinput.data('alreadyinitialized', true);
112        _currentSpinnerId += 1;
113        originalinput.data('spinnerid', _currentSpinnerId);
114
115
116        if (!originalinput.is('input')) {
117          console.log('Must be an input.');
118          return;
119        }
120
121        _initSettings();
122        _setInitval();
123        _checkValue();
124        _buildHtml();
125        _initElements();
126        _hideEmptyPrefixPostfix();
127        _bindEvents();
128        _bindEventsInterface();
129        elements.input.css('display', 'block');
130      }
131
132      function _setInitval() {
133        if (settings.initval !== '' && originalinput.val() === '') {
134          originalinput.val(settings.initval);
135        }
136      }
137
138      function changeSettings(newsettings) {
139        _updateSettings(newsettings);
140        _checkValue();
141
142        var value = elements.input.val();
143
144        if (value !== '') {
145          value = Number(elements.input.val());
146          elements.input.val(value.toFixed(settings.decimals));
147        }
148      }
149
150      function _initSettings() {
151        settings = $.extend({}, defaults, originalinput_data, _parseAttributes(), options);
152      }
153
154      function _parseAttributes() {
155        var data = {};
156        $.each(attributeMap, function(key, value) {
157          var attrName = 'bts-' + value + '';
158          if (originalinput.is('[data-' + attrName + ']')) {
159            data[key] = originalinput.data(attrName);
160          }
161        });
162        return data;
163      }
164
165      function _updateSettings(newsettings) {
166        settings = $.extend({}, settings, newsettings);
167      }
168
169      function _buildHtml() {
170        var initval = originalinput.val(),
171            parentelement = originalinput.parent();
172
173        if (initval !== '') {
174          initval = Number(initval).toFixed(settings.decimals);
175        }
176
177        originalinput.data('initvalue', initval).val(initval);
178        originalinput.addClass('form-control');
179
180        if (parentelement.hasClass('input-group')) {
181          _advanceInputGroup(parentelement);
182        }
183        else {
184          _buildInputGroup();
185        }
186      }
187
188      function _advanceInputGroup(parentelement) {
189        parentelement.addClass('bootstrap-touchspin');
190
191        var prev = originalinput.prev(),
192            next = originalinput.next();
193
194        var downhtml,
195            uphtml,
196            prefixhtml = '<span class="input-group-addon bootstrap-touchspin-prefix">' + settings.prefix + '</span>',
197            postfixhtml = '<span class="input-group-addon bootstrap-touchspin-postfix">' + settings.postfix + '</span>';
198
199        if (prev.hasClass('input-group-btn')) {
200          downhtml = '<button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button>';
201          prev.append(downhtml);
202        }
203        else {
204          downhtml = '<span class="input-group-btn"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span>';
205          $(downhtml).insertBefore(originalinput);
206        }
207
208        if (next.hasClass('input-group-btn')) {
209          uphtml = '<button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button>';
210          next.prepend(uphtml);
211        }
212        else {
213          uphtml = '<span class="input-group-btn"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span>';
214          $(uphtml).insertAfter(originalinput);
215        }
216
217        $(prefixhtml).insertBefore(originalinput);
218        $(postfixhtml).insertAfter(originalinput);
219
220        container = parentelement;
221      }
222
223      function _buildInputGroup() {
224        var html;
225
226        if (settings.verticalbuttons) {
227          html = '<div class="input-group bootstrap-touchspin"><span class="input-group-addon bootstrap-touchspin-prefix">' + settings.prefix + '</span><span class="input-group-addon bootstrap-touchspin-postfix">' + settings.postfix + '</span><span class="input-group-btn-vertical"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-up" type="button"><i class="' + settings.verticalupclass + '"></i></button><button class="' + settings.buttonup_class + ' bootstrap-touchspin-down" type="button"><i class="' + settings.verticaldownclass + '"></i></button></span></div>';
228        }
229        else {
230          html = '<div class="input-group bootstrap-touchspin"><span class="input-group-btn"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span><span class="input-group-addon bootstrap-touchspin-prefix">' + settings.prefix + '</span><span class="input-group-addon bootstrap-touchspin-postfix">' + settings.postfix + '</span><span class="input-group-btn"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span></div>';
231        }
232
233        container = $(html).insertBefore(originalinput);
234
235        $('.bootstrap-touchspin-prefix', container).after(originalinput);
236
237        if (originalinput.hasClass('input-sm')) {
238          container.addClass('input-group-sm');
239        }
240        else if (originalinput.hasClass('input-lg')) {
241          container.addClass('input-group-lg');
242        }
243      }
244
245      function _initElements() {
246        elements = {
247          down: $('.bootstrap-touchspin-down', container),
248          up: $('.bootstrap-touchspin-up', container),
249          input: $('input', container),
250          prefix: $('.bootstrap-touchspin-prefix', container).addClass(settings.prefix_extraclass),
251          postfix: $('.bootstrap-touchspin-postfix', container).addClass(settings.postfix_extraclass)
252        };
253      }
254
255      function _hideEmptyPrefixPostfix() {
256        if (settings.prefix === '') {
257          elements.prefix.hide();
258        }
259
260        if (settings.postfix === '') {
261          elements.postfix.hide();
262        }
263      }
264
265      function _bindEvents() {
266        originalinput.on('keydown', function(ev) {
267          var code = ev.keyCode || ev.which;
268
269          if (code === 38) {
270            if (spinning !== 'up') {
271              upOnce();
272              startUpSpin();
273            }
274            ev.preventDefault();
275          }
276          else if (code === 40) {
277            if (spinning !== 'down') {
278              downOnce();
279              startDownSpin();
280            }
281            ev.preventDefault();
282          }
283        });
284
285        originalinput.on('keyup', function(ev) {
286          var code = ev.keyCode || ev.which;
287
288          if (code === 38) {
289            stopSpin();
290          }
291          else if (code === 40) {
292            stopSpin();
293          }
294        });
295
296        originalinput.on('blur', function() {
297          _checkValue();
298        });
299
300        elements.down.on('keydown', function(ev) {
301          var code = ev.keyCode || ev.which;
302
303          if (code === 32 || code === 13) {
304            if (spinning !== 'down') {
305              downOnce();
306              startDownSpin();
307            }
308            ev.preventDefault();
309          }
310        });
311
312        elements.down.on('keyup', function(ev) {
313          var code = ev.keyCode || ev.which;
314
315          if (code === 32 || code === 13) {
316            stopSpin();
317          }
318        });
319
320        elements.up.on('keydown', function(ev) {
321          var code = ev.keyCode || ev.which;
322
323          if (code === 32 || code === 13) {
324            if (spinning !== 'up') {
325              upOnce();
326              startUpSpin();
327            }
328            ev.preventDefault();
329          }
330        });
331
332        elements.up.on('keyup', function(ev) {
333          var code = ev.keyCode || ev.which;
334
335          if (code === 32 || code === 13) {
336            stopSpin();
337          }
338        });
339
340        elements.down.on('mousedown.touchspin', function(ev) {
341          elements.down.off('touchstart.touchspin');  // android 4 workaround
342
343          if (originalinput.is(':disabled')) {
344            return;
345          }
346
347          downOnce();
348          startDownSpin();
349
350          ev.preventDefault();
351          ev.stopPropagation();
352        });
353
354        elements.down.on('touchstart.touchspin', function(ev) {
355          elements.down.off('mousedown.touchspin');  // android 4 workaround
356
357          if (originalinput.is(':disabled')) {
358            return;
359          }
360
361          downOnce();
362          startDownSpin();
363
364          ev.preventDefault();
365          ev.stopPropagation();
366        });
367
368        elements.up.on('mousedown.touchspin', function(ev) {
369          elements.up.off('touchstart.touchspin');  // android 4 workaround
370
371          if (originalinput.is(':disabled')) {
372            return;
373          }
374
375          upOnce();
376          startUpSpin();
377
378          ev.preventDefault();
379          ev.stopPropagation();
380        });
381
382        elements.up.on('touchstart.touchspin', function(ev) {
383          elements.up.off('mousedown.touchspin');  // android 4 workaround
384
385          if (originalinput.is(':disabled')) {
386            return;
387          }
388
389          upOnce();
390          startUpSpin();
391
392          ev.preventDefault();
393          ev.stopPropagation();
394        });
395
396        elements.up.on('mouseout touchleave touchend touchcancel', function(ev) {
397          if (!spinning) {
398            return;
399          }
400
401          ev.stopPropagation();
402          stopSpin();
403        });
404
405        elements.down.on('mouseout touchleave touchend touchcancel', function(ev) {
406          if (!spinning) {
407            return;
408          }
409
410          ev.stopPropagation();
411          stopSpin();
412        });
413
414        elements.down.on('mousemove touchmove', function(ev) {
415          if (!spinning) {
416            return;
417          }
418
419          ev.stopPropagation();
420          ev.preventDefault();
421        });
422
423        elements.up.on('mousemove touchmove', function(ev) {
424          if (!spinning) {
425            return;
426          }
427
428          ev.stopPropagation();
429          ev.preventDefault();
430        });
431
432        $(document).on(_scopeEventNames(['mouseup', 'touchend', 'touchcancel'], _currentSpinnerId).join(' '), function(ev) {
433          if (!spinning) {
434            return;
435          }
436
437          ev.preventDefault();
438          stopSpin();
439        });
440
441        $(document).on(_scopeEventNames(['mousemove', 'touchmove', 'scroll', 'scrollstart'], _currentSpinnerId).join(' '), function(ev) {
442          if (!spinning) {
443            return;
444          }
445
446          ev.preventDefault();
447          stopSpin();
448        });
449
450        originalinput.on('mousewheel DOMMouseScroll', function(ev) {
451          if (!settings.mousewheel || !originalinput.is(':focus')) {
452            return;
453          }
454
455          var delta = ev.originalEvent.wheelDelta || -ev.originalEvent.deltaY || -ev.originalEvent.detail;
456
457          ev.stopPropagation();
458          ev.preventDefault();
459
460          if (delta < 0) {
461            downOnce();
462          }
463          else {
464            upOnce();
465          }
466        });
467      }
468
469      function _bindEventsInterface() {
470        originalinput.on('touchspin.uponce', function() {
471          stopSpin();
472          upOnce();
473        });
474
475        originalinput.on('touchspin.downonce', function() {
476          stopSpin();
477          downOnce();
478        });
479
480        originalinput.on('touchspin.startupspin', function() {
481          startUpSpin();
482        });
483
484        originalinput.on('touchspin.startdownspin', function() {
485          startDownSpin();
486        });
487
488        originalinput.on('touchspin.stopspin', function() {
489          stopSpin();
490        });
491
492        originalinput.on('touchspin.updatesettings', function(e, newsettings) {
493          changeSettings(newsettings);
494        });
495      }
496
497      function _forcestepdivisibility(value) {
498        switch (settings.forcestepdivisibility) {
499          case 'round':
500            return (Math.round(value / settings.step) * settings.step).toFixed(settings.decimals);
501          case 'floor':
502            return (Math.floor(value / settings.step) * settings.step).toFixed(settings.decimals);
503          case 'ceil':
504            return (Math.ceil(value / settings.step) * settings.step).toFixed(settings.decimals);
505          default:
506            return value;
507        }
508      }
509
510      function _checkValue() {
511        var val, parsedval, returnval;
512
513        val = originalinput.val();
514
515        if (val === '') {
516          if (settings.replacementval !== '') {
517            originalinput.val(settings.replacementval);
518            originalinput.trigger('change');
519          }
520          return;
521        }
522
523        if (settings.decimals > 0 && val === '.') {
524          return;
525        }
526
527        parsedval = parseFloat(val);
528
529        if (isNaN(parsedval)) {
530          if (settings.replacementval !== '') {
531            parsedval = settings.replacementval;
532          }
533          else {
534            parsedval = 0;
535          }
536        }
537
538        returnval = parsedval;
539
540        if (parsedval.toString() !== val) {
541          returnval = parsedval;
542        }
543
544        if (parsedval < settings.min) {
545          returnval = settings.min;
546        }
547
548        if (parsedval > settings.max) {
549          returnval = settings.max;
550        }
551
552        returnval = _forcestepdivisibility(returnval);
553
554        if (Number(val).toString() !== returnval.toString()) {
555          originalinput.val(returnval);
556          originalinput.trigger('change');
557        }
558      }
559
560      function _getBoostedStep() {
561        if (!settings.booster) {
562          return settings.step;
563        }
564        else {
565          var boosted = Math.pow(2, Math.floor(spincount / settings.boostat)) * settings.step;
566
567          if (settings.maxboostedstep) {
568            if (boosted > settings.maxboostedstep) {
569              boosted = settings.maxboostedstep;
570              value = Math.round((value / boosted)) * boosted;
571            }
572          }
573
574          return Math.max(settings.step, boosted);
575        }
576      }
577
578      function upOnce() {
579        _checkValue();
580
581        value = parseFloat(elements.input.val());
582        if (isNaN(value)) {
583          value = 0;
584        }
585
586        var initvalue = value,
587            boostedstep = _getBoostedStep();
588
589        value = value + boostedstep;
590
591        if (value > settings.max) {
592          value = settings.max;
593          originalinput.trigger('touchspin.on.max');
594          stopSpin();
595        }
596
597        elements.input.val(Number(value).toFixed(settings.decimals));
598
599        if (initvalue !== value) {
600          originalinput.trigger('change');
601        }
602      }
603
604      function downOnce() {
605        _checkValue();
606
607        value = parseFloat(elements.input.val());
608        if (isNaN(value)) {
609          value = 0;
610        }
611
612        var initvalue = value,
613            boostedstep = _getBoostedStep();
614
615        value = value - boostedstep;
616
617        if (value < settings.min) {
618          value = settings.min;
619          originalinput.trigger('touchspin.on.min');
620          stopSpin();
621        }
622
623        elements.input.val(value.toFixed(settings.decimals));
624
625        if (initvalue !== value) {
626          originalinput.trigger('change');
627        }
628      }
629
630      function startDownSpin() {
631        stopSpin();
632
633        spincount = 0;
634        spinning = 'down';
635
636        originalinput.trigger('touchspin.on.startspin');
637        originalinput.trigger('touchspin.on.startdownspin');
638
639        downDelayTimeout = setTimeout(function() {
640          downSpinTimer = setInterval(function() {
641            spincount++;
642            downOnce();
643          }, settings.stepinterval);
644        }, settings.stepintervaldelay);
645      }
646
647      function startUpSpin() {
648        stopSpin();
649
650        spincount = 0;
651        spinning = 'up';
652
653        originalinput.trigger('touchspin.on.startspin');
654        originalinput.trigger('touchspin.on.startupspin');
655
656        upDelayTimeout = setTimeout(function() {
657          upSpinTimer = setInterval(function() {
658            spincount++;
659            upOnce();
660          }, settings.stepinterval);
661        }, settings.stepintervaldelay);
662      }
663
664      function stopSpin() {
665        clearTimeout(downDelayTimeout);
666        clearTimeout(upDelayTimeout);
667        clearInterval(downSpinTimer);
668        clearInterval(upSpinTimer);
669
670        switch (spinning) {
671          case 'up':
672            originalinput.trigger('touchspin.on.stopupspin');
673            originalinput.trigger('touchspin.on.stopspin');
674            break;
675          case 'down':
676            originalinput.trigger('touchspin.on.stopdownspin');
677            originalinput.trigger('touchspin.on.stopspin');
678            break;
679        }
680
681        spincount = 0;
682        spinning = false;
683      }
684
685    });
686
687  };
688
689})(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.