// ** Common javascript functions ***
// This script is included in all pages via master page Header.ascx control



// *** Constants ***
var POUND_SYMBOL = "\u00a3"; //Unicode for £

// *** Control formatting change functions ***

function ControlIsEnabled(ctl) {
//Funtion returns true/false if the control is enabled
//This is planned for use with embedded controls
	return !ctl.disabled;
}

function ChangeEnableControl(controlName, enable, removeValue) {
//Performs enable or disable depending on parameters supplied
// - Enables the named control if "enable" and "removeValue" are not supplied
// - Disables control if "enable" is false

	//Perform Disable if it has been specified then exit
	if (enable != null) {
		//Optional parameter "enable" is specified
		if (enable == false) {
			DisableControl(controlName, removeValue);
			return;
		}
	}
	
	EnableControl(controlName);
	
}

function DisableControl(controlName, removeValue) {
//Disables and optionally clears the value in the named control

	
	
	var ctl = document.getElementById(controlName);
	
	if (ctl!=null) {
	
		if (removeValue) ctl.value = "";
		
		if (ctl.type == "text")
		{
			ctl.readOnly = true;
			ctl.tabindex = 0;
		}
		else
			{ctl.disabled=true;}
			
	
		
		//Do not apply formatting to radio buttons
		if (ctl.type!="radio") {
			if (ctl.className) {
				if (ctl.className != "DisabledBox") {
					ctl.oldEnabledClassName = ctl.className;
				}
			} else {
				ctl.oldEnabledClassName="";
			}
			ctl.className = "DisabledBox";
		}
	}
}

function EnableControl(controlName) {
//Enables the specified control

	var ctl = document.getElementById(controlName);
	
	if (ctl!=null) {
	
		ctl.disabled=false;
		ctl.readOnly=false;
		
		//Do not apply formatting to radio buttons
		if (ctl.type!="radio") {
			if (ctl.className) {
				if (ctl.className != "EnabledBox") {
					if (ctl.oldEnabledClassName) {
						ctl.className = ctl.oldEnabledClassName;
					} else {
						ctl.className="EnabledBox";
					}
				}
			} else {
				ctl.className = "EnabledBox";
			}
			ctl.oldEnabledClassName = "";
		}
	}
}

function DisablePageControls()
{   
    DisablePageAnchors();
 
    // disable controls on all forms   
    if (document.all || document.getElementById)
    {
        for (i = 0; i < document.forms.length; i++)
        {
            DisableFormControls(document.forms[i]);
        }        
    }    
}


function DisableFormControls(targetForm)
{
    if (document.all || document.getElementById)
    {            
        for (i = 0; i < targetForm.length; i++)
        {
            var formElement = targetForm.elements[i];
                                                
            // We only want to disable viewable page elements. Things like viewstate should be left enabled.
            if (formElement.name.indexOf('PageContent') != -1)
            {          
                formElement.disabled = true;
            }                    
        }
    }    
}


function DisablePageAnchors()
{
    if (document.getElementsByTagName)    
	{	
	    var anchors = document.getElementsByTagName('a');
	    
	    for (var i = 0; i < anchors.length; i++)
		{
		    DisableAnchor(anchors[i]);
	    }
	}
}


function DisableAnchor(obj) {
    obj.disabled = true;
    obj.removeAttribute('href');        
}



function DisableActiveTabLinks(targetFormId)
{
    if (document.getElementsByTagName)    
	{	
	    targetForm = document.getElementById(targetFormId);
	    
	    var tds = document.getElementsByTagName('td');
	    
	    for (var i = 0; i < tds.length; i++)
		{
		    var td = tds[i];
		    
            if (td.className == 'TabActive')
            {
                td.className == 'TabInactive';
                
	            var anchors = td.getElementsByTagName('a');
	            
	            if (anchors.length > 0) 
		        {
		            anchor = anchors[0];
		            
		            // replace original anchor with a disabled copy so hidden original can submit properly
		            anchor.style.display = 'none';
		            
		            var newAnchor = document.createElement('a');
		            newAnchor.innerHTML = anchor.innerHTML;		            
		            DisableAnchor(newAnchor);
		            
		            td.appendChild(newAnchor);
		        }            
            }
	    }
	}
}

function DisableHtmlElements(elementId) {

    var disableElement = document.getElementById(elementId);

    if (disableElement) {

        var elements = disableElement.getElementsByTagName("*");

        for (i = 0; i < elements.length; i++) {

            var element = elements[i];

            // disable buttons for now. Beware! Disabling other elements e.g. select-one, will not submit their value
            if (element.type == 'button' || element.type == 'submit' || element.type == 'reset') {
                element.disabled = true;
            }

            if (element.type == 'select-one' || element.type == 'select-multiple' || element.type == 'checkbox') {
                disableHtmlElement(element);
            }	            
        }
    }
}

