<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<!-- 
 * +-------------------------------------------------------------------------+ 
 * | jsPro - String Test Page                                                 | 
 * +-------------------------------------------------------------------------+ 
 * | 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 <[email protected]>                     | 
 * +-------------------------------------------------------------------------+ 
 * $Id: string.html,v 1.6 2003/09/23 14:48:15 wigleys Exp $ 
--> 
<html> 
    <head> 
        <title>jsPro - String</title> 
        <!-- error.js --> 
        <script type="text/javascript"> 
/** 
 * +-------------------------------------------------------------------------+ 
 * | 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 <[email protected]>                     | 
 * |            Randolph Fielding <[email protected]>                  | 
 * +-------------------------------------------------------------------------+ 
 * $Id: error.js,v 1.15 2003/09/22 04:41:10 gator4life Exp $ 
 */ 
 
 
/** 
 * Property used in <code>Error.handleError</code> 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 <code>Error.debugLevel</code> to control how errors are reported. If 
 * <code>Error.debugLevel</code> is set to 4, you must substitute the name of 
 * your <code>Debug()</code> instance for <code>oDebug</code> in the line 
 * <code>var jsProDebugWindow = oDebug</code>. 
 * 
 * @summary             handles thrown exceptions 
 * @author              Stuart Wigley 
 * @author              Randolph Fielding 
 * @version             1.2, 09/03/03 
 * @interface           <code>Error.handleError()</code> 
 * @requires            <code>Debug.print(vMixedValue, sMessageType)</code> 
 * @see                 <code>Debug()</code> 
 * @see                 <code>Debug.print()</code> 
 */ 
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           <code>new ArrayIndexOutOfBoundsException(sMethodName, 
 *                      iIndex, iArrayLength)</code> 
 * @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           <code>new IllegalArgumentException(sMethodName, 
 *                      vExpectedArgs, iActualArgs)</code> 
 * @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           <code>new IllegalValueException(sMethodName, 
 *                      sVariableName, vExpectedVal, vActualVal)</code> 
 * @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           <code>new MethodNotAvailableException(sMethodName, 
 *                      sMethodNameNA)</code> 
 * @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           <code>new PropertyNotAvailableException(sMethodName, 
 *                      sPropNameNA)</code> 
 * @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           <code>new TypeMismatchException(sMethodName, 
 *                      sExpectedType, sActualType)</code> 
 * @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           <code>new UnknownException(sMethodName)</code> 
 * @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(); 
        </script> 
        <!-- debug.js --> 
        <script type="text/javascript"> 
/** 
 * +-------------------------------------------------------------------------+ 
 * | 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 <[email protected]>                     | 
 * |            Randolph Fielding <[email protected]>                  | 
 * +-------------------------------------------------------------------------+ 
 * $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           <code>new Debug()</code> 
 */ 
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           <code>Debug.clear()</code> 
 * @return              <code>true</code> if no exceptions are encountered 
 * @return              <code>null</code> 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           <code>Debug.print(vMixedValue)</code> 
 * @interface           <code>Debug.print(vMixedValue, iMessageType)</code> 
 * @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              <code>true</code> if no exceptions are encountered 
 * @return              <code>null</code> 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; 
    } 
} 
        </script> 
        <!-- test.js --> 
        <script type="text/javascript"> 
/** 
 * +-------------------------------------------------------------------------+ 
 * | 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 <[email protected]>                     | 
 * |            Randolph Fielding <[email protected]>                  | 
 * +-------------------------------------------------------------------------+ 
 * $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           <code>new Test()</code> 
 */ 
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           <code>Test.evaluateMethod(oButton, sClass)</code> 
 * @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              <code>null</code> 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; 
        } 
    } 
} 
        </script> 
        <!-- string.js --> 
        <script type="text/javascript"> 
