
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
}

String.prototype.ltrim = function() {
	return this.replace(/^\s+/,"");
}

String.prototype.rtrim = function() {
	return this.replace(/\s+$/,"");
}

Number.prototype.PadDigits = function PadDigits(totalDigits) 
{ 
    var str = this.toString();
    var pd = '';
    
    if (totalDigits > str.length)
    {
        for (i=0; i < (totalDigits - str.length); i++)
        {
            pd += '0';
        }
    }
    return pd + this.toString();
} 

function IsNav() {
    return (navigator.appName == "Netscape")
}

function IsOpera()
{
    return (navigator.appName == "Opera")
}

function IsFirefox()
{
    var re = new RegExp("Safari", "i");
    if (navigator.appName == "Netscape")
    {
        if (re.test(navigator.appVersion)) {return false;}
        else {return true;}
    }
    else {return false;}
}

function IsSafari()
{
    var re = new RegExp("Safari", "i");
    if (navigator.appName == "Netscape" && re.test(navigator.appVersion)) {return true;}
}

function IsIE() {
    return (navigator.appName == "Microsoft Internet Explorer")
}

function IsIE7Above()
{
    try
    {
        if (IsIE())
        {
            var s = navigator.appVersion;
            var pos1 = s.indexOf("MSIE");
            var pos2 = s.indexOf(";", pos1);
            var sVer = s.substring(pos1 + ("MSIE ".length), pos2);
            
            var iBeta = s.search(/[a-z]|[A-Z]/);
            if (iBeta != -1) {sVer = sVer.substring(0, iBeta);}
            
            if (sVer == "7.0" || parseFloat(sVer) >= 7.0) {return true;}
            else {return false;}
        }
        else {return false;}
    }
    catch (err) {return false;}
}

function GetFramedWindowWidthAdjusted()
{
    try
    {
        var sDialogLeft = window.dialogLeft;
        var iDialogLeft = parseInt(sDialogLeft.substring(0, sDialogLeft.indexOf("px")));
        var sDialogWidth = window.dialogWidth;
        var iDialogWidth = parseInt(sDialogWidth.substring(0, sDialogWidth.indexOf("px")));
        return ( iDialogWidth + ((window.screenLeft - iDialogLeft) * 2) );
    }
    catch (err) {return 6;}
}

function GetFramedWindowHeightAdjusted()
{
    try
    {
        var sDialogTop = window.dialogTop;
        var iDialogTop = parseInt(sDialogTop.substring(0, sDialogTop.indexOf("px")));
        var sDialogLeft = window.dialogLeft;
        var iDialogLeft = parseInt(sDialogLeft.substring(0, sDialogLeft.indexOf("px")));
        var sDialogHeight = window.dialogHeight;
        var iDialogHeight = parseInt(sDialogHeight.substring(0, sDialogHeight.indexOf("px")));
        return ( iDialogHeight + (window.screenTop - iDialogTop) + (window.screenLeft - iDialogLeft) );
    }
    catch (err) {return 28;}
}

function BambooAppUINonFatalErrorLog(oAppMainWindow, err)
{
    if (oAppMainWindow.IsDebugMsgAlerted)
    {
        alert(err);
    }
}

function GetShortFullDatetimeString(date)
{
    return (date.getFullYear() + "/" + (date.getMonth()+1).PadDigits(2) + "/" + date.getDate().PadDigits(2) + " " + date.getHours().PadDigits(2) + ":" + date.getMinutes().PadDigits(2) + ":" + date.getSeconds().PadDigits(2));
}

function GetShortFullDateString(date)
{
    return (date.getFullYear() + "/" + (date.getMonth()+1).PadDigits(2) + "/" + date.getDate().PadDigits(2));
}

function GetPixelNumberFromExpression(strPX)
{
    return new Number(strPX.replace(new RegExp("px"), ""));
}

function GetFloatFromExpression(strPercent)
{
    var a = new Number(strPercent.replace(new RegExp("%"), ""));
    return (a / 100.0);
}

function GetTruthValue(str)
{
    switch (str.toLowerCase().trim())
    {
        case "yes":
        case "true":
        case "t":
        case "y":
            return true;
            break;
        default:
            return false;
            break;
    }
}

