API Docs for: 0.0.1
Show:

File: src/js-ext/lib/string.js

/**
 *
 * 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})?$/,
        replaceBKP;

    /**
     * Checks whether the substring is part if this String.
     * Alias for (String.indexOf(substring) > -1)
     *
     * @method 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
     */
    String.contains || (StringPrototype.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 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: we ALWAYS set this method --> ES6 native `startsWiths` lacks the second argument
    StringPrototype.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 parsable
     * @return {Boolean} whether the string is parsable
     */
    String.parsable || (StringPrototype.parsable=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));
    });

    /**
     * Checks if the string starts with the value specified by `test`
     *
     * @method 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: we ALWAYS set this method --> ES6 native `startsWiths` lacks the second argument
    StringPrototype.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.substitute({message: 'Hello'}); // results into 'Hello !'
     *
     * @method substitute
     * @param obj {Object} Object containing replacement values.
     * @return {String} the substitute result.
     */
    String.substitute || (StringPrototype.substitute=function(obj) {
        return this.replace(SUBREGEX, function (match, key) {
            return (obj[key]===undefined) ? '' : 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.toDate(); // --> Wed Feb 10 2010 15:45:30 GMT+0100 (CET)
     *
     * @method toDate
     * @return {Date|null} the Date represented by the String's value or null when invalid
     */
    String.toDate || (StringPrototype.toDate=function() {
        return DATEPATTERN.test(this) ? new Date(this) : null;
    });

    /**
     * Generated the string without any white-spaces at the start or end.
     *
     * @method trim
     * @return {String} new String without leading and trailing white-spaces
     */
    String.trim || (StringPrototype.trim=function() {
        return this.replace(TRIMREGEX, '');
    });

    /**
     * Generated the string without any white-spaces at the beginning.
     *
     * @method trimLeft
     * @return {String} new String without leading white-spaces
     */
    String.trimLeft || (StringPrototype.trimLeft=function() {
        return this.replace(TRIM_LEFT_REGEX, '');
    });

    /**
     * Generated the string without any white-spaces at the end.
     *
     * @method trimRight
     * @return {String} new String without trailing white-spaces
     */
    String.trimRight || (StringPrototype.trimRight=function() {
        return this.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 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
     */
    replaceBKP = StringPrototype.replace;
    StringPrototype.replace=function(search, replacement, caseInsensitive) {
        var re;
        if (caseInsensitive) {
            re = new RegExp(search, 'i');
            return this.replace(re, replacement);
        }
        else {
            return replaceBKP.apply(this, arguments);
        }
    };

    /**
     * Replaces search-characters by a replacement. Replaces all occurences.
     * Does not alter the String itself, but returns a new String with the replacements.
     *
     * @method 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
     */
    String.replaceAll || (StringPrototype.replaceAll=function(search, replacement, caseInsensitive) {
        var re = new RegExp(search, 'g' + (caseInsensitive ? 'i' : ''));
        return this.replace(re, replacement);
    });

    /**
     * Validates if the String's value represents a valid emailaddress.
     *
     * @method validateEmail
     * @return {Boolean} whether the String's value is a valid emailaddress.
     */
    StringPrototype.validateEmail = function() {
        return PATTERN_EMAIL.test(this);
    };

    /**
     * Validates if the String's value represents a valid floated number.
     *
     * @method validateFloat
     * @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.validateFloat = 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 validateHexaColor
     * @param [alpha=false] {Boolean} whether to accept alpha transparancy
     * @return {Boolean} whether the String's value is a valid hexadecimal color.
     */
    StringPrototype.validateHexaColor = 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 validateNumber
     * @return {Boolean} whether the String's value is a valid integer number.
     */
    StringPrototype.validateNumber = function() {
        return PATTERN_INTEGER.test(this);
    };

    /**
     * Validates if the String's value represents a valid boolean.
     *
     * @method validateBoolean
     * @return {Boolean} whether the String's value is a valid boolean.
     */
    StringPrototype.validateBoolean = 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 validateDate
     * @return {Boolean} whether the String's value is a valid Date object.
     */
    StringPrototype.validateDate = function() {
        return DATEPATTERN.test(this);
    };

    /**
     * Validates if the String's value represents a valid URL.
     *
     * @method validateURL
     * @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.validateURL = 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));