/** 
 * +-------------------------------------------------------------------------+ 
 * | 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 <[email protected]>                     | 
 * |            Randolph Fielding <[email protected]>                  | 
 * +-------------------------------------------------------------------------+ 
 * $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           <code>String.addSlashes()</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.cat(vValue)</code> 
 * @interface           <code>String.cat(vValue, iDocType)</code> 
 * @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 
 *                      <code>vValue</code> conforms to (HTML: 0; XHTML: 1; 
 *                      Windows text: 2; UNIX text: 3; Macintosh text: 4) 
 *                      (optional) 
 * @return              a concatenated string 
 * @return              <code>null</code> 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 = '<BR>'; break; 
                case 1 : sEolTerminator = '<br />'; 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           <code>String.compress()</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.count()</code> 
 * @return              an associative array of counted characters 
 * @return              <code>null</code> 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           <code>String.htmlEntities()</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.htmlSpecialChars()</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.insert(vValue)</code> 
 * @interface           <code>String.insert(vValue, iStart)</code> 
 * @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              <code>null</code> 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           <code>String.isEmailAddress()</code> 
 * @return              <code>true</code> if this string is a standard email 
 *                      address 
 * @return              <code>false</code> if this string is not a standard 
 *                      email address 
 * @return              <code>null</code> 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           <code>String.levenshtein(sTarget)</code> 
 * @param sTarget       the target string 
 * @return              the Levenshtein distance between this string and 
 *                      <code>sTarget</code> 
 * @return              <code>null</code> 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           <code>String.lpad(sPadString)</code> 
 * @interface           <code>String.lpad(sPadString, iMultiplier)</code> 
 * @requires            <code>String.pad(sPadString, iMultiplier, iSide)</code> 
 * @param sPadString    the string used for padding 
 * @param iMultiplier   the number of times to repeat <code>sPadString</code> 
 *                      (optional) 
 * @return              a modified string 
 * @return              <code>null</code> if an exception is encountered 
 * @throws              IllegalArgumentException 
 * @throws              IllegalValueException 
 * @throws              MethodNotAvailableException 
 * @throws              TypeMismatchException 
 * @throws              UnknownException 
 * @see                 <code>String.pad()</code> 
 */ 
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           <code>String.ltrim()</code> 
 * @requires            <code>String.trim(iSide)</code> 
 * @return              a modified string 
 * @return              <code>null</code> if an exception is encountered 
 * @throws              IllegalArgumentException 
 * @throws              MethodNotAvailableException 
 * @throws              UnknownException 
 * @see                 <code>String.trim()</code> 
 */ 
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 <BR> elements or XHTML <br /> elements. 
 * 
 * @summary             newline to <br> conversion 
 * @author              Stuart Wigley 
 * @author              Randolph Fielding 
 * @version             1.1, 08/04/03 
 * @interface           <code>String.nl2br()</code> 
 * @interface           <code>String.nl2br(iDocType)</code> 
 * @param iDocType      an integer representing the document type to convert 
 *                      newline characters into (HTML: 0; XHTML: 1) (optional) 
 * @return              a modified string 
 * @return              <code>null</code> 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 = '<BR>'; break; 
            case 1  : 
            default : var sBrElement = '<br />'; 
        } 
 
        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           <code>String.overlay(vValue)</code> 
 * @interface           <code>String.overlay(vValue, iStart)</code> 
 * @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              <code>null</code> 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           <code>String.pad(sPadString)</code> 
 * @interface           <code>String.pad(sPadString, iMultiplier)</code> 
 * @interface           <code>String.pad(sPadString, iMultiplier, iSide)</code> 
 * @param sPadString    the string used for padding 
 * @param iMultiplier   the number of times to repeat <code>sPadString</code> 
 *                      (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              <code>null</code> 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           <code>String.remove()</code> 
 * @interface           <code>String.remove(iStart)</code> 
 * @interface           <code>String.remove(iStart, iLength)</code> 
 * @param iStart        the index of the character to start at (optional) 
 * @param iLength       the number of characters to remove beginning at 
 *                      <code>iStart</code> (optional) 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.repeat(iMultiplier)</code> 
 * @param iMultiplier   the number of times to repeat this string 
 * @return              a new string 
 * @return              <code>null</code> 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           <code>String.repeatChars(iMultiplier)</code> 
 * @param iMultiplier   the number of times to repeat each character in this 
 *                      string 
 * @return              a new string 
 * @return              <code>null</code> 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           <code>String.reverse()</code> 
 * @interface           <code>String.reverse(iStart)</code> 
 * @interface           <code>String.reverse(iStart, iLength)</code> 
 * @param iStart        the index of the character to start at (optional) 
 * @param iLength       the number of characters to reverse the order of 
 *                      beginning at <code>iStart</code> (optional) 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.rot13()</code> 
 * @return              an encoded string 
 * @return              <code>null</code> 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           <code>String.rpad(sPadString)</code> 
 * @interface           <code>String.rpad(sPadString, iMultiplier)</code> 
 * @requires            <code>String.pad(sPadString, iMultiplier, iSide)</code> 
 * @param sPadString    the string used for padding 
 * @param iMultiplier   the number of times to repeat <code>sPadString</code> 
 *                      (optional) 
 * @return              a modified string 
 * @return              <code>null</code> if an exception is encountered 
 * @throws              IllegalArgumentException 
 * @throws              IllegalValueException 
 * @throws              MethodNotAvailableException 
 * @throws              TypeMismatchException 
 * @throws              UnknownException 
 * @see                 <code>String.pad()</code> 
 */ 
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           <code>String.rtrim()</code> 
 * @requires            <code>String.trim(iSide)</code> 
 * @return              a modified string 
 * @return              <code>null</code> if an exception is encountered 
 * @throws              IllegalArgumentException 
 * @throws              MethodNotAvailableException 
 * @throws              UnknownException 
 * @see                 <code>String.trim()</code> 
 */ 
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           <code>String.swap()</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.trim()</code> 
 * @interface           <code>String.trim(iSide)</code> 
 * @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              <code>null</code> 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           <code>String.truncate(iLength)</code> 
 * @interface           <code>String.truncate(iLength, bUseEllipsis)</code> 
 * @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) <code>iLength</code> is 
 *                      greater than or equal to the length of the original 
 *                      string or (2) <code>iLength <= 3</code> and 
 *                      <code>bUseEllipsis = true</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.ucFirst()</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.ucWords()</code> 
 * @return              a modified string 
 * @return              <code>null</code> 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           <code>String.wordWrap()</code> 
 * @interface           <code>String.wordWrap(iColumnNum)</code> 
 * @interface           <code>String.wordWrap(iColumnNum, iDocType)</code> 
 * @interface           <code>String.wordWrap(iColumnNum, iDocType, 
 *                      bSplitWords)</code> 
 * @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              <code>null</code> 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 = '<BR>'; 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 = '<br />'; 
        } 
 
        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; 
    } 
} 
        </script>         
        <script type="text/javascript"> 
            var oDebug = new Debug(); 
            var oTest = new Test(); 
        </script> 
    </head> 
    <body> 
        <table> 
            <tbody> 
                <tr> 
                    <td colspan="4"><input id="inputString" name="inputString" type="text" size="50" /></td> 
                </tr> 
                <tr> 
                    <td>String.addSlashes()</td> 
                    <td> </td> 
                    <td><input id="addSlashes" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="addSlashesResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.cat()</td> 
                    <td> 
                        <input id="cat1" name="input" type="text" size="5" /> 
                        <input id="cat2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="cat" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="catResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.compress()</td> 
                    <td> </td> 
                    <td><input id="compress" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="compressResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.count()</td> 
                    <td> </td> 
                    <td><input id="count" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="countResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.htmlEntities()</td> 
                    <td> </td> 
                    <td><input id="htmlEntities" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="htmlEntitiesResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.htmlSpecialChars()</td> 
                    <td> </td> 
                    <td><input id="htmlSpecialChars" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="htmlSpecialCharsResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.insert()</td> 
                    <td> 
                        <input id="insert1" name="input" type="text" size="5" /> 
                        <input id="insert2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="insert" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="insertResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.isEmailAddress()</td> 
                    <td> </td> 
                    <td><input id="isEmailAddress" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="isEmailAddressResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.levenshtein()</td> 
                    <td><input id="levenshtein1" name="input" type="text" size="5" /></td> 
                    <td><input id="levenshtein" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="levenshteinResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.lpad()</td> 
                    <td> 
                        <input id="lpad1" name="input" type="text" size="5" /> 
                        <input id="lpad2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="lpad" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="lpadResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.ltrim()</td> 
                    <td> </td> 
                    <td><input id="ltrim" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="ltrimResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.nl2br()</td> 
                    <td><input id="nl2br1" name="input" type="text" size="5" /></td> 
                    <td><input id="nl2br" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="nl2brResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.overlay()</td> 
                    <td> 
                        <input id="overlay1" name="input" type="text" size="5" /> 
                        <input id="overlay2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="overlay" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="overlayResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.pad()</td> 
                    <td> 
                        <input id="pad1" name="input" type="text" size="5" /> 
                        <input id="pad2" name="input" type="text" size="5" /> 
                        <input id="pad3" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="pad" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="padResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.remove()</td> 
                    <td> 
                        <input id="remove1" name="input" type="text" size="5" /> 
                        <input id="remove2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="remove" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="removeResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.repeat()</td> 
                    <td><input id="repeat1" name="input" type="text" size="5" /></td> 
                    <td><input id="repeat" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="repeatResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.repeatChars()</td> 
                    <td><input id="repeatChars1" name="input" type="text" size="5" /></td> 
                    <td><input id="repeatChars" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="repeatCharsResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.reverse()</td> 
                    <td> 
                        <input id="reverse1" name="input" type="text" size="5" /> 
                        <input id="reverse2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="reverse" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="reverseResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.rot13()</td> 
                    <td> </td> 
                    <td><input id="rot13" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="rot13Result" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.rpad()</td> 
                    <td> 
                        <input id="rpad1" name="input" type="text" size="5" /> 
                        <input id="rpad2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="rpad" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="rpadResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.rtrim()</td> 
                    <td> </td> 
                    <td><input id="rtrim" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="rtrimResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.swap()</td> 
                    <td> </td> 
                    <td><input id="swap" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="swapResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.trim()</td> 
                    <td><input id="trim1" name="input" type="text" size="5" /></td> 
                    <td><input id="trim" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="trimResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.truncate()</td> 
                    <td> 
                        <input id="truncate1" name="input" type="text" size="5" /> 
                        <input id="truncate2" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="truncate" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="truncateResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.ucFirst()</td> 
                    <td> </td> 
                    <td><input id="ucFirst" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="ucFirstResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.ucWords()</td> 
                    <td> </td> 
                    <td><input id="ucWords" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="ucWordsResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
                <tr> 
                    <td>String.wordWrap()</td> 
                    <td> 
                        <input id="wordWrap1" name="input" type="text" size="5" /> 
                        <input id="wordWrap2" name="input" type="text" size="5" /> 
                        <input id="wordWrap3" name="input" type="text" size="5" /> 
                    </td> 
                    <td><input id="wordWrap" type="button" value="Calculate >" onclick="oTest.evaluateMethod(this, '\'' + document.getElementById('inputString').value + '\'')" /></td> 
                    <td><input id="wordWrapResult" name="output" type="text" size="30" readonly="readonly" /></td> 
                </tr> 
            </tbody> 
        </table> 
    </body> 
</html> 
 
 
            
          
     
   |     
 
 |