    /**
     * Creates an arrow for the defined size and color.
     * @param image if a image should be used else <code>null</code>
     * @param zIndex the zIndex
     * @param size the size of the arrow (width and height)
     * @param color the color of the arrow
     */
    function createArrow( image, zIndex, size, color )
    {
        if ( image )
        {
            var img = document.createElement( 'IMG' );
            img.src = image;
            img.style.position = 'absolute';
            img.style.zIndex = zIndex;

            return img;
        }

        var i, j, row, cell, img;
        var maxcols = Math.ceil( size / 2 );
        var table = document.createElement( 'TABLE' );
        table.style.position = 'absolute';
        table.style.zIndex = zIndex;
        table.cellSpacing = '0';
        table.cellPadding = '0';

        for ( i=0; i < maxcols; i++ )
        {
            createRowForArrow( table, i+1, size, color );
        }

        for ( i=maxcols; i > 0; i-- )
        {
            createRowForArrow( table, i, size, color );
        }

        return table;
    }

    /**
     * Creates a row for the arrow.
     * @param table the table
     * @param cols the number of first columns
     * @param size the size of the arrow
     * @param color the color of the arrow
     */
    function createRowForArrow( table, cols, size, color )
    {
        var row, cell;
        var maxcols = Math.ceil( size / 2 );
        row = table.insertRow( this.currentRow++ );

        if ( navigator.appName == 'Microsoft Internet Explorer' )
        {
            cell = row.insertCell( 0 );
            cell.colSpan = cols;
            cell.bgColor = color;
            cell.appendChild( createSpacer( 1, 1 ) );

            if ( maxcols - cols > 0 )
            {
                cell = row.insertCell( 1 );
                cell.colSpan = maxcols - cols;
                cell.appendChild( createSpacer( 1, 1 ) );
            }
        }
        else
        {
            var i;
            for ( i=0; i < maxcols; i++ )
            {
                cell = row.insertCell( i );
                if ( i < cols )
                {
                    cell.bgColor = color;
                }
                cell.appendChild( createSpacer( 1, 1 ) );
            }
        }
    }

   /**
    * Creates a color tone with the given start color to the end color.
    * @param startColor the start color
    * @param endColor the end color
    * @param steps the number of steps
    * @return a list of colors
    */
   function createColorTone( startColor, endColor, steps )
   {
        var ret = new Array();
        var i, currentRed, currentGreen, currentBlue, currentColor, tmp;
        var startRed = fromHex( startColor.substring( 1, 3 ) );
        var startGreen = fromHex( startColor.substring( 3, 5 ) );
        var startBlue = fromHex( startColor.substring( 5, 7 ) );
        var endRed = fromHex( endColor.substring( 1, 3 ) );
        var endGreen = fromHex( endColor.substring( 3, 5 ) );
        var endBlue = fromHex( endColor.substring( 5, 7 ) );

        var stepRed = ( endRed - startRed ) / ( steps - 1 );
        var stepGreen = ( endGreen - startGreen ) / ( steps - 1 );
        var stepBlue = ( endBlue - startBlue ) / ( steps - 1 );

        ret[0] = startColor;

        for ( i=1; i < steps; i++ )
        {
            currentRed = Math.round( startRed + stepRed * i );
            currentGreen = Math.round( startGreen + stepGreen * i );
            currentBlue = Math.round( startBlue + stepBlue * i );

            currentColor = '#' + toHex( currentRed ) + toHex( currentGreen ) + toHex( currentBlue );
            ret[i] = currentColor;
        }

        return ret;
    }

    /**
     * Creates a document element for an spacer image.
     * @param width the width
     * @param height the height
     * @return the document element
     */
    function createSpacer( width, height )
    {
        var img = document.createElement( 'IMG' );
        img.src = 'scripts/spacer.gif';
        img.width = width;
        img.height = height;
        img.border = '0';

        return img;
    }

    /**
     * Creates a table at the given position and zIndex.
     * @param x the x coordinate
     * @param y the y coordinate
     * @return the table
     **/
    function createTableAt( x, y, zIndex )
    {
        var table = document.createElement( 'TABLE' );
        table.border = '0';
        table.cellSpacing = '0';
        table.cellPadding = '0';
        table.style.position = 'absolute';
        table.style.left = x;
        table.style.top = y;
        table.style.zIndex = zIndex;

        return table;
    }

    /**
     * Converts a hexadecimal string to a decimal number.
     * @param string the hexadecimal string
     */
    function fromHex( string )
    {
        return parseInt( string, 16 );
    }

    /**
     * Returns the absolute left position of an element.
     * @param element the element
     * @return the absolute left position
     */
    function getAbsoluteLeft( element )
    {
        if ( element.offsetParent )
        {
            return element.offsetLeft + getAbsoluteLeft( element.offsetParent );
        }
        return element.offsetLeft;
    }

    /**
    * Returns the absolute top position of an element.
    * @param the element
    * @return the absolute top position
    */
    function getAbsoluteTop( element )
    {
        if ( element.offsetParent )
        {
            return element.offsetTop + getAbsoluteTop( element.offsetParent );
        }
        return element.offsetTop;
    }

    /**
     * Returns the selection start of an element.
     * @param element the element
     * @return the selection start
     */
    function getSelectionStart( element )
    {
        if ( typeof( element.selectionStart ) != 'undefined' )
        {
            return element.selectionStart;
        }
    }

    /**
     * Returns the selection end of an element.
     * @param the element
     * @return the selection end
     */
    function getSelectionEnd( element )
    {
        if ( typeof( element.selectionEnd ) != 'undefined' )
        {
            return element.selectionEnd;
        }
    }

    /**
     * Surrounds the selection with a start and a end value.
     * @param element the element
     * @param start the start value
     * @param end the end value
     */
    function surroundSelection( element, start, end )
    {
        if ( element.range )
        {
            if ( element.range.text )
            {
                element.range.text = start.replace( /\{0\}/, element.range.text ) + element.range.text + end.replace( /\{0\}/, element.range.text );
            }
            else
            {
                element.value = start.replace( /\{0\}/, element.value ) + element.value + end.replace( /\{0\}/, element.value );
            }
            element.focus();
            return;
        }
        var selection = element.value.substring( getSelectionStart( element ), getSelectionEnd( element ) );
        var text = element.value.substring( 0, getSelectionStart( element ) );
        text = text + start.replace( /\{0\}/, selection );
        text = text + selection;
        text = text + end.replace( /\{0\}/, selection );
        text = text + element.value.substring( getSelectionEnd( element ) );
        element.value = text;
        element.focus();
    }

    /**
     * Converts a decimal number to a hexadecimal.
     * @param decimal the decimal number
     * @return the hexadecimal number
     */
    function toHex( decimal )
    {
        var hex = decimal.toString( 16 ).toUpperCase();
        if ( hex.length < 2 )
        {
            hex = '0' + hex;
        }
        return hex;
    }
