UNPKG

itsa-jsext

Version:

Extensions to native javascript-objects, all within the itsa_ namespace

282 lines (259 loc) 11 kB
/** * * Pollyfils for often used functionality for Strings * * <i>Copyright (c) 2014 ITSA - https://github.com/itsa</i> * New BSD License - http://choosealicense.com/licenses/bsd-3-clause/ * * @module js-ext * @submodule lib/string.js * @class String * */ "use strict"; (function(StringPrototype) { var SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g, DATEPATTERN = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z/, WHITESPACE_CLASS = "[\\s\uFEFF\xA0]+", TRIM_LEFT_REGEX = new RegExp("^" + WHITESPACE_CLASS), TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"), TRIMREGEX = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"), PATTERN_EMAIL = new RegExp("^[\\w!#$%&'*+/=?`{|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]\\.)+[a-zA-Z]{2,}$"), PATTERN_URLEND = "([a-zA-Z0-9]+\\.)*(?:[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]\\.)+[a-zA-Z]{2,}(/[\\w-]+)*$", PATTERN_URLHTTP = new RegExp("^http://"+PATTERN_URLEND), PATTERN_URLHTTPS = new RegExp("^https://"+PATTERN_URLEND), PATTERN_URL = new RegExp("^(https?://)?"+PATTERN_URLEND), PATTERN_INTEGER = /^(([-]?[1-9][0-9]*)|0)$/, PATTERN_FLOAT_START = "^([-]?(([1-9][0-9]*)|0))?(\\", PATTERN_FLOAT_END = "[0-9]+)?$", PATTERN_FLOAT_COMMA = new RegExp(PATTERN_FLOAT_START + "," + PATTERN_FLOAT_END), PATTERN_FLOAT_DOT = new RegExp(PATTERN_FLOAT_START + "." + PATTERN_FLOAT_END), PATTERN_HEX_COLOR_ALPHA = /^#?[0-9A-F]{4}([0-9A-F]{4})?$/, PATTERN_HEX_COLOR = /^#?[0-9A-F]{3}([0-9A-F]{3})?$/; /** * Checks whether the substring is part if this String. * Alias for (String.indexOf(substring) > -1) * * @method itsa_contains * @param substring {String} the substring to test for * @param [caseInsensitive=false] {Boolean} whether to ignore case-sensivity * @return {Boolean} whether the substring is found */ StringPrototype.itsa_contains = function(substring, caseInsensitive) { return caseInsensitive ? (this.toLowerCase().indexOf(substring.toLowerCase()) > -1) : (this.indexOf(substring) > -1); }; /** * Checks if the string ends with the value specified by `test` * * @method itsa_endsWith * @param test {String} the string to test for * @param [caseInsensitive=false] {Boolean} whether to ignore case-sensivity * @return {Boolean} whether the string ends with `test` */ // NOTE: ES6 native `endsWith` lacks the second argument StringPrototype.itsa_endsWith = function(test, caseInsensitive) { return (new RegExp(test+"$", caseInsensitive ? "i": "")).test(this); }; /** * Checks if the string can be parsed into a number when using `parseInt()` * * @method itsa_isParsable * @return {Boolean} whether the string is parsable */ StringPrototype.itsa_isParsable = function() { // strange enough, NaN doen't let compare itself, so we need a strange test: // parseInt(value, 10)===parseInt(value, 10) // which returns `true` for a parsable value, otherwise false return (parseInt(this)===parseInt(this)); }; /** * Uppercases the first character * * @method itsa_sentence * @return {String} The same string with its first character uppercased */ StringPrototype.itsa_sentence = function() { return (this.length>0) ? this[0].toUpperCase() + this.substr(1) : ""; }; /** * Checks if the string starts with the value specified by `test` * * @method itsa_startsWith * @param test {String} the string to test for * @param [caseInsensitive=false] {Boolean} whether to ignore case-sensivity * @return {Boolean} whether the string starts with `test` */ // NOTE: ES6 native `startsWith` lacks the second argument StringPrototype.itsa_startsWith = function(test, caseInsensitive) { return (new RegExp("^"+test, caseInsensitive ? "i": "")).test(this); }; /** * Performs `{placeholder}` substitution on a string. The object passed * provides values to replace the `{placeholder}`s. * `{placeholder}` token names must match property names of the object. * * `{placeholder}` tokens that are undefined on the object map will be removed. * * @example * var greeting = '{message} {who}!'; * greeting.itsa_substitute({message: 'Hello'}); // results into 'Hello !' * * @method itsa_substitute * @param obj {Object} Object containing replacement values. * @param [retainUndefined=false] {Boolean} whether to keep placeholders that are undefined in `obj` * @return {String} the substitute result. */ StringPrototype.itsa_substitute = function(obj, retainUndefined) { return this.itsa_replace(SUBREGEX, function (match, key) { return (obj[key]===undefined) ? (retainUndefined ? "{"+key+"}" : "") : obj[key]; }); }; /** * Returns a ISO-8601 Date-object build by the String's value. * If the String-value doesn't match ISO-8601, `null` will be returned. * * ISO-8601 Date's are generated by JSON.stringify(), so it's very handy to be able to reconvert them. * * @example * var birthday = '2010-02-10T14:45:30.000Z'; * birthday.itsa_toDate(); // --> Wed Feb 10 2010 15:45:30 GMT+0100 (CET) * * @method itsa_toDate * @return {Date|null} the Date represented by the String's value or null when invalid */ StringPrototype.itsa_toDate = function() { return DATEPATTERN.test(this) ? new Date(this) : null; }; /** * Generated the string without any white-spaces at the start or end. * * @method itsa_trim * @return {String} new String without leading and trailing white-spaces */ StringPrototype.itsa_trim = function() { return this.itsa_replace(TRIMREGEX, ""); }; /** * Generated the string without any white-spaces at the beginning. * * @method itsa_trimLeft * @return {String} new String without leading white-spaces */ StringPrototype.itsa_trimLeft = function() { return this.itsa_replace(TRIM_LEFT_REGEX, ""); }; /** * Generated the string without any white-spaces at the end. * * @method itsa_trimRight * @return {String} new String without trailing white-spaces */ StringPrototype.itsa_trimRight = function() { return this.itsa_replace(TRIM_RIGHT_REGEX, ""); }; /** * Replaces search-characters by a replacement. Replaces only the firts occurence. * Does not alter the String itself, but returns a new String with the replacement. * * @method itsa_replace * @param search {String} the character(s) to be replaced * @param replacement {String} the replacement * @param [caseInsensitive=false] {Boolean} whether to do search case-insensitive * @return {String} new String with the replacement */ StringPrototype.itsa_replace = function(search, replacement, caseInsensitive) { return StringPrototype.replace.call(this, caseInsensitive ? new RegExp(search, "i") : search, replacement); }; /** * Replaces search-characters by a replacement. Replaces all occurences. * Does not alter the String itself, but returns a new String with the replacements. * * @method itsa_replaceAll * @param search {String} the character(s) to be replaced * @param replacement {String} the replacement * @param [caseInsensitive=false] {Boolean} whether to do search case-insensitive * @return {String} new String with the replacements */ StringPrototype.itsa_replaceAll=function(search, replacement, caseInsensitive) { return StringPrototype.replace.call(this, new RegExp(search, "g" + (caseInsensitive ? "i" : "")), replacement); }; /** * Validates if the String's value represents a valid emailaddress. * * @method itsa_isValidEmail * @return {Boolean} whether the String's value is a valid emailaddress. */ StringPrototype.itsa_isValidEmail = function() { return PATTERN_EMAIL.test(this); }; /** * Validates if the String's value represents a valid floated number. * * @method itsa_isValidFloat * @param [comma] {Boolean} whether to use a comma as decimal separator instead of a dot * @return {Boolean} whether the String's value is a valid floated number. */ StringPrototype.itsa_isValidFloat = function(comma) { return comma ? PATTERN_FLOAT_COMMA.test(this) : PATTERN_FLOAT_DOT.test(this); }; /** * Validates if the String's value represents a hexadecimal color. * * @method itsa_isValidHexaColor * @param [alpha=false] {Boolean} whether to accept alpha transparancy * @return {Boolean} whether the String's value is a valid hexadecimal color. */ StringPrototype.itsa_isValidHexaColor = function(alpha) { return alpha ? PATTERN_HEX_COLOR_ALPHA.test(this) : PATTERN_HEX_COLOR.test(this); }; /** * Validates if the String's value represents a valid integer number. * * @method itsa_isValidNumber * @return {Boolean} whether the String's value is a valid integer number. */ StringPrototype.itsa_isValidNumber = function() { return PATTERN_INTEGER.test(this); }; /** * Validates if the String's value represents a valid boolean. * * @method itsa_isValidBoolean * @return {Boolean} whether the String's value is a valid boolean. */ StringPrototype.itsa_isValidBoolean = function() { var length = this.length, check; if ((length<4) || (length>5)) { return false; } check = this.toUpperCase(); return ((check==="TRUE") || (check==="FALSE")); }; /** * Validates if the String's value represents a valid Date. * * @method itsa_isValidDate * @return {Boolean} whether the String's value is a valid Date object. */ StringPrototype.itsa_isValidDate = function() { return DATEPATTERN.test(this); }; /** * Validates if the String's value represents a valid URL. * * @method itsa_isValidURL * @param [options] {Object} * @param [options.http] {Boolean} to force matching starting with `http://` * @param [options.https] {Boolean} to force matching starting with `https://` * @return {Boolean} whether the String's value is a valid URL. */ StringPrototype.itsa_isValidURL = function(options) { var instance = this; options || (options={}); if (options.http && options.https) { return false; } return options.http ? PATTERN_URLHTTP.test(instance) : (options.https ? PATTERN_URLHTTPS.test(instance) : PATTERN_URL.test(instance)); }; }(String.prototype));