
/******************************************************************************
 **********                     Logging                      **********
 ******************************************************************************/
CBLog = {
    _isOn          : false,
    _logLine       : 0,
    _logDiv        : null,
    _containerDiv  : null,
    _growDownwards : false,
    _indentLevel   : 0,
    _indentText    : "",

    log : function(msg)
    {
        if (this._logLine < 0)
            return; // logging really disabled
            
        if (this._logLine == 0)
        {
            this._containerDiv = document.getElementById('CBLogContainer');
            this._logDiv       = document.getElementById('CBLog');
        
            if ((this._logDiv == null) || (this._containerDiv == null))
            {
                this._logLine = -1; // not found, don't bother with any more logging
                return;
            }
        }

        if (this._isOn)
            this._containerDiv.style.display = "block";       // code wants us to turn on
        else if (this._containerDiv.style.display == "block") // local developer manually turned us on
            this._isOn = true;
        else
            return;

       var logEntry = '<b>' + (new String(++this._logLine)).padLeft(4,'0') + ':</b> ' + this._indentText + msg;

        if (this._growDownwards)
            this._logDiv.innerHTML = this._logDiv.innerHTML + '<br>' + logEntry;
        else
            this._logDiv.innerHTML = logEntry + '<br>' + this._logDiv.innerHTML;
    },
    
    _indentTab : "&nbsp;&nbsp;&nbsp;&nbsp;",
    
    setIndent : function(level)
    {
        if (level != null)
            this._indentLevel = level;
        
        if (this._indentLevel < 0) this._indentLevel = 0;
        
        this._indentText = '';
            
        for (var i = 0; i < this._indentLevel; i++)
        {
            this._indentText += this._indentTab;
        }
    },
    
    pushIndent : function() { this._indentLevel++; this.setIndent(); },
    popIndent  : function() { this._indentLevel--; this.setIndent(); }
}

/******************************************************************************
 **********                 String Extension Methods                 **********
 ******************************************************************************/


String.isNullOrEmpty = function(string)
{
	
	// Return true for both null and undefined.
	
	if (string == null)
	{
		return true;
	}
	else if (typeof string == "undefined")
	{
		return true
	}
	
	// Make sure we have a string object so that we can test the length
	// property.
	
	if (typeof string != "string")
	{
		string = new String(string);
	}
	
	if (string.length == 0)
	{
		return true;
	}
	
	return false;
	
};


String.prototype.trim = function()
{
	return this.replace(/^\s+/g, "").replace(/\s+$/g, "");
};


String.prototype.strip = function(string)
{
	return this.replace(string, "", "ig");
};


// Performs a case insensitive string comparison.

String.matches = function(string1, string2)
{
	if (string1.toUpperCase() == string2.toUpperCase())
	{
		return true;
	}
	else
	{
		return false;
	}
};

String.prototype.matches = function(string)
{
	return String.matches(this, string);
};


// Left pads the string with the specified character so that the string length
// equals the specified count. If a character is not provided, a space is used.

String.prototype.padLeft = function(length, character)
{
	
	if (!character)
	{
		character = " ";
	}
	
	var paddingLength = length - this.length;
	var padding = "";
	
	while (padding.length < paddingLength)
	{
		padding += character;
	}
	
	return padding + this;
	
};


/******************************************************************************
 **********                 Number Extension Methods                 **********
 ******************************************************************************/

Number.isNumber = function(value)
{
	return !isNaN(new Number(value));
};

// Converts a localized string into a number object. Except for the string
// itself, all arguments are optional.

Number.stringToNumber = function(string, decimalDivider, thousandsSeparator,
		currencyIdentifier)
{
	
	// Strip out the percentage sign. This seems to be consistent between
	// locales so we don't need it passed in.
	
	string = string.strip("%");
	
	// Strip out the currency identifier.
	
	if (!String.isNullOrEmpty(currencyIdentifier))
	{
		string = string.strip(currencyIdentifier);
	}
	
	// Strip out the thousands separator.
	
	if (!String.isNullOrEmpty(thousandsSeparator))
	{
		string = string.strip(thousandsSeparator);
	}
	
	// Normalize the decimal separator.
	
	if (!String.isNullOrEmpty(decimalDivider) && decimalDivider != ".")
	{
		string = string.replace(decimalDivider, ".")
	}
	
	// Try to convert the string to a number.
	
	var number = new Number(string);
	
	return number;
	
}


/******************************************************************************
 **********                 RegExp Extension Methods                 **********
 ******************************************************************************/

// Returns an array of substring matches. This can be used if you just want an
// array of all the matches instead of manually iterating through the regular
// expression and processing elements one at a time.

RegExp.prototype.matches = function(string)
{
	
	var matches = new Array();
	var match;
	
	while (match = this.exec(string))
	{
		matches.push(match[0]);
	}
	
	return matches;
	
};