function disableHtmlElement(elem) {
    if (elem != null) {
        elem.onfocus = function preventFocus(e) { this.blur(); };
        elem.style.backgroundColor = '#CCCCCC';
    }
}



//****************************************


// *** Character suppression functions ***

function RemoveExcessPrecision(field, precision, maxValue){
//Removes any excess decimal places beyond the defined precision
// field : the string to be processed
// precision : the number of decimal places allowed
// maxValue : OPTIONAL - the maximum value of field

//Example use:
//<asp:TextBox id="txtFundValue" runat="server" onkeyup="RemoveExcessPrecision(this,2)">

	SuppressNonNumber(field);
	
	//Remove any excess characters after decimal place
	var decIndex = field.value.indexOf(".");
	if (decIndex != -1){
		while(decIndex < field.value.length - precision - 1){
			// delete the excess characters
			field.value = field.value.substring(0, decIndex + precision + 1);
			//re-check to capture rapid auto typing
			decIndex = field.value.indexOf(".");
		}
	};
	
	//If they exceed the max value - keep field focus (used for onBlur() events)
	if(maxValue != null && maxValue > 0){
		if(parseFloat(field.value) > maxValue){
			field.focus();
		}
	};
	
	//if 0 is the leading digit - remove it.
	while((field.value.charAt(0)=="0" && field.value.charAt(1)!=".") && field.value.length > 1){
		field.value = field.value.substring(1,field.value.length);
	};
}

function SuppressNonAlphaNumeric(field)
{
	exp = new RegExp("^([\\d\\w]*)$");
	SuppressNonRegex(field,exp);					
}
function SuppressNonPostcode(field)
{
	exp = new RegExp("^([A-Z0-9 ]*)$","i");
	SuppressNonRegex(field,exp);					
}
function SuppressNonNumber(field)
{
	exp = new RegExp("^([\\d]*[.]{0,1}[\\d]*)$");
	SuppressNonRegex(field,exp);					
}
function SuppressNonInteger(field)
{
	exp = new RegExp("^([\\d]*)$");
	SuppressNonRegex(field,exp);					
}
function SuppressNonDate(field)
{
	exp = new RegExp("^([\\d\\\/]*)$");
	SuppressNonRegex(field,exp);					
}
function SuppressNonAlphabetic(field)
{
	exp = new RegExp("^([A-Z]*)$","i");
	SuppressNonRegex(field,exp);					
}
function SuppressNonRegexCtlID(fieldID,regex) {
//gets the control identified by filedID and then calls SuppressNonRegex
	var field = document.getElementById(fieldID);
	SuppressNonRegex(field,regex);
}
function SuppressNonRegex(field,regex)
{
//Suppress any characters not matched by the regex string parameter
//Used by specific Suppress functions above, this should not be called directly from user code

	var i, sTemp, bValid = false, endChar = "";
	
	//Loop, removing invalid char from end of string until a good one is found
	while(field.value.length > 0 && !bValid){
		endChar = field.value.charAt(field.value.length-1);
		if (field.value.match(regex) == null){
			// delete the last character if it does not match the regex
			field.value = field.value.substring(0,field.value.length-1);
		}else{
			//stop checking as soon as a valid character is found
			bValid = true;
		}
	}

}
//*****************************************************


// *** String utility functions ***


function leftTrim(sString)  {
//remove leading white space
	while (sString.substring(0,1) == ' ') {
		sString = sString.substring(1, sString.length);
	}
	return sString;
}

function rightTrim(sString)  {
//remove trailing white space
	while (sString.substring(sString.length-1, sString.length) == ' ') {
		sString = sString.substring(0,sString.length-1);
	}
	return sString;
}

function trimAll(sString)  {
//remove all white space
	while (sString.substring(0,1) == ' ') {
		sString = sString.substring(1, sString.length);
	}
	while (sString.substring(sString.length-1, sString.length) == ' ') {
		sString = sString.substring(0,sString.length-1);
	}
	return sString;
}

//****************************************
//Date functions
//***************************************

function IsDate (day,month,year) 
{
    var date = new Date(year, month-1 ,day); 
    if ( (date.getFullYear() == year) && ( month == date.getMonth()+1 ) && (day == date.getDate()) )
		{return true;}
    else 
		{return false;}
} 

// AgeNextBirthday returns age next birthday based on the
// date argument, or -1 if date is invalid or in the future.
function AgeNextBirthday(dd, mm, ccyy)
{
    var age = CalculateAge(dd, mm, ccyy);
    if (age == -1) return -1;
    else return ++age;
}

