Language Basics JavaScript DHTML





    
        jsPro - String
        
        
/**
 * +-------------------------------------------------------------------------+
 * | jsPro - Error                                                           |
 * +-------------------------------------------------------------------------+
 * | Copyright (C) 2001-2003 Stuart Wigley                                   |
 * +-------------------------------------------------------------------------+
 * | This library is free software; you can redistribute it and/or modify it |
 * | under the terms of the GNU Lesser General Public License as published by|
 * | the Free Software Foundation; either version 2.1 of the License, or (at |
 * | your option) any later version.                                         |
 * |                                                                         |
 * | This library is distributed in the hope that it will be useful, but     |
 * | WITHOUT ANY WARRANTY; without even the implied warranty of              |
 * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
 * | General Public License for more details.                                |
 * |                                                                         |
 * | You should have received a copy of the GNU Lesser General Public License|
 * | along with this library; if not, write to the Free Software Foundation, |
 * | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA             |
 * +-------------------------------------------------------------------------+
 * | Authors:   Stuart Wigley                      |
 * |            Randolph Fielding                   |
 * +-------------------------------------------------------------------------+
 * $Id: error.js,v 1.15 2003/09/22 04:41:10 gator4life Exp $
 */
/**
 * Property used in Error.handleError to specify how errors are
 * reported. Permissable values are:
 *
 * 0    No errors are reported.
 * 1    Report the error name and error message using the status bar of the
 *      active browser window.
 * 2    Report the error name and error message using an alert box.
 * 3    Report the error name, error message and debug message using an alert
 *      box.
 * 4    Report the error name, error message and debug message using a debug
 *      window. An instance of the Debug() class must be available.
 */
Error.prototype.debugLevel = 4;
/**
 * Uses Error.debugLevel to control how errors are reported. If
 * Error.debugLevel is set to 4, you must substitute the name of
 * your Debug() instance for oDebug in the line
 * var jsProDebugWindow = oDebug.
 *
 * @summary             handles thrown exceptions
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.2, 09/03/03
 * @interface           Error.handleError()
 * @requires            Debug.print(vMixedValue, sMessageType)
 * @see                 Debug()
 * @see                 Debug.print()
 */
Error.prototype.handleError = function() {
    var sDebugMessage = this.debug;
    var sErrorMessage = (sDebugMessage) ? sDebugMessage : '';
    switch (this.debugLevel) {
        case 0 :
            break;
        case 1 :
            window.status = this.name + ': ' + this.message;
            break;
        case 2 :
            window.alert(this.name + '\n\n' + this.message);
            break;
        case 3 :
            window.alert(this.name + '\n\n' + this.message + '\n\n' + sErrorMessage);
            break;
        case 4 :
            var jsProDebugWindow = oDebug;
            if (jsProDebugWindow) {
                var oDebugWindow = jsProDebugWindow.debugWindow;
                if (oDebugWindow && !oDebugWindow.closed) {
                    jsProDebugWindow.print(this.name + ' ' + this.message + ' ' + sErrorMessage, 1);
                }
            }
    }
}
/**
 * Creates an object that is a subclass of Error for handling
 * ArrayIndexOutOfBounds exceptions.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 06/27/03
 * @interface           new ArrayIndexOutOfBoundsException(sMethodName,
 *                      iIndex, iArrayLength)

 * @param sMethodName   the name of the method where the exception was thrown
 * @param iIndex        the index of a hypothetical array member attempting to
 *                      be accessed
 * @param iArrayLength  the length of the array
 */
function ArrayIndexOutOfBoundsException(sMethodName, iIndex, iArrayLength) {
    this.name = 'ArrayIndexOutOfBoundsException';
    this.message = sMethodName + ' has been accessed with an illegal index that is either negative or greater than the size of the array.';
    this.debug = 'Attempting to access index ' + iIndex.toString() + ', but array has an index range of 0 to ' + (iArrayLength - 1).toString() + '.';
}
ArrayIndexOutOfBoundsException.prototype = new Error();
/**
 * Creates an object that is a subclass of Error for handling IllegalArgument
 * exceptions.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.2, 07/24/03
 * @interface           new IllegalArgumentException(sMethodName,
 *                      vExpectedArgs, iActualArgs)

 * @param sMethodName   the name of the method where the exception was thrown
 * @param vExpectedArgs the number of arguments expected
 * @param iActualArgs   the number of arguments received
 */
function IllegalArgumentException(sMethodName, vExpectedArgs, iActualArgs) {
    this.name = 'IllegalArgumentException';
    this.message = sMethodName + ' has been passed an illegal number of arguments.';
    this.debug = 'Expected ' + vExpectedArgs.toString() + ' argument(s), but received ' + iActualArgs.toString() + ' argument(s).';
}
IllegalArgumentException.prototype = new Error();
/**
 * Creates an object that is a subclass of Error for handling IllegalValue
 * exceptions.
 *
 * @author              Randolph Fielding
 * @version             1.0, 09/22/03
 * @interface           new IllegalValueException(sMethodName,
 *                      sVariableName, vExpectedVal, vActualVal)

 * @param sMethodName   the name of the method where the exception was thrown
 * @param sVariableName the name of the variable containing the illegal value
 * @param vExpectedVal  the value expected in the variable containing the
 *                      illegal value
 * @param vActualVal    the value currently in the variable containing the
 *                      illegal value
 */
function IllegalValueException(sMethodName, sVariableName, vExpectedVal, vActualVal) {
    this.name = 'IllegalValueException';
    this.message = sMethodName + ' has encountered an illegal value in variable ' + sVariableName + '.'
    this.debug = 'Expected a value of ' + vExpectedVal.toString() + ', but contains a value of ' + vActualVal.toString() + '.'
}
IllegalValueException.prototype = new Error();
/**
 * Creates an object that is a subclass of Error for handling
 * MethodNotAvailable exceptions.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 06/27/03
 * @interface           new MethodNotAvailableException(sMethodName,
 *                      sMethodNameNA)

 * @param sMethodName   the name of the method where the exception was thrown
 * @param sMethodNameNA the name of the method that was not available
 */
function MethodNotAvailableException(sMethodName, sMethodNameNA) {
    this.name = 'MethodNotAvailableException';
    this.message = 'A method has been called that is not available.';
    this.debug = sMethodName + ' attempted to call ' + sMethodNameNA + '.';
}
MethodNotAvailableException.prototype = new Error();
/**
 * Creates an object that is a subclass of Error for handling
 * PropertyNotAvailable exceptions.
 *
 * @author              Randolph Fielding
 * @version             1.1, 08/01/03
 * @interface           new PropertyNotAvailableException(sMethodName,
 *                      sPropNameNA)

 * @param sMethodName   the name of the method where the exception was thrown
 * @param sPropNameNA   the name of the property that was not available
 */
function PropertyNotAvailableException(sMethodName, sPropNameNA) {
    this.name = 'PropertyNotAvailableException';
    this.message = 'A property has been accessed that is not available.';
    this.debug = sMethodName + ' attempted to access ' + sPropNameNA + '.';
}
PropertyNotAvailableException.prototype = new Error();
/**
 * Creates an object that is a subclass of Error for handling TypeMismatch
 * exceptions.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.2, 07/24/03
 * @interface           new TypeMismatchException(sMethodName,
 *                      sExpectedType, sActualType)

 * @param sMethodName   the name of the method where the exception was thrown
 * @param sExpectedType the name of the expected type of an argument
 * @param sActualType   the name of the actual type of an argument
 */
