/*

  Discard Changes Confirmation Script

  APECS .NET
  Issue #10838
  MDG


  REVISION HISTORY:

  Created: 2004.02.18
  Updated: 2004.02.21 - Implemented exclusions
                      - Script now works for WebControls
  Updated: 2004.02.23 - Controls with "onchangeConfirmDiscard" or "onclickConfirmDiscard" set to "true"
                        are automatically considered as excluded.
  Updated: 2004.02.26 - Included support for link (anchor) objects.
  Updated: 2004.02.27 - Included support for returning the return value of the original event handler functions. 
  Updated: 2004.03.04 - Corrected conditions for automatic exclusions (as implemented on 2004.02.23).
  Updated: 2004.03.11 - Added new function for logout to trigger the discard changes window.
  Updated: 2004.03.17 - Corrected code for returning "boolean" return values of the original event handler functions.


  INSTRUCTIONS:

  1. A hidden field with an ID set to "hfModified" must exist on the ASPX page.

     Example:

       <input id="hfModified" type="hidden">

  2. Include this script file on the ASPX page.

     Example:

       <script language="JavaScript" src="/js/discard_changes.js"></script>

  3. Add the "uf_InitializeConfirmDiscard()" function in the "onload" event of the BODY tag.

     Example:

	   <body onload="uf_InitializeConfirmDiscard();">

  4. For each control that needs to display the confirmation prompt before executing the "onclick" event,
     add an "onclickConfirmDiscard" attribute and set it to "true".

     Example:

       <input type="button" id="btClear" value="Clear" onclick="uf_Clear();" onclickConfirmDiscard="true">

  5. For each control that needs to display the confirmation prompt before executing the "onchange" event,
     add an "onchangeConfirmDiscard" attribute and set it to "true".

     Example:

       <select id="ddlbSelectTable" onchange="uf_SelectTableChange();" onchangeConfirmDiscard="true">

  6. After executing a server-side function that "successfully" saves or resets changes in the form fields,
     the JavaScript function "uf_ResetModifiedFlag()" must be also be executed to set back the Modified flag
     to "false". In calling this function, "RegisterStartupScript" must be used and not "Response.Write".
     "Response.Write" will not work and will even cause an error because it would call the function even
     before the script is written on the page.

     Example:

       RegisterStartupScript("ResetModifiedFlag", "<script language='JavaScript'>uf_ResetModifiedFlag();</script>")

     A better alternative is to encapsulate the code above in a server-side function to make the code more
     readable and easier to use.

     Example:

       Sub uf_ResetModifiedFlag()
	     RegisterStartupScript("ResetModifiedFlag", "<script language='JavaScript'>uf_ResetModifiedFlag();</script>")
       End Sub

  7. (NEW FEATURE: 2004.02.21)

     For each control that should not be monitored for changes, add an "excludeonConfirmDiscard" attribute and set it
     to "true". Controls with the "onclickConfirmDiscard" or "onchangeConfirmDiscard" attribute set to true are
     automatically considered as excluded so the "excludeonConfirmDiscard" attribute no longer needs to be set.

     Example:

       <input type="text" id="txtSearch" excludeonConfirmDiscard="true">


  IMPORTANT NOTES:

  1. Instructions 1, 2, & 3 can be implemented on a base page. Instructions 4, 5, 6, & 7 should be implemented on
     each page that requires this script. The server-side function suggested on Instruction 6 can be written
     on the base page and referenced on the corresponding descendant pages.

  2. Choosing "Cancel" in the "Discard Changes?" prompt of a SELECT object (drop-down or multi-select list box)
     automatically resets the selection to the previously selected item (before the change was triggered).

  3. The attribute "prevIndex" is reserved for all SELECT objects that will use this script. This attribute must
     not be used for any other purpose.

  4. Since JavaScript is case-sensitive, please make sure that the attribute names are coded exactly as stated above.
  
*/



function uf_InitializeConfirmDiscard() {
    uf_SetModifyEventHandler();
    uf_SetConfirmEventHandler();
}

function uf_SetModifyEventHandler() {
	var llFormLength = document.forms.length;

	for(intCtr=0; intCtr<llFormLength; intCtr++)
	{
		formValue = document.forms[intCtr];
		var llEleLength = formValue.elements.length;

        for(intCtr2=0;intCtr2<llEleLength;intCtr2++)
        {
			objElem = formValue.elements[intCtr2];
            objType = objElem.type.toLowerCase();

			if (objElem.getAttribute("excludeonConfirmDiscard")) {
				if (objElem.getAttribute("excludeonConfirmDiscard").toLowerCase() == "true") continue;
			} else if (objElem.getAttribute("onchangeConfirmDiscard")) {
				if (objElem.getAttribute("onchangeConfirmDiscard").toLowerCase() == "true") continue;
			} else if (objElem.getAttribute("onclickConfirmDiscard")) {
				if (objElem.getAttribute("onclickConfirmDiscard").toLowerCase() == "true") continue;
			}

            if (objType!="button" && objType!="hidden" && objType!="submit" &&
                objType!="reset"  && objType!="password")
            {
				if (objType=="checkbox" || objType=="radio") {
					if (objElem.onclick) objElem.onclickBeforeModify = objElem.onclick;
					objElem.onclick = uf_ModifyEventHandler;
				} else {
					if (objElem.onchange) objElem.onchangeBeforeModify = objElem.onchange;
					objElem.onchange = uf_ModifyEventHandler;
				}
            }
        }
    }
}

