spinner.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * Fuel UX Spinner
  3. * https://github.com/ExactTarget/fuelux
  4. *
  5. * Copyright (c) 2012 ExactTarget
  6. * Licensed under the MIT license.
  7. */
  8. !function ($) {
  9. // SPINNER CONSTRUCTOR AND PROTOTYPE
  10. var Spinner = function (element, options) {
  11. this.$element = $(element);
  12. this.options = $.extend({}, $.fn.spinner.defaults, options);
  13. this.$input = this.$element.find('.spinner-input');
  14. this.$element.on('keyup', this.$input, $.proxy(this.change, this));
  15. if (this.options.hold) {
  16. this.$element.on('mousedown', '.spinner-up', $.proxy(function() { this.startSpin(true); } , this));
  17. this.$element.on('mouseup', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));
  18. this.$element.on('mouseout', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));
  19. this.$element.on('mousedown', '.spinner-down', $.proxy(function() {this.startSpin(false);} , this));
  20. } else {
  21. this.$element.on('click', '.spinner-up', $.proxy(function() { this.step(true); } , this));
  22. this.$element.on('click', '.spinner-down', $.proxy(function() { this.step(false); }, this));
  23. }
  24. this.switches = {
  25. count: 1,
  26. enabled: true
  27. };
  28. if (this.options.speed === 'medium') {
  29. this.switches.speed = 300;
  30. } else if (this.options.speed === 'fast') {
  31. this.switches.speed = 100;
  32. } else {
  33. this.switches.speed = 500;
  34. }
  35. this.lastValue = null;
  36. this.render();
  37. if (this.options.disabled) {
  38. this.disable();
  39. }
  40. };
  41. Spinner.prototype = {
  42. constructor: Spinner,
  43. render: function () {
  44. var inputValue = this.$input.val();
  45. if (inputValue) {
  46. this.value(inputValue);
  47. } else {
  48. this.$input.val(this.options.value);
  49. }
  50. this.$input.attr('maxlength', (this.options.max + '').split('').length);
  51. },
  52. change: function () {
  53. var newVal = this.$input.val();
  54. if(newVal/1){
  55. this.options.value = newVal/1;
  56. }else{
  57. newVal = newVal.replace(/[^0-9]/g,'');
  58. this.$input.val(newVal);
  59. this.options.value = newVal/1;
  60. }
  61. this.triggerChangedEvent();
  62. },
  63. stopSpin: function () {
  64. clearTimeout(this.switches.timeout);
  65. this.switches.count = 1;
  66. this.triggerChangedEvent();
  67. },
  68. triggerChangedEvent: function () {
  69. var currentValue = this.value();
  70. if (currentValue === this.lastValue) return;
  71. this.lastValue = currentValue;
  72. // Primary changed event
  73. this.$element.trigger('changed', currentValue);
  74. // Undocumented, kept for backward compatibility
  75. this.$element.trigger('change');
  76. },
  77. startSpin: function (type) {
  78. if (!this.options.disabled) {
  79. var divisor = this.switches.count;
  80. if (divisor === 1) {
  81. this.step(type);
  82. divisor = 1;
  83. } else if (divisor < 3){
  84. divisor = 1.5;
  85. } else if (divisor < 8){
  86. divisor = 2.5;
  87. } else {
  88. divisor = 4;
  89. }
  90. this.switches.timeout = setTimeout($.proxy(function() {this.iterator(type);} ,this),this.switches.speed/divisor);
  91. this.switches.count++;
  92. }
  93. },
  94. iterator: function (type) {
  95. this.step(type);
  96. this.startSpin(type);
  97. },
  98. step: function (dir) {
  99. var curValue = this.options.value;
  100. var limValue = dir ? this.options.max : this.options.min;
  101. if ((dir ? curValue < limValue : curValue > limValue)) {
  102. var newVal = curValue + (dir ? 1 : -1) * this.options.step;
  103. if (dir ? newVal > limValue : newVal < limValue) {
  104. this.value(limValue);
  105. } else {
  106. this.value(newVal);
  107. }
  108. } else if (this.options.cycle) {
  109. var cycleVal = dir ? this.options.min : this.options.max;
  110. this.value(cycleVal);
  111. }
  112. },
  113. value: function (value) {
  114. if (!isNaN(parseFloat(value)) && isFinite(value)) {
  115. value = parseFloat(value);
  116. this.options.value = value;
  117. this.$input.val(value);
  118. return this;
  119. } else {
  120. return this.options.value;
  121. }
  122. },
  123. disable: function () {
  124. this.options.disabled = true;
  125. this.$input.attr('disabled','');
  126. this.$element.find('button').addClass('disabled');
  127. },
  128. enable: function () {
  129. this.options.disabled = false;
  130. this.$input.removeAttr("disabled");
  131. this.$element.find('button').removeClass('disabled');
  132. }
  133. };
  134. // SPINNER PLUGIN DEFINITION
  135. $.fn.spinner = function (option,value) {
  136. var methodReturn;
  137. var $set = this.each(function () {
  138. var $this = $(this);
  139. var data = $this.data('spinner');
  140. var options = typeof option === 'object' && option;
  141. if (!data) $this.data('spinner', (data = new Spinner(this, options)));
  142. if (typeof option === 'string') methodReturn = data[option](value);
  143. });
  144. return (methodReturn === undefined) ? $set : methodReturn;
  145. };
  146. $.fn.spinner.defaults = {
  147. value: 1,
  148. min: 1,
  149. max: 999,
  150. step: 1,
  151. hold: true,
  152. speed: 'medium',
  153. disabled: false
  154. };
  155. $.fn.spinner.Constructor = Spinner;
  156. // SPINNER DATA-API
  157. $(function () {
  158. $('body').on('mousedown.spinner.data-api', '.spinner', function () {
  159. var $this = $(this);
  160. if ($this.data('spinner')) return;
  161. $this.spinner($this.data());
  162. });
  163. });
  164. }(window.jQuery);