function TypeMismatchException(sMethodName, sExpectedType, sActualType) {
    this.name = 'TypeMismatchException';
    this.message = sMethodName + ' has been passed an argument with an illegal or inappropriate type.';
    this.debug = 'Expected an argument with a type of ' + sExpectedType + ', but received an argument with a type of ' + sActualType + '.';
}
TypeMismatchException.prototype = new Error();
/**
 * Creates an object that is a subclass of Error for handling Unknown
 * exceptions.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 06/27/03
 * @interface           new UnknownException(sMethodName)
 * @param sMethodName   the name of the method where the exception was thrown
 */
function UnknownException(sMethodName) {
    this.name = 'UnknownException';
    this.message = 'An unknown error has occurred in ' + sMethodName + '.';
}
UnknownException.prototype = new Error();
        
        
        
/**
 * +-------------------------------------------------------------------------+
 * | jsPro - Debug                                                           |
 * +-------------------------------------------------------------------------+
 * | Copyright (C) 2001-2003 Stuart Wigley                                   |
 * +-------------------------------------------------------------------------+
 * | This library is free software; you can redistribute it and/or modify it |
 * | under the terms of the GNU Lesser General Public License as published by|
 * | the Free Software Foundation; either version 2.1 of the License, or (at |
 * | your option) any later version.                                         |
 * |                                                                         |
 * | This library is distributed in the hope that it will be useful, but     |
 * | WITHOUT ANY WARRANTY; without even the implied warranty of              |
 * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
 * | General Public License for more details.                                |
 * |                                                                         |
 * | You should have received a copy of the GNU Lesser General Public License|
 * | along with this library; if not, write to the Free Software Foundation, |
 * | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA             |
 * +-------------------------------------------------------------------------+
 * | Authors:   Stuart Wigley                      |
 * |            Randolph Fielding                   |
 * +-------------------------------------------------------------------------+
 * $Id: debug.js,v 1.6 2003/09/22 05:07:41 gator4life Exp $
 */
/**
 * Creates an object that opens a window for debugging.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/05/03
 * @interface           new Debug()
 */
function Debug() {
    this.debugWindow = window.open('../debug/debug.html', 'debug', 'width=400,height=600,resizable=yes,scrollbars=yes');
}
/**
 * Clears the contents of the debug window.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/05/03
 * @interface           Debug.clear()
 * @return              true if no exceptions are encountered
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              UnknownException
 */
Debug.prototype.clear = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments != 0) {
            throw vError = new IllegalArgumentException('Debug.clear', 0, iNumArguments);
        }
        var oMessageContainer = document.getElementById('messageContainer');
        if (!oMessageContainer) {
            throw vError = new UnknownException('Debug.clear');
        }
        while (oMessageContainer.hasChildNodes()) {
            oMessageContainer.removeChild(oMessageContainer.firstChild);
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : true;
    }
}
/**
 * Displays content within the debug window.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.2, 09/05/03
 * @interface           Debug.print(vMixedValue)
 * @interface           Debug.print(vMixedValue, iMessageType)
 * @param vMixedValue   content to be displayed within the debug window
 * @param iMessageType  an integer representing the type of content to display
 *                      within the debug window (information: 0; error: 1)
 *                      (optional)
 * @return              true if no exceptions are encountered
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              TypeMismatchException
 * @throws              UnknownException
 */
Debug.prototype.print = function(vMixedValue) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iMessageType = 0;
        if ((iNumArguments < 1) || (iNumArguments > 2)) {
            throw vError = new IllegalArgumentException('Debug.print', '1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iMessageType = arguments[1];
        }
        if ((typeof iMessageType != 'number') || (iMessageType.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('Debug.print', 'integer', typeof iMessageType);
        }
        if ((iMessageType != 0) && (iMessageType != 1)) {
            throw vError = new IllegalValueException('Debug.print', 'iMessageType', '0 or 1', iMessageType);
        }
        var oDebugWindow = this.debugWindow;
        if (!oDebugWindow || oDebugWindow.closed) {
            throw vError = new UnknownException('Debug.print');
        }
        var oDocument = oDebugWindow.document;
        if (!oDocument) {
            throw vError = new UnknownException('Debug.print');
        }
        var oMessageContainer = oDocument.getElementById('messageContainer');
        if (!oMessageContainer) {
            throw vError = new UnknownException('Debug.print');
        }
        var oTitleRow = oDocument.createElement('tr');
        var oTitleCell = oDocument.createElement('td');
        var oBodyRow = oDocument.createElement('tr');
        var oBodyCell = oDocument.createElement('td');
        if (!oTitleRow || !oTitleCell || !oBodyRow || !oBodyCell) {
            throw vError = new UnknownException('Debug.print');
        }
        var oTitleRowStyle = oTitleRow.style;
        if (oTitleRowStyle) {
            oTitleRowStyle.backgroundColor = '#EEE';
            oTitleRowStyle.fontWeight = 700;
        }
        var sOutputString = vMixedValue.toString();
        var sTitle = 'info';
        var sBody = sOutputString;
        if (iMessageType == 1) {
            sTitle = sOutputString.match(/\w+/);
            sBody = sOutputString.replace(/\w+/, '');
            var oBodyCellStyle = oBodyCell.style;
            if (oBodyCellStyle) {
                oBodyCell.style.backgroundColor = '#FCC';
            }
        }
        oMessageContainer.appendChild(oTitleRow);
        oTitleRow.appendChild(oTitleCell);
        oTitleCell.appendChild(oDocument.createTextNode(sTitle));
        oMessageContainer.appendChild(oBodyRow);
        oBodyRow.appendChild(oBodyCell);
        oBodyCell.appendChild(oDocument.createTextNode(sBody));
        oDebugWindow.focus();
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : true;
    }
}
        
        
        
/**
 * +-------------------------------------------------------------------------+
 * | jsPro - Test                                                            |
 * +-------------------------------------------------------------------------+
 * | Copyright (C) 2001-2003 Stuart Wigley                                   |
 * +-------------------------------------------------------------------------+
 * | This library is free software; you can redistribute it and/or modify it |
 * | under the terms of the GNU Lesser General Public License as published by|
 * | the Free Software Foundation; either version 2.1 of the License, or (at |
 * | your option) any later version.                                         |
 * |                                                                         |
 * | This library is distributed in the hope that it will be useful, but     |
 * | WITHOUT ANY WARRANTY; without even the implied warranty of              |
 * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
 * | General Public License for more details.                                |
 * |                                                                         |
 * | You should have received a copy of the GNU Lesser General Public License|
 * | along with this library; if not, write to the Free Software Foundation, |
 * | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA             |
 * +-------------------------------------------------------------------------+
 * | Authors:   Stuart Wigley                      |
 * |            Randolph Fielding                   |
 * +-------------------------------------------------------------------------+
 * $Id: test.js,v 1.6 2003/09/15 05:07:09 gator4life Exp $
 */
