telegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchat
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
474 lines
17 KiB
474 lines
17 KiB
/** |
|
* @class Ext.String |
|
* |
|
* A collection of useful static methods to deal with strings. |
|
* @singleton |
|
*/ |
|
Ext.String = (function() { |
|
// @define Ext.lang.String |
|
// @define Ext.String |
|
// @require Ext |
|
// @require Ext.lang.Array |
|
var 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, |
|
escapeRe = /('|\\)/g, |
|
escapeRegexRe = /([-.*+?\^${}()|\[\]\/\\])/g, |
|
basicTrimRe = /^\s+|\s+$/g, |
|
whitespaceRe = /\s+/, |
|
varReplace = /(^[^a-z]*|[^\w])/gi, |
|
charToEntity, |
|
entityToChar, |
|
charToEntityRegex, |
|
entityToCharRegex, |
|
htmlEncodeReplaceFn = function(match, capture) { |
|
return charToEntity[capture]; |
|
}, |
|
htmlDecodeReplaceFn = function(match, capture) { |
|
return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10)); |
|
}, |
|
boundsCheck = function(s, other){ |
|
if (s === null || s === undefined || other === null || other === undefined) { |
|
return false; |
|
} |
|
|
|
return other.length <= s.length; |
|
}, |
|
|
|
ExtString; |
|
|
|
return ExtString = { |
|
|
|
/** |
|
* Inserts a substring into a string. |
|
* @param {String} s The original string. |
|
* @param {String} value The substring to insert. |
|
* @param {Number} index The index to insert the substring. Negative indexes will insert from the end of |
|
* the string. Example: |
|
* |
|
* Ext.String.insert("abcdefg", "h", -1); // abcdefhg |
|
* |
|
* @return {String} The value with the inserted substring |
|
*/ |
|
insert: function(s, value, index) { |
|
if (!s) { |
|
return value; |
|
} |
|
|
|
if (!value) { |
|
return s; |
|
} |
|
|
|
var len = s.length; |
|
|
|
if (!index && index !== 0) { |
|
index = len; |
|
} |
|
|
|
if (index < 0) { |
|
index *= -1; |
|
if (index >= len) { |
|
// negative overflow, insert at start |
|
index = 0; |
|
} else { |
|
index = len - index; |
|
} |
|
} |
|
|
|
if (index === 0) { |
|
s = value + s; |
|
} else if (index >= s.length) { |
|
s += value; |
|
} else { |
|
s = s.substr(0, index) + value + s.substr(index); |
|
} |
|
return s; |
|
}, |
|
|
|
/** |
|
* Checks if a string starts with a substring |
|
* @param {String} s The original string |
|
* @param {String} start The substring to check |
|
* @param {Boolean} [ignoreCase=false] True to ignore the case in the comparison |
|
*/ |
|
startsWith: function(s, start, ignoreCase){ |
|
var result = boundsCheck(s, start); |
|
|
|
if (result) { |
|
if (ignoreCase) { |
|
s = s.toLowerCase(); |
|
start = start.toLowerCase(); |
|
} |
|
result = s.lastIndexOf(start, 0) === 0; |
|
} |
|
return result; |
|
}, |
|
|
|
/** |
|
* Checks if a string ends with a substring |
|
* @param {String} s The original string |
|
* @param {String} end The substring to check |
|
* @param {Boolean} [ignoreCase=false] True to ignore the case in the comparison |
|
*/ |
|
endsWith: function(s, end, ignoreCase){ |
|
var result = boundsCheck(s, end); |
|
|
|
if (result) { |
|
if (ignoreCase) { |
|
s = s.toLowerCase(); |
|
end = end.toLowerCase(); |
|
} |
|
result = s.indexOf(end, s.length - end.length) !== -1; |
|
} |
|
return result; |
|
}, |
|
|
|
/** |
|
* Converts a string of characters into a legal, parse-able JavaScript `var` name as long as the passed |
|
* string contains at least one alphabetic character. Non alphanumeric characters, and *leading* non alphabetic |
|
* characters will be removed. |
|
* @param {String} s A string to be converted into a `var` name. |
|
* @return {String} A legal JavaScript `var` name. |
|
*/ |
|
createVarName: function(s) { |
|
return s.replace(varReplace, ''); |
|
}, |
|
|
|
/** |
|
* Convert certain characters (&, <, >, ', and ") to their HTML character equivalents for literal display in web pages. |
|
* @param {String} value The string to encode. |
|
* @return {String} The encoded text. |
|
* @method |
|
*/ |
|
htmlEncode: function(value) { |
|
return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn); |
|
}, |
|
|
|
/** |
|
* Convert certain characters (&, <, >, ', and ") from their HTML character equivalents. |
|
* @param {String} value The string to decode. |
|
* @return {String} The decoded text. |
|
* @method |
|
*/ |
|
htmlDecode: function(value) { |
|
return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn); |
|
}, |
|
|
|
/** |
|
* Checks if a string has values needing to be html encoded. |
|
* @private |
|
* @param {String} s The string to test |
|
* @return {Boolean} `true` if the string contains HTML characters |
|
*/ |
|
hasHtmlCharacters: function(s) { |
|
return charToEntityRegex.test(s); |
|
}, |
|
|
|
/** |
|
* Adds a set of character entity definitions to the set used by |
|
* {@link Ext.String#htmlEncode} and {@link Ext.String#htmlDecode}. |
|
* |
|
* This object should be keyed by the entity name sequence, |
|
* with the value being the textual representation of the entity. |
|
* |
|
* Ext.String.addCharacterEntities({ |
|
* '&Uuml;':'Ü', |
|
* '&ccedil;':'ç', |
|
* '&ntilde;':'ñ', |
|
* '&egrave;':'è' |
|
* }); |
|
* var s = Ext.String.htmlEncode("A string with entities: èÜçñ"); |
|
* |
|
* __Note:__ the values of the character entities defined on this object are expected |
|
* to be single character values. As such, the actual values represented by the |
|
* characters are sensitive to the character encoding of the JavaScript source |
|
* file when defined in string literal form. Script tags referencing server |
|
* resources with character entities must ensure that the 'charset' attribute |
|
* of the script node is consistent with the actual character encoding of the |
|
* server resource. |
|
* |
|
* The set of character entities may be reset back to the default state by using |
|
* the {@link Ext.String#resetCharacterEntities} method |
|
* |
|
* @param {Object} newEntities The set of character entities to add to the current |
|
* definitions. |
|
*/ |
|
addCharacterEntities: function(newEntities) { |
|
var charKeys = [], |
|
entityKeys = [], |
|
key, echar; |
|
for (key in newEntities) { |
|
echar = newEntities[key]; |
|
entityToChar[key] = echar; |
|
charToEntity[echar] = key; |
|
charKeys.push(echar); |
|
entityKeys.push(key); |
|
} |
|
charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g'); |
|
entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g'); |
|
}, |
|
|
|
/** |
|
* Resets the set of character entity definitions used by |
|
* {@link Ext.String#htmlEncode} and {@link Ext.String#htmlDecode} back to the |
|
* default state. |
|
*/ |
|
resetCharacterEntities: function() { |
|
charToEntity = {}; |
|
entityToChar = {}; |
|
// add the default set |
|
this.addCharacterEntities({ |
|
'&' : '&', |
|
'>' : '>', |
|
'<' : '<', |
|
'"' : '"', |
|
''' : "'" |
|
}); |
|
}, |
|
|
|
/** |
|
* Appends content to the query string of a URL, handling logic for whether to place |
|
* a question mark or ampersand. |
|
* @param {String} url The URL to append to. |
|
* @param {String} string The content to append to the URL. |
|
* @return {String} The resulting URL |
|
*/ |
|
urlAppend : function(url, string) { |
|
if (!Ext.isEmpty(string)) { |
|
return url + (url.indexOf('?') === -1 ? '?' : '&') + string; |
|
} |
|
|
|
return url; |
|
}, |
|
|
|
/** |
|
* Trims whitespace from either end of a string, leaving spaces within the string intact. Example: |
|
* |
|
* var s = ' foo bar '; |
|
* alert('-' + s + '-'); //alerts "- foo bar -" |
|
* alert('-' + Ext.String.trim(s) + '-'); //alerts "-foo bar-" |
|
* |
|
* @param {String} string The string to trim. |
|
* @return {String} The trimmed string. |
|
*/ |
|
trim: function(string) { |
|
if (string) { |
|
string = string.replace(trimRegex, ""); |
|
} |
|
return string || ''; |
|
}, |
|
|
|
/** |
|
* Capitalize the first letter of the given string. |
|
* @param {String} string |
|
* @return {String} |
|
*/ |
|
capitalize: function(string) { |
|
if (string) { |
|
string = string.charAt(0).toUpperCase() + string.substr(1); |
|
} |
|
return string || ''; |
|
}, |
|
|
|
/** |
|
* Uncapitalize the first letter of a given string. |
|
* @param {String} string |
|
* @return {String} |
|
*/ |
|
uncapitalize: function(string) { |
|
if (string) { |
|
string = string.charAt(0).toLowerCase() + string.substr(1); |
|
} |
|
return string || ''; |
|
}, |
|
|
|
/** |
|
* Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length. |
|
* @param {String} value The string to truncate. |
|
* @param {Number} length The maximum length to allow before truncating. |
|
* @param {Boolean} [word=false] `true` to try to find a common word break. |
|
* @return {String} The converted text. |
|
*/ |
|
ellipsis: function(value, length, word) { |
|
if (value && value.length > length) { |
|
if (word) { |
|
var vs = value.substr(0, length - 2), |
|
index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?')); |
|
if (index !== -1 && index >= (length - 15)) { |
|
return vs.substr(0, index) + "..."; |
|
} |
|
} |
|
return value.substr(0, length - 3) + "..."; |
|
} |
|
return value; |
|
}, |
|
|
|
/** |
|
* Escapes the passed string for use in a regular expression. |
|
* @param {String} string The string to escape. |
|
* @return {String} The escaped string. |
|
*/ |
|
escapeRegex: function(string) { |
|
return string.replace(escapeRegexRe, "\\$1"); |
|
}, |
|
|
|
/** |
|
* Creates a `RegExp` given a string `value` and optional flags. For example, the |
|
* following two regular expressions are equivalent. |
|
* |
|
* var regex1 = Ext.String.createRegex('hello'); |
|
* |
|
* var regex2 = /^hello$/i; |
|
* |
|
* The following two regular expressions are also equivalent: |
|
* |
|
* var regex1 = Ext.String.createRegex('world', false, false, false); |
|
* |
|
* var regex2 = /world/; |
|
* |
|
* @param {String/RegExp} value The String to convert to a `RegExp`. |
|
* @param {Boolean} [startsWith=true] Pass `false` to allow a match to start |
|
* anywhere in the string. By default the `value` will match only at the start |
|
* of the string. |
|
* @param {Boolean} [endsWith=true] Pass `false` to allow the match to end before |
|
* the end of the string. By default the `value` will match only at the end of the |
|
* string. |
|
* @param {Boolean} [ignoreCase=true] Pass `false` to make the `RegExp` case |
|
* sensitive (removes the 'i' flag). |
|
* @since 5.0.0 |
|
* @return {RegExp} |
|
*/ |
|
createRegex: function (value, startsWith, endsWith, ignoreCase) { |
|
var ret = value; |
|
|
|
if (value != null && !value.exec) { // not a regex |
|
ret = ExtString.escapeRegex(String(value)); |
|
|
|
if (startsWith !== false) { |
|
ret = '^' + ret; |
|
} |
|
if (endsWith !== false) { |
|
ret += '$'; |
|
} |
|
|
|
ret = new RegExp(ret, (ignoreCase !== false) ? 'i' : ''); |
|
} |
|
|
|
return ret; |
|
}, |
|
|
|
/** |
|
* Escapes the passed string for ' and \. |
|
* @param {String} string The string to escape. |
|
* @return {String} The escaped string. |
|
*/ |
|
escape: function(string) { |
|
return string.replace(escapeRe, "\\$1"); |
|
}, |
|
|
|
/** |
|
* Utility function that allows you to easily switch a string between two alternating values. The passed value |
|
* is compared to the current string, and if they are equal, the other value that was passed in is returned. If |
|
* they are already different, the first value passed in is returned. Note that this method returns the new value |
|
* but does not change the current string. |
|
* |
|
* // alternate sort directions |
|
* sort = Ext.String.toggle(sort, 'ASC', 'DESC'); |
|
* |
|
* // instead of conditional logic: |
|
* sort = (sort === 'ASC' ? 'DESC' : 'ASC'); |
|
* |
|
* @param {String} string The current string. |
|
* @param {String} value The value to compare to the current string. |
|
* @param {String} other The new value to use if the string already equals the first value passed in. |
|
* @return {String} The new value. |
|
*/ |
|
toggle: function(string, value, other) { |
|
return string === value ? other : value; |
|
}, |
|
|
|
/** |
|
* Pads the left side of a string with a specified character. This is especially useful |
|
* for normalizing number and date strings. Example usage: |
|
* |
|
* var s = Ext.String.leftPad('123', 5, '0'); |
|
* // s now contains the string: '00123' |
|
* |
|
* @param {String} string The original string. |
|
* @param {Number} size The total length of the output string. |
|
* @param {String} [character=' '] (optional) The character with which to pad the original string. |
|
* @return {String} The padded string. |
|
*/ |
|
leftPad: function(string, size, character) { |
|
var result = String(string); |
|
character = character || " "; |
|
while (result.length < size) { |
|
result = character + result; |
|
} |
|
return result; |
|
}, |
|
|
|
/** |
|
* Returns a string with a specified number of repetitions a given string pattern. |
|
* The pattern be separated by a different string. |
|
* |
|
* var s = Ext.String.repeat('---', 4); // = '------------' |
|
* var t = Ext.String.repeat('--', 3, '/'); // = '--/--/--' |
|
* |
|
* @param {String} pattern The pattern to repeat. |
|
* @param {Number} count The number of times to repeat the pattern (may be 0). |
|
* @param {String} sep An option string to separate each pattern. |
|
*/ |
|
repeat: function(pattern, count, sep) { |
|
if (count < 1) { |
|
count = 0; |
|
} |
|
for (var buf = [], i = count; i--; ) { |
|
buf.push(pattern); |
|
} |
|
return buf.join(sep || ''); |
|
}, |
|
|
|
/** |
|
* Splits a string of space separated words into an array, trimming as needed. If the |
|
* words are already an array, it is returned. |
|
* |
|
* @param {String/Array} words |
|
*/ |
|
splitWords: function (words) { |
|
if (words && typeof words == 'string') { |
|
return words.replace(basicTrimRe, '').split(whitespaceRe); |
|
} |
|
return words || []; |
|
} |
|
}; |
|
}()); |
|
|
|
// initialize the default encode / decode entities |
|
Ext.String.resetCharacterEntities(); |
|
|
|
/** |
|
* Old alias to {@link Ext.String#htmlEncode} |
|
* @deprecated Use {@link Ext.String#htmlEncode} instead |
|
* @method |
|
* @member Ext |
|
* @inheritdoc Ext.String#htmlEncode |
|
*/ |
|
Ext.htmlEncode = Ext.String.htmlEncode; |
|
|
|
|
|
/** |
|
* Old alias to {@link Ext.String#htmlDecode} |
|
* @deprecated Use {@link Ext.String#htmlDecode} instead |
|
* @method |
|
* @member Ext |
|
* @inheritdoc Ext.String#htmlDecode |
|
*/ |
|
Ext.htmlDecode = Ext.String.htmlDecode; |
|
|
|
/** |
|
* Old alias to {@link Ext.String#urlAppend} |
|
* @deprecated Use {@link Ext.String#urlAppend} instead |
|
* @method |
|
* @member Ext |
|
* @inheritdoc Ext.String#urlAppend |
|
*/ |
|
Ext.urlAppend = Ext.String.urlAppend;
|
|
|