/*!
* Copyright (c) 2009 Francesco Mele jsbeans@francescomele.com
*
* This Software is licenced under the LGPL Licence (GNU Lesser General
* Public License).
* In addition to the LGPL Licence the Software is subject to the
* following conditions:
*
* i every modification must be public and comunicated to the Author
* ii every "jsbean" added to this library must be self consistent
* except for the dependence from jsbeans-x.x.x.js
* iii copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* A collection of utilities for strings
* @namespace jsbeans
* @class string
* @static
*/
jsbeans.define("jsbeans.string");
/**
* A common issue: removes blanks from the beginning and the ending of a given string.
* @method trim
* @param str {String} the string to trim
* @return {String} a new trimmed string
* @static
*/
jsbeans.string.trim = function(str) {
return str == null ? null : str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
};
/**
* Removes blanks fron the ending of a given string.
* @param str {String} the string to trim
* @return {String}
* @static
*/
jsbeans.string.trimRight = function(str) {
return str == null ? null : str.replace(/\s\s*$/, '');
};
/**
* Removes blanks fron the beginning of a given string
* @param str {String} the string to trim
* @return {String}
* @static
*/
jsbeans.string.trimLeft = function(str) {
return str == null ? null : str.replace(/^\s\s*/, '');
};
/**
* Checks if a string has no characters ("")
* @param str {String}
* @return {boolean}
* @static
*/
jsbeans.string.isEmpty = function(str) {
return str == null ? false : str == "";
};
/**
* Checks if a given string has no characters or is null
* @param str {String}
* @return {boolean}
* @static
*/
jsbeans.string.isEmptyOrNull = function(str) {
return str == null || str == "";
};
/**
* Alias for <code class="methd">jsbeans.string.isEmptyOrNull</code>
* @param str {String} the string to check
* @return {boolean}
* @static
*/
jsbeans.string.isNullOrEmpty = function(str) {
return jsbeans.string.isEmptyOrNull(str);
};
/**
* Checks if a string has same characters of another string at the beginning.<br/>
* Optionally the comparison starts from a given {@param} <code class="param">offset</code> (number of characters from the start)
* @param str {String}
* @param search {String} the string to search for
* @param [offset] {Integer}
* @static
*/
jsbeans.string.startsWith = function(str, search /*, offset*/) {
if (str == null) {
return false;
}
if (jsbeans.string.isEmptyOrNull(search)) {
return true;
}
var offset = arguments.length == 3 ? arguments[2] : 0;
offset = offset < 0 ? 0 : offset;
return str.substring(offset).indexOf(search) == 0;
};
/**
* Checks if a string has same characters of another string at the ending.<br/>
* Optionally the comparison starts from a given {@param} <code class="param">offset</code> (number of characters from the end)
* @param str {String}
* @param search {String} the string to search for
* @param [offset] {Integer}
* @static
*/
jsbeans.string.endsWith = function(str, search /*, offset*/) {
if (str == null) {
return false;
}
if (jsbeans.string.isEmptyOrNull(search)) {
return true;
}
var offset = arguments.length == 3 ? arguments[2] : 0;
offset = offset < 0 ? 0 : offset;
return str.split("").reverse().join("").substring(offset).indexOf(search.split("").reverse().join("")) == 0;
};
/**
* Truncates a given string at a defined number of characters substituting last chars with a string ("..." by default. Can be overridden)
* @param str {String} the string to truncate
* @param length {Integer} default 10
* @param [options] {JSON}
* <pre>
* href: <String>, // an url invoked on an anchor (tag <code>a</code>), default '#'
* ellipsisString: <String> // the substitution for truncated string, default '...'
* </pre>
* @return {String} a new, truncated, string
* @static
*/
jsbeans.string.ellipsis = function(str, len /*, options*/) {
// TODO sure? what about options (e.g. users want to change page)???
if (jsbeans.string.isEmptyOrNull(str)) {
return str;
}
var l = parseInt(len);
if (isNaN(l)) {
l = 10;
}
var options = arguments[2] || {};
options.href = options.href || "#";
options.ellipsisString = options.ellipsisString || "...";// other strings can be: "Read more" or "continue"
var a = "<a href=\"" + options.href + "\">" + options.ellipsisString + "</a>";
var sLen = str.length;
var eLen = options.ellipsisString.length;
var res = "";
if ((sLen + eLen + 1) <= l) {
res = str;
}
else {
var spl = str.split(" ");
var s;
for (var i = 0; i < spl.length; i++) {
s = spl[i];
if (s != "" && res.length + eLen + 1 <= l) {
res += s + " ";
}
}
}
return res + " " + a;
};
/**
* Sample for <a href="mailto:myname@mydomain.com">Write me</a>:<br/>
* jsbeans.string.e_m_a_i_l_Encrypt("Xmyn", "ame", "mydomain", "com", "Write me");
* @param first {String}
* @param second {String}
* @param domain {String}
* @param extension {String}
* @param label {String}
* @return {document.write}
* @static
*/
jsbeans.string.e_m_a_i_l_Encrypt = function(first, second, domain, extension, label) {
document.write("<a href=\"m" + "ailt" + "o:" + first.substring(1) + second + "@" + domain + "." + extension + "\" title=\"" + label + "\">" + label + "</a>");
};
/**
* Transforms a number, occasionally bytes, in a human readable format with B, KB, MB, ... at the end.
* @param bytes {Integer}
* @param [decimals] {Integer} default 1
* @return {String} a formatted, human readable, string
* @static
*/
jsbeans.string.getFileSize = function(bytes /*, decimals*/) {
if (typeof(bytes) == "undefined" || bytes == null || bytes == "") {
return null;
}
// makes sure it's an integer
try {
bytes = parseInt(bytes);
}
catch(e) {
return null;
}
if (isNaN(bytes)) {
return null;
}
var decimals = typeof(arguments[1]) == "undefined" ? 1 : arguments[1];
decimals = decimals < 0 ? 0 : decimals;
var suffix = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
var i = 0;
while ((bytes / 1024) >= 1) {
bytes = bytes / 1024;
i++;
}
if (decimals > 0) {
bytes = ("" + bytes).substr(0, ("" + bytes).indexOf(".") + (decimals + 1));
}
else {
bytes = ("" + bytes).substr(0, ("" + bytes).indexOf("."));
}
if ((decimals == 0 || !arguments[1]) && jsbeans.string.endsWith(bytes, "0")) {
bytes = bytes.substr(0, bytes.length - 2);
}
return bytes + " " + suffix[i];
};
/**
* Safe replacer for native parseInt function<br/>
* Sample:<br/>
* parseInt("0q") returns 0<br/>
* jsbeans.string.parseInt("0q") returns NaN
* @param str {String}
* @return {Integer}
* @static
*/
jsbeans.string.parseInt = function(v) {
if (v == null || v == "") {
return NaN;
}
if (v.indexOf(".") != -1) {
v = v.split(".")[0];
}
var re = /[0-9]/;
for (var i = 0; i < v.length; i++) {
if (!re.test(v.charAt(i))) {
return NaN;
}
}
while (jsbeans.string.startsWith(v, "0")) {
v = v.substring(1);
}
return v == "" ? 0 : parseInt(v);
};
/**
* Translate a string into its hexdecimal format.
* @param str {String} the string to translate
* @return {String} the translated string
* @static
*/
jsbeans.string.toHex = function(s) {
if (s == null || s == "") {
return null;
}
var giveHex = function(dec) {
var res = "" + dec;
if (dec==10) res = "a";
else if(dec == 11) res = "b";
else if(dec == 12) res = "c";
else if(dec == 13) res = "d";
else if(dec == 14) res = "e";
else if(dec == 15) res = "f";
return res;
};
var dec2Hex = function(dec) {
return giveHex(Math.floor(dec / 16)) + giveHex(dec % 16);
};
var re = /(\w{1})/gi;
s = s.replace(re, function(str,p1,offset,s) {
return "%" + dec2Hex(str.charCodeAt(0));
});
return s.split(" ").join("%20");
};
/**
* Translate a string from its hexdecimal format into a human readable format
* @param str {String} the string to translate
* @return {String} the human readable, translated string
* @static
*/
jsbeans.string.fromHex = function(s) {
if (s == null || s == "") {
return null;
}
var re = /%([a-f0-9]{2})/gi;
return s.replace(re, function(str,p1,offset,s) {
return String.fromCharCode(eval("0x"+p1));
});
};
/**
* An <code>innerText</code> functionality.<br/>
* It removes all tags and their content returning only contained text.
* @param str {String} a string to parse, normally in HTML or XML format
* @return {String} the inner text, without HTML tags
* @static
*/
jsbeans.string.stripHTML = function(s) {
if (jsbeans.string.isEmptyOrNull(s)) {
return s;
}
return s.replace(/<(?:.|\s)*?>/g, '');
};
/**
* Removes {@param} <code class="param">match</code> from {@param} <code class="param">str</code> starting from {@param} <code class="param">offset</code>.
* @method remove
* @param str {String}
* @param match {String}
* @param [offset] {Integer} default 0
* @return {String}
* @static
* */
jsbeans.string.remove = function(str, match /*, offset*/) {
if (jsbeans.string.isEmptyOrNull(str) || jsbeans.string.isEmptyOrNull(match)) {
return str;
}
var offset = arguments.length == 3 ? arguments[2] : 0;
offset = offset < 0 ? 0 : offset;
return str.substring(offset).split(match).join("");
};
/**
* Returns true if given {@param} <code class="param">str</code> is '1', 'true' (case insensitive), 't' (case insensitive) or, eventually, any other value that matches {@param} <code class="param">match</code>
* @param str {String}
* @param [match] {String}
* @return {boolean}
* @static
* */
jsbeans.string.parseBoolean = jsbeans.string.parseBool = function(str /*, match*/) {
if (jsbeans.string.isEmptyOrNull(str)) {
return false;
}
if (arguments[1]) {
return str.match(new RegExp(arguments[1])) == null ? false : true;
}
else {
return (str == "1" || str.toLowerCase() == "true" || str.toLowerCase() == "t") ? true : false;
}
};
/**
* Translate a 3-ple RGB (red, green, blue) into hexadecimal equivalent.<br/>
* Example: 255, 255, 255 is FFFFFF
* @param red {Integer}
* @param green {Integer}
* @param blue {Integer}
* @return {String} the hexadeciaml equivalent
* @static
*/
jsbeans.string.rgbToHex = function(red, green, blue) {
var red = parseInt(red);
var green = parseInt(green);
var blue = parseInt(blue);
if (isNaN(red) || isNaN(green) || isNaN(blue)) {
return null;
}
var getHex = function(d) {
if (d < 10 || d > 15) {
return "" + d;
}
else {
return String.fromCharCode(d + 55); // d = 10, "A" = 65; d = 11, "B" = 66; ...
}
};
var a = getHex(Math.floor(red / 16));
var b = getHex(red % 16);
var c = getHex(Math.floor(green / 16));
var d = getHex(green % 16);
var e = getHex(Math.floor(blue / 16));
var f = getHex(blue % 16);
return a + b + c + d + e + f;
};
/**
* Translate an hexadecimal color into its equivalent RGB (red, green, blue) format.
* @param hex {String}
* @param [jsonFormat] {boolean} if true the return type will be in JSON format
* @return {Array | JSON} an array of int for red, green and blue OR a JSON if second argument is true.
* <pre>
* red: <Integer>,
* green: <Integer>,
* blue: <Integer>
* </pre>
* @static
*/
jsbeans.string.hexToRgb = function(hex /*, jsonFormat*/) {
if (hex == null || hex.length != 6) {
return null;
}
var getDec = function(h) {
var cCode = h.charCodeAt(0);
if (cCode < 65 || cCode > 70) {
return eval(h);
}
else {
return cCode - 55;
}
};
var hex = hex.toUpperCase();
var a = getDec(hex.substring(0, 1));
var b = getDec(hex.substring(1, 2));
var c = getDec(hex.substring(2, 3));
var d = getDec(hex.substring(3, 4));
var e = getDec(hex.substring(4, 5));
var f = getDec(hex.substring(5, 6));
var red = (a * 16) + b;
var green = (c * 16) + d;
var blue = (e * 16) + f;
if (arguments[1] === true) {
return {red: red, green: green, blue: blue};
}
else {
return [red, green, blue];
}
};
/**
* Replace positional placeholder in the form <code>{n}</code> where 'n' is an integer within {@param} <code class="param">str</code><br/>
* Sample 1:<pre>jsbeans.string.format('My name is {0} and my email is {1}', 'Ciccio', 'ciccio@example.com');</pre> returns 'My name is Ciccio and my email is ciccio@example.com'.
* Sample 2:<pre>jsbeans.string.format('My name is {name} and my email is {email}', {name: 'Ciccio', email: 'ciccio@example.com'});</pre> returns 'My name is Ciccio and my email is ciccio@example.com'.
* @param str {String} the string to format
* @param args {Array | JSON | arguments} a list of replacers or an Array or a JSON. If second argument is an Object (Array or JSON), no other argument is taken in account.
* @return {String} the new formatted string
* @static
*/
jsbeans.string.format = function(str) {
if (arguments.length > 1) {
var arg;
// replaceres are in an Array
if (arguments[1] != null && typeof(arguments[1]) === "object" && arguments[1].constructor == Array) {
for (var i = 0; i < arguments[1].length; i++) {
arg = arguments[1][i];
str = str.split("{" + (i) + "}").join(arg);
}
}
// replacers are in JSON format
else if (arguments[1] != null && typeof(arguments[1]) === "object") {
var json = arguments[1];
for (var arg in json) {
str = str.split("{" + arg + "}").join(json[arg]);
}
}
// ordered list of replacers as varargs
else {
for (var i = 1; i < arguments.length; i++) {
arg = arguments[i];
str = str.split("{" + (i-1) + "}").join(arg);
}
}
}
return str;
};