/**
 * Creates an object that provides methods for testing all jsPro libraries.
 *
 * @author              Stuart Wigley
 * @version             1.0, 07/24/03
 * @interface           new Test()
 */
function Test() { }
/**
 * Evaluates and returns the result of a jsPro method using assumptions about
 * the structure and ids of HTML elements in the jsPro HTML test files.
 *
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/20/03
 * @interface           Test.evaluateMethod(oButton, sClass)
 * @param oButton       the HTML input-button element that is clicked
 * @param sClass        the name of the jsPro class instance being tested
 * @return              the result of attempting to evaluate a jsPro method
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              TypeMismatchException
 */
Test.prototype.evaluateMethod = function(oButton, sClass) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments != 2) {
            throw vError = new IllegalArgumentException('Error.evaluateMethod', 2, iNumArguments);
        }
        if (typeof oButton != 'object') {
            throw vError = new TypeMismatchException('Error.evaluateMethod', 'object', typeof oButton);
        }
        if (typeof sClass != 'string') {
            throw vError = new TypeMismatchException('Error.evaluateMethod', 'string', typeof sClass);
        }
        var sMethodName = oButton.id;
        var oInput1 = document.getElementById(sMethodName + '1');
        var oInput2 = document.getElementById(sMethodName + '2');
        var oInput3 = document.getElementById(sMethodName + '3');
        var oOutput = document.getElementById(sMethodName + 'Result');
        var sArguments = '';
        if (oInput1) {
            var sInput1Value = oInput1.value;
            if (sInput1Value != '') {
                var fInput1Value = parseFloat(sInput1Value);
                sArguments += (isNaN(fInput1Value)) ? '\'' + sInput1Value + '\'' : fInput1Value;
            }
        }
        if (oInput2) {
            var sInput2Value = oInput2.value;
            if (sInput2Value != '') {
                var fInput2Value = parseFloat(sInput2Value);
                sArguments += (isNaN(fInput2Value)) ? ', \'' + sInput2Value + '\'' : ', ' + fInput2Value;
            }
        }
        if (oInput3) {
            var sInput3Value = oInput3.value;
            if (sInput3Value != '') {
                var fInput3Value = parseFloat(sInput3Value);
                sArguments += (isNaN(fInput3Value)) ? ', \'' + sInput3Value + '\'' : ', ' + fInput3Value;
            }
        }
        var vResult = eval(sClass + '.' + sMethodName + '(' + sArguments + ')');
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        if (oOutput) {
            oOutput.value = vResult;
        }
    }
}
        
        
        
/**
 * +-------------------------------------------------------------------------+
 * | jsPro - String                                                          |
 * +-------------------------------------------------------------------------+
 * | Copyright (C) 2001-2003 Stuart Wigley                                   |
 * +-------------------------------------------------------------------------+
 * | This library is free software; you can redistribute it and/or modify it |
 * | under the terms of the GNU Lesser General Public License as published by|
 * | the Free Software Foundation; either version 2.1 of the License, or (at |
 * | your option) any later version.                                         |
 * |                                                                         |
 * | This library is distributed in the hope that it will be useful, but     |
 * | WITHOUT ANY WARRANTY; without even the implied warranty of              |
 * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
 * | General Public License for more details.                                |
 * |                                                                         |
 * | You should have received a copy of the GNU Lesser General Public License|
 * | along with this library; if not, write to the Free Software Foundation, |
 * | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA             |
 * +-------------------------------------------------------------------------+
 * | Authors:   Stuart Wigley                      |
 * |            Randolph Fielding                   |
 * +-------------------------------------------------------------------------+
 * $Id: string.js,v 1.23 2003/09/25 05:03:01 gator4life Exp $
 */
