1/*jshint undef: true, unused:true */ 2/*global jQuery: true */ 3 4/*!========================================================================= 5 * Bootstrap TouchSpin 6 * v2.5.0 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 * amid2887 - https://github.com/amid2887 18 * 19 * Licensed under the Apache License, Version 2.0 (the "License"); 20 * you may not use this file except in compliance with the License. 21 * You may obtain a copy of the License at 22 * 23 * http://www.apache.org/licenses/LICENSE-2.0 24 * 25 * Unless required by applicable law or agreed to in writing, software 26 * distributed under the License is distributed on an "AS IS" BASIS, 27 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 * See the License for the specific language governing permissions and 29 * limitations under the License. 30 * 31 * ====================================================================== */ 32 33(function ($) { 34 "use strict"; 35 36 $.fn.TouchSpin = function (options) { 37 38 var defaults = { 39 min: 0, 40 max: 100, 41 initval: "", 42 step: 1, 43 decimals: 0, 44 stepinterval: 100, 45 forcestepdivisibility: 'round', // none | floor | round | ceil 46 stepintervaldelay: 500, 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 }; 58 59 return this.each(function () { 60 61 var settings, 62 originalinput = $(this), 63 originalinput_data = originalinput.data(), 64 container, 65 elements, 66 value, 67 downSpinTimer, 68 upSpinTimer, 69 downDelayTimeout, 70 upDelayTimeout, 71 spincount = 0, 72 spinning = false; 73 74 init(); 75 76 function init() { 77 if (originalinput.data("alreadyinitialized")) { 78 return; 79 } 80 81 originalinput.data("alreadyinitialized", true); 82 83 if (!originalinput.is("input")) { 84 console.log("Must be an input."); 85 return; 86 } 87 88 _initSettings(); 89 _setInitval(); 90 _checkValue(); 91 _buildHtml(); 92 _initElements(); 93 _bindEvents(); 94 _bindEventsInterface(); 95 } 96 97 function _setInitval() { 98 if (settings.initval !== "" && originalinput.val() === "") { 99 originalinput.val(settings.initval); 100 } 101 } 102 103 function changeSettings(newsettings) { 104 _updateSettings(newsettings); 105 _checkValue(); 106 107 var value = Number(elements.input.val()); 108 elements.input.val(value.toFixed(settings.decimals)); 109 } 110 111 function _initSettings() { 112 settings = $.extend({}, defaults, originalinput_data, options); 113 } 114 115 function _updateSettings(newsettings) { 116 settings = $.extend({}, settings, newsettings); 117 } 118 119 function _buildHtml() { 120 var initval = originalinput.val(), 121 parentelement = originalinput.parent(); 122 123 if (initval !== "") { 124 initval = Number(initval).toFixed(settings.decimals); 125 } 126 127 originalinput.data("initvalue", initval).val(initval); 128 originalinput.addClass("form-control"); 129 130 $("<style type='text/css'>.bootstrap-touchspin-prefix:empty,.bootstrap-touchspin-postfix:empty{display:none;}</style>").appendTo("head"); 131 132 if (parentelement.hasClass("input-group")) { 133 _advanceInputGroup(parentelement); 134 } 135 else { 136 _buildInputGroup(); 137 } 138 139 } 140 141 function _advanceInputGroup(parentelement) { 142 parentelement.addClass("bootstrap-touchspin"); 143 144 var prev = originalinput.prev(), 145 next = originalinput.next(); 146 147 var downhtml, 148 uphtml, 149 prefixhtml = '<span class="input-group-addon bootstrap-touchspin-prefix">' + settings.prefix + '</span>', 150 postfixhtml = '<span class="input-group-addon bootstrap-touchspin-postfix">' + settings.postfix + '</span>'; 151 152 if (prev.hasClass("input-group-btn")) { 153 downhtml = '<button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">-</button>', 154 prev.append(downhtml); 155 } 156 else { 157 downhtml = '<span class="input-group-btn"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">-</button></span>'; 158 $(downhtml).insertBefore(originalinput); 159 } 160 161 if (next.hasClass("input-group-btn")) { 162 uphtml = '<button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">+</button>', 163 next.prepend(uphtml); 164 } 165 else { 166 uphtml = '<span class="input-group-btn"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">+</button></span>'; 167 $(uphtml).insertAfter(originalinput); 168 } 169 170 $(prefixhtml).insertBefore(originalinput); 171 $(postfixhtml).insertAfter(originalinput); 172 173 container = parentelement; 174 } 175 176 function _buildInputGroup() { 177 var html = '<div class="input-group bootstrap-touchspin"><span class="input-group-btn"><button class="' + settings.buttondown_class + ' 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="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">+</button></span></div>'; 178 179 container = $(html).insertBefore(originalinput); 180 181 $(".bootstrap-touchspin-prefix", container).after(originalinput); 182 183 if (originalinput.hasClass("input-sm")) { 184 container.addClass("input-group-sm"); 185 } 186 else if (originalinput.hasClass("input-lg")) { 187 container.addClass("input-group-lg"); 188 } 189 } 190 191 function _initElements() { 192 elements = { 193 down: $(".bootstrap-touchspin-down", container), 194 up: $(".bootstrap-touchspin-up", container), 195 input: $("input", container), 196 prefix: $(".bootstrap-touchspin-prefix", container).addClass(settings.prefix_extraclass), 197 postfix: $(".bootstrap-touchspin-postfix", container).addClass(settings.postfix_extraclass) 198 }; 199 } 200 201 function _bindEvents() {
202 originalinput.on("keydown", function (ev) { 203 var code = ev.keyCode || ev.which; 204 205 if (code === 38) { 206 if (spinning !== "up") { 207 upOnce(); 208 startUpSpin(); 209 } 210 ev.preventDefault(); 211 } 212 else if (code === 40) { 213 if (spinning !== "down") { 214 downOnce(); 215 startDownSpin(); 216 } 217 ev.preventDefault(); 218 } 219 }); 220 221 originalinput.on("keyup", function (ev) { 222 var code = ev.keyCode || ev.which; 223 224 if (code === 38) { 225 stopSpin(); 226 } 227 else if (code === 40) { 228 stopSpin(); 229 } 230 }); 231 232 originalinput.on("blur", function () { 233 _checkValue(); 234 }); 235 236 elements.down.on("keydown", function (ev) { 237 var code = ev.keyCode || ev.which; 238 239 if (code === 32 || code === 13) { 240 if (spinning !== "down") { 241 downOnce(); 242 startDownSpin(); 243 } 244 ev.preventDefault(); 245 } 246 }); 247 248 elements.down.on("keyup", function (ev) { 249 var code = ev.keyCode || ev.which; 250 251 if (code === 32 || code === 13) { 252 stopSpin(); 253 } 254 }); 255 256 elements.up.on("keydown", function (ev) { 257 var code = ev.keyCode || ev.which; 258 259 if (code === 32 || code === 13) { 260 if (spinning !== "up") { 261 upOnce(); 262 startUpSpin(); 263 } 264 ev.preventDefault(); 265 } 266 }); 267 268 elements.up.on("keyup", function (ev) { 269 var code = ev.keyCode || ev.which; 270 271 if (code === 32 || code === 13) { 272 stopSpin(); 273 } 274 }); 275 276 elements.down.on("mousedown touchstart", function (ev) { 277 downOnce(); 278 startDownSpin(); 279 280 ev.preventDefault(); 281 ev.stopPropagation(); 282 }); 283 284 elements.up.on("mousedown touchstart", function (ev) { 285 upOnce(); 286 startUpSpin(); 287 288 ev.preventDefault(); 289 ev.stopPropagation(); 290 }); 291 292 elements.up.on("mouseout touchleave touchend touchcancel", function (ev) { 293 if (!spinning) { 294 return; 295 } 296 297 ev.stopPropagation(); 298 stopSpin(); 299 }); 300 301 elements.down.on("mouseout touchleave touchend touchcancel", function (ev) { 302 if (!spinning) { 303 return; 304 } 305 306 ev.stopPropagation(); 307 stopSpin(); 308 }); 309 310 elements.down.on("mousemove touchmove", function (ev) { 311 if (!spinning) { 312 return; 313 } 314 315 ev.stopPropagation(); 316 ev.preventDefault(); 317 }); 318 319 elements.up.on("mousemove touchmove", function (ev) { 320 if (!spinning) { 321 return; 322 } 323 324 ev.stopPropagation(); 325 ev.preventDefault(); 326 }); 327 328 $(document).on("mouseup touchend touchcancel", function (ev) { 329 if (!spinning) { 330 return; 331 } 332 333 ev.preventDefault(); 334 stopSpin(); 335 }); 336 337 $(document).on("mousemove touchmove scroll scrollstart", function (ev) { 338 if (!spinning) { 339 return; 340 } 341 342 ev.preventDefault(); 343 stopSpin(); 344 }); 345 346 if (settings.mousewheel) { 347 originalinput.on("mousewheel DOMMouseScroll", function (ev) { 348 var delta = ev.originalEvent.wheelDelta || -ev.originalEvent.detail; 349 350 ev.stopPropagation(); 351 ev.preventDefault(); 352 353 if (delta < 0) { 354 downOnce(); 355 } 356 else { 357 upOnce(); 358 } 359 }); 360 } 361 } 362 363 function _bindEventsInterface() { 364 originalinput.on('touchspin.uponce', function () { 365 stopSpin(); 366 upOnce(); 367 }); 368 369 originalinput.on('touchspin.downonce', function () { 370 stopSpin(); 371 downOnce(); 372 }); 373 374 originalinput.on('touchspin.startupspin', function () { 375 startUpSpin(); 376 }); 377 378 originalinput.on('touchspin.startdownspin', function () { 379 startDownSpin(); 380 }); 381 382 originalinput.on('touchspin.stopspin', function () { 383 stopSpin(); 384 }); 385 386 originalinput.on('touchspin.updatesettings', function (e, newsettings) { 387 changeSettings(newsettings); 388 }); 389 } 390 391 function _forcestepdivisibility(value) { 392 switch (settings.forcestepdivisibility) { 393 case 'round': 394 return (Math.round(value / settings.step) * settings.step).toFixed(settings.decimals); 395 break; 396 case 'floor': 397 return (Math.floor(value / settings.step) * settings.step).toFixed(settings.decimals); 398 break;
399 case 'ceil': 400 return (Math.ceil(value / settings.step) * settings.step).toFixed(settings.decimals); 401 break; 402 default: 403 return value; 404 } 405 } 406 407 function _checkValue() { 408 var val, parsedval, returnval; 409 410 val = originalinput.val(); 411 412 if (val === "") { 413 return; 414 } 415 416 if (settings.decimals > 0 && val === ".") { 417 return; 418 } 419 420 parsedval = parseFloat(val); 421 422 if (isNaN(parsedval)) { 423 parsedval = 0; 424 } 425 426 returnval = parsedval; 427 428 if (parsedval.toString() !== val) { 429 returnval = parsedval; 430 } 431 432 if (parsedval < settings.min) { 433 returnval = settings.min; 434 } 435 436 if (parsedval > settings.max) { 437 returnval = settings.max; 438 } 439 440 returnval = _forcestepdivisibility(returnval); 441 442 if (Number(val).toString() !== returnval.toString()) { 443 originalinput.val(returnval); 444 originalinput.trigger("change"); 445 } 446 } 447 448 function _getBoostedStep() { 449 if (!settings.booster) { 450 return settings.step; 451 } 452 else { 453 var boosted = Math.pow(2, Math.floor(spincount / settings.boostat)) * settings.step; 454 455 if (settings.maxboostedstep) { 456 if (boosted > settings.maxboostedstep) { 457 boosted = settings.maxboostedstep; 458 value = Math.round((value / boosted) * boosted); 459 } 460 } 461 462 return Math.max(settings.step, boosted); 463 } 464 } 465 466 function upOnce() { 467 _checkValue(); 468 469 value = parseFloat(elements.input.val()); 470 if (isNaN(value)) { 471 value = 0; 472 } 473 474 var initvalue = value, 475 boostedstep = _getBoostedStep(); 476 477 value = value + boostedstep; 478 479 if (value > settings.max) { 480 stopSpin(); 481 value = settings.max; 482 originalinput.trigger("touchspin.max"); 483 } 484 485 elements.input.val(Number(value).toFixed(settings.decimals)); 486 487 if (initvalue !== value) { 488 originalinput.trigger("change"); 489 } 490 } 491 492 function downOnce() { 493 _checkValue(); 494 495 value = parseFloat(elements.input.val()); 496 if (isNaN(value)) { 497 value = 0; 498 } 499 500 var initvalue = value, 501 boostedstep = _getBoostedStep(); 502 503 value = value - boostedstep; 504 505 if (value < settings.min) { 506 stopSpin(); 507 value = settings.min; 508 originalinput.trigger("touchspin.min"); 509 } 510 511 elements.input.val(value.toFixed(settings.decimals)); 512 513 if (initvalue !== value) { 514 originalinput.trigger("change"); 515 } 516 } 517 518 function startDownSpin() { 519 stopSpin(); 520 521 spincount = 0; 522 spinning = "down"; 523 524 downDelayTimeout = setTimeout(function () { 525 downSpinTimer = setInterval(function () { 526 spincount++; 527 downOnce(); 528 }, settings.stepinterval); 529 }, settings.stepintervaldelay); 530 } 531 532 function startUpSpin() { 533 stopSpin(); 534 535 spincount = 0; 536 spinning = "up"; 537 538 upDelayTimeout = setTimeout(function () { 539 upSpinTimer = setInterval(function () { 540 spincount++; 541 upOnce(); 542 }, settings.stepinterval); 543 }, settings.stepintervaldelay); 544 } 545 546 function stopSpin() { 547 clearTimeout(downDelayTimeout); 548 clearTimeout(upDelayTimeout); 549 clearInterval(downSpinTimer); 550 clearInterval(upSpinTimer); 551 552 spincount = 0; 553 spinning = false;
554 } 555 556 }); 557 558 }; 559 560})(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.