function PrepareRegExWithEscapeChars(str)
{
    var sRtn = str.replace(/\\/g, "\\\\");
    sRtn = sRtn.replace(/\$/g, "\\$");
    sRtn = sRtn.replace(/\(/g, "\\(");
    sRtn = sRtn.replace(/\)/g, "\\)");
    sRtn = sRtn.replace(/\*/g, "\\*");
    sRtn = sRtn.replace(/\+/g, "\\+");
    sRtn = sRtn.replace(/\./g, "\\.");
    sRtn = sRtn.replace(/\[/g, "\\[");
    sRtn = sRtn.replace(/\]/g, "\\]");
    sRtn = sRtn.replace(/\?/g, "\\?");
    sRtn = sRtn.replace(/\//g, "\\/");
    sRtn = sRtn.replace(/\^/g, "\\^");
    sRtn = sRtn.replace(/\{/g, "\\{");
    sRtn = sRtn.replace(/\}/g, "\\}");
    sRtn = sRtn.replace(/\|/g, "\\|");
    return new RegExp(sRtn);
}

function EscapeHtml(str)
{
   var div = document.createElement('div');
   var text = document.createTextNode(str);
   div.appendChild(text);
   return div.innerHTML;
} 

function GetOptimalPhaseStep(MaxLength, SteppingFactor, MaxNoOfSteps, MinNoOfSteps)
{
    // don't know where this 45 comes from, nor what the following remark means, just copied it from Apple web site
	//var steps = Math.round(MaxLength / 45); // duration / 5.0;
	var steps = Math.round(MaxLength / SteppingFactor);
	steps = (steps > MaxNoOfSteps ? MaxNoOfSteps : (steps < MinNoOfSteps ? MinNoOfSteps : steps));
	var dPhaseAngle = Math.PI / steps;
	return dPhaseAngle;
}

function CriticallyDampedStreching(oPanel, startHeight, endHeight, deltaPhaseAngle, currentPhaseAngle, msTimeStep, postCall)
{
	currentPhaseAngle += deltaPhaseAngle;
	if(currentPhaseAngle > Math.PI) {currentPhaseAngle = Math.PI;}
	var dh =  (endHeight - startHeight) * (1.0 - Math.pow( (1.0 + Math.cos(currentPhaseAngle)) / 2.0, 2));
	var newH = startHeight + dh;

	newH = Math.round(newH > endHeight && endHeight > startHeight ? endHeight : (newH < endHeight && endHeight < startHeight ? startHeight : newH));
	newH = (newH > 0 ? newH : 0);
	oPanel.style.pixelHeight = newH;
	
	if(endHeight == 0 && newH == 0)
	{
		oPanel.style.display = "none";
	}
	
	
	if(currentPhaseAngle >= Math.PI) {
		if(postCall) window.setTimeout(postCall, msTimeStep);
		return;
	}

	window.setTimeout(function() { CriticallyDampedStreching(oPanel, startHeight, endHeight, deltaPhaseAngle, currentPhaseAngle, msTimeStep, postCall); }, msTimeStep);
}

// NOTE: this function has a problematic effect when some underlying container layer(s) has smaller screen clip size than its content size
// it would cause "unwanted" vertical or even horizontal scrolling of those underlying layer(s), unpredictably
// so this must be used with care.  namely, the content size (e.g. img); overflowing; and scrolling behaviour of container layer(s).
// however, this function is currently UN-USED since element.focus() method could automatically do the same scrolling w/o such ill-effect.
function VerticallyScrollSelectedEntryIntoView(oDomEntry, oDomScrollViewPanel)
{
    var posType = 0;
    
    if ( (oDomEntry.offsetTop + oDomEntry.offsetHeight) < oDomScrollViewPanel.scrollTop )
    {
        posType = ScrollViewVertPosType.HIDDEN_ABOVE;
    }
    else if ( oDomEntry.offsetTop < oDomScrollViewPanel.scrollTop && 
                (oDomEntry.offsetTop + oDomEntry.offsetHeight) > oDomScrollViewPanel.scrollTop )
    {
        posType = ScrollViewVertPosType.PARTIALLY_HIDDEN_ABOVE;
    }
    else if  ( oDomEntry.offsetTop > oDomScrollViewPanel.scrollTop && 
                (oDomEntry.offsetTop + oDomEntry.offsetHeight) > oDomScrollViewPanel.scrollTop &&
                (oDomEntry.offsetTop + oDomEntry.offsetHeight) < (oDomScrollViewPanel.scrollTop + oDomScrollViewPanel.offsetHeight) )
    {
        posType = ScrollViewVertPosType.VISIBLE;
    }
    else if ( oDomEntry.offsetTop < (oDomScrollViewPanel.scrollTop + oDomScrollViewPanel.offsetHeight) && 
                (oDomEntry.offsetTop + oDomEntry.offsetHeight) > (oDomScrollViewPanel.scrollTop + oDomScrollViewPanel.offsetHeight) )
    {
        posType = ScrollViewVertPosType.PARTIALLY_HIDDEN_BELOW;
    }
    else if ( oDomEntry.offsetTop > (oDomScrollViewPanel.scrollTop + oDomScrollViewPanel.offsetHeight))
    {
        posType = ScrollViewVertPosType.HIDDEN_BELOW;
    }
    
    switch (posType)
    {
        case ScrollViewVertPosType.HIDDEN_ABOVE:
            oDomEntry.scrollIntoView(true);
            break;
        case ScrollViewVertPosType.PARTIALLY_HIDDEN_ABOVE:
            oDomEntry.scrollIntoView(true);
            break;
        case ScrollViewVertPosType.VISIBLE:
            break;
        case ScrollViewVertPosType.PARTIALLY_HIDDEN_BELOW:
            oDomEntry.scrollIntoView(false);
            break;
        case ScrollViewVertPosType.HIDDEN_BELOW:
            oDomEntry.scrollIntoView(false);
            break;
        default:
            break;
    }

}

function GetPageDownNewSelectedIndex(currentSelectedIndex, arrDomEntries, oDomScrollViewPanel)
{
    if (currentSelectedIndex >= (arrDomEntries.length-1))  // currently selected item is already at the end of list
    {
        return currentSelectedIndex;
    }
    // currently selected item is within (or above) the scroll view
    else if (arrDomEntries[currentSelectedIndex+1].offsetTop < (oDomScrollViewPanel.scrollTop + oDomScrollViewPanel.offsetHeight) )
    {
        // loop until the very last item within the scroll view (including partially show items), and return it
        var i = currentSelectedIndex;
        while ( ((i+1) < arrDomEntries.length) && (arrDomEntries[i+1].offsetTop < (oDomScrollViewPanel.scrollTop + oDomScrollViewPanel.offsetHeight)) )
        {
            i++;
        }
        return i;
    }
    // currently selected item just at the end of the scroll view
    else
    {
        // loop for a page (i.e. loop for item bottom until it just make it <= another offsetHeight)
        var i = currentSelectedIndex;
        while ( ((i+1) < arrDomEntries.length) && (arrDomEntries[i+1].offsetTop < (oDomScrollViewPanel.scrollTop + 2*oDomScrollViewPanel.offsetHeight)) )
        {
            i++;
        }
        return i;
    }
}

function GetPageUpNewSelectedIndex(currentSelectedIndex, arrDomEntries, oDomScrollViewPanel)
{
    if (currentSelectedIndex <= 0)  // currently selected item is already at the top of list
    {
        return currentSelectedIndex;
    }
    // currently selected item is within (or below) the scroll view
    else if ( (arrDomEntries[currentSelectedIndex-1].offsetTop + arrDomEntries[currentSelectedIndex-1].offsetHeight) > oDomScrollViewPanel.scrollTop)
    {
        // loop until the very first item within the scroll view (including partially show items), and return it
        var i = currentSelectedIndex;
        while ( ((i-1) >= 0) && ((arrDomEntries[i-1].offsetTop + arrDomEntries[currentSelectedIndex-1].offsetHeight) > oDomScrollViewPanel.scrollTop) )
        {
            i--;
        }
        return i;
    }
    // currently selected item just at the top of the scroll view
    else
    {
        // loop for a page (i.e. loop for item top until it just make it <= another offsetHeight)
        var i = currentSelectedIndex;
        while ( ((i-1) >= 0) && ((arrDomEntries[i-1].offsetTop + arrDomEntries[currentSelectedIndex-1].offsetHeight) > (oDomScrollViewPanel.scrollTop - oDomScrollViewPanel.offsetHeight)) )
        {
            i--;
        }
        return i;
    }
}

function GetRandomDialogLeft(PixelWidth)
{
    return Math.round(Math.random() * (window.screen.availWidth - PixelWidth));
}

function GetRandomDialogTop(PixelHeight)
{
    return Math.round(Math.random() * (window.screen.availHeight - PixelHeight));
}

function GetCenteredDialogLeft(PixelWidth)
{
    return Math.round((window.screen.availWidth - PixelWidth) / 2);
}

function GetCenteredDialogTop(PixelHeight)
{
    return Math.round((window.screen.availHeight - PixelHeight) / 2);
}

