Larry Steinle

April 10, 2011

JavaScript Characters

Filed under: RegEx,Web — Larry Steinle @ 11:55 pm
Tags: , , , ,

While reviewing the C language I was reminded of the cType.h library. The cType library is a Character Type helper class. After short consideration I thought it might be helpful to have an equivalent in JavaScript.

Character Analysis Features

The objective was to create an external JavaScript file that could be referenced to gain access to the helper functions. The external JavaScript file would provide access to a Char object (pay attention to casing because char is a reserved word in JavaScript). Additionally, the String object would be extended so that a Char object could be retrieved from any position in the string value making it easier to analyze the specific character.

The Char object will provide the following behaviors:

  • Translate an ASC II code to a character (also available in String).
  • Translate a character to an ASC II code (also available in String).
  • Test a character to identify if it is:
    • An alpha character (a-z or A-Z),
    • An alpha or digit character,
    • A control character (null, unit separator or delete),
    • A digit (0-9),
    • A graph (a print character other than space),
    • A hex digit (0-9, a-f, A-F),
    • Is lower case (a-f, 0-9 or whitespace),
    • A number (a value that can be converted to a number which means that it can contain a digit, period, plus or minus sign and dollar sign),
    • A print character (ASC Code 20 (space) to 126 (tilde)),
    • A punctuation character (Print character other than space, letter or digit),
    • A space character (space, form feed, new line, carriage return, tab or vertical tab),
    • Is upper case (A-Z, 0-9 or whitespace), or
    • A whitespace character (non-printable character).
  • Replace a character in a string.
  • Remove a character from a string.

Test Char Class

Before getting into the details of the Char helper class let’s review how the class can be used and at the same time provide a test platform to demonstrate how well the class works.

In the test class we’ll create a simple input text tag that will display the last key press and show the results of the character analysis. This way we can press keys and verify that the result is what we would expect from the Char helper class.

Char Tester Web Page

Char Tester Web Page

<!DOCTYPE html>
<html>
<head>
    <title>Test Char</title>
    <script type="text/javascript" src="Char.js"></script>
    <script type="text/javascript">
        var htmlTable;

        function analyzeKey(event) {
            var e = (!event) ? window.event : event;

            var character = null;
            if (e.keyCode)
                character = Char.toChar(e.keyCode);
            else if (e.which)
                character = Char.toChar(e.which);

            clearLog();
            logInfo("Character", "[" + character + "]", "Key pressed");
            logInfo("Asc Code", Char.toAsc(0, character), "ASC II Code for pressed key");
            logInfo("Is Alpha", Char.isAlpha(character), "Character is a letter.");
            logInfo("Is AlphaDigit", Char.isAlphaNum(character), "Character is a letter or number.");
            logInfo("Is Control", Char.isControl(character), "Character is 0 (Null), 31 (Unit Separator) or 127 (Delete).");
            logInfo("Is Digit", Char.isDigit(character), "Character is a number.");
            logInfo("Is Graph", Char.isGraph(character), "Print character other than space.");
            logInfo("Is Hex", Char.isHexDigit(character), "Character is a number or a letter between A and F.");
            logInfo("Is Lower", Char.isLower(character), "Character is a letter between a and z.");
            logInfo("Is Numeric", Char.isNumeric(character), "Character is a number or string is a value that can be converted to a number.");
            logInfo("Is Print", Char.isPrint(character), "Character is an asc code between 20 (space) and 126 (~).");
            logInfo("Is Punct", Char.isPunct(character), "Print character other than space, letter or digit.");
            logInfo("Is Space", Char.isSpace(character), "Space, form feed, new line, carriage return, tab or vertical tab.");
            logInfo("Is Upper", Char.isUpper(character), "Character is a letter between A and Z.");
            logInfo("Is Whitespace", Char.isWhitespace(character), "Character is non-printable.");

            logInfo("Replace Second Char", Char.setCharAt("3", "Replace Second Char", 1), "Should replace the first e with a 3.");
            logInfo("Remove Second Char", Char.removeCharAt("Remove Second Char", 1), "Should remove the first e.")

            flushLog();
        }

        function clearLog() {
            document.getElementById("Results").innerHTML = "";
            htmlTable = ""
        }

        function logInfo(test, value, desc) {
            htmlTable += "<tr><th>" + test + "</th><td>" + value + "</td><td>" + desc + "</td></tr>";
        }

        function flushLog() {
            document.getElementById("Results").innerHTML = "<table>" + htmlTable + "</table>";
        }
    </script>