/**
 * Escapes null bytes, quotation marks (double quotes), apostrophes (single
 * quotes), and reverse solidi (backslashes) in this string with backslashes.
 *
 * @summary             escape certain characters with backslashes
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 07/05/03
 * @interface           String.addSlashes()
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.addSlashes = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.addSlashes', 0, iNumArguments);
        }
        var iStringLength = this.length;
        var sEscapedString = '';
        for (var i = 0; i < iStringLength; i++) {
            var iCharCode = this.charCodeAt(i);
            var sChar = this.charAt(i);
            sEscapedString += ((iCharCode == 0) || (iCharCode == 34) || (iCharCode == 39) || (iCharCode == 92)) ? '\\' + sChar : sChar;
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sEscapedString;
    }
}
/**
 * Concatenate the string representation of the specified value to the end of
 * this string. An end-of-line terminator specific to a certain document type
 * will be inserted between the string and the specified value if a document
 * type is specified.
 *
 * @summary             concatenate
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.3, 09/25/03
 * @interface           String.cat(vValue)
 * @interface           String.cat(vValue, iDocType)
 * @param vValue        the value to be concatenated to the end of this string
 * @param iDocType      an integer representing the document type that the
 *                      end-of-line terminator between the string and
 *                      vValue conforms to (HTML: 0; XHTML: 1;
 *                      Windows text: 2; UNIX text: 3; Macintosh text: 4)
 *                      (optional)
 * @return              a concatenated string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.cat = function(vValue) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iDocType = null;
        if ((iNumArguments < 1) || (iNumArguments > 2)) {
            throw vError = new IllegalArgumentException('String.cat', '1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iDocType = arguments[1];
        }
        var sEolTerminator = '';
        if (iDocType) {
            if ((typeof iDocType != 'number') || (iDocType.toString().indexOf('.') != -1)) {
                throw vError = new TypeMismatchException('String.cat', 'integer', typeof iDocType);
            }
            if ((iDocType != 0) && (iDocType != 1) && (iDocType != 2) && (iDocType != 3) && (iDocType != 4)) {
                throw vError = new IllegalValueException('String.cat', 'iDocType', '0, 1, 2, 3 or 4', iDocType);
            }
            switch (iDocType) {
                case 0 : sEolTerminator = '
'; break;
                case 1 : sEolTerminator = ''; break;
                case 2 : sEolTerminator = '\r\n'; break;
                case 3 : sEolTerminator = '\n'; break;
                case 4 : sEolTerminator = '\r'; break;
            }
        }
        var sCatString = this + sEolTerminator + vValue.toString();
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sCatString;
    }
}
/**
 * Replaces all UNIX, Windows and Macintosh newline characters, tabs and
 * repeated spaces in this string with single spaces.
 *
 * @summary             compress whitespace to single spaces
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/21/03
 * @interface           String.compress()
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.compress = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.compress', 0, iNumArguments);
        }
        var sModifiedString = this.replace(/(\r\n)|(\r)|(\n)|(\t)|(\s+)/g, ' ');
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Returns an associative array keyed on the characters of this string. Each
 * member of the associative array contains an integer value representing the
 * number of occurrences of that member's key in this string.
 *
 * @summary             count occurrence of characters
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 07/05/03
 * @interface           String.count()
 * @return              an associative array of counted characters
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.count = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.count', 0, iNumArguments);
        }
        var iStringLength = this.length;
        var aCountedArray = new Array();
        for (var i = 0; i < iStringLength; i++) {
            var sChar = this.charAt(i);
            aCountedArray[sChar] = (aCountedArray[sChar] == undefined) ? 1 : ++aCountedArray[sChar];
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : aCountedArray;
    }
}
/**
 * Replaces all characters in this string defined in the XHTML 1.0 Entity Sets
 * (Latin-1 Characters, Special Characters, and Symbols) with their Numeric
 * Entity References.
 *
 * @summary             encode XHTML 1.0 entities
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/03/03
 * @interface           String.htmlEntities()
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.htmlEntities = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.htmlEntities', 0, iNumArguments);
        }
        var iStringLength = this.length;
        var sModifiedString = '';
        for (var i = 0; i < iStringLength; i++) {
            var iCharCode = this.charCodeAt(i);
            if (iCharCode ==   34  ||  iCharCode ==   38  ||  iCharCode ==   39  ||  iCharCode ==   60  ||
                iCharCode ==   62  || (iCharCode >=  160  &&  iCharCode <=  255) ||  iCharCode ==  338  ||
                iCharCode ==  339  ||  iCharCode ==  352  ||  iCharCode ==  353  ||  iCharCode ==  376  ||
                iCharCode ==  402  ||  iCharCode ==  710  ||  iCharCode ==  732  || (iCharCode >=  913  &&
                iCharCode <=  929) || (iCharCode >=  931  &&  iCharCode <=  937) || (iCharCode >=  945  &&
                iCharCode <=  969) ||  iCharCode ==  977  ||  iCharCode ==  978  ||  iCharCode ==  982  ||
                iCharCode == 8194  ||  iCharCode == 8195  ||  iCharCode == 8201  || (iCharCode >= 8204  &&
                iCharCode <= 8207) ||  iCharCode == 8211  ||  iCharCode == 8212  || (iCharCode >= 8216  &&
                iCharCode <= 8218) || (iCharCode >= 8220  &&  iCharCode <= 8222) || (iCharCode >= 8224  &&
                iCharCode <= 8226) ||  iCharCode == 8230  ||  iCharCode == 8240  ||  iCharCode == 8242  ||
                iCharCode == 8243  ||  iCharCode == 8249  ||  iCharCode == 8250  ||  iCharCode == 8254  ||
                iCharCode == 8260  ||  iCharCode == 8364  ||  iCharCode == 8465  ||  iCharCode == 8472  ||
                iCharCode == 8476  ||  iCharCode == 8482  ||  iCharCode == 8501  || (iCharCode >= 8592  &&
                iCharCode <= 8596) ||  iCharCode == 8629  || (iCharCode >= 8656  &&  iCharCode <= 8660) ||
                iCharCode == 8704  ||  iCharCode == 8706  ||  iCharCode == 8707  ||  iCharCode == 8709  ||
               (iCharCode >= 8711  &&  iCharCode <= 8713) ||  iCharCode == 8715  ||  iCharCode == 8719  ||
                iCharCode == 8721  ||  iCharCode == 8722  ||  iCharCode == 8727  ||  iCharCode == 8730  ||
                iCharCode == 8733  ||  iCharCode == 8734  ||  iCharCode == 8736  || (iCharCode >= 8743  &&
                iCharCode <= 8747) ||  iCharCode == 8756  ||  iCharCode == 8764  ||  iCharCode == 8773  ||
                iCharCode == 8776  ||  iCharCode == 8800  ||  iCharCode == 8801  ||  iCharCode == 8804  ||
                iCharCode == 8805  || (iCharCode >= 8834  &&  iCharCode <= 8836) ||  iCharCode == 8838  ||
                iCharCode == 8839  ||  iCharCode == 8853  ||  iCharCode == 8855  ||  iCharCode == 8869  ||
                iCharCode == 8901  || (iCharCode >= 8968  &&  iCharCode <= 8971) ||  iCharCode == 9001  ||
                iCharCode == 9002  ||  iCharCode == 9674  ||  iCharCode == 9824  ||  iCharCode == 9827  ||
                iCharCode == 9829  ||  iCharCode == 9830) {
                sModifiedString += '&#' + iCharCode + ';';
            } else {
                sModifiedString += this.charAt(i);
            }
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Replaces a small group of characters in this string defined in the HTML
 * 4.01 Special Characters Set with their Character Entity References.
 *
 * @summary             encode subset of HTML special characters
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/04/03
 * @interface           String.htmlSpecialChars()
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.htmlSpecialChars = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.htmlSpecialChars', 0, iNumArguments);
        }
        var iStringLength = this.length;
        var sModifiedString = '';
        for (var i = 0; i < iStringLength; i++) {
            switch (this.charCodeAt(i)) {
                case 34 : sModifiedString += '"'; break;
                case 38 : sModifiedString += '&' ; break;
                case 39 : sModifiedString += ''' ; break;
                case 60 : sModifiedString += '<'  ; break;
                case 62 : sModifiedString += '>'  ; break;
                default : sModifiedString += this.charAt(i);
            }
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Inserts the string representation of the specified value at the beginning
 * of this string or at a given position within this string (if the optional
 * start argument is specified).
 *
 * @summary             insert one string into another
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/21/03
 * @interface           String.insert(vValue)
 * @interface           String.insert(vValue, iStart)
 * @param vValue        the value to be inserted into this string
 * @param iStart        the index of the character to start at (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              ArrayIndexOutOfBoundsException
 * @throws              IllegalArgumentException
 * @throws              TypeMismatchException
 */
