hjg
2024-10-30 8cf23534166c07e711aac2a25911ada317ba01f0
提交 | 用户 | 时间
58d006 1 /*jshint undef: true, unused:true */
A 2 /*global jQuery: true */
3
4 /*!=========================================================================
5  *  Bootstrap TouchSpin
6  *  v1.3.1
7  *
8  *  A mobile and touch friendly input spinner component for Bootstrap 3.
9  *
10  *      https://github.com/istvan-meszaros/bootstrap-touchspin
11  *      http://www.virtuosoft.eu/code/bootstrap-touchspin/
12  *
13  *  Copyright 2013 István Ujj-Mészáros
14  *
15  *  Thanks for the contributors:
16  *      Stefan Bauer - https://github.com/sba
17  *
18  *  Licensed under the Apache License, Version 2.0 (the "License");
19  *  you may not use this file except in compliance with the License.
20  *  You may obtain a copy of the License at
21  *
22  *      http://www.apache.org/licenses/LICENSE-2.0
23  *
24  *  Unless required by applicable law or agreed to in writing, software
25  *  distributed under the License is distributed on an "AS IS" BASIS,
26  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27  *  See the License for the specific language governing permissions and
28  *  limitations under the License.
29  *
30 * ====================================================================== */
31
32 (function($) {
33     "use strict";
34
35     $.fn.TouchSpin = function(options) {
36
37         return this.each(function() {
38
39             var settings,
40                 originalinput = $(this),
41                 container,
42                 elements, // added by keenthemes to set fixed input groups
43                 value,
44                 downSpinTimer,
45                 upSpinTimer,
46                 downDelayTimeout,
47                 upDelayTimeout,
48                 spincount = 0,
49                 spinning = false;
50
51             init();
52
53             function init()
54             {
55                 if (originalinput.data("alreadyinitialized")) {
56                     return;
57                 }
58
59                 originalinput.data("alreadyinitialized", true);
60
61                 if (!originalinput.is("input")) {
62                     console.log("Must be an input.");
63                     return;
64                 }
65
66                 _initSettings();
67                 _checkValue();
68                 _buildHtml();
69                 _initElements();
70                 _bindEvents();
71                 _bindEventsInterface();
72             }
73
74             function _initSettings()
75             {
76                 settings = $.extend({
77                     min: 0,
78                     max: 100,
79                     step: 1,
80                     decimals: 0,
81                     stepinterval: 100,
82                     stepintervaldelay: 500,
83                     prefix: "",
84                     postfix: "",
85                     booster: true,
86                     boostat: 10,
87                     maxboostedstep: false,
88                     mousewheel: true
89                 }, options);
90             }
91
92             function _buildHtml()
93             {
94                 originalinput.data("initvalue", originalinput.val()).val(Number(originalinput.val()).toFixed(settings.decimals));
95
96                 var html = '<div class="input-group bootstrap-touchspin '+(settings.inputGroupClass ? settings.inputGroupClass : '')+'" style=""><span class="input-group-btn"><button class="btn '+(settings.spinDownClass ? settings.spinDownClass : 'btn-default')+' bootstrap-touchspin-down" type="button">-</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="btn '+(settings.spinUpClass ? settings.spinUpClass : 'btn-default')+' bootstrap-touchspin-up" type="button">+</button></span></div>';
97
98                 container = $(html).insertBefore(originalinput);
99
100                 $(".bootstrap-touchspin-prefix", container).after(originalinput);
101
102                 $("<style type='text/css'>.bootstrap-touchspin-prefix:empty,.bootstrap-touchspin-postfix:empty{display:none;}</style>").appendTo("head");
103
104                 originalinput.addClass("form-control");
105             }
106
107             function _initElements()
108             {
109                 elements = {
110                     down: $(".bootstrap-touchspin-down", container),
111                     up: $(".bootstrap-touchspin-up", container),
112                     input: $("input", container),
113                     prefix: $(".bootstrap-touchspin-prefix", container),
114                     postfix: $(".bootstrap-touchspin-postfix", container)
115                 };
116             }
117
118             function _bindEvents()
119             {
120                 originalinput.on("keydown", function(ev) {
121                     var code = ev.keyCode || ev.which;
122
123                     if (code === 38) {
124                         if (spinning !== "up") {
125                             upOnce();
126                             startUpSpin();
127                         }
128                         ev.preventDefault();
129                     }
130                     else if (code === 40) {
131                         if (spinning !== "down") {
132                             downOnce();
133                             startDownSpin();
134                         }
135                         ev.preventDefault();
136                     }
137                 });
138
139                 originalinput.on("keyup", function(ev) {
140                     var code = ev.keyCode || ev.which;
141
142                     if (code === 38) {
143                         stopSpin();
144                     }
145                     else if (code === 40) {
146                         stopSpin();
147                     }
148                     else {
149                         _checkValue();
150                     }
151                 });
152
153                 elements.down.on("keydown", function(ev) {
154                     var code = ev.keyCode || ev.which;
155
156                     if (code === 32 || code === 13) {
157                         if (spinning !== "down") {
158                             downOnce();
159                             startDownSpin();
160                         }
161                         ev.preventDefault();
162                     }
163                 });
164
165                 elements.down.on("keyup", function(ev) {
166                     var code = ev.keyCode || ev.which;
167
168                     if (code === 32 || code === 13) {
169                         stopSpin();
170                     }
171                 });
172
173                 elements.up.on("keydown", function(ev) {
174                     var code = ev.keyCode || ev.which;
175
176                     if (code === 32 || code === 13) {
177                         if (spinning !== "up") {
178                             upOnce();
179                             startUpSpin();
180                         }
181                         ev.preventDefault();
182                     }
183                 });
184
185                 elements.up.on("keyup", function(ev) {
186                     var code = ev.keyCode || ev.which;
187
188                     if (code === 32 || code === 13) {
189                         stopSpin();
190                     }
191                 });
192
193                 elements.down.on("mousedown touchstart", function(ev) {
194                     downOnce();
195                     startDownSpin();
196
197                     ev.preventDefault();
198                     ev.stopPropagation();
199                 });
200
201                 elements.up.on("mousedown touchstart", function(ev) {
202                     upOnce();
203                     startUpSpin();
204
205                     ev.preventDefault();
206                     ev.stopPropagation();
207                 });
208
209                 elements.up.on("mouseout touchleave touchend touchcancel", function(ev) {
210                     if (!spinning) {
211                         return;
212                     }
213
214                     ev.stopPropagation();
215                     stopSpin();
216                 });
217
218                 elements.down.on("mouseout touchleave touchend touchcancel", function(ev) {
219                     if (!spinning) {
220                         return;
221                     }
222
223                     ev.stopPropagation();
224                     stopSpin();
225                 });
226
227                 elements.down.on("mousemove touchmove", function(ev) {
228                     if (!spinning) {
229                         return;
230                     }
231
232                     ev.stopPropagation();
233                     ev.preventDefault();
234                 });
235
236                 elements.up.on("mousemove touchmove", function(ev) {
237                     if (!spinning) {
238                         return;
239                     }
240
241                     ev.stopPropagation();
242                     ev.preventDefault();
243                 });
244
245                 $(document).on("mouseup touchend touchcancel", function(ev) {
246                     if (!spinning) {
247                         return;
248                     }
249
250                     ev.preventDefault();
251                     stopSpin();
252                 });
253
254                 $(document).on("mousemove touchmove scroll scrollstart", function(ev) {
255                     if (!spinning) {
256                         return;
257                     }
258
259                     ev.preventDefault();
260                     stopSpin();
261                 });
262
263                 if (settings.mousewheel) {
264                     originalinput.bind("mousewheel DOMMouseScroll", function(ev) {
265                         var delta = ev.originalEvent.wheelDelta || -ev.originalEvent.detail;
266
267                         ev.stopPropagation();
268                         ev.preventDefault();
269
270                         if (delta < 0) {
271                             downOnce();
272                         }
273                         else {
274                             upOnce();
275                         }
276                     });
277                 }
278             }
279
280             function _bindEventsInterface() {
281                 originalinput.on('touchspin.uponce', function() {
282                     stopSpin();
283                     upOnce();
284                 });
285
286                 originalinput.on('touchspin.downonce', function() {
287                     stopSpin();
288                     downOnce();
289                 });
290
291                 originalinput.on('touchspin.startupspin', function() {
292                     startUpSpin();
293                 });
294
295                 originalinput.on('touchspin.startdownspin', function() {
296                     startDownSpin();
297                 });
298
299                 originalinput.on('touchspin.stopspin', function() {
300                     stopSpin();
301                 });
302             }
303
304             function _checkValue() {
305                 var val, parsedval, returnval;
306
307                 val = originalinput.val();
308
309                 if (settings.decimals > 0 && val === ".") {
310                     return;
311                 }
312
313                 parsedval = parseFloat(val);
314
315                 if (isNaN(parsedval)) {
316                     parsedval = 0;
317                 }
318
319                 returnval = parsedval;
320
321                 if (parsedval.toString() !== val) {
322                     returnval = parsedval;
323                 }
324
325                 if (parsedval < settings.min) {
326                     returnval = settings.min;
327                 }
328
329                 if (parsedval > settings.max) {
330                     returnval = settings.max;
331                 }
332
333                 if (Number(val).toString() !== returnval.toString()) {
334                     originalinput.val(returnval);
335                     originalinput.trigger("change");
336                 }
337             }
338
339             function _getBoostedStep() {
340                 if (!settings.booster) {
341                     return settings.step;
342                 }
343                 else {
344                     var boosted = Math.pow(2,Math.floor(spincount / settings.boostat)) * settings.step;
345
346                     if (settings.maxboostedstep) {
347                         if (boosted > settings.maxboostedstep) {
348                             boosted = settings.maxboostedstep;
349                             value = Math.round((value / boosted) * boosted);
350                         }
351                     }
352
353                     return Math.max(settings.step, boosted);
354                 }
355             }
356
357             function upOnce() {
358                 value = parseFloat(elements.input.val());
359                 if (isNaN(value)) {
360                     value = 0;
361                 }
362
363                 var initvalue = value,
364                     boostedstep = _getBoostedStep();
365
366                 value =  value + boostedstep;
367
368                 if (value > settings.max) {
369                     stopSpin();
370                     value = settings.max;
371                     originalinput.trigger("touchspin.max");
372                 }
373
374                 elements.input.val(Number(value).toFixed(settings.decimals));
375
376                 if (initvalue !== value) {
377                     originalinput.trigger("change");
378                 }
379             }
380
381             function downOnce() {
382                 value = parseFloat(elements.input.val());
383                 if (isNaN(value)) {
384                     value = 0;
385                 }
386
387                 var initvalue = value,
388                     boostedstep = _getBoostedStep();
389
390                 value = value - boostedstep;
391
392                 if (value < settings.min) {
393                     stopSpin();
394                     value = settings.min;
395                     originalinput.trigger("touchspin.min");
396                 }
397
398                 elements.input.val(value.toFixed(settings.decimals));
399
400                 if (initvalue !== value) {
401                     originalinput.trigger("change");
402                 }
403             }
404
405             function startDownSpin() {
406                 stopSpin();
407
408                 spincount = 0;
409                 spinning = "down";
410
411                 downDelayTimeout = setTimeout(function() {
412                     downSpinTimer = setInterval(function() {
413                         spincount++;
414                         downOnce();
415                     }, settings.stepinterval);
416                 }, settings.stepintervaldelay);
417             }
418
419             function startUpSpin() {
420                 stopSpin();
421
422                 spincount = 0;
423                 spinning = "up";
424
425                 upDelayTimeout = setTimeout(function() {
426                     upSpinTimer = setInterval(function() {
427                         spincount++;
428                         upOnce();
429                     }, settings.stepinterval);
430                 }, settings.stepintervaldelay);
431             }
432
433             function stopSpin() {
434                 clearTimeout(downDelayTimeout);
435                 clearTimeout(upDelayTimeout);
436                 clearInterval(downSpinTimer);
437                 clearInterval(upSpinTimer);
438
439                 spincount = 0;
440                 spinning = false;
441             }
442
443         });
444
445     };
446
447 })(jQuery);