diff --git a/public/src/modules/string.js b/public/src/modules/string.js index 83e283e934..386a091dc6 100644 --- a/public/src/modules/string.js +++ b/public/src/modules/string.js @@ -1,3 +1,980 @@ /* string.js - Copyright (C) 2012-2013, JP Richardson -*/!function(){"use strict";function n(e,t){t!==null&&t!==undefined?typeof t=="string"?e.s=t:e.s=t.toString():e.s=t,e.orig=t,t!==null&&t!==undefined?e.__defineGetter__?e.__defineGetter__("length",function(){return e.s.length}):e.length=t.length:e.length=-1}function r(e){n(this,e)}function u(){for(var e in s)(function(e){var t=s[e];i.hasOwnProperty(e)||(o.push(e),i[e]=function(){return String.prototype.s=this,t.apply(this,arguments)})})(e)}function a(){for(var e=0;er?n.slice(s,i):"")},camelize:function(){var e=this.trim().s.replace(/(\-|_|\s)+(.)?/g,function(e,t,n){return n?n.toUpperCase():""});return new this.constructor(e)},capitalize:function(){return new this.constructor(this.s.substr(0,1).toUpperCase()+this.s.substring(1).toLowerCase())},charAt:function(e){return this.s.charAt(e)},chompLeft:function(e){var t=this.s;return t.indexOf(e)===0?(t=t.slice(e.length),new this.constructor(t)):this},chompRight:function(e){if(this.endsWith(e)){var t=this.s;return t=t.slice(0,t.length-e.length),new this.constructor(t)}return this},collapseWhitespace:function(){var e=this.s.replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"");return new this.constructor(e)},contains:function(e){return this.s.indexOf(e)>=0},count:function(e){var t=0,n=this.s.indexOf(e);while(n>=0)t+=1,n=this.s.indexOf(e,n+1);return t},dasherize:function(){var e=this.trim().s.replace(/[_\s]+/g,"-").replace(/([A-Z])/g,"-$1").replace(/-+/g,"-").toLowerCase();return new this.constructor(e)},decodeHtmlEntities:function(){var e=this.s;return e=e.replace(/&#(\d+);?/g,function(e,t){return String.fromCharCode(t)}).replace(/&#[xX]([A-Fa-f0-9]+);?/g,function(e,t){return String.fromCharCode(parseInt(t,16))}).replace(/&([^;\W]+;?)/g,function(e,n){var r=n.replace(/;$/,""),i=t[n]||n.match(/;$/)&&t[r];return typeof i=="number"?String.fromCharCode(i):typeof i=="string"?i:e}),new this.constructor(e)},endsWith:function(e){var t=this.s.length-e.length;return t>=0&&this.s.indexOf(e,t)===t},escapeHTML:function(){return new this.constructor(this.s.replace(/[&<>"']/g,function(e){return"&"+m[e]+";"}))},ensureLeft:function(e){var t=this.s;return t.indexOf(e)===0?this:new this.constructor(e+t)},ensureRight:function(e){var t=this.s;return this.endsWith(e)?this:new this.constructor(t+e)},humanize:function(){if(this.s===null||this.s===undefined)return new this.constructor("");var e=this.underscore().replace(/_id$/,"").replace(/_/g," ").trim().capitalize();return new this.constructor(e)},isAlpha:function(){return!/[^a-z\xC0-\xFF]/.test(this.s.toLowerCase())},isAlphaNumeric:function(){return!/[^0-9a-z\xC0-\xFF]/.test(this.s.toLowerCase())},isEmpty:function(){return this.s===null||this.s===undefined?!0:/^[\s\xa0]*$/.test(this.s)},isLower:function(){return this.isAlpha()&&this.s.toLowerCase()===this.s},isNumeric:function(){return!/[^0-9]/.test(this.s)},isUpper:function(){return this.isAlpha()&&this.s.toUpperCase()===this.s},left:function(e){if(e>=0){var t=this.s.substr(0,e);return new this.constructor(t)}return this.right(-e)},lines:function(){return this.replaceAll("\r\n","\n").s.split("\n")},pad:function(e,t){t==null&&(t=" ");if(this.s.length>=e)return new this.constructor(this.s);e-=this.s.length;var n=Array(Math.ceil(e/2)+1).join(t),r=Array(Math.floor(e/2)+1).join(t);return new this.constructor(n+this.s+r)},padLeft:function(e,t){return t==null&&(t=" "),this.s.length>=e?new this.constructor(this.s):new this.constructor(Array(e-this.s.length+1).join(t)+this.s)},padRight:function(e,t){return t==null&&(t=" "),this.s.length>=e?new this.constructor(this.s):new this.constructor(this.s+Array(e-this.s.length+1).join(t))},parseCSV:function(e,t,n,r){e=e||",",n=n||"\\",typeof t=="undefined"&&(t='"');var i=0,s=[],o=[],u=this.s.length,a=!1,f=this,l=function(e){return f.s.charAt(e)};if(typeof r!="undefined")var c=[];t||(a=!0);while(i=0){var t=this.s.substr(this.s.length-e,e);return new this.constructor(t)}return this.left(-e)},setValue:function(e){return n(this,e),this},slugify:function(){var e=(new r(this.s.replace(/[^\w\s-]/g,"").toLowerCase())).dasherize().s;return e.charAt(0)==="-"&&(e=e.substr(1)),new this.constructor(e)},startsWith:function(e){return this.s.lastIndexOf(e,0)===0},stripPunctuation:function(){return new this.constructor(this.s.replace(/[^\w\s]|_/g,"").replace(/\s+/g," "))},stripTags:function(){var e=this.s,t=arguments.length>0?arguments:[""];return d(t,function(t){e=e.replace(RegExp("]*>","gi"),"")}),new this.constructor(e)},template:function(e,t,n){var r=this.s,t=t||p.TMPL_OPEN,n=n||p.TMPL_CLOSE,i=t.replace(/[-[\]()*\s]/g,"\\$&").replace(/\$/g,"\\$"),s=n.replace(/[-[\]()*\s]/g,"\\$&").replace(/\$/g,"\\$"),o=new RegExp(i+"(.+?)"+s,"g"),u=r.match(o)||[];return u.forEach(function(i){var s=i.substring(t.length,i.length-n.length);typeof e[s]!="undefined"&&(r=r.replace(i,e[s]))}),new this.constructor(r)},times:function(e){return new this.constructor((new Array(e+1)).join(this.s))},toBoolean:function(){if(typeof this.orig=="string"){var e=this.s.toLowerCase();return e==="true"||e==="yes"||e==="on"}return this.orig===!0||this.orig===1},toFloat:function(e){var t=parseFloat(this.s);return e?parseFloat(t.toFixed(e)):t},toInt:function(){return/^\s*-?0x/i.test(this.s)?parseInt(this.s,16):parseInt(this.s,10)},trim:function(){var e;return typeof i.trim=="undefined"?e=this.s.replace(/(^\s*|\s*$)/g,""):e=this.s.trim(),new this.constructor(e)},trimLeft:function(){var e;return i.trimLeft?e=this.s.trimLeft():e=this.s.replace(/(^\s*)/g,""),new this.constructor(e)},trimRight:function(){var e;return i.trimRight?e=this.s.trimRight():e=this.s.replace(/\s+$/,""),new this.constructor(e)},truncate:function(e,t){var n=this.s;e=~~e,t=t||"...";if(n.length<=e)return new this.constructor(n);var i=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},s=n.slice(0,e+1).replace(/.(?=\W*\w*$)/g,i);return s.slice(s.length-2).match(/\w\w/)?s=s.replace(/\s*\S+$/,""):s=(new r(s.slice(0,s.length-1))).trimRight().s,(s+t).length>n.length?new r(n):new r(n.slice(0,s.length)+t)},toCSV:function(){function u(e){return e!==null&&e!==""}var e=",",t='"',n="\\",i=!0,s=!1,o=[];typeof arguments[0]=="object"?(e=arguments[0].delimiter||e,e=arguments[0].separator||e,t=arguments[0].qualifier||t,i=!!arguments[0].encloseNumbers,n=arguments[0].escape||n,s=!!arguments[0].keys):typeof arguments[0]=="string"&&(e=arguments[0]),typeof arguments[1]=="string"&&(t=arguments[1]),arguments[1]===null&&(t=null);if(this.orig instanceof Array)o=this.orig;else for(var a in this.orig)this.orig.hasOwnProperty(a)&&(s?o.push(a):o.push(this.orig[a]));var f=n+t,l=[];for(var c=0;c",quot:'"',apos:"'",amp:"&"},m={};for(var g in v)m[v[g]]=g;t={amp:"&",gt:">",lt:"<",quot:'"',apos:"'",AElig:198,Aacute:193,Acirc:194,Agrave:192,Aring:197,Atilde:195,Auml:196,Ccedil:199,ETH:208,Eacute:201,Ecirc:202,Egrave:200,Euml:203,Iacute:205,Icirc:206,Igrave:204,Iuml:207,Ntilde:209,Oacute:211,Ocirc:212,Ograve:210,Oslash:216,Otilde:213,Ouml:214,THORN:222,Uacute:218,Ucirc:219,Ugrave:217,Uuml:220,Yacute:221,aacute:225,acirc:226,aelig:230,agrave:224,aring:229,atilde:227,auml:228,ccedil:231,eacute:233,ecirc:234,egrave:232,eth:240,euml:235,iacute:237,icirc:238,igrave:236,iuml:239,ntilde:241,oacute:243,ocirc:244,ograve:242,oslash:248,otilde:245,ouml:246,szlig:223,thorn:254,uacute:250,ucirc:251,ugrave:249,uuml:252,yacute:253,yuml:255,copy:169,reg:174,nbsp:160,iexcl:161,cent:162,pound:163,curren:164,yen:165,brvbar:166,sect:167,uml:168,ordf:170,laquo:171,not:172,shy:173,macr:175,deg:176,plusmn:177,sup1:185,sup2:178,sup3:179,acute:180,micro:181,para:182,middot:183,cedil:184,ordm:186,raquo:187,frac14:188,frac12:189,frac34:190,iquest:191,times:215,divide:247,"OElig;":338,"oelig;":339,"Scaron;":352,"scaron;":353,"Yuml;":376,"fnof;":402,"circ;":710,"tilde;":732,"Alpha;":913,"Beta;":914,"Gamma;":915,"Delta;":916,"Epsilon;":917,"Zeta;":918,"Eta;":919,"Theta;":920,"Iota;":921,"Kappa;":922,"Lambda;":923,"Mu;":924,"Nu;":925,"Xi;":926,"Omicron;":927,"Pi;":928,"Rho;":929,"Sigma;":931,"Tau;":932,"Upsilon;":933,"Phi;":934,"Chi;":935,"Psi;":936,"Omega;":937,"alpha;":945,"beta;":946,"gamma;":947,"delta;":948,"epsilon;":949,"zeta;":950,"eta;":951,"theta;":952,"iota;":953,"kappa;":954,"lambda;":955,"mu;":956,"nu;":957,"xi;":958,"omicron;":959,"pi;":960,"rho;":961,"sigmaf;":962,"sigma;":963,"tau;":964,"upsilon;":965,"phi;":966,"chi;":967,"psi;":968,"omega;":969,"thetasym;":977,"upsih;":978,"piv;":982,"ensp;":8194,"emsp;":8195,"thinsp;":8201,"zwnj;":8204,"zwj;":8205,"lrm;":8206,"rlm;":8207,"ndash;":8211,"mdash;":8212,"lsquo;":8216,"rsquo;":8217,"sbquo;":8218,"ldquo;":8220,"rdquo;":8221,"bdquo;":8222,"dagger;":8224,"Dagger;":8225,"bull;":8226,"hellip;":8230,"permil;":8240,"prime;":8242,"Prime;":8243,"lsaquo;":8249,"rsaquo;":8250,"oline;":8254,"frasl;":8260,"euro;":8364,"image;":8465,"weierp;":8472,"real;":8476,"trade;":8482,"alefsym;":8501,"larr;":8592,"uarr;":8593,"rarr;":8594,"darr;":8595,"harr;":8596,"crarr;":8629,"lArr;":8656,"uArr;":8657,"rArr;":8658,"dArr;":8659,"hArr;":8660,"forall;":8704,"part;":8706,"exist;":8707,"empty;":8709,"nabla;":8711,"isin;":8712,"notin;":8713,"ni;":8715,"prod;":8719,"sum;":8721,"minus;":8722,"lowast;":8727,"radic;":8730,"prop;":8733,"infin;":8734,"ang;":8736,"and;":8743,"or;":8744,"cap;":8745,"cup;":8746,"int;":8747,"there4;":8756,"sim;":8764,"cong;":8773,"asymp;":8776,"ne;":8800,"equiv;":8801,"le;":8804,"ge;":8805,"sub;":8834,"sup;":8835,"nsub;":8836,"sube;":8838,"supe;":8839,"oplus;":8853,"otimes;":8855,"perp;":8869,"sdot;":8901,"lceil;":8968,"rceil;":8969,"lfloor;":8970,"rfloor;":8971,"lang;":9001,"rang;":9002,"loz;":9674,"spades;":9824,"clubs;":9827,"hearts;":9829,"diams;":9830}}.call(this); +*/ + +!(function() { + "use strict"; + + var VERSION = '1.8.0'; + + var ENTITIES = {}; + +//****************************************************************************** +// Added an initialize function which is essentially the code from the S +// constructor. Now, the S constructor calls this and a new method named +// setValue calls it as well. The setValue function allows constructors for +// modules that extend string.js to set the initial value of an object without +// knowing the internal workings of string.js. +// +// Also, all methods which return a new S object now call: +// +// return new this.constructor(s); +// +// instead of: +// +// return new S(s); +// +// This allows extended objects to keep their proper instanceOf and constructor. +//****************************************************************************** + + function initialize (object, s) { + if (s !== null && s !== undefined) { + if (typeof s === 'string') + object.s = s; + else + object.s = s.toString(); + } else { + object.s = s; //null or undefined + } + + object.orig = s; //original object, currently only used by toCSV() and toBoolean() + + if (s !== null && s !== undefined) { + if (object.__defineGetter__) { + object.__defineGetter__('length', function() { + return object.s.length; + }) + } else { + object.length = s.length; + } + } else { + object.length = -1; + } + } + + function S(s) { + initialize(this, s); + } + + var __nsp = String.prototype; + var __sp = S.prototype = { + + between: function(left, right) { + var s = this.s; + var startPos = s.indexOf(left); + var endPos = s.indexOf(right, startPos + left.length); + if (endPos == -1 && right != null) + return new this.constructor('') + else if (endPos == -1 && right == null) + return new this.constructor(s.substring(startPos + left.length)) + else + return new this.constructor(s.slice(startPos + left.length, endPos)); + }, + + //# modified slightly from https://github.com/epeli/underscore.string + camelize: function() { + var s = this.trim().s.replace(/(\-|_|\s)+(.)?/g, function(mathc, sep, c) { + return (c ? c.toUpperCase() : ''); + }); + return new this.constructor(s); + }, + + capitalize: function() { + return new this.constructor(this.s.substr(0, 1).toUpperCase() + this.s.substring(1).toLowerCase()); + }, + + charAt: function(index) { + return this.s.charAt(index); + }, + + chompLeft: function(prefix) { + var s = this.s; + if (s.indexOf(prefix) === 0) { + s = s.slice(prefix.length); + return new this.constructor(s); + } else { + return this; + } + }, + + chompRight: function(suffix) { + if (this.endsWith(suffix)) { + var s = this.s; + s = s.slice(0, s.length - suffix.length); + return new this.constructor(s); + } else { + return this; + } + }, + + //#thanks Google + collapseWhitespace: function() { + var s = this.s.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, ''); + return new this.constructor(s); + }, + + contains: function(ss) { + return this.s.indexOf(ss) >= 0; + }, + + count: function(ss) { + var count = 0 + , pos = this.s.indexOf(ss) + + while (pos >= 0) { + count += 1 + pos = this.s.indexOf(ss, pos + 1) + } + + return count + }, + + //#modified from https://github.com/epeli/underscore.string + dasherize: function() { + var s = this.trim().s.replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase(); + return new this.constructor(s); + }, + + decodeHtmlEntities: function() { //https://github.com/substack/node-ent/blob/master/index.js + var s = this.s; + s = s.replace(/&#(\d+);?/g, function (_, code) { + return String.fromCharCode(code); + }) + .replace(/&#[xX]([A-Fa-f0-9]+);?/g, function (_, hex) { + return String.fromCharCode(parseInt(hex, 16)); + }) + .replace(/&([^;\W]+;?)/g, function (m, e) { + var ee = e.replace(/;$/, ''); + var target = ENTITIES[e] || (e.match(/;$/) && ENTITIES[ee]); + + if (typeof target === 'number') { + return String.fromCharCode(target); + } + else if (typeof target === 'string') { + return target; + } + else { + return m; + } + }) + + return new this.constructor(s); + }, + + endsWith: function(suffix) { + var l = this.s.length - suffix.length; + return l >= 0 && this.s.indexOf(suffix, l) === l; + }, + + escapeHTML: function() { //from underscore.string + return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; })); + }, + + ensureLeft: function(prefix) { + var s = this.s; + if (s.indexOf(prefix) === 0) { + return this; + } else { + return new this.constructor(prefix + s); + } + }, + + ensureRight: function(suffix) { + var s = this.s; + if (this.endsWith(suffix)) { + return this; + } else { + return new this.constructor(s + suffix); + } + }, + + humanize: function() { //modified from underscore.string + if (this.s === null || this.s === undefined) + return new this.constructor('') + var s = this.underscore().replace(/_id$/,'').replace(/_/g, ' ').trim().capitalize() + return new this.constructor(s) + }, + + isAlpha: function() { + return !/[^a-z\xC0-\xFF]/.test(this.s.toLowerCase()); + }, + + isAlphaNumeric: function() { + return !/[^0-9a-z\xC0-\xFF]/.test(this.s.toLowerCase()); + }, + + isEmpty: function() { + return this.s === null || this.s === undefined ? true : /^[\s\xa0]*$/.test(this.s); + }, + + isLower: function() { + return this.isAlpha() && this.s.toLowerCase() === this.s; + }, + + isNumeric: function() { + return !/[^0-9]/.test(this.s); + }, + + isUpper: function() { + return this.isAlpha() && this.s.toUpperCase() === this.s; + }, + + left: function(N) { + if (N >= 0) { + var s = this.s.substr(0, N); + return new this.constructor(s); + } else { + return this.right(-N); + } + }, + + lines: function() { //convert windows newlines to unix newlines then convert to an Array of lines + return this.replaceAll('\r\n', '\n').s.split('\n'); + }, + + pad: function(len, ch) { //https://github.com/component/pad + if (ch == null) ch = ' '; + if (this.s.length >= len) return new this.constructor(this.s); + len = len - this.s.length; + var left = Array(Math.ceil(len / 2) + 1).join(ch); + var right = Array(Math.floor(len / 2) + 1).join(ch); + return new this.constructor(left + this.s + right); + }, + + padLeft: function(len, ch) { //https://github.com/component/pad + if (ch == null) ch = ' '; + if (this.s.length >= len) return new this.constructor(this.s); + return new this.constructor(Array(len - this.s.length + 1).join(ch) + this.s); + }, + + padRight: function(len, ch) { //https://github.com/component/pad + if (ch == null) ch = ' '; + if (this.s.length >= len) return new this.constructor(this.s); + return new this.constructor(this.s + Array(len - this.s.length + 1).join(ch)); + }, + + parseCSV: function(delimiter, qualifier, escape, lineDelimiter) { //try to parse no matter what + delimiter = delimiter || ','; + escape = escape || '\\' + if (typeof qualifier == 'undefined') + qualifier = '"'; + + var i = 0, fieldBuffer = [], fields = [], len = this.s.length, inField = false, self = this; + var ca = function(i){return self.s.charAt(i)}; + if (typeof lineDelimiter !== 'undefined') var rows = []; + + if (!qualifier) + inField = true; + + while (i < len) { + var current = ca(i); + switch (current) { + case escape: + //fix for issues #32 and #35 + if (inField && ((escape !== qualifier) || ca(i+1) === qualifier)) { + i += 1; + fieldBuffer.push(ca(i)); + break; + } + if (escape !== qualifier) break; + case qualifier: + inField = !inField; + break; + case delimiter: + if (inField && qualifier) + fieldBuffer.push(current); + else { + fields.push(fieldBuffer.join('')) + fieldBuffer.length = 0; + } + break; + case lineDelimiter: + if (inField) { + fieldBuffer.push(current); + } else { + if (rows) { + fields.push(fieldBuffer.join('')) + rows.push(fields); + fields = []; + fieldBuffer.length = 0; + } + } + break; + default: + if (inField) + fieldBuffer.push(current); + break; + } + i += 1; + } + + fields.push(fieldBuffer.join('')); + if (rows) { + rows.push(fields); + return rows; + } + return fields; + }, + + replaceAll: function(ss, r) { + //var s = this.s.replace(new RegExp(ss, 'g'), r); + var s = this.s.split(ss).join(r) + return new this.constructor(s); + }, + + right: function(N) { + if (N >= 0) { + var s = this.s.substr(this.s.length - N, N); + return new this.constructor(s); + } else { + return this.left(-N); + } + }, + + setValue: function (s) { + initialize(this, s); + return this; + }, + + slugify: function() { + var sl = (new S(this.s.replace(/[^\w\s-]/g, '').toLowerCase())).dasherize().s; + if (sl.charAt(0) === '-') + sl = sl.substr(1); + return new this.constructor(sl); + }, + + startsWith: function(prefix) { + return this.s.lastIndexOf(prefix, 0) === 0; + }, + + stripPunctuation: function() { + //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,"")); + return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " ")); + }, + + stripTags: function() { //from sugar.js + var s = this.s, args = arguments.length > 0 ? arguments : ['']; + multiArgs(args, function(tag) { + s = s.replace(RegExp('<\/?' + tag + '[^<>]*>', 'gi'), ''); + }); + return new this.constructor(s); + }, + + template: function(values, opening, closing) { + var s = this.s + var opening = opening || Export.TMPL_OPEN + var closing = closing || Export.TMPL_CLOSE + + var open = opening.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$') + var close = closing.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$') + var r = new RegExp(open + '(.+?)' + close, 'g') + //, r = /\{\{(.+?)\}\}/g + var matches = s.match(r) || []; + + matches.forEach(function(match) { + var key = match.substring(opening.length, match.length - closing.length);//chop {{ and }} + if (typeof values[key] != 'undefined') + s = s.replace(match, values[key]); + }); + return new this.constructor(s); + }, + + times: function(n) { + return new this.constructor(new Array(n + 1).join(this.s)); + }, + + toBoolean: function() { + if (typeof this.orig === 'string') { + var s = this.s.toLowerCase(); + return s === 'true' || s === 'yes' || s === 'on' || s === '1'; + } else + return this.orig === true || this.orig === 1; + }, + + toFloat: function(precision) { + var num = parseFloat(this.s) + if (precision) + return parseFloat(num.toFixed(precision)) + else + return num + }, + + toInt: function() { //thanks Google + // If the string starts with '0x' or '-0x', parse as hex. + return /^\s*-?0x/i.test(this.s) ? parseInt(this.s, 16) : parseInt(this.s, 10) + }, + + trim: function() { + var s; + if (typeof __nsp.trim === 'undefined') + s = this.s.replace(/(^\s*|\s*$)/g, '') + else + s = this.s.trim() + return new this.constructor(s); + }, + + trimLeft: function() { + var s; + if (__nsp.trimLeft) + s = this.s.trimLeft(); + else + s = this.s.replace(/(^\s*)/g, ''); + return new this.constructor(s); + }, + + trimRight: function() { + var s; + if (__nsp.trimRight) + s = this.s.trimRight(); + else + s = this.s.replace(/\s+$/, ''); + return new this.constructor(s); + }, + + truncate: function(length, pruneStr) { //from underscore.string, author: github.com/rwz + var str = this.s; + + length = ~~length; + pruneStr = pruneStr || '...'; + + if (str.length <= length) return new this.constructor(str); + + var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; }, + template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA' + + if (template.slice(template.length-2).match(/\w\w/)) + template = template.replace(/\s*\S+$/, ''); + else + template = new S(template.slice(0, template.length-1)).trimRight().s; + + return (template+pruneStr).length > str.length ? new S(str) : new S(str.slice(0, template.length)+pruneStr); + }, + + toCSV: function() { + var delim = ',', qualifier = '"', escape = '\\', encloseNumbers = true, keys = false; + var dataArray = []; + + function hasVal(it) { + return it !== null && it !== ''; + } + + if (typeof arguments[0] === 'object') { + delim = arguments[0].delimiter || delim; + delim = arguments[0].separator || delim; + qualifier = arguments[0].qualifier || qualifier; + encloseNumbers = !!arguments[0].encloseNumbers; + escape = arguments[0].escape || escape; + keys = !!arguments[0].keys; + } else if (typeof arguments[0] === 'string') { + delim = arguments[0]; + } + + if (typeof arguments[1] === 'string') + qualifier = arguments[1]; + + if (arguments[1] === null) + qualifier = null; + + if (this.orig instanceof Array) + dataArray = this.orig; + else { //object + for (var key in this.orig) + if (this.orig.hasOwnProperty(key)) + if (keys) + dataArray.push(key); + else + dataArray.push(this.orig[key]); + } + + var rep = escape + qualifier; + var buildString = []; + for (var i = 0; i < dataArray.length; ++i) { + var shouldQualify = hasVal(qualifier) + if (typeof dataArray[i] == 'number') + shouldQualify &= encloseNumbers; + + if (shouldQualify) + buildString.push(qualifier); + + if (dataArray[i] !== null && dataArray[i] !== undefined) { + var d = new S(dataArray[i]).replaceAll(qualifier, rep).s; + buildString.push(d); + } else + buildString.push('') + + if (shouldQualify) + buildString.push(qualifier); + + if (delim) + buildString.push(delim); + } + + //chop last delim + //console.log(buildString.length) + buildString.length = buildString.length - 1; + return new this.constructor(buildString.join('')); + }, + + toString: function() { + return this.s; + }, + + //#modified from https://github.com/epeli/underscore.string + underscore: function() { + var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase(); + if ((new S(this.s.charAt(0))).isUpper()) { + s = '_' + s; + } + return new this.constructor(s); + }, + + unescapeHTML: function() { //from underscore.string + return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){ + var match; + + if (entityCode in escapeChars) { + return escapeChars[entityCode]; + } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) { + return String.fromCharCode(parseInt(match[1], 16)); + } else if (match = entityCode.match(/^#(\d+)$/)) { + return String.fromCharCode(~~match[1]); + } else { + return entity; + } + })); + }, + + valueOf: function() { + return this.s.valueOf(); + } + + } + + var methodsAdded = []; + function extendPrototype() { + for (var name in __sp) { + (function(name){ + var func = __sp[name]; + if (!__nsp.hasOwnProperty(name)) { + methodsAdded.push(name); + __nsp[name] = function() { + String.prototype.s = this; + return func.apply(this, arguments); + } + } + })(name); + } + } + + function restorePrototype() { + for (var i = 0; i < methodsAdded.length; ++i) + delete String.prototype[methodsAdded[i]]; + methodsAdded.length = 0; + } + + +/************************************* +/* Attach Native JavaScript String Properties +/*************************************/ + + var nativeProperties = getNativeStringProperties(); + for (var name in nativeProperties) { + (function(name) { + var stringProp = __nsp[name]; + if (typeof stringProp == 'function') { + //console.log(stringProp) + if (!__sp[name]) { + if (nativeProperties[name] === 'string') { + __sp[name] = function() { + //console.log(name) + return new this.constructor(stringProp.apply(this, arguments)); + } + } else { + __sp[name] = stringProp; + } + } + } + })(name); + } + + +/************************************* +/* Function Aliases +/*************************************/ + + __sp.repeat = __sp.times; + __sp.include = __sp.contains; + __sp.toInteger = __sp.toInt; + __sp.toBool = __sp.toBoolean; + __sp.decodeHTMLEntities = __sp.decodeHtmlEntities //ensure consistent casing scheme of 'HTML' + + +//****************************************************************************** +// Set the constructor. Without this, string.js objects are instances of +// Object instead of S. +//****************************************************************************** + + __sp.constructor = S; + + +/************************************* +/* Private Functions +/*************************************/ + + function getNativeStringProperties() { + var names = getNativeStringPropertyNames(); + var retObj = {}; + + for (var i = 0; i < names.length; ++i) { + var name = names[i]; + var func = __nsp[name]; + try { + var type = typeof func.apply('teststring', []); + retObj[name] = type; + } catch (e) {} + } + return retObj; + } + + function getNativeStringPropertyNames() { + var results = []; + if (Object.getOwnPropertyNames) { + results = Object.getOwnPropertyNames(__nsp); + results.splice(results.indexOf('valueOf'), 1); + results.splice(results.indexOf('toString'), 1); + return results; + } else { //meant for legacy cruft, this could probably be made more efficient + var stringNames = {}; + var objectNames = []; + for (var name in String.prototype) + stringNames[name] = name; + + for (var name in Object.prototype) + delete stringNames[name]; + + //stringNames['toString'] = 'toString'; //this was deleted with the rest of the object names + for (var name in stringNames) { + results.push(name); + } + return results; + } + } + + function Export(str) { + return new S(str); + }; + + //attach exports to StringJSWrapper + Export.extendPrototype = extendPrototype; + Export.restorePrototype = restorePrototype; + Export.VERSION = VERSION; + Export.TMPL_OPEN = '{{'; + Export.TMPL_CLOSE = '}}'; + Export.ENTITIES = ENTITIES; + + + +/************************************* +/* Exports +/*************************************/ + + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = Export; + + } else { + + if(typeof define === "function" && define.amd) { + define('src/modules/string', [], function() { + return Export; + }); + } else { + window.S = Export; + } + } + + +/************************************* +/* 3rd Party Private Functions +/*************************************/ + + //from sugar.js + function multiArgs(args, fn) { + var result = [], i; + for(i = 0; i < args.length; i++) { + result.push(args[i]); + if(fn) fn.call(args, args[i], i); + } + return result; + } + + //from underscore.string + var escapeChars = { + lt: '<', + gt: '>', + quot: '"', + apos: "'", + amp: '&' + }; + + //from underscore.string + var reversedEscapeChars = {}; + for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; } + + ENTITIES = { + "amp" : "&", + "gt" : ">", + "lt" : "<", + "quot" : "\"", + "apos" : "'", + "AElig" : 198, + "Aacute" : 193, + "Acirc" : 194, + "Agrave" : 192, + "Aring" : 197, + "Atilde" : 195, + "Auml" : 196, + "Ccedil" : 199, + "ETH" : 208, + "Eacute" : 201, + "Ecirc" : 202, + "Egrave" : 200, + "Euml" : 203, + "Iacute" : 205, + "Icirc" : 206, + "Igrave" : 204, + "Iuml" : 207, + "Ntilde" : 209, + "Oacute" : 211, + "Ocirc" : 212, + "Ograve" : 210, + "Oslash" : 216, + "Otilde" : 213, + "Ouml" : 214, + "THORN" : 222, + "Uacute" : 218, + "Ucirc" : 219, + "Ugrave" : 217, + "Uuml" : 220, + "Yacute" : 221, + "aacute" : 225, + "acirc" : 226, + "aelig" : 230, + "agrave" : 224, + "aring" : 229, + "atilde" : 227, + "auml" : 228, + "ccedil" : 231, + "eacute" : 233, + "ecirc" : 234, + "egrave" : 232, + "eth" : 240, + "euml" : 235, + "iacute" : 237, + "icirc" : 238, + "igrave" : 236, + "iuml" : 239, + "ntilde" : 241, + "oacute" : 243, + "ocirc" : 244, + "ograve" : 242, + "oslash" : 248, + "otilde" : 245, + "ouml" : 246, + "szlig" : 223, + "thorn" : 254, + "uacute" : 250, + "ucirc" : 251, + "ugrave" : 249, + "uuml" : 252, + "yacute" : 253, + "yuml" : 255, + "copy" : 169, + "reg" : 174, + "nbsp" : 160, + "iexcl" : 161, + "cent" : 162, + "pound" : 163, + "curren" : 164, + "yen" : 165, + "brvbar" : 166, + "sect" : 167, + "uml" : 168, + "ordf" : 170, + "laquo" : 171, + "not" : 172, + "shy" : 173, + "macr" : 175, + "deg" : 176, + "plusmn" : 177, + "sup1" : 185, + "sup2" : 178, + "sup3" : 179, + "acute" : 180, + "micro" : 181, + "para" : 182, + "middot" : 183, + "cedil" : 184, + "ordm" : 186, + "raquo" : 187, + "frac14" : 188, + "frac12" : 189, + "frac34" : 190, + "iquest" : 191, + "times" : 215, + "divide" : 247, + "OElig;" : 338, + "oelig;" : 339, + "Scaron;" : 352, + "scaron;" : 353, + "Yuml;" : 376, + "fnof;" : 402, + "circ;" : 710, + "tilde;" : 732, + "Alpha;" : 913, + "Beta;" : 914, + "Gamma;" : 915, + "Delta;" : 916, + "Epsilon;" : 917, + "Zeta;" : 918, + "Eta;" : 919, + "Theta;" : 920, + "Iota;" : 921, + "Kappa;" : 922, + "Lambda;" : 923, + "Mu;" : 924, + "Nu;" : 925, + "Xi;" : 926, + "Omicron;" : 927, + "Pi;" : 928, + "Rho;" : 929, + "Sigma;" : 931, + "Tau;" : 932, + "Upsilon;" : 933, + "Phi;" : 934, + "Chi;" : 935, + "Psi;" : 936, + "Omega;" : 937, + "alpha;" : 945, + "beta;" : 946, + "gamma;" : 947, + "delta;" : 948, + "epsilon;" : 949, + "zeta;" : 950, + "eta;" : 951, + "theta;" : 952, + "iota;" : 953, + "kappa;" : 954, + "lambda;" : 955, + "mu;" : 956, + "nu;" : 957, + "xi;" : 958, + "omicron;" : 959, + "pi;" : 960, + "rho;" : 961, + "sigmaf;" : 962, + "sigma;" : 963, + "tau;" : 964, + "upsilon;" : 965, + "phi;" : 966, + "chi;" : 967, + "psi;" : 968, + "omega;" : 969, + "thetasym;" : 977, + "upsih;" : 978, + "piv;" : 982, + "ensp;" : 8194, + "emsp;" : 8195, + "thinsp;" : 8201, + "zwnj;" : 8204, + "zwj;" : 8205, + "lrm;" : 8206, + "rlm;" : 8207, + "ndash;" : 8211, + "mdash;" : 8212, + "lsquo;" : 8216, + "rsquo;" : 8217, + "sbquo;" : 8218, + "ldquo;" : 8220, + "rdquo;" : 8221, + "bdquo;" : 8222, + "dagger;" : 8224, + "Dagger;" : 8225, + "bull;" : 8226, + "hellip;" : 8230, + "permil;" : 8240, + "prime;" : 8242, + "Prime;" : 8243, + "lsaquo;" : 8249, + "rsaquo;" : 8250, + "oline;" : 8254, + "frasl;" : 8260, + "euro;" : 8364, + "image;" : 8465, + "weierp;" : 8472, + "real;" : 8476, + "trade;" : 8482, + "alefsym;" : 8501, + "larr;" : 8592, + "uarr;" : 8593, + "rarr;" : 8594, + "darr;" : 8595, + "harr;" : 8596, + "crarr;" : 8629, + "lArr;" : 8656, + "uArr;" : 8657, + "rArr;" : 8658, + "dArr;" : 8659, + "hArr;" : 8660, + "forall;" : 8704, + "part;" : 8706, + "exist;" : 8707, + "empty;" : 8709, + "nabla;" : 8711, + "isin;" : 8712, + "notin;" : 8713, + "ni;" : 8715, + "prod;" : 8719, + "sum;" : 8721, + "minus;" : 8722, + "lowast;" : 8727, + "radic;" : 8730, + "prop;" : 8733, + "infin;" : 8734, + "ang;" : 8736, + "and;" : 8743, + "or;" : 8744, + "cap;" : 8745, + "cup;" : 8746, + "int;" : 8747, + "there4;" : 8756, + "sim;" : 8764, + "cong;" : 8773, + "asymp;" : 8776, + "ne;" : 8800, + "equiv;" : 8801, + "le;" : 8804, + "ge;" : 8805, + "sub;" : 8834, + "sup;" : 8835, + "nsub;" : 8836, + "sube;" : 8838, + "supe;" : 8839, + "oplus;" : 8853, + "otimes;" : 8855, + "perp;" : 8869, + "sdot;" : 8901, + "lceil;" : 8968, + "rceil;" : 8969, + "lfloor;" : 8970, + "rfloor;" : 8971, + "lang;" : 9001, + "rang;" : 9002, + "loz;" : 9674, + "spades;" : 9824, + "clubs;" : 9827, + "hearts;" : 9829, + "diams;" : 9830 + } + + +}).call(this);