root / snf-app / synnefo / ui / static / snf / js / lib / underscore.string.js @ 483c9197
History | View | Annotate | Download (13.4 kB)
1 |
// Underscore.string
|
---|---|
2 |
// (c) 2010 Esa-Matti Suuronen <esa-matti aet suuronen dot org>
|
3 |
// Underscore.strings is freely distributable under the terms of the MIT license.
|
4 |
// Documentation: https://github.com/edtsech/underscore.string
|
5 |
// Some code is borrowed from MooTools and Alexandru Marasteanu.
|
6 |
|
7 |
// Version 1.1.6
|
8 |
|
9 |
|
10 |
(function(root){
|
11 |
'use strict';
|
12 |
|
13 |
if (typeof _ != 'undefined') { |
14 |
var _reverse = _().reverse,
|
15 |
_include = _.include; |
16 |
} |
17 |
|
18 |
// Defining helper functions.
|
19 |
|
20 |
var nativeTrim = String.prototype.trim;
|
21 |
|
22 |
var parseNumber = function(source) { return source * 1 || 0; }; |
23 |
|
24 |
var strRepeat = function(i, m) { |
25 |
for (var o = []; m > 0; o[--m] = i); |
26 |
return o.join(''); |
27 |
}; |
28 |
|
29 |
var slice = function(a){ |
30 |
return Array.prototype.slice.call(a);
|
31 |
}; |
32 |
|
33 |
var defaultToWhiteSpace = function(characters){ |
34 |
if (characters) {
|
35 |
return _s.escapeRegExp(characters);
|
36 |
} |
37 |
return '\\s'; |
38 |
}; |
39 |
|
40 |
var sArgs = function(method){ |
41 |
return function(){ |
42 |
var args = slice(arguments); |
43 |
for(var i=0; i<args.length; i++) |
44 |
args[i] = args[i] == null ? '' : '' + args[i]; |
45 |
return method.apply(null, args); |
46 |
}; |
47 |
}; |
48 |
|
49 |
// sprintf() for JavaScript 0.7-beta1
|
50 |
// http://www.diveintojavascript.com/projects/javascript-sprintf
|
51 |
//
|
52 |
// Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
|
53 |
// All rights reserved.
|
54 |
|
55 |
var sprintf = (function() { |
56 |
function get_type(variable) { |
57 |
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); |
58 |
} |
59 |
|
60 |
var str_repeat = strRepeat;
|
61 |
|
62 |
var str_format = function() { |
63 |
if (!str_format.cache.hasOwnProperty(arguments[0])) { |
64 |
str_format.cache[arguments[0]] = str_format.parse(arguments[0]); |
65 |
} |
66 |
return str_format.format.call(null, str_format.cache[arguments[0]], arguments); |
67 |
}; |
68 |
|
69 |
str_format.format = function(parse_tree, argv) { |
70 |
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; |
71 |
for (i = 0; i < tree_length; i++) { |
72 |
node_type = get_type(parse_tree[i]); |
73 |
if (node_type === 'string') { |
74 |
output.push(parse_tree[i]); |
75 |
} |
76 |
else if (node_type === 'array') { |
77 |
match = parse_tree[i]; // convenience purposes only
|
78 |
if (match[2]) { // keyword argument |
79 |
arg = argv[cursor]; |
80 |
for (k = 0; k < match[2].length; k++) { |
81 |
if (!arg.hasOwnProperty(match[2][k])) { |
82 |
throw(sprintf('[_.sprintf] property "%s" does not exist', match[2][k])); |
83 |
} |
84 |
arg = arg[match[2][k]];
|
85 |
} |
86 |
} else if (match[1]) { // positional argument (explicit) |
87 |
arg = argv[match[1]];
|
88 |
} |
89 |
else { // positional argument (implicit) |
90 |
arg = argv[cursor++]; |
91 |
} |
92 |
|
93 |
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { |
94 |
throw(sprintf('[_.sprintf] expecting number but found %s', get_type(arg))); |
95 |
} |
96 |
switch (match[8]) { |
97 |
case 'b': arg = arg.toString(2); break; |
98 |
case 'c': arg = String.fromCharCode(arg); break; |
99 |
case 'd': arg = parseInt(arg, 10); break; |
100 |
case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; |
101 |
case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; |
102 |
case 'o': arg = arg.toString(8); break; |
103 |
case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; |
104 |
case 'u': arg = Math.abs(arg); break; |
105 |
case 'x': arg = arg.toString(16); break; |
106 |
case 'X': arg = arg.toString(16).toUpperCase(); break; |
107 |
} |
108 |
arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); |
109 |
pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; |
110 |
pad_length = match[6] - String(arg).length;
|
111 |
pad = match[6] ? str_repeat(pad_character, pad_length) : ''; |
112 |
output.push(match[5] ? arg + pad : pad + arg);
|
113 |
} |
114 |
} |
115 |
return output.join(''); |
116 |
}; |
117 |
|
118 |
str_format.cache = {}; |
119 |
|
120 |
str_format.parse = function(fmt) { |
121 |
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; |
122 |
while (_fmt) {
|
123 |
if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { |
124 |
parse_tree.push(match[0]);
|
125 |
} |
126 |
else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { |
127 |
parse_tree.push('%');
|
128 |
} |
129 |
else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { |
130 |
if (match[2]) { |
131 |
arg_names |= 1;
|
132 |
var field_list = [], replacement_field = match[2], field_match = []; |
133 |
if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { |
134 |
field_list.push(field_match[1]);
|
135 |
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { |
136 |
if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { |
137 |
field_list.push(field_match[1]);
|
138 |
} |
139 |
else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { |
140 |
field_list.push(field_match[1]);
|
141 |
} |
142 |
else {
|
143 |
throw('[_.sprintf] huh?'); |
144 |
} |
145 |
} |
146 |
} |
147 |
else {
|
148 |
throw('[_.sprintf] huh?'); |
149 |
} |
150 |
match[2] = field_list;
|
151 |
} |
152 |
else {
|
153 |
arg_names |= 2;
|
154 |
} |
155 |
if (arg_names === 3) { |
156 |
throw('[_.sprintf] mixing positional and named placeholders is not (yet) supported'); |
157 |
} |
158 |
parse_tree.push(match); |
159 |
} |
160 |
else {
|
161 |
throw('[_.sprintf] huh?'); |
162 |
} |
163 |
_fmt = _fmt.substring(match[0].length);
|
164 |
} |
165 |
return parse_tree;
|
166 |
}; |
167 |
|
168 |
return str_format;
|
169 |
})(); |
170 |
|
171 |
|
172 |
|
173 |
// Defining underscore.string
|
174 |
|
175 |
var _s = {
|
176 |
|
177 |
isBlank: sArgs(function(str){ |
178 |
return (/^\s*$/).test(str); |
179 |
}), |
180 |
|
181 |
stripTags: sArgs(function(str){ |
182 |
return str.replace(/<\/?[^>]+>/ig, ''); |
183 |
}), |
184 |
|
185 |
capitalize : sArgs(function(str) { |
186 |
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase(); |
187 |
}), |
188 |
|
189 |
chop: sArgs(function(str, step){ |
190 |
step = parseNumber(step) || str.length; |
191 |
var arr = [];
|
192 |
for (var i = 0; i < str.length;) { |
193 |
arr.push(str.slice(i,i + step)); |
194 |
i = i + step; |
195 |
} |
196 |
return arr;
|
197 |
}), |
198 |
|
199 |
clean: sArgs(function(str){ |
200 |
return _s.strip(str.replace(/\s+/g, ' ')); |
201 |
}), |
202 |
|
203 |
count: sArgs(function(str, substr){ |
204 |
var count = 0, index; |
205 |
for (var i=0; i < str.length;) { |
206 |
index = str.indexOf(substr, i); |
207 |
index >= 0 && count++;
|
208 |
i = i + (index >= 0 ? index : 0) + substr.length; |
209 |
} |
210 |
return count;
|
211 |
}), |
212 |
|
213 |
chars: sArgs(function(str) { |
214 |
return str.split(''); |
215 |
}), |
216 |
|
217 |
escapeHTML: sArgs(function(str) { |
218 |
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>') |
219 |
.replace(/"/g, '"').replace(/'/g, "'"); |
220 |
}), |
221 |
|
222 |
unescapeHTML: sArgs(function(str) { |
223 |
return str.replace(/</g, '<').replace(/>/g, '>') |
224 |
.replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, '&'); |
225 |
}), |
226 |
|
227 |
escapeRegExp: sArgs(function(str){ |
228 |
// From MooTools core 1.2.4
|
229 |
return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); |
230 |
}), |
231 |
|
232 |
insert: sArgs(function(str, i, substr){ |
233 |
var arr = str.split(''); |
234 |
arr.splice(parseNumber(i), 0, substr);
|
235 |
return arr.join(''); |
236 |
}), |
237 |
|
238 |
includes: sArgs(function(str, needle){ |
239 |
return str.indexOf(needle) !== -1; |
240 |
}), |
241 |
|
242 |
include: function(obj, needle) { |
243 |
if (!_include || (/string|number/).test(typeof obj)) { |
244 |
return this.includes(obj, needle); |
245 |
} else {
|
246 |
return _include(obj, needle);
|
247 |
} |
248 |
}, |
249 |
|
250 |
join: sArgs(function(sep) { |
251 |
var args = slice(arguments); |
252 |
return args.join(args.shift());
|
253 |
}), |
254 |
|
255 |
lines: sArgs(function(str) { |
256 |
return str.split("\n"); |
257 |
}), |
258 |
|
259 |
reverse: function(obj){ |
260 |
if (!_reverse || (/string|number/).test(typeof obj)) { |
261 |
return Array.prototype.reverse.apply(String(obj).split('')).join(''); |
262 |
} else {
|
263 |
return _reverse.call(_(obj));
|
264 |
} |
265 |
}, |
266 |
|
267 |
splice: sArgs(function(str, i, howmany, substr){ |
268 |
var arr = str.split(''); |
269 |
arr.splice(parseNumber(i), parseNumber(howmany), substr); |
270 |
return arr.join(''); |
271 |
}), |
272 |
|
273 |
startsWith: sArgs(function(str, starts){ |
274 |
return str.length >= starts.length && str.substring(0, starts.length) === starts; |
275 |
}), |
276 |
|
277 |
endsWith: sArgs(function(str, ends){ |
278 |
return str.length >= ends.length && str.substring(str.length - ends.length) === ends;
|
279 |
}), |
280 |
|
281 |
succ: sArgs(function(str){ |
282 |
var arr = str.split(''); |
283 |
arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1)); |
284 |
return arr.join(''); |
285 |
}), |
286 |
|
287 |
titleize: sArgs(function(str){ |
288 |
var arr = str.split(' '), |
289 |
word; |
290 |
for (var i=0; i < arr.length; i++) { |
291 |
word = arr[i].split('');
|
292 |
if(typeof word[0] !== 'undefined') word[0] = word[0].toUpperCase(); |
293 |
i+1 === arr.length ? arr[i] = word.join('') : arr[i] = word.join('') + ' '; |
294 |
} |
295 |
return arr.join(''); |
296 |
}), |
297 |
|
298 |
camelize: sArgs(function(str){ |
299 |
return _s.trim(str).replace(/(\-|_|\s)+(.)?/g, function(match, separator, chr) { |
300 |
return chr ? chr.toUpperCase() : ''; |
301 |
}); |
302 |
}), |
303 |
|
304 |
underscored: function(str){ |
305 |
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/\-|\s+/g, '_').toLowerCase(); |
306 |
}, |
307 |
|
308 |
dasherize: function(str){ |
309 |
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1-$2').replace(/^([A-Z]+)/, '-$1').replace(/\_|\s+/g, '-').toLowerCase(); |
310 |
}, |
311 |
|
312 |
trim: sArgs(function(str, characters){ |
313 |
if (!characters && nativeTrim) {
|
314 |
return nativeTrim.call(str);
|
315 |
} |
316 |
characters = defaultToWhiteSpace(characters); |
317 |
return str.replace(new RegExp('\^[' + characters + ']+|[' + characters + ']+$', 'g'), ''); |
318 |
}), |
319 |
|
320 |
ltrim: sArgs(function(str, characters){ |
321 |
characters = defaultToWhiteSpace(characters); |
322 |
return str.replace(new RegExp('\^[' + characters + ']+', 'g'), ''); |
323 |
}), |
324 |
|
325 |
rtrim: sArgs(function(str, characters){ |
326 |
characters = defaultToWhiteSpace(characters); |
327 |
return str.replace(new RegExp('[' + characters + ']+$', 'g'), ''); |
328 |
}), |
329 |
|
330 |
truncate: sArgs(function(str, length, truncateStr){ |
331 |
truncateStr = truncateStr || '...';
|
332 |
length = parseNumber(length); |
333 |
return str.length > length ? str.slice(0,length) + truncateStr : str; |
334 |
}), |
335 |
|
336 |
words: function(str, delimiter) { |
337 |
return String(str).split(delimiter || " "); |
338 |
}, |
339 |
|
340 |
pad: sArgs(function(str, length, padStr, type) { |
341 |
var padding = '', |
342 |
padlen = 0;
|
343 |
|
344 |
length = parseNumber(length); |
345 |
|
346 |
if (!padStr) { padStr = ' '; } |
347 |
else if (padStr.length > 1) { padStr = padStr.charAt(0); } |
348 |
switch(type) {
|
349 |
case 'right': |
350 |
padlen = (length - str.length); |
351 |
padding = strRepeat(padStr, padlen); |
352 |
str = str+padding; |
353 |
break;
|
354 |
case 'both': |
355 |
padlen = (length - str.length); |
356 |
padding = { |
357 |
'left' : strRepeat(padStr, Math.ceil(padlen/2)), |
358 |
'right': strRepeat(padStr, Math.floor(padlen/2)) |
359 |
}; |
360 |
str = padding.left+str+padding.right; |
361 |
break;
|
362 |
default: // 'left' |
363 |
padlen = (length - str.length); |
364 |
padding = strRepeat(padStr, padlen);; |
365 |
str = padding+str; |
366 |
} |
367 |
return str;
|
368 |
}), |
369 |
|
370 |
lpad: function(str, length, padStr) { |
371 |
return _s.pad(str, length, padStr);
|
372 |
}, |
373 |
|
374 |
rpad: function(str, length, padStr) { |
375 |
return _s.pad(str, length, padStr, 'right'); |
376 |
}, |
377 |
|
378 |
lrpad: function(str, length, padStr) { |
379 |
return _s.pad(str, length, padStr, 'both'); |
380 |
}, |
381 |
|
382 |
sprintf: sprintf,
|
383 |
|
384 |
vsprintf: function(fmt, argv){ |
385 |
argv.unshift(fmt); |
386 |
return sprintf.apply(null, argv); |
387 |
}, |
388 |
|
389 |
toNumber: function(str, decimals) { |
390 |
var num = parseNumber(parseNumber(str).toFixed(parseNumber(decimals)));
|
391 |
return (!(num === 0 && (str !== "0" && str !== 0))) ? num : Number.NaN; |
392 |
}, |
393 |
|
394 |
strRight: sArgs(function(sourceStr, sep){ |
395 |
var pos = (!sep) ? -1 : sourceStr.indexOf(sep); |
396 |
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr; |
397 |
}), |
398 |
|
399 |
strRightBack: sArgs(function(sourceStr, sep){ |
400 |
var pos = (!sep) ? -1 : sourceStr.lastIndexOf(sep); |
401 |
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr; |
402 |
}), |
403 |
|
404 |
strLeft: sArgs(function(sourceStr, sep){ |
405 |
var pos = (!sep) ? -1 : sourceStr.indexOf(sep); |
406 |
return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr; |
407 |
}), |
408 |
|
409 |
strLeftBack: sArgs(function(sourceStr, sep){ |
410 |
var pos = sourceStr.lastIndexOf(sep);
|
411 |
return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr; |
412 |
}) |
413 |
|
414 |
}; |
415 |
|
416 |
// Aliases
|
417 |
|
418 |
_s.strip = _s.trim; |
419 |
_s.lstrip = _s.ltrim; |
420 |
_s.rstrip = _s.rtrim; |
421 |
_s.center = _s.lrpad; |
422 |
_s.ljust = _s.lpad; |
423 |
_s.rjust = _s.rpad; |
424 |
|
425 |
// CommonJS module is defined
|
426 |
if (typeof module !== 'undefined' && module.exports) { |
427 |
// Export module
|
428 |
module.exports = _s; |
429 |
|
430 |
// Integrate with Underscore.js
|
431 |
} else if (typeof root._ !== 'undefined') { |
432 |
root._.mixin(_s); |
433 |
|
434 |
// Or define it
|
435 |
} else {
|
436 |
root._ = _s; |
437 |
} |
438 |
|
439 |
}(this || window));
|