Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / core / src / lang / String.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.String
17  *
18  * A collection of useful static methods to deal with strings
19  * @singleton
20  */
21
22 Ext.String = {
23     trimRegex: /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,
24     escapeRe: /('|\\)/g,
25     formatRe: /\{(\d+)\}/g,
26     escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
27
28     /**
29      * Convert certain characters (&, <, >, and ") to their HTML character equivalents for literal display in web pages.
30      * @param {String} value The string to encode
31      * @return {String} The encoded text
32      * @method
33      */
34     htmlEncode: (function() {
35         var entities = {
36             '&': '&amp;',
37             '>': '&gt;',
38             '<': '&lt;',
39             '"': '&quot;'
40         }, keys = [], p, regex;
41         
42         for (p in entities) {
43             keys.push(p);
44         }
45         
46         regex = new RegExp('(' + keys.join('|') + ')', 'g');
47         
48         return function(value) {
49             return (!value) ? value : String(value).replace(regex, function(match, capture) {
50                 return entities[capture];    
51             });
52         };
53     })(),
54
55     /**
56      * Convert certain characters (&, <, >, and ") from their HTML character equivalents.
57      * @param {String} value The string to decode
58      * @return {String} The decoded text
59      * @method
60      */
61     htmlDecode: (function() {
62         var entities = {
63             '&amp;': '&',
64             '&gt;': '>',
65             '&lt;': '<',
66             '&quot;': '"'
67         }, keys = [], p, regex;
68         
69         for (p in entities) {
70             keys.push(p);
71         }
72         
73         regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
74         
75         return function(value) {
76             return (!value) ? value : String(value).replace(regex, function(match, capture) {
77                 if (capture in entities) {
78                     return entities[capture];
79                 } else {
80                     return String.fromCharCode(parseInt(capture.substr(2), 10));
81                 }
82             });
83         };
84     })(),
85
86     /**
87      * Appends content to the query string of a URL, handling logic for whether to place
88      * a question mark or ampersand.
89      * @param {String} url The URL to append to.
90      * @param {String} string The content to append to the URL.
91      * @return (String) The resulting URL
92      */
93     urlAppend : function(url, string) {
94         if (!Ext.isEmpty(string)) {
95             return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
96         }
97
98         return url;
99     },
100
101     /**
102      * Trims whitespace from either end of a string, leaving spaces within the string intact.  Example:
103      * @example
104 var s = '  foo bar  ';
105 alert('-' + s + '-');         //alerts "- foo bar -"
106 alert('-' + Ext.String.trim(s) + '-');  //alerts "-foo bar-"
107
108      * @param {String} string The string to escape
109      * @return {String} The trimmed string
110      */
111     trim: function(string) {
112         return string.replace(Ext.String.trimRegex, "");
113     },
114
115     /**
116      * Capitalize the given string
117      * @param {String} string
118      * @return {String}
119      */
120     capitalize: function(string) {
121         return string.charAt(0).toUpperCase() + string.substr(1);
122     },
123
124     /**
125      * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
126      * @param {String} value The string to truncate
127      * @param {Number} length The maximum length to allow before truncating
128      * @param {Boolean} word True to try to find a common word break
129      * @return {String} The converted text
130      */
131     ellipsis: function(value, len, word) {
132         if (value && value.length > len) {
133             if (word) {
134                 var vs = value.substr(0, len - 2),
135                 index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
136                 if (index !== -1 && index >= (len - 15)) {
137                     return vs.substr(0, index) + "...";
138                 }
139             }
140             return value.substr(0, len - 3) + "...";
141         }
142         return value;
143     },
144
145     /**
146      * Escapes the passed string for use in a regular expression
147      * @param {String} string
148      * @return {String}
149      */
150     escapeRegex: function(string) {
151         return string.replace(Ext.String.escapeRegexRe, "\\$1");
152     },
153
154     /**
155      * Escapes the passed string for ' and \
156      * @param {String} string The string to escape
157      * @return {String} The escaped string
158      */
159     escape: function(string) {
160         return string.replace(Ext.String.escapeRe, "\\$1");
161     },
162
163     /**
164      * Utility function that allows you to easily switch a string between two alternating values.  The passed value
165      * is compared to the current string, and if they are equal, the other value that was passed in is returned.  If
166      * they are already different, the first value passed in is returned.  Note that this method returns the new value
167      * but does not change the current string.
168      * <pre><code>
169     // alternate sort directions
170     sort = Ext.String.toggle(sort, 'ASC', 'DESC');
171
172     // instead of conditional logic:
173     sort = (sort == 'ASC' ? 'DESC' : 'ASC');
174        </code></pre>
175      * @param {String} string The current string
176      * @param {String} value The value to compare to the current string
177      * @param {String} other The new value to use if the string already equals the first value passed in
178      * @return {String} The new value
179      */
180     toggle: function(string, value, other) {
181         return string === value ? other : value;
182     },
183
184     /**
185      * Pads the left side of a string with a specified character.  This is especially useful
186      * for normalizing number and date strings.  Example usage:
187      *
188      * <pre><code>
189 var s = Ext.String.leftPad('123', 5, '0');
190 // s now contains the string: '00123'
191        </code></pre>
192      * @param {String} string The original string
193      * @param {Number} size The total length of the output string
194      * @param {String} character (optional) The character with which to pad the original string (defaults to empty string " ")
195      * @return {String} The padded string
196      */
197     leftPad: function(string, size, character) {
198         var result = String(string);
199         character = character || " ";
200         while (result.length < size) {
201             result = character + result;
202         }
203         return result;
204     },
205
206     /**
207      * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens.  Each
208      * token must be unique, and must increment in the format {0}, {1}, etc.  Example usage:
209      * <pre><code>
210 var cls = 'my-class', text = 'Some text';
211 var s = Ext.String.format('&lt;div class="{0}">{1}&lt;/div>', cls, text);
212 // s now contains the string: '&lt;div class="my-class">Some text&lt;/div>'
213        </code></pre>
214      * @param {String} string The tokenized string to be formatted
215      * @param {String} value1 The value to replace token {0}
216      * @param {String} value2 Etc...
217      * @return {String} The formatted string
218      */
219     format: function(format) {
220         var args = Ext.Array.toArray(arguments, 1);
221         return format.replace(Ext.String.formatRe, function(m, i) {
222             return args[i];
223         });
224     },
225
226     /**
227      * Returns a string with a specified number of repititions a given string pattern.
228      * The pattern be separated by a different string.
229      *
230      *      var s = Ext.String.repeat('---', 4); // = '------------'
231      *      var t = Ext.String.repeat('--', 3, '/'); // = '--/--/--'
232      *
233      * @param {String} pattern The pattern to repeat.
234      * @param {Number} count The number of times to repeat the pattern (may be 0).
235      * @param {String} sep An option string to separate each pattern.
236      */
237     repeat: function(pattern, count, sep) {
238         for (var buf = [], i = count; i--; ) {
239             buf.push(pattern);
240         }
241         return buf.join(sep || '');
242     }
243 };
244