1 | /** |
---|
2 | * jqPlot |
---|
3 | * Pure JavaScript plotting plugin using jQuery |
---|
4 | * |
---|
5 | * Version: @VERSION |
---|
6 | * |
---|
7 | * Copyright (c) 2009-2011 Chris Leonello |
---|
8 | * jqPlot is currently available for use in all personal or commercial projects |
---|
9 | * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL |
---|
10 | * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can |
---|
11 | * choose the license that best suits your project and use it accordingly. |
---|
12 | * |
---|
13 | * Although not required, the author would appreciate an email letting him |
---|
14 | * know of any substantial use of jqPlot. You can reach the author at: |
---|
15 | * chris at jqplot dot com or see http://www.jqplot.com/info.php . |
---|
16 | * |
---|
17 | * If you are feeling kind and generous, consider supporting the project by |
---|
18 | * making a donation at: http://www.jqplot.com/donate.php . |
---|
19 | * |
---|
20 | * sprintf functions contained in jqplot.sprintf.js by Ash Searle: |
---|
21 | * |
---|
22 | * version 2007.04.27 |
---|
23 | * author Ash Searle |
---|
24 | * http://hexmen.com/blog/2007/03/printf-sprintf/ |
---|
25 | * http://hexmen.com/js/sprintf.js |
---|
26 | * The author (Ash Searle) has placed this code in the public domain: |
---|
27 | * "This code is unrestricted: you are free to use it however you like." |
---|
28 | * |
---|
29 | */ |
---|
30 | (function($) { |
---|
31 | /** |
---|
32 | * JavaScript printf/sprintf functions. |
---|
33 | * |
---|
34 | * This code has been adapted from the publicly available sprintf methods |
---|
35 | * by Ash Searle. His original header follows: |
---|
36 | * |
---|
37 | * This code is unrestricted: you are free to use it however you like. |
---|
38 | * |
---|
39 | * The functions should work as expected, performing left or right alignment, |
---|
40 | * truncating strings, outputting numbers with a required precision etc. |
---|
41 | * |
---|
42 | * For complex cases, these functions follow the Perl implementations of |
---|
43 | * (s)printf, allowing arguments to be passed out-of-order, and to set the |
---|
44 | * precision or length of the output based on arguments instead of fixed |
---|
45 | * numbers. |
---|
46 | * |
---|
47 | * See http://perldoc.perl.org/functions/sprintf.html for more information. |
---|
48 | * |
---|
49 | * Implemented: |
---|
50 | * - zero and space-padding |
---|
51 | * - right and left-alignment, |
---|
52 | * - base X prefix (binary, octal and hex) |
---|
53 | * - positive number prefix |
---|
54 | * - (minimum) width |
---|
55 | * - precision / truncation / maximum width |
---|
56 | * - out of order arguments |
---|
57 | * |
---|
58 | * Not implemented (yet): |
---|
59 | * - vector flag |
---|
60 | * - size (bytes, words, long-words etc.) |
---|
61 | * |
---|
62 | * Will not implement: |
---|
63 | * - %n or %p (no pass-by-reference in JavaScript) |
---|
64 | * |
---|
65 | * @version 2007.04.27 |
---|
66 | * @author Ash Searle |
---|
67 | * |
---|
68 | * You can see the original work and comments on his blog: |
---|
69 | * http://hexmen.com/blog/2007/03/printf-sprintf/ |
---|
70 | * http://hexmen.com/js/sprintf.js |
---|
71 | */ |
---|
72 | |
---|
73 | /** |
---|
74 | * @Modifications 2009.05.26 |
---|
75 | * @author Chris Leonello |
---|
76 | * |
---|
77 | * Added %p %P specifier |
---|
78 | * Acts like %g or %G but will not add more significant digits to the output than present in the input. |
---|
79 | * Example: |
---|
80 | * Format: '%.3p', Input: 0.012, Output: 0.012 |
---|
81 | * Format: '%.3g', Input: 0.012, Output: 0.0120 |
---|
82 | * Format: '%.4p', Input: 12.0, Output: 12.0 |
---|
83 | * Format: '%.4g', Input: 12.0, Output: 12.00 |
---|
84 | * Format: '%.4p', Input: 4.321e-5, Output: 4.321e-5 |
---|
85 | * Format: '%.4g', Input: 4.321e-5, Output: 4.3210e-5 |
---|
86 | */ |
---|
87 | $.jqplot.sprintf = function() { |
---|
88 | function pad(str, len, chr, leftJustify) { |
---|
89 | var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr); |
---|
90 | return leftJustify ? str + padding : padding + str; |
---|
91 | |
---|
92 | } |
---|
93 | |
---|
94 | function thousand_separate(value) { |
---|
95 | var value_str = new String(value); |
---|
96 | for (var i=10; i>0; i--) { |
---|
97 | if (value_str == (value_str = value_str.replace(/^(\d+)(\d{3})/, "$1"+$.jqplot.sprintf.thousandsSeparator+"$2"))) break; |
---|
98 | } |
---|
99 | return value_str; |
---|
100 | } |
---|
101 | |
---|
102 | function justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace) { |
---|
103 | var diff = minWidth - value.length; |
---|
104 | if (diff > 0) { |
---|
105 | var spchar = ' '; |
---|
106 | if (htmlSpace) { spchar = ' '; } |
---|
107 | if (leftJustify || !zeroPad) { |
---|
108 | value = pad(value, minWidth, spchar, leftJustify); |
---|
109 | } else { |
---|
110 | value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length); |
---|
111 | } |
---|
112 | } |
---|
113 | return value; |
---|
114 | } |
---|
115 | |
---|
116 | function formatBaseX(value, base, prefix, leftJustify, minWidth, precision, zeroPad, htmlSpace) { |
---|
117 | // Note: casts negative numbers to positive ones |
---|
118 | var number = value >>> 0; |
---|
119 | prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || ''; |
---|
120 | value = prefix + pad(number.toString(base), precision || 0, '0', false); |
---|
121 | return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); |
---|
122 | } |
---|
123 | |
---|
124 | function formatString(value, leftJustify, minWidth, precision, zeroPad, htmlSpace) { |
---|
125 | if (precision != null) { |
---|
126 | value = value.slice(0, precision); |
---|
127 | } |
---|
128 | return justify(value, '', leftJustify, minWidth, zeroPad, htmlSpace); |
---|
129 | } |
---|
130 | |
---|
131 | var a = arguments, i = 0, format = a[i++]; |
---|
132 | |
---|
133 | return format.replace($.jqplot.sprintf.regex, function(substring, valueIndex, flags, minWidth, _, precision, type) { |
---|
134 | if (substring == '%%') { return '%'; } |
---|
135 | |
---|
136 | // parse flags |
---|
137 | var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, htmlSpace = false, thousandSeparation = false; |
---|
138 | for (var j = 0; flags && j < flags.length; j++) switch (flags.charAt(j)) { |
---|
139 | case ' ': positivePrefix = ' '; break; |
---|
140 | case '+': positivePrefix = '+'; break; |
---|
141 | case '-': leftJustify = true; break; |
---|
142 | case '0': zeroPad = true; break; |
---|
143 | case '#': prefixBaseX = true; break; |
---|
144 | case '&': htmlSpace = true; break; |
---|
145 | case '\'': thousandSeparation = true; break; |
---|
146 | } |
---|
147 | |
---|
148 | // parameters may be null, undefined, empty-string or real valued |
---|
149 | // we want to ignore null, undefined and empty-string values |
---|
150 | |
---|
151 | if (!minWidth) { |
---|
152 | minWidth = 0; |
---|
153 | } |
---|
154 | else if (minWidth == '*') { |
---|
155 | minWidth = +a[i++]; |
---|
156 | } |
---|
157 | else if (minWidth.charAt(0) == '*') { |
---|
158 | minWidth = +a[minWidth.slice(1, -1)]; |
---|
159 | } |
---|
160 | else { |
---|
161 | minWidth = +minWidth; |
---|
162 | } |
---|
163 | |
---|
164 | // Note: undocumented perl feature: |
---|
165 | if (minWidth < 0) { |
---|
166 | minWidth = -minWidth; |
---|
167 | leftJustify = true; |
---|
168 | } |
---|
169 | |
---|
170 | if (!isFinite(minWidth)) { |
---|
171 | throw new Error('$.jqplot.sprintf: (minimum-)width must be finite'); |
---|
172 | } |
---|
173 | |
---|
174 | if (!precision) { |
---|
175 | precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0); |
---|
176 | } |
---|
177 | else if (precision == '*') { |
---|
178 | precision = +a[i++]; |
---|
179 | } |
---|
180 | else if (precision.charAt(0) == '*') { |
---|
181 | precision = +a[precision.slice(1, -1)]; |
---|
182 | } |
---|
183 | else { |
---|
184 | precision = +precision; |
---|
185 | } |
---|
186 | |
---|
187 | // grab value using valueIndex if required? |
---|
188 | var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++]; |
---|
189 | |
---|
190 | switch (type) { |
---|
191 | case 's': { |
---|
192 | if (value == null) { |
---|
193 | return ''; |
---|
194 | } |
---|
195 | return formatString(String(value), leftJustify, minWidth, precision, zeroPad, htmlSpace); |
---|
196 | } |
---|
197 | case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad, htmlSpace); |
---|
198 | case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad,htmlSpace); |
---|
199 | case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); |
---|
200 | case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); |
---|
201 | case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace).toUpperCase(); |
---|
202 | case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); |
---|
203 | case 'i': { |
---|
204 | var number = parseInt(+value, 10); |
---|
205 | if (isNaN(number)) { |
---|
206 | return ''; |
---|
207 | } |
---|
208 | var prefix = number < 0 ? '-' : positivePrefix; |
---|
209 | var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number)); |
---|
210 | value = prefix + pad(number_str, precision, '0', false); |
---|
211 | //value = prefix + pad(String(Math.abs(number)), precision, '0', false); |
---|
212 | return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); |
---|
213 | } |
---|
214 | case 'd': { |
---|
215 | var number = Math.round(+value); |
---|
216 | if (isNaN(number)) { |
---|
217 | return ''; |
---|
218 | } |
---|
219 | var prefix = number < 0 ? '-' : positivePrefix; |
---|
220 | var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number)); |
---|
221 | value = prefix + pad(number_str, precision, '0', false); |
---|
222 | return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); |
---|
223 | } |
---|
224 | case 'e': |
---|
225 | case 'E': |
---|
226 | case 'f': |
---|
227 | case 'F': |
---|
228 | case 'g': |
---|
229 | case 'G': |
---|
230 | { |
---|
231 | var number = +value; |
---|
232 | if (isNaN(number)) { |
---|
233 | return ''; |
---|
234 | } |
---|
235 | var prefix = number < 0 ? '-' : positivePrefix; |
---|
236 | var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())]; |
---|
237 | var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; |
---|
238 | var number_str = Math.abs(number)[method](precision); |
---|
239 | number_str = thousandSeparation ? thousand_separate(number_str): number_str; |
---|
240 | value = prefix + number_str; |
---|
241 | return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform](); |
---|
242 | } |
---|
243 | case 'p': |
---|
244 | case 'P': |
---|
245 | { |
---|
246 | // make sure number is a number |
---|
247 | var number = +value; |
---|
248 | if (isNaN(number)) { |
---|
249 | return ''; |
---|
250 | } |
---|
251 | var prefix = number < 0 ? '-' : positivePrefix; |
---|
252 | |
---|
253 | var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/); |
---|
254 | var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length; |
---|
255 | var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0; |
---|
256 | |
---|
257 | if (Math.abs(number) < 1) { |
---|
258 | if (sd + zeros <= precision) { |
---|
259 | value = prefix + Math.abs(number).toPrecision(sd); |
---|
260 | } |
---|
261 | else { |
---|
262 | if (sd <= precision - 1) { |
---|
263 | value = prefix + Math.abs(number).toExponential(sd-1); |
---|
264 | } |
---|
265 | else { |
---|
266 | value = prefix + Math.abs(number).toExponential(precision-1); |
---|
267 | } |
---|
268 | } |
---|
269 | } |
---|
270 | else { |
---|
271 | var prec = (sd <= precision) ? sd : precision; |
---|
272 | value = prefix + Math.abs(number).toPrecision(prec); |
---|
273 | } |
---|
274 | var textTransform = ['toString', 'toUpperCase']['pP'.indexOf(type) % 2]; |
---|
275 | return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform](); |
---|
276 | } |
---|
277 | case 'n': return ''; |
---|
278 | default: return substring; |
---|
279 | } |
---|
280 | }); |
---|
281 | }; |
---|
282 | |
---|
283 | $.jqplot.sprintf.thousandsSeparator = ','; |
---|
284 | |
---|
285 | $.jqplot.sprintf.regex = /%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g; |
---|
286 | |
---|
287 | })(jQuery); |
---|