String.prototype.insert = function(vValue) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iStart = 0;
        if ((iNumArguments < 1) || (iNumArguments > 2)) {
            throw vError = new IllegalArgumentException('String.insert', '1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iStart = arguments[1];
        }
        if ((typeof iStart != 'number') || (iStart.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.insert', 'integer', typeof iStart);
        }
        var iStringLength = this.length;
        if ((iStart < 0) || (iStart >= iStringLength)) {
            throw vError = new ArrayIndexOutOfBoundsException('String.insert', iStart, iStringLength);
        }
        var sModifiedString = '';
        for (var i = 0; i < iStringLength; i++) {
            if (i == iStart) {
                sModifiedString += vValue.toString();
            }
            sModifiedString += this.charAt(i);
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Tests this string with a regular expression for standard email address
 * compliance.
 *
 * @summary             is email address?
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/04/03
 * @interface           String.isEmailAddress()
 * @return              true if this string is a standard email
 *                      address
 * @return              false if this string is not a standard
 *                      email address
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.isEmailAddress = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.isEmailAddress', 0, iNumArguments);
        }
        var xEmailAddress = /^[-.\w]+@(((([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))|(([-a-zA-Z0-9]+\.)+[a-zA-Z]{2,4}))$/;
        var bIsEmailAddress = xEmailAddress.test(this);
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : bIsEmailAddress;
    }
}
/**
 * Calculates the Levenshtein distance between this string (the source string)
 * and a target string. The Levenshtein distance is an integer that represents
 * the minimum number of characters you have to replace, insert or delete to
 * convert a source string into a target string.
 *
 * @summary             Levenshtein distance
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/10/03
 * @interface           String.levenshtein(sTarget)
 * @param sTarget       the target string
 * @return              the Levenshtein distance between this string and
 *                      sTarget
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              TypeMismatchException
 */
String.prototype.levenshtein = function(sTarget) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments != 1) {
            throw vError = new IllegalArgumentException('String.levenshtein', 1, iNumArguments);
        }
        if (typeof sTarget != 'string') {
            throw vError = new TypeMismatchException('String.levenshtein', 'string', typeof sTarget);
        }
        var sUpCaseSource = this.toUpperCase();
        var sUpCaseTarget = sTarget.toUpperCase();
        var iSourceLength = sUpCaseSource.length;
        var iTargetLength = sUpCaseTarget.length;
        if (iSourceLength == 0) {
            var iLevenshteinDistance = iTargetLength;
        } else if (iTargetLength == 0) {
            var iLevenshteinDistance = iSourceLength;
        } else {
            var aMatrix = new Array();
            for (var n = 0; n <= iSourceLength; n++) {
                aMatrix[n] = new Array();
                aMatrix[n][0] = n;
            }
            for (var m = 0; m <= iTargetLength; m++) {
                aMatrix[0][m] = m;
            }
            for (var i = 1; i <= iSourceLength; i++) {
                var sSourceChar = sUpCaseSource.charAt(i - 1);
                for (var j = 1; j <= iTargetLength; j++) {
                    var sTargetChar = sUpCaseTarget.charAt(j - 1);
                    var iCost = (sSourceChar == sTargetChar) ? 0 : 1;
                    var iNum1 = aMatrix[i - 1][j] + 1;
                    var iNum2 = aMatrix[i][j - 1] + 1;
                    var iNum3 = aMatrix[i - 1][j - 1] + iCost;
                    aMatrix[i][j] = ((iNum1 < iNum2) && (iNum1 < iNum3)) ? iNum1 : (iNum2 < iNum3) ? iNum2 : iNum3;
                }
            }
            var iLevenshteinDistance = aMatrix[iSourceLength][iTargetLength];
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : iLevenshteinDistance;
    }
}
/**
 * Pads the left side of this string with another string for a specified
 * number of times.
 *
 * @summary             pad left side
 * @author              Randolph Fielding
 * @version             1.0, 08/07/03
 * @interface           String.lpad(sPadString)
 * @interface           String.lpad(sPadString, iMultiplier)
 * @requires            String.pad(sPadString, iMultiplier, iSide)
 * @param sPadString    the string used for padding
 * @param iMultiplier   the number of times to repeat sPadString
 *                      (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              MethodNotAvailableException
 * @throws              TypeMismatchException
 * @throws              UnknownException
 * @see                 String.pad()
 */
String.prototype.lpad = function(sPadString) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iMultiplier = 1;
        if (!('pad' in this)) {
            throw vError = new MethodNotAvailableException('String.lpad', 'String.pad');
        }
        if ((iNumArguments < 1) || (iNumArguments > 2)) {
            throw vError = new IllegalArgumentException('String.lpad', '1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iMultiplier = arguments[1];
        }
        if (typeof sPadString != 'string') {
            throw vError = new TypeMismatchException('String.lpad', 'string', typeof sPadString);
        }
        if ((typeof iMultiplier != 'number') || (iMultiplier.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.lpad', 'integer', typeof iMultiplier);
        }
        if (iMultiplier < 0) {
            throw vError = new IllegalValueException('String.lpad', 'iMultiplier', '0 or greater', iMultiplier);
        }
        var sPaddedString = this.pad(sPadString, iMultiplier, -1);
        if (!sPaddedString) {
            throw vError = new UnknownException('String.lpad');
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sPaddedString;
    }
}
/**
 * Trims whitespace characters from the left side of this string.
 *
 * @summary             trim left side
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/03/03
 * @interface           String.ltrim()
 * @requires            String.trim(iSide)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              MethodNotAvailableException
 * @throws              UnknownException
 * @see                 String.trim()
 */
String.prototype.ltrim = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (!('trim' in this)) {
            throw vError = new MethodNotAvailableException('String.ltrim', 'String.trim');
        }
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.ltrim', 0, iNumArguments);
        }
        var sTrimmedString = this.trim(-1);
        if (!sTrimmedString) {
            throw vError = new UnknownException('String.ltrim');
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sTrimmedString;
    }
}
/**
 * Replaces all UNIX, Windows and Macintosh newline characters in this string
 * with either HTML 
 elements or XHTML  elements.
 *
 * @summary             newline to 
 conversion
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/04/03
 * @interface           String.nl2br()
 * @interface           String.nl2br(iDocType)
 * @param iDocType      an integer representing the document type to convert
 *                      newline characters into (HTML: 0; XHTML: 1) (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              TypeMismatchException
 */
