1(function ($) { 2 $.fn.countTo = function (options) { 3 options = options || {}; 4 5 return $(this).each(function () { 6 // set options for current element 7 var settings = $.extend({}, $.fn.countTo.defaults, { 8 from: $(this).data('from'), 9 to: $(this).data('to'), 10 speed: $(this).data('speed'), 11 refreshInterval: $(this).data('refresh-interval'), 12 decimals: $(this).data('decimals'), 13 prefix: $(this).data('prefix'), 14 suffix: $(this).data('suffix'), 15 withCommas: $(this).data('with-commas'), 16 ordinal: $(this).data('ordinal') 17 }, options); 18 19 // how many times to update the value, and how much to increment the value on each update 20 var loops = Math.ceil(settings.speed / settings.refreshInterval), 21 increment = (settings.to - settings.from) / loops; 22 23 // references & variables that will change with each update 24 var self = this, 25 $self = $(this), 26 loopCount = 0, 27 value = settings.from, 28 data = $self.data('countTo') || {}; 29 30 $self.data('countTo', data); 31 32 // if an existing interval can be found, clear it first 33 if (data.interval) { 34 clearInterval(data.interval); 35 } 36 data.interval = setInterval(updateTimer, settings.refreshInterval); 37 38 // initialize the element with the starting value 39 render(value); 40 41 function updateTimer() { 42 value += increment; 43 loopCount++; 44 45 render(value); 46
47 if (typeof(settings.onUpdate) == 'function') { 48 settings.onUpdate.call(self, value); 49 } 50 51 if (loopCount >= loops) { 52 // remove the interval 53 $self.removeData('countTo'); 54 clearInterval(data.interval); 55 value = settings.to; 56 57 if (typeof(settings.onComplete) == 'function') { 58 settings.onComplete.call(self, value); 59 } 60 } 61 } 62 63 function render(value) { 64 var formattedValue = settings.formatter.call(self, value, settings); 65 $self.text(formattedValue); 66 } 67 }); 68 }; 69 70 $.fn.countTo.defaults = { 71 from: 0, // the number the element should start at 72 to: 0, // the number the element should end at 73 speed: 1000, // how long it should take to count between the target numbers 74 refreshInterval: 100, // how often the element should be updated 75 decimals: 0, // the number of decimal places to show 76 prefix: '', // the prefix to appear before the number 77 suffix: '', // the suffix to appear after the number (and ordinal, if set) 78 withCommas: false, // whether the number should show thousand/million commas 79 ordinal: false, // whether it should show 1st, 2nd, 3rd and so on 80 ordinalHandler: ordinalHandler, // handler for formatting the ordinals 81 formatter: formatter, // handler for formatting the value before rendering 82 onUpdate: null, // callback method for every time the element is updated 83 onComplete: null // callback method for when the element finishes updating 84 }; 85 86 function ordinalHandler(settings) { 87 if(settings.ordinal !== false) { 88 var s = ["th","st","nd","rd"], 89 v = settings.to % 100; 90 return s[(v-20)%10]||s[v]||s[0]; 91 } 92 return ''; 93 } 94 95 function numberWithCommas(value, settings) { 96 if(settings.withCommas !== false) { 97 var parts = value.toString().split("."); 98 parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); 99 return parts.join("."); 100 } 101 return value; 102 } 103 104 function formatter(value, settings) { 105 return settings.prefix + numberWithCommas( value.toFixed(settings.decimals), settings ) + settings.suffix + settings.ordinalHandler.call(self, settings); 106 } 107 108}(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.