</head>
<body>
    Press a Key:&nbsp;
    <input type="text"
           onkeydown="this.value='';javascript:analyzeKey();return true;"
           onkeypress="this.value='';javascript:analyzeKey();return true;">
    </input>

    <dir id="Results"></dir>
</body>
</html>

Char Class

Create a file with the name “Char.js” and place the following code into the new file. This file will be referenced from the test class.

Notice that the String object is extended to provide access to the Character at the specified position and how the CharObject class is exposed via the instantiated global Char variable.

//<Purpose>
//Extend the String object to provide access to Char object.
//</Purpose>
if (!String.prototype.getChar) {
    //<Purpose>
    //Get the char at the specified index position in the value.
    //If an index is not supplied uses position 0.
    //</Purpose>
    String.prototype.getChar = function(pos) {
        if ((pos == null) || (pos == undefined)) pos = 0;
        return new CharObject(this.charAt(pos));
    };
}

//Provide access to Char object functionality outside of string prototype.
var Char = new CharObject();

//<Purpose>
//Provides a set of methods to assist with character management.
//</Purpose>
function CharObject(value, pos) {
    //Return correct reference in the event that this is used with a tool like jQuery.
    var me = this;
    var innerValue = null;
    innerValue = value;
    if ((innerValue) && (innerValue.length > 0)) {
        if (!pos) pos = 0;
        innerValue = innerValue.charAt(pos);
    }

    //Regular Expressions to Test Char or String Value
    var alphaPattern = /^[a-zA-Z]*$/;
    var alphaNumPattern = /^[a-zA-Z0-9]*$/;
    var containSpaceCharPattern =/[ ]/;
    var controlPattern = /^[\x00\x1F\x7F]*$/;
    var digitPattern = /^[0-9]*$/;
    var hexDigitPattern = /^[0-9a-fA-F]*$/;
    var isLowerCasePattern = /^[a-z0-9\s]*$/;
    var printCharPattern = /^[\x20-\x7E]*$/;
    var spaceLetterDigitPattern = /[ 0-9a-zA-Z]/;
    var spacePattern = /^[ \f\n\r\t\v]*$/;
    var upperCasePattern = /^[A-Z0-9\s]*$/;
    var whitespacePattern = /^[\s]*$/;

    //<Purpose>
    //Get a boolean value that indicates if the value contains letters.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isAlpha = function(value) {
        if (!value) value = innerValue;
        return alphaPattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that inidicates if the value contains letters or digits.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    //<Remarks>
    //Does not return true for decimal, minus or plus.
    //</Remarks>
    this.isAlphaNum = function(value) {
        if (!value) value = innerValue;
        return alphaNumPattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value is a control character.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    //<Remarks>
    //In ASCII, control characters are 0x00 (Null) to 0x1F (Unit Separator), and 0x7F (Delete).
    //</Remarks>
    this.isControl = function(value) {
        if (!value) value = innerValue;
        return controlPattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value contains only digits.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isDigit = function(value) {
        if (!value) value = innerValue;
        return digitPattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value contains printing character other than space.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isGraph = function(value) {
        if (!value) value = innerValue;
        return ((printCharPattern.test(value)) && !(containSpaceCharPattern(value)));
    }

    //<Purpose>
    //Get a boolean value that indicates if the value is a hexdecimal value.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isHexDigit = function(value) {
        if (!value) value = innerValue;
        return hexDigitPattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value is lower case.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isLower = function(value) {
        if (!value) value = innerValue;
        return isLowerCasePattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value is a number.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    //<Remarks>
    //For a character this is the same as IsDigit but for a string
    //indicates if the value can be converted to a number.
    //isNaN returns false with fraction statements like 1/4.
    //IsNumeric returns false with fraction statements.
    //</Remarks>
    //<References>
    //http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric
    //</References>
    this.isNumeric = function(value) {
        if (!value) value = innerValue;
        return ((value - 0 == value) && (value.length > 0));
    }

    //<Purpose>
    //Get a boolean value that indicates if the value has printable characters.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    //<Remarks>
    //In ASCII, printing characters are 0x20 (' ') to 0x7E ('~').
    //</Remarks>
    this.isPrint = function(value) {
        if (!value) value = innerValue;
        return printCharPattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value contains printing character other than space, letter and digit.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isPunct = function(value) {
        if (!value) value = innerValue;
        return ((printCharPattern.test(value)) && (!spaceLetterDigitPattern.test(value)));
    }

    //<Purpose>
    //Get a boolean value that indicates if the value is a space, formfeed, newline, carriage return, tab, vertical tab
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isSpace = function(value) {
        if (!value) value = innerValue;
        return spacePattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value is upper case.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isUpper = function(value) {
        if (!value) value = innerValue;
        return upperCasePattern.test(value);
    }

    //<Purpose>
    //Get a boolean value that indicates if the value has non-printable characters.
    //</Purpose>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.isWhitespace = function(value) {
        if (!value) value = innerValue;
        return whitespacePattern.test(value);
    }

    //<Purpose>
    //Remove a character at a specified location in the string value.
    //If an index is not supplied uses position 0.
    //</Purpose>
    //<Parameter name="original">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    //<Parameter name="index">
    //Optional. Required only if the value is a string and you need to
    //remove a character at a position greater than zero.
    //</Parameter>
    //<Returns>
    //Returns value unchanged if the index is less than zero or greater than the length of the string,
    //otherwise returns the value with the character removed from the specified index position.
    //</Returns>
    this.removeCharAt = function(original, index) {
        if (!original) value = innerValue;
        var newValue = me.setCharAt("", original, index);
        if (newValue == null)
            return original;
        else
            return newValue;
    }

    //<Purpose>
    //Replace a character at a specified location in the string value.
    //If an index is not supplied uses position 0.
    //</Purpose>
    //<Parameter name="replacement">
    //Required. The character value to insert into the string at the specified position.
    //</Parameter>
    //<Parameter name="original">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    //<Parameter name="index">
    //Optional. Required only if the value is a string and you need to replace
    //a character at a position greater than zero.
    //</Parameter>
    //<Returns>
    //Returns null if index is less than zero or greater than the length of the value,
    //otherwise returns the value with the replaced character at the specified index position.
    //</Returns>
    //<References>
    //http://www.openjs.com/scripts/strings/setcharat_function.php
    //</References>
    this.setCharAt = function(replacement, original, index) {
        if (!original) original = innerValue;
        if (!index) index = 0;
        if ((index < 0) || (index > original.length))
          return original;
        else
          return original.substr(0,index) + replacement + original.substr(index+1);
    }

    //<Purpose>
    //Get the ASC code value for the character at the specified position.
    //If an index is not supplied uses position 0.
    //</Purpose>
    //<Parameter name="index">
    //Optional. Required only if the value is a string and you need to get
    //the AscII code value for a character at position greater than zero.
    //</Parameter>
    //<Parameter name="value">
    //Optional. Char or string value. When omitted uses the character
    //value that was passed into the class during instantiation.
    //</Parameter>
    this.toAsc = function(index, value) {
        if (!value) value = innerValue;
        if (!index) index = 0;
        return value.charCodeAt(index);
    }

    //<Purpose>
    //Convert the asc ii code to a char value.
    //</Purpose>
    //<Parameter name="asc">
    //Required. A whole number.
    //</Parameter>
    this.toChar = function(asc) {
        return String.fromCharCode(asc);
    }

    //<Purpose>
    //Get the char as a string value.
    //</Purpose>
    this.toString = function() {
        return innerValue;
    }
}
Advertisements

1 Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: