// Underscore.strings // (c) 2010 Esa-Matti Suuronen // Underscore.strings is freely distributable under the terms of the MIT license. // Documentation: http://bitbucket.org/epeli/underscore.strings/ // Some code is borrowed from MooTools and Alexandru Marasteanu. // Version 1.0 (function(){ // ------------------------- Baseline setup --------------------------------- // Establish the root object, "window" in the browser, or "global" on the server. var root = this; var nativeTrim = String.prototype.trim; function str_repeat(i, m) { for (var o = []; m > 0; o[--m] = i); return o.join(''); } function defaultToWhiteSpace(characters){ if (characters) { return _s.escapeRegExp(characters); } return '\\s'; } var _s; _s = root._s = { capitalize : function(str) { return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase(); }, join: function(sep) { // TODO: Could this be faster by converting // arguments to Array and using array.join(sep)? sep = String(sep); var str = ""; for (var i=1; i < arguments.length; i += 1) { str += String(arguments[i]); if ( i !== arguments.length-1 ) { str += sep; } } return str; }, escapeRegExp: function(str){ // From MooTools core 1.2.4 return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); }, reverse: function(str){ return Array.prototype.reverse.apply(str.split('')).join(''); }, contains: function(str, needle){ return str.indexOf(needle) !== -1; }, clean: function(str){ return _s.strip(str.replace(/\s+/g, ' ')); }, trim: function(str, characters){ if (!characters && nativeTrim) { return nativeTrim.call(str); } characters = defaultToWhiteSpace(characters); return str.replace(new RegExp('\^[' + characters + ']+|[' + characters + ']+$', 'g'), ''); }, ltrim: function(str, characters){ characters = defaultToWhiteSpace(characters); return str.replace(new RegExp('\^[' + characters + ']+', 'g'), ''); }, rtrim: function(str, characters){ characters = defaultToWhiteSpace(characters); return str.replace(new RegExp('[' + characters + ']+$', 'g'), ''); }, startsWith: function(str, starts){ return str.length >= starts.length && str.substring(0, starts.length) === starts; }, endsWith: function(str, ends){ return str.length >= ends.length && str.substring(str.length - ends.length) === ends; }, /** * Credits for this function goes to * http://www.diveintojavascript.com/projects/sprintf-for-javascript * * Copyright (c) Alexandru Marasteanu * All rights reserved. * */ sprintf: function(){ var i = 0, a, f = arguments[i++], o = [], m, p, c, x, s = ''; while (f) { if (m = /^[^\x25]+/.exec(f)) { o.push(m[0]); } else if (m = /^\x25{2}/.exec(f)) { o.push('%'); } else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) { if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) { throw('Too few arguments.'); } if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) { throw('Expecting number but found ' + typeof(a)); } switch (m[7]) { case 'b': a = a.toString(2); break; case 'c': a = String.fromCharCode(a); break; case 'd': a = parseInt(a); break; case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break; case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break; case 'o': a = a.toString(8); break; case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break; case 'u': a = Math.abs(a); break; case 'x': a = a.toString(16); break; case 'X': a = a.toString(16).toUpperCase(); break; } a = (/[def]/.test(m[7]) && m[2] && a >= 0 ? '+'+ a : a); c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' '; x = m[5] - String(a).length - s.length; p = m[5] ? str_repeat(c, x) : ''; o.push(s + (m[4] ? a + p : p + a)); } else { throw('Huh ?!'); } f = f.substring(m[0].length); } return o.join(''); } } // Some aliases root._s.strip = _s.trim; root._s.lstrip = _s.ltrim; root._s.rstrip = _s.rtrim; // Integrate with Underscore.js if (root._) { root._.mixin(root._s); } }());