function uf_ModifyEventHandler() {
	if (this.type=="checkbox" || this.type=="radio") {
		if (this.onclickBeforeModify) this.onclickBeforeModify();
	} else {
		if (this.onchangeBeforeModify) this.onchangeBeforeModify();
	}
	uf_SetModifiedFlag();
}

function uf_SetConfirmEventHandler() {
	var llFormLength = document.forms.length;
	var llLinkLength = document.links.length;

	for(intCtr=0; intCtr<llFormLength; intCtr++)
	{
		formValue = document.forms[intCtr];
		var llEleLength = formValue.elements.length;

        for(intCtr2=0;intCtr2<llEleLength;intCtr2++)
        {
            objElem = formValue.elements[intCtr2];
            if (objElem.getAttribute("onclickConfirmDiscard")) {
				if (objElem.getAttribute("onclickConfirmDiscard").toLowerCase() == "true") {
					if (objElem.onclick) objElem.onclickBeforeConfirm = objElem.onclick;
					objElem.onclick = uf_ConfirmDiscardOnClick;
				}
			}
            if (objElem.getAttribute("onchangeConfirmDiscard")) {
				if (objElem.getAttribute("onchangeConfirmDiscard").toLowerCase() == "true") {
					if (objElem.onclick) objElem.onclickBeforeSaveValue = objElem.onclick;
					objElem.onclick = uf_SaveValueOnClick;
					if (objElem.onchange) objElem.onchangeBeforeConfirm = objElem.onchange;
					objElem.onchange = uf_ConfirmDiscardOnChange;
				}
            }
        }
    }
    
	for(intCtr=0; intCtr<llLinkLength; intCtr++)
	{
		objElem = document.links[intCtr];
        if (objElem.getAttribute("onclickConfirmDiscard")) {
			if (objElem.getAttribute("onclickConfirmDiscard").toLowerCase() == "true") {
				if (objElem.onclick) objElem.onclickBeforeConfirm = objElem.onclick;
				objElem.onclick = uf_ConfirmDiscardOnClick;
			}
		}
	}
}

function uf_SaveValueOnClick() {
	if (this.type.substr(0,6).toLowerCase() == "select") {
		this.setAttribute("prevIndex", this.selectedIndex);
	}
	if (this.onclickBeforeSaveValue) return this.onclickBeforeSaveValue();
}

function uf_ConfirmDiscardOnClick() {
	var lbReturnVal;
	if (uf_IsModified()) {
		if ( confirm("Discard changes?") ) {
			// commented-out: MDG 03/17/2004 - Issue #10858 //
			//if (this.onclickBeforeConfirm) lbReturnVal = this.onclickBeforeConfirm();
			// new code: MDG 03/17/2004 - Issue #10858 //
			if (this.onclickBeforeConfirm) lbReturnVal = (this.onclickBeforeConfirm());
			uf_ResetModifiedFlag();
		} else {
			return false;
		}
	} else {
		// commented-out: MDG 03/17/2004 - Issue #10858 //
		//if (this.onclickBeforeConfirm) lbReturnVal = this.onclickBeforeConfirm();
		// new code: MDG 03/17/2004 - Issue #10858 //
		if (this.onclickBeforeConfirm) lbReturnVal = (this.onclickBeforeConfirm());
	}
	return lbReturnVal;
}

//GVS - 03/11/2004 - function for logout to trigger the discard changes window
function uf_CallDiscardOnClick() {	
	if (uf_IsModified()) {
		if ( confirm("Discard changes?") ) {			
			return true;
		} else {
			return false;
		}	
	}
	return true;
}

function uf_ConfirmDiscardOnChange() {
	var lbReturnVal;
	if (uf_IsModified()) {
		if ( confirm("Discard changes?") ) {
			if (this.onchangeBeforeConfirm) lbReturnVal = this.onchangeBeforeConfirm();
			uf_ResetModifiedFlag();
		} else if (this.type.substr(0,6).toLowerCase() == "select") {
			this.selectedIndex = this.getAttribute("prevIndex");
			return false;
		}
	} else {
		if (this.onchangeBeforeConfirm) lbReturnVal = this.onchangeBeforeConfirm();
	}
	return lbReturnVal;
}

function uf_IsModified() {
	if (document.getElementById("hfModified")) {
		if (document.getElementById("hfModified").value.toLowerCase() != "false"
		 && document.getElementById("hfModified").value.toLowerCase() != "true") {
			document.getElementById("hfModified").value = "false";
		}
		if (document.getElementById("hfModified").value.toLowerCase() == "true") {
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}	
}

function uf_ResetModifiedFlag() {
	if (document.getElementById("hfModified")) {
		document.getElementById("hfModified").value = "false";
	}
}

function uf_SetModifiedFlag() {
	if (document.getElementById("hfModified")) {
		document.getElementById("hfModified").value = "true";
	}
}