// CalculateAge calculates an age in years from a given date. It returns
// -1 if the date argument is invalid or is greater than today.
function CalculateAge(dd, mm, ccyy)
{
    if (!IsDate(dd, mm, ccyy)) return -1;

    mm--;    // Javascript months are zero-based.

    var birthday = new Date(ccyy, mm, dd);

    var today = new Date();

    // Set today time to zero to be consistent with initialized birthday.
    today.setHours(0);
    today.setMinutes(0);
    today.setSeconds(0);
    today.setMilliseconds(0);

    if (birthday > today) return -1;

    var years = today.getFullYear() - birthday.getFullYear();

    /*
        Find out whether they have had their birthday yet this year. If not,
        deduct a year.

        Note that if the birthday is 29 Feb and today is 28 Feb on a non-leap year, 
        this will give us 1 March and assume they haven't had their birthday yet. 
        Since this only affects less than 0.07 percent of the population, and has 
        a 3 in 1461 chance of falling on Feb 28 in a non-leap year, we can ignore it.
    */

    birthday.setYear(today.getFullYear());

    if(today < birthday) years--;

    return years;
}

//****************************************
//general utility functions
//***************************************

function ClearField(fieldname)
{
	GetElement(ClientPrefix + fieldname).value="";
}


function HasTextEntered(textbox)
{
	if (textbox.value.length == 0)
		{return false;}
	else
		{return true;}

}

function GetElement(ID)
{
	return document.getElementById(ID);
}

function GetNumericValue(controlID)
{
	var ctlVal =  GetElement(controlID).value
	if (ctlVal == '')
		{ctlVal = 0;}
	
	return new Number(ctlVal);
	
}


function ExtractClientPrefixFromElement(field)
{
	var clientPrefix = field.id.substring(0, field.id.lastIndexOf("_")+1);
	return clientPrefix;
	
}


/**
* Get the value of a css style as computed by the browser (i.e. applied through the 'style' attribute or in a CSS class).
*/
function getStyle(element, cssRule){
    if(element){
    	var strValue = "";
    	if(document.defaultView && document.defaultView.getComputedStyle){
    	    //mozilla expects the CSS style name: font-family
    		strValue = document.defaultView.getComputedStyle(element, "").getPropertyValue(cssRule);
    	}
    	else if(element.currentStyle){
            //IE expects the style in the camel-case format: fontFamily
    		cssRule = cssRule.replace(/\-(\w)/g, function (strMatch, p1){
    			return p1.toUpperCase();
    		});
    		strValue = element.currentStyle[cssRule];
    	}
    	return strValue;
	} else {
        return null;
	}
}

/*************** MultiCastDelegate object *******************
See the Development Wiki for documentation.
*************************************************************/
function MultiCastDelegate()
{
    this.Delegates = new Array();
    this.AddDelegate = MultiCastDelegate_AddDelegate;
    this.RemoveDelegate = MultiCastDelegate_RemoveDelegate;
    this.RaiseEvent = MultiCastDelegate_RaiseEvent;
}

function MultiCastDelegate_AddDelegate(delegateFunction)
{
    this.Delegates[this.Delegates.length] = delegateFunction;
}

function MultiCastDelegate_RemoveDelegate(delegateFunction)
{
    var temp = new Array();
    for (var i = 0; i < this.Delegates.length; i++) 
		if (this.Delegates[i]!=delegateFunction) temp[temp.length] = this.Delegates[i];
	this.Delegates = temp;
}

function MultiCastDelegate_RaiseEvent(eventArgs)
{   
    for (var i = 0; i < this.Delegates.length; i++) this.Delegates[i](eventArgs);
}

function MultiCastDelegate_EventArgs(value)
{
    this.Value = value;
}
/*************** End of MultiCastDelegate object ****************/

//****************************************
//help functions
//***************************************

 function showHelp(target)
 {     
    //Open new window, containing help, passing url
    window.open(target, 'Help', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=650,height=600,left = 10,top = 10');
 }
 
 
//****************************************
//event helper functions
//***************************************

 
// append onunload event handler to event handler chain (see http://simonwillison.net/2004/May/26/addLoadEvent/)
function addOnUnloadEvent(func) {    
    var oldonunload = window.onunload;
    
    if (typeof window.onunload != 'function') {
        window.onunload = func;
    } else {
        window.onunload = function() {
            if (oldonunload) {
                oldonunload();
            }
            func();
        }
    }
}

// append onsubmit event handler to event handler chain (see http://simonwillison.net/2004/May/26/addLoadEvent/)
function addOnSubmitEvent(form, func) {    
    var oldonsubmit = form.onsubmit;
    
    if (typeof form.onsubmit != 'function') {
        form.onsubmit = func;
    } else {
        form.onsubmit = function() {
            if (oldonsubmit) {
                oldonsubmit();
            }
            func();
        }
    }
}    

//add an event listener for any type of event on any DOM node. Example call:
//  addEvent(window, 'load', function(){ alert('in window.onload event handler'); });
function addEvent(obj, evType, fn){ 
 if (obj.addEventListener){ 
   obj.addEventListener(evType, fn, false); 
   return true; 
 } else if (obj.attachEvent){ 
   var r = obj.attachEvent("on"+evType, fn); 
   return r; 
 } else { 
   return false; 
 }
}