String.prototype.nl2br = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iDocType = 1;
        if (iNumArguments > 1) {
            throw vError = new IllegalArgumentException('String.nl2br', '0 or 1', iNumArguments);
        } else if (iNumArguments == 1) {
            iDocType = arguments[0];
        }
        if ((typeof iDocType != 'number') || (iDocType.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.nl2br', 'integer', typeof iDocType);
        }
        if ((iDocType != 0) && (iDocType != 1)) {
            throw vError = new IllegalValueException('String.nl2br', 'iDocType', '0 or 1', iDocType);
        }
        switch (iDocType) {
            case 0  : var sBrElement = '
'; break;
            case 1  :
            default : var sBrElement = '';
        }
        var sModifiedString = this.replace(/(\r\n)|(\r)|(\n)/g, sBrElement);
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Overlays the string representation of the specified value over the beginning
 * of this string or over a later portion of this string (if the optional start
 * argument is specified).
 *
 * @summary             overlay one string over another
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/21/03
 * @interface           String.overlay(vValue)
 * @interface           String.overlay(vValue, iStart)
 * @param vValue        the value to be overlayed over this string
 * @param iStart        the index of the character to start at (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              ArrayIndexOutOfBoundsException
 * @throws              IllegalArgumentException
 * @throws              TypeMismatchException
 */
String.prototype.overlay = function(vValue) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iStart = 0;
        if ((iNumArguments < 1) || (iNumArguments > 2)) {
            throw vError = new IllegalArgumentException('String.overlay', '1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iStart = arguments[1];
        }
        if ((typeof iStart != 'number') || (iStart.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.overlay', 'integer', typeof iStart);
        }
        var iStringLength = this.length;
        if ((iStart < 0) || (iStart >= iStringLength)) {
            throw vError = new ArrayIndexOutOfBoundsException('String.overlay', iStart, iStringLength);
        }
        var sModifiedString = '';
        for (var i = 0; i < iStringLength; i++) {
            if (i == iStart) {
                var sValue = vValue.toString();
                sModifiedString += sValue;
                i += sValue.length;
                if (i >= iStringLength) {
                    break;
                }
            }
            sModifiedString += this.charAt(i);
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Pads either both sides, the left side, or the right side of this string
 * with another string for a specified number of times.
 *
 * @summary             pad
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/07/03
 * @interface           String.pad(sPadString)
 * @interface           String.pad(sPadString, iMultiplier)
 * @interface           String.pad(sPadString, iMultiplier, iSide)
 * @param sPadString    the string used for padding
 * @param iMultiplier   the number of times to repeat sPadString
 *                      (optional)
 * @param iSide         an integer representing the side(s) of the string to
 *                      pad (left: -1; both: 0; right: 1) (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              TypeMismatchException
 */
String.prototype.pad = function(sPadString) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iMultiplier = 1;
        var iSide = 1;
        if ((iNumArguments == 0) || (iNumArguments > 3)) {
            throw vError = new IllegalArgumentException('String.pad', '1, 2 or 3', iNumArguments);
        } else if (iNumArguments == 3) {
            iMultiplier = arguments[1];
            iSide = arguments[2];
        } else if (iNumArguments == 2) {
            iMultiplier = arguments[1];
        }
        if (typeof sPadString != 'string') {
            throw vError = new TypeMismatchException('String.pad', 'string', typeof sPadString);
        }
        if ((typeof iMultiplier != 'number') || (iMultiplier.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.pad', 'integer', typeof iMultiplier);
        }
        if (iMultiplier < 0) {
            throw vError = new IllegalValueException('String.pad', 'iMultiplier', '0 or greater', iMultiplier);
        }
        if ((typeof iSide != 'number') || (iSide.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.pad', 'integer', typeof iSide);
        }
        if ((iSide != -1) && (iSide != 0) && (iSide != 1)) {
            throw vError = new IllegalValueException('String.pad', 'iSide', '-1, 0 or 1', iSide);
        }
        var sRepeatedPadString = '';
        for (var i = 0; i < iMultiplier; i++) {
            sRepeatedPadString += sPadString;
        }
        switch (iSide) {
            case -1 : var sPaddedString = sRepeatedPadString + this; break;
            case  0 : var sPaddedString = sRepeatedPadString + this + sRepeatedPadString; break;
            case  1 :
            default : var sPaddedString = this + sRepeatedPadString;
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sPaddedString;
    }
}
/**
 * Removes all characters from this string or a subset of characters from this
 * string (if the optional start and length arguments are specified).
 *
 * @summary             remove characters
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/21/03
 * @interface           String.remove()
 * @interface           String.remove(iStart)
 * @interface           String.remove(iStart, iLength)
 * @param iStart        the index of the character to start at (optional)
 * @param iLength       the number of characters to remove beginning at
 *                      iStart (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              ArrayIndexOutOfBoundsException
 * @throws              IllegalArgumentException
 * @throws              TypeMismatchException
 */
String.prototype.remove = function() {
    try {
        var vError = null;
        var iStringLength = this.length;
        var iNumArguments = arguments.length;
        var iStart = 0;
        var iLength = iStringLength;
        if (iNumArguments > 2) {
            throw vError = new IllegalArgumentException('String.remove', '0, 1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iStart = arguments[0];
            iLength = arguments[1];
        } else if (iNumArguments == 1) {
            iStart = arguments[0];
            iLength -= iStart;
        }
        if ((typeof iStart != 'number') || (iStart.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.remove', 'integer', typeof iStart);
        }
        if ((typeof iLength != 'number') || (iLength.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.remove', 'integer', typeof iLength);
        }
        var iEnd = iStart + iLength;
        if (iStart < 0) {
            throw vError = new ArrayIndexOutOfBoundsException('String.remove', iStart, iStringLength);
        }
        if (iLength <= 0) {
            throw vError = new ArrayIndexOutOfBoundsException('String.remove', iLength, iStringLength);
        }
        if (iEnd > iStringLength) {
            throw vError = new ArrayIndexOutOfBoundsException('String.remove', iEnd, iStringLength);
        }
        var sModifiedString = this.replace(new RegExp(this.slice(iStart, iEnd)), '');
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Repeats this string a specified number of times.
 *
 * @summary             repeat
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/04/03
 * @interface           String.repeat(iMultiplier)
 * @param iMultiplier   the number of times to repeat this string
 * @return              a new string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              TypeMismatchException
 */
String.prototype.repeat = function(iMultiplier) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments != 1) {
            throw vError = new IllegalArgumentException('String.repeat', 1, iNumArguments);
        }
        if ((typeof iMultiplier != 'number') || (iMultiplier.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.repeat', 'integer', typeof iMultiplier);
        }
        if (iMultiplier < 0) {
            throw vError = new IllegalValueException('String.repeat', 'iMultiplier', '0 or greater', iMultiplier);
        }
        var sRepeatedString = '';
        for (var i = 0; i < iMultiplier; i++) {
            sRepeatedString += this;
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sRepeatedString;
    }
}
/**
 * Repeats each character in this string, in succession, a specified number of
 * times.
 *
 * @summary             repeat characters
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/21/03
 * @interface           String.repeatChars(iMultiplier)
 * @param iMultiplier   the number of times to repeat each character in this
 *                      string
 * @return              a new string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              TypeMismatchException
 */
String.prototype.repeatChars = function(iMultiplier) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments != 1) {
            throw vError = new IllegalArgumentException('String.repeatChars', 1, iNumArguments);
        }
        if ((typeof iMultiplier != 'number') || (iMultiplier.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.repeatChars', 'integer', typeof iMultiplier);
        }
        if (iMultiplier < 0) {
            throw vError = new IllegalValueException('String.repeatChars', 'iMultiplier', '0 or greater', iMultiplier);
        }
        var iStringLength = this.length;
        var sRepeatedString = '';
        for (var i = 0; i < iStringLength; i++) {
            for (var j = 0; j < iMultiplier; j++) {
                sRepeatedString += this.charAt(i);
            }
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sRepeatedString;
    }
}
/**
 * Reverses the order of all characters within this string or a subset of
 * characters within this string (if the optional start and length arguments
 * are specified).
 *
 * @summary             reverse
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/03/03
 * @interface           String.reverse()
 * @interface           String.reverse(iStart)
 * @interface           String.reverse(iStart, iLength)
 * @param iStart        the index of the character to start at (optional)
 * @param iLength       the number of characters to reverse the order of
 *                      beginning at iStart (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              ArrayIndexOutOfBoundsException
 * @throws              IllegalArgumentException
 * @throws              TypeMismatchException
 */
String.prototype.reverse = function() {
    try {
        var vError = null;
        var iStringLength = this.length;
        var iNumArguments = arguments.length;
        var iStart = 0;
        var iLength = iStringLength;
        if (iNumArguments > 2) {
            throw vError = new IllegalArgumentException('String.reverse', '0, 1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iStart = arguments[0];
            iLength = arguments[1];
        } else if (iNumArguments == 1) {
            iStart = arguments[0];
            iLength -= iStart;
        }
        if ((typeof iStart != 'number') || (iStart.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.reverse', 'integer', typeof iStart);
        }
        if ((typeof iLength != 'number') || (iLength.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.reverse', 'integer', typeof iLength);
        }
        var iEnd = iStart + iLength;
        if (iStart < 0) {
            throw vError = new ArrayIndexOutOfBoundsException('String.reverse', iStart, iStringLength);
        }
        if (iLength <= 0) {
            throw vError = new ArrayIndexOutOfBoundsException('String.reverse', iLength, iStringLength);
        }
        if (iEnd > iStringLength) {
            throw vError = new ArrayIndexOutOfBoundsException('String.reverse', iEnd, iStringLength);
        }
        var sStringBeginning = this.substr(0, iStart);
        var sStringEnd = this.substr(iEnd);
        var sReversedString = '';
        for (var i = iEnd - 1; i >= iStart; i--) {
            sReversedString += this.charAt(i);
        }
        var sModifiedString = sStringBeginning + sReversedString + sStringEnd;
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Performs rot13 encoding on this string, which shifts every letter in this
 * string by 13 places of the alphabet and leaves numbers or other characters
 * unchanged.
 *
 * @summary             rotate 13 encoding
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/09/03
 * @interface           String.rot13()
 * @return              an encoded string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.rot13 = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.rot13', 0, iNumArguments);
        }
        var sLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
        var iStringLength = this.length;
        var sEncodedString = '';
        for (var i = 0; i < iStringLength; i++) {
            var iCharCode = this.charCodeAt(i);
            var sChar = this.charAt(i);
            if ((iCharCode < 65) || ((iCharCode > 90) && (iCharCode < 97)) || (iCharCode > 122)) {
                sEncodedString += sChar;
            } else {
                var iCharIndex = sLetters.search(new RegExp(sChar));
                if (iCharIndex != -1) {
                    if (((iCharIndex >= 0) && (iCharIndex <= 12)) || ((iCharIndex >= 26) && (iCharIndex <= 38))) {
                        sEncodedString += sLetters.charAt(iCharIndex + 13);
                    } else{
                        sEncodedString += sLetters.charAt(iCharIndex - 13);
                    }
                } else {
                    sEncodedString += sChar;
                }
            }
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sEncodedString;
    }
}
/**
 * Pads the right side of this string with another string for a specified
 * number of times.
 *
 * @summary             pad right side
 * @author              Randolph Fielding
 * @version             1.0, 08/07/03
 * @interface           String.rpad(sPadString)
 * @interface           String.rpad(sPadString, iMultiplier)
 * @requires            String.pad(sPadString, iMultiplier, iSide)
 * @param sPadString    the string used for padding
 * @param iMultiplier   the number of times to repeat sPadString
 *                      (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              MethodNotAvailableException
 * @throws              TypeMismatchException
 * @throws              UnknownException
 * @see                 String.pad()
 */
String.prototype.rpad = function(sPadString) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iMultiplier = 1;
        if (!('pad' in this)) {
            throw vError = new MethodNotAvailableException('String.rpad', 'String.pad');
        }
        if ((iNumArguments < 1) || (iNumArguments > 2)) {
            throw vError = new IllegalArgumentException('String.rpad', '1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            iMultiplier = arguments[1];
        }
        if (typeof sPadString != 'string') {
            throw vError = new TypeMismatchException('String.rpad', 'string', typeof sPadString);
        }
        if ((typeof iMultiplier != 'number') || (iMultiplier.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.rpad', 'integer', typeof iMultiplier);
        }
        if (iMultiplier < 0) {
            throw vError = new IllegalValueException('String.rpad', 'iMultiplier', '0 or greater', iMultiplier);
        }
        var sPaddedString = this.pad(sPadString, iMultiplier, 1);
        if (!sPaddedString) {
            throw vError = new UnknownException('String.rpad');
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sPaddedString;
    }
}
/**
 * Trims whitespace characters from the right side of this string.
 *
 * @summary             trim right side
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/03/03
 * @interface           String.rtrim()
 * @requires            String.trim(iSide)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              MethodNotAvailableException
 * @throws              UnknownException
 * @see                 String.trim()
 */
String.prototype.rtrim = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (!('trim' in this)) {
            throw vError = new MethodNotAvailableException('String.rtrim', 'String.trim');
        }
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.rtrim', 0, iNumArguments);
        }
        var sTrimmedString = this.trim(1);
        if (!sTrimmedString) {
            throw vError = new UnknownException('String.rtrim');
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sTrimmedString;
    }
}
/**
 * Swaps every second character in this string with the character immediately
 * preceding it.
 *
 * @summary             swap characters
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/21/03
 * @interface           String.swap()
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.swap = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.swap', 0, iNumArguments);
        }
        var iStringLength = this.length;
        var sModifiedString = '';
        for (var i = 0; i < iStringLength; i += 2) {
            if ((i + 1) < iStringLength) {
                sModifiedString += this.charAt(i + 1);
            }
            sModifiedString += this.charAt(i);
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Trims whitespace characters from either both sides, the left side, or the
 * right side of this string.
 *
 * @summary             trim
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/03/03
 * @interface           String.trim()
 * @interface           String.trim(iSide)
 * @param iSide         an integer representing the side(s) of the string to
 *                      trim whitespace from (left: -1; both: 0; right: 1)
 *                      (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              TypeMismatchException
 */
String.prototype.trim = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iSide = 0;
        if (iNumArguments > 1) {
            throw vError = new IllegalArgumentException('String.trim', '0 or 1', iNumArguments);
        } else if (iNumArguments == 1) {
            iSide = arguments[0];
        }
        if ((typeof iSide != 'number') || (iSide.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.trim', 'integer', typeof iSide);
        }
        if ((iSide != -1) && (iSide != 0) && (iSide != 1)) {
            throw vError = new IllegalValueException('String.trim', 'iSide', '-1, 0 or 1', iSide);
        }
        switch (iSide) {
            case -1 : var sTrimmedString = this.replace(/^\s*/, ''); break;
            case  1 : var sTrimmedString = this.replace(/\s*$/, ''); break;
            case  0 :
            default : var sTrimmedString = this.replace(/^\s*/, '').replace(/\s*$/, '');
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sTrimmedString;
    }
}
/**
 * Truncates this string to the specified length. If specified, the final three
 * characters of the truncated string are replaced with an ellipsis.
 *
 * @summary             truncate
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 09/21/03
 * @interface           String.truncate(iLength)
 * @interface           String.truncate(iLength, bUseEllipsis)
 * @param iLength       the index of the character to truncate at
 * @param bUseEllipsis  a boolean value representing whether the final three
 *                      characters should be replaced with an ellipsis or not
 *                      (optional)
 * @return              the original string if (1) iLength is
 *                      greater than or equal to the length of the original
 *                      string or (2) iLength <= 3 and
 *                      bUseEllipsis = true
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              ArrayIndexOutOfBoundsException
 * @throws              IllegalArgumentException
 * @throws              TypeMismatchException
 */
String.prototype.truncate = function(iLength) {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var bUseEllipsis = false;
        if ((iNumArguments < 1) || (iNumArguments > 2)) {
            throw vError = new IllegalArgumentException('String.truncate', '1 or 2', iNumArguments);
        } else if (iNumArguments == 2) {
            bUseEllipsis = arguments[1];
        }
        if ((typeof iLength != 'number') || (iLength.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.truncate', 'integer', typeof iLength);
        }
        if (typeof bUseEllipsis != 'boolean') {
            throw vError = new TypeMismatchException('String.truncate', 'boolean', typeof bUseEllipsis);
        }
        var iStringLength = this.length;
        if (iLength < 0) {
            throw vError = new ArrayIndexOutOfBoundsException('String.truncate', iLength, iStringLength);
        }
        var sTruncatedString = '';
        if ((iLength >= iStringLength) || (bUseEllipsis && (iLength <= 3))) {
            sTruncatedString = this;
        } else {
            for (var i = 0; i < iLength; i++) {
                sTruncatedString += (bUseEllipsis && ((iLength - i) <= 3)) ? '.' : this.charAt(i);
            }
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sTruncatedString;
    }
}
/**
 * Converts the first character of this string to uppercase.
 *
 * @summary             uppercase first character
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 07/05/03
 * @interface           String.ucFirst()
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.ucFirst = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.ucFirst', 0, iNumArguments);
        }
        var sModifiedString = this.charAt(0).toUpperCase() + this.substr(1);
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Converts the first character of each word in this string to uppercase.
 *
 * @summary             uppercase words
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/07/03
 * @interface           String.ucWords()
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 */
String.prototype.ucWords = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        if (iNumArguments > 0) {
            throw vError = new IllegalArgumentException('String.ucWords', 0, iNumArguments);
        }
        var iStringLength = this.length;
        var sModifiedString = '';
        var bUpperCase = false;
        for (var i = 0; i < iStringLength; i++) {
            var iCharCode = this.charCodeAt(i);
            var sChar = this.charAt(i);
            var sUpperChar = sChar.toUpperCase();
            if ((iCharCode == 9) || (iCharCode == 10) || (iCharCode == 11) || (iCharCode == 13) || (iCharCode == 14) || (iCharCode == 32)) {
                sModifiedString += sChar;
                bUpperCase = true;
            } else if (i == 0) {
                sModifiedString += sUpperChar;
            } else {
                if (bUpperCase) {
                    sModifiedString += sUpperChar;
                    bUpperCase = false;
                } else {
                    sModifiedString += sChar;
                }
            }
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
/**
 * Wraps this string at a specified column width with a specified end-of-line
 * terminator designated by the document type. Words can also be split during
 * the wrap if specified.
 *
 * @summary             word wrap
 * @author              Stuart Wigley
 * @author              Randolph Fielding
 * @version             1.1, 08/10/03
 * @interface           String.wordWrap()
 * @interface           String.wordWrap(iColumnNum)
 * @interface           String.wordWrap(iColumnNum, iDocType)
 * @interface           String.wordWrap(iColumnNum, iDocType,
 *                      bSplitWords)

 * @param iColumnNum    the column number where wrapping should occur
 *                      (optional)
 * @param iDocType      an integer representing the document type that
 *                      end-of-line terminators conform to (HTML: 0; XHTML: 1;
 *                      Windows text: 2; UNIX text: 3; Macintosh text: 4)
 *                      (optional)
 * @param bSplitWords   designates whether words should be split during the
 *                      wrap (optional)
 * @return              a modified string
 * @return              null if an exception is encountered
 * @throws              IllegalArgumentException
 * @throws              IllegalValueException
 * @throws              TypeMismatchException
 */
String.prototype.wordWrap = function() {
    try {
        var vError = null;
        var iNumArguments = arguments.length;
        var iColumnNum = 80;
        var iDocType = 1;
        var bSplitWords = false;
        if (iNumArguments > 3) {
            throw vError = new IllegalArgumentException('String.wordWrap', '0, 1, 2 or 3', iNumArguments);
        } else if (iNumArguments == 3) {
            iColumnNum = arguments[0];
            iDocType = arguments[1];
            bSplitWords = arguments[2];
        } else if (iNumArguments == 2) {
            iColumnNum = arguments[0];
            iDocType = arguments[1];
        } else if (iNumArguments == 1) {
            iColumnNum = arguments[0];
        }
        if ((typeof iColumnNum != 'number') || (iColumnNum.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.wordWrap', 'integer', typeof iColumnNum);
        }
        if (iColumnNum < 1) {
            throw vError = new IllegalValueException('String.wordWrap', 'iColumnNum', '1 or greater', iColumnNum);
        }
        if ((typeof iDocType != 'number') || (iDocType.toString().indexOf('.') != -1)) {
            throw vError = new TypeMismatchException('String.wordWrap', 'integer', typeof iDocType);
        }
        if ((iDocType != 0) && (iDocType != 1) && (iDocType != 2) && (iDocType != 3) && (iDocType != 4)) {
            throw vError = new IllegalValueException('String.wordWrap', 'iDocType', '0, 1, 2, 3 or 4', iDocType);
        }
        if (typeof bSplitWords != 'boolean') {
            throw vError = new TypeMismatchException('String.wordWrap', 'boolean', typeof bSplitWords);
        }
        switch (iDocType) {
            case 0  : var sEolTerminator = '
'; break;
            case 2  : var sEolTerminator = '\r\n'; break;
            case 3  : var sEolTerminator = '\n'; break;
            case 4  : var sEolTerminator = '\r'; break;
            case 1  :
            default : var sEolTerminator = '';
        }
        var sModifiedString = '';
        if (bSplitWords) {
            var iStringLength = this.length;
            for (var i = 0; i < iStringLength; i++) {
                var sChar = this.charAt(i);
                if (((i % iColumnNum) == 0) && (i != 0)) {
                    sModifiedString += sEolTerminator + sChar;
                } else {
                    sModifiedString += sChar;
                }
            }
        } else {
            var aWords = this.split(' ');
            var iNumWords = aWords.length;
            var iLineLength = 0;
            for (var j = 0; j < iNumWords; j++) {
                var iWordLength = aWords[j].length;
                var iTempLineLength = iWordLength + iLineLength;
                if (iTempLineLength > iColumnNum) {
                    sModifiedString += sEolTerminator + aWords[j] + ((j == (iNumWords - 1)) ? '' : ' ');
                    iLineLength = iWordLength + 1;
                } else if (iTempLineLength == iColumnNum) {
                    sModifiedString += aWords[j] + ((j == (iNumWords - 1)) ? '' : sEolTerminator);
                    iLineLength = 0;
                } else {
                    sModifiedString += aWords[j] + ((j == (iNumWords - 1)) ? '' : ' ');
                    iLineLength += iWordLength + 1;
                }
            }
        }
    }
    catch (vError) {
        if (vError instanceof Error) {
            vError.handleError();
        }
    }
    finally {
        return vError ? null : sModifiedString;
    }
}
                
        
            var oDebug = new Debug();
            var oTest = new Test();
        
    
    
        
            
                
                    
                

                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                
            
        
String.addSlashes() 
String.cat()
                        
                        
                    
String.compress() 
String.count() 
String.htmlEntities() 
String.htmlSpecialChars() 
String.insert()
                        
                        
                    
String.isEmailAddress() 
String.levenshtein()
String.lpad()
                        
                        
                    
String.ltrim() 
String.nl2br()
String.overlay()
                        
                        
                    
String.pad()
                        
                        
                        
                    
String.remove()
                        
                        
                    
String.repeat()
String.repeatChars()
String.reverse()
                        
                        
                    
String.rot13() 
String.rpad()
                        
                        
                    
String.rtrim() 
String.swap() 
String.trim()
String.truncate()
                        
                        
                    
String.ucFirst() 
String.ucWords() 
String.wordWrap()