You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
6.0 KiB

  1. /** @preserve jQuery animateNumber plugin v0.0.12
  2. * (c) 2013, Alexandr Borisov.
  3. * https://github.com/aishek/jquery-animateNumber
  4. */
  5. // ['...'] notation using to avoid names minification by Google Closure Compiler
  6. (function ($) {
  7. var reverse = function (value) {
  8. return value.split('').reverse().join('');
  9. };
  10. var defaults = {
  11. numberStep: function (now, tween) {
  12. var floored_number = Math.floor(now),
  13. target = $(tween.elem);
  14. target.text(floored_number);
  15. }
  16. };
  17. var handle = function (tween) {
  18. var elem = tween.elem;
  19. if (elem.nodeType && elem.parentNode) {
  20. var handler = elem._animateNumberSetter;
  21. if (!handler) {
  22. handler = defaults.numberStep;
  23. }
  24. handler(tween.now, tween);
  25. }
  26. };
  27. if (!$.Tween || !$.Tween.propHooks) {
  28. $.fx.step.number = handle;
  29. } else {
  30. $.Tween.propHooks.number = {
  31. set: handle
  32. };
  33. }
  34. var extract_number_parts = function (separated_number, group_length) {
  35. var numbers = separated_number.split('').reverse(),
  36. number_parts = [],
  37. current_number_part,
  38. current_index,
  39. q;
  40. for (var i = 0, l = Math.ceil(separated_number.length / group_length); i < l; i++) {
  41. current_number_part = '';
  42. for (q = 0; q < group_length; q++) {
  43. current_index = i * group_length + q;
  44. if (current_index === separated_number.length) {
  45. break;
  46. }
  47. current_number_part = current_number_part + numbers[current_index];
  48. }
  49. number_parts.push(current_number_part);
  50. }
  51. return number_parts;
  52. };
  53. var remove_precending_zeros = function (number_parts) {
  54. var last_index = number_parts.length - 1,
  55. last = reverse(number_parts[last_index]);
  56. number_parts[last_index] = reverse(parseInt(last, 10).toString());
  57. return number_parts;
  58. };
  59. $.animateNumber = {
  60. numberStepFactories: {
  61. /**
  62. * Creates numberStep handler, which appends string to floored animated number on each step.
  63. *
  64. * @example
  65. * // will animate to 100 with "1 %", "2 %", "3 %", ...
  66. * $('#someid').animateNumber({
  67. * number: 100,
  68. * numberStep: $.animateNumber.numberStepFactories.append(' %')
  69. * });
  70. *
  71. * @params {String} suffix string to append to animated number
  72. * @returns {Function} numberStep-compatible function for use in animateNumber's parameters
  73. */
  74. append: function (suffix) {
  75. return function (now, tween) {
  76. var floored_number = Math.floor(now),
  77. target = $(tween.elem);
  78. target.prop('number', now).text(floored_number + suffix);
  79. };
  80. },
  81. /**
  82. * Creates numberStep handler, which format floored numbers by separating them to groups.
  83. *
  84. * @example
  85. * // will animate with 1 ... 217,980 ... 95,217,980 ... 7,095,217,980
  86. * $('#world-population').animateNumber({
  87. * number: 7095217980,
  88. * numberStep: $.animateNumber.numberStepFactories.separator(',')
  89. * });
  90. * @example
  91. * // will animate with 1% ... 217,980% ... 95,217,980% ... 7,095,217,980%
  92. * $('#salesIncrease').animateNumber({
  93. * number: 7095217980,
  94. * numberStep: $.animateNumber.numberStepFactories.separator(',', 3, '%')
  95. * });
  96. *
  97. * @params {String} [separator=' '] string to separate number groups
  98. * @params {String} [group_length=3] number group length
  99. * @params {String} [suffix=''] suffix to append to number
  100. * @returns {Function} numberStep-compatible function for use in animateNumber's parameters
  101. */
  102. separator: function (separator, group_length, suffix) {
  103. separator = separator || ' ';
  104. group_length = group_length || 3;
  105. suffix = suffix || '';
  106. return function (now, tween) {
  107. var floored_number = Math.floor(now),
  108. separated_number = floored_number.toString(),
  109. target = $(tween.elem);
  110. if (separated_number.length > group_length) {
  111. var number_parts = extract_number_parts(separated_number, group_length);
  112. separated_number = remove_precending_zeros(number_parts).join(separator);
  113. separated_number = reverse(separated_number);
  114. }
  115. target.prop('number', now).text(separated_number + suffix);
  116. };
  117. }
  118. }
  119. };
  120. $.fn.animateNumber = function () {
  121. var options = arguments[0],
  122. settings = $.extend({}, defaults, options),
  123. target = $(this),
  124. args = [settings];
  125. for (var i = 1, l = arguments.length; i < l; i++) {
  126. args.push(arguments[i]);
  127. }
  128. // needs of custom step function usage
  129. if (options.numberStep) {
  130. // assigns custom step functions
  131. var items = this.each(function () {
  132. this._animateNumberSetter = options.numberStep;
  133. });
  134. // cleanup of custom step functions after animation
  135. var generic_complete = settings.complete;
  136. settings.complete = function () {
  137. items.each(function () {
  138. delete this._animateNumberSetter;
  139. });
  140. if (generic_complete) {
  141. generic_complete.apply(this, arguments);
  142. }
  143. };
  144. }
  145. return target.animate.apply(target, args);
  146. };
  147. }(jQuery));