The current example for how to control the dirty flag for an ASPX web page with an oBout modal window is the DepartmentAttorneysEdit.aspx page in the UI Appeals folder.
The figure above shows the “DepartmentAttorneysEdit.aspx” page highlighted in blue, and the “DepartmentAttorneysEdit.js” JavaScript file is at the top of the picture.
The “DepartmentAttorneysEdit.aspx” page contains an oBout grid that displays a list of phone numbers for the attorneys.

When the user highlights a row in the grid and clicks the “Edit” button or just clicks on the “Add” button, a JavaScript method opens an oBout dialog window in either edit or add mode respectively. These two buttons use the JavaScript code:
function DisplayDialog(mode) {
if ($.SamplejQuery.dirtyFlag != 'undefined' && $.SamplejQuery.dirtyFlag == '1') {
alert('You have unsaved data on this page. You must click SAVE or CANCEL before making changes to items in the grid.'); //Customer Service Message
}
else {
if (mode == 1) { document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_lblOwTitle').innerHTML = "Add Phone Number";
document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtPhoneNumber').value = "";
document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtExt').value = "";
document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtBestTimeToCall').value = "";
if ($.SamplejQuery.dirtyFlag == '1') {
SetDirtyFlagToFalse();
}
owPhoneNumber.Open();
}
else {
if (gvwPhoneNumber.SelectedRecords.length == 0) {
//if no records are selected when the Edit button is clicked, display alert message
alert('No record selected. You must select a record from the grid in order to perform the requested action.');
return false;
}
else {
document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_lblOwTitle').innerHTML = "Edit Phone Number";
var phoneNumber = gvwPhoneNumber.SelectedRecords[0];
var phoneType = document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_ddlPhoneType');
for (var i = 0; i < phoneType.options.length; i++) {
if (phoneType.options[i].text == phoneNumber.PhoneType) {
phoneType.options[i].selected = true;
}
}
document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtPhoneNumber').value = phoneNumber.PhoneNumber;
document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtExt').value = phoneNumber.Extension;
document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtBestTimeToCall').value = phoneNumber.BestTimeToCall;
if ($.SamplejQuery.dirtyFlag == '1') {
SetDirtyFlagToFalse();
}
owPhoneNumber.Open();
}
}
}
}
Note: Be sure that the modal buttons do not have any in-line JavaScript in their “onclick” events that would interfere with the jQuery dirty flag code. For instance, notice that there are no “onclick” events for the buttons below utilized in the examples depicted above in this document.
<input id="btnSave_Phone" type="button" value="Save" class="arts_ButtonStandard" />
<input id="btnCancel_Phone" type="button" value="Cancel" class="arts_ButtonStandard" />
The programmer does not want the dialog window to open if the parent form controls have data in them changed by the user. The programmer should then add the JavaScript conditional if statement to check the dirty flag, and if it is true, then an alert message informs the user “You have unsaved data on this page. You must click SAVE or CANCEL before making changes to items in the grid.” The JavaScript for this condition is:
if ($.SamplejQuery.dirtyFlag != 'undefined' && $.SamplejQuery.dirtyFlag == '1') {
alert('You have unsaved data on this page. You must click SAVE or CANCEL before making changes to items in the grid.'); //CSM.0036
}
else {
The “if” conditional statement prevents the modal form from opening by displaying a modal JavaScript alert with the message and only an “OK” button:

If the dirty flag is false, then the JavaScript code runs that opens and populates the form with data to edit or a blank form for adding a new phone number. Notice in the code added below that the programmer has set the dirty flag to false after the form is populated:
if ($.SamplejQuery.dirtyFlag == '1') {
SetDirtyFlagToFalse();
If the user enters or changes data on the modal form and saves the data, the programmer set the dirty flag to false before going back to the parent ASPX form. If the user cancels the form input, and hits the cancel button, the programmer must also set the dirty flag to false before returning to the parent form. Why? The oBout window is on the parent form, and they must share the same form dirty flag. There is only one dirty flag per form, and if a parent form opens an oBout dialog window, then the dirty flag must be set to false for new user input. The code below handles user saves and cancels, and this must be added to the form JavaScript file:
$(document).ready(function() { $("input:button:[id*='Save_Phone']").click(function() {
SavePhoneNumber();
});
$("input:button:[id*='Cancel_Phone']").click(function(e) {
if (!e.isPropagationStopped())
CancelDialog();
});
});
If the user clicks the “btnSave_Phone” button, then the “SavePhoneNumber()” JavaScript method runs. If the user clicks the “btnCancel_Phone” form button, then the JavaScript “CancelDialog()” method will run if the flag is not dirty. If the flag is dirty, then the user will be presented with the JavaScript confirm message box that informs them that the form is dirty, and they have choice of leaving the page by hitting “OK” or remain on the page by hitting “Cancel”:

If the user saves the data or cancels the changes on the modal form, the programmer must add the code to set the dirty flag to false in the appropriate form JavaScript file methods. For example:
function SavePhoneNumber() {
var phoneNumber = new Object();
var validation = ValidatePhoneType();
if (validation == true) {
var title = document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_lblOwTitle').innerHTML;
var mode = title.substring(0, 3);
phoneNumber.PhoneType = document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_ddlPhoneType').value;
phoneNumber.PhoneNumber = document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtPhoneNumber').value;
phoneNumber.PhoneExt = document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtExt').value;
phoneNumber.BestTimeToCall = document.getElementById('ctl00_ContentPlaceHolder1_owPhoneNumber_txtBestTimeToCall').value;
if ($.SamplejQuery.dirtyFlag == '1') {
SetDirtyFlagToFalse();
}
The jQuery code method “SetDirtyFlagToFalse()” sets the dirty flag back to false before returning to the parent page.
The programmer may add the dirty flag “SetDirtyFlagToFalse()” and ““ResetDirtyFlag()” methods to code-behind form logic as well by using the below methodology:
ClientScript.RegisterStartupScript(this.GetType(), "ResetDirtyFlagScript", "<script language=JavaScript>ResetDirtyFlag();</script>");
The developer should remember that the following code is in the BasePage base class that the page code-behind is derived from. If the page is not derived from the BasePage base class, then the following code must be added to the page code-behind aspx.cs file.
//---------------------------------------------------------------------------
/// <summary>
/// Method Name: AddDirtyFlag
/// Description: This method adds dirty flag functionality to any page that derives
/// from this class.
/// </summary>
//---------------------------------------------------------------------------
private void AddDirtyFlag() {
var sb = new StringBuilder(); // Check to see if the include script exists already.
if (!this.Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "jQueryLink")) {
sb.Append(" <script src=\""); sb.Append(ResolveClientUrl(JQUERYURL));
sb.Append("\" type=\"text/javascript\"></script>"); this.Page.ClientScript.RegisterStartupScript(this.GetType(), "jQueryLink", sb.ToString()); }
sb.Length = 0;
if (!this.Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "DirtyFlagLink")) {
sb.Append(" <script src=\""); sb.Append(ResolveClientUrl(DIRTYFLAGJSCODEURL));
sb.Append("\" type=\"text/javascript\"></script>"); this.Page.ClientScript.RegisterStartupScript(this.GetType(), "DirtyFlagLink", sb.ToString()); }
sb.Length = 0;
if (BypassDirtyControls != null && BypassDirtyControls.Count > 0) {
sb.Append("<script type=\"text/javascript\" language=\"javascript\">"); sb.Append("$(window).load(function() {"); sb.Append("setDirtyFlagAttribute([\""); sb.Append(String.Join("\",\"", BypassDirtyControls.ToArray())); sb.Append("\"])"); sb.Append("} );"); sb.Append("</script>"); }
if (!this.Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "ByPassDirtyFlagList")) {
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "ByPassDirtyFlagList", sb.ToString()); }
//Reset the dirty flag on postback
if (IsPostBack) {
Control postbackControl = DHS.AppBase.Global.GetPostBackControl(this.Page); if (postbackControl == null || postbackControl.ID == null) {
return; }
else
{
if (postbackControl.GetType().ToString() != "System.Web.UI.WebControls.Button" && postbackControl.GetType().ToString() != "System.Web.UI.WebControls.LinkButton" && !IsControlInDirtyBypassList(postbackControl.ClientID.ToString()))
{
if (!this.Page.ClientScript.IsStartupScriptRegistered("ResetSetDirtyFlag")) {
string jScript = string.Empty; jScript = @"<script language='javascript' type='text/javascript'> if (typeof ($.DHSJQuery.dirtyFlag) != 'undefined')
{
$.DHSJQuery.dirtyFlag = 1;
}
</script>"; this.Page.ClientScript.RegisterStartupScript(this.GetType(), "ResetSetDirtyFlag", jScript); }
}
if (postbackControl.ID.ToUpper().Contains("SAVE")) {
if (!this.Page.ClientScript.IsStartupScriptRegistered("SaveButtonClicked")) {
string jScript = string.Empty; jScript = @"<script language='javascript' type='text/javascript'> if (typeof ($.DHSJQuery.SaveClicked) != 'undefined')
{
$.DHSJQuery.SaveClicked = 1;
}
</script>"; this.Page.ClientScript.RegisterStartupScript(this.GetType(), "SaveButtonClicked", jScript); }
}
}
}
}
//---------------------------------------------------------------------------
/// <summary>
/// Method Name: IsControlInDirtyBypassList
/// Description: Method that checks to see if the control that caused
/// a postback exists in the bypass dirty flag list.
/// </summary>
///
/// <param name="ctrlName">The name of the control that caused the postback</param>
/// <returns>boolean</returns>
//---------------------------------------------------------------------------
private bool IsControlInDirtyBypassList(string ctrlName) {
bool retVal = false; if (BypassDirtyControls != null) {
if (BypassDirtyControls.Contains(ctrlName)) {
retVal = true; }
}
return retVal; }
//---------------------------------------------------------------------------
/// <summary>
/// Method Name: AddDefaultJavascript
/// Description: This method adds JavaScript code and includes to any page that derives
/// from this class. Also Adds a client postback variable to determine if
/// a postback has occurred.
/// </summary>
//---------------------------------------------------------------------------
private void AddDefaultJavascript() {
var sb = new StringBuilder(); sb.Append("<script type=\"text/javascript\" language=\"javascript\">"); sb.Append("function addListener(obj, evt, handler) {"); sb.Append("if (obj.addEventListener) {"); sb.Append("obj.addEventListener(evt, handler, false);"); sb.Append("}else if (obj.attachEvent) {"); sb.Append("obj.attachEvent('on' + evt, handler);}}"); sb.Append("</script>"); if (!this.Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "AddListener")) {
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "AddListener", sb.ToString()); }
sb.Length = 0;
if (!IsPostBack) {
sb.Append("<script type=\"text/javascript\" language=\"javascript\">"); sb.Append("var isPostBack = false;"); sb.Append("</script>"); }
else
{
sb.Append("<script type=\"text/javascript\" language=\"javascript\">"); sb.Append("var isPostBack = true;"); sb.Append("</script>"); }
if (!this.Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "ClientPostBack")) {
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "ClientPostBack", sb.ToString()); }
sb.Length = 0;
// Check to see if the include script exists already.
if (!this.Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "jQueryLink")) {
sb.Append(" <script src=\""); sb.Append(ResolveClientUrl(JQUERYURL));
sb.Append("\" type=\"text/javascript\"></script>"); this.Page.ClientScript.RegisterStartupScript(this.GetType(), "jQueryLink", sb.ToString()); }
Also, if the page code-behind aspx.cs file is not derived from the base class BasePage, then the following code must be added to the page load event:
//---------------------------------------------------------------------------
/// <summary>
/// Method Name: Page_Load
/// Description: During load, if the current request is a postback, control
/// properties are loaded with information recovered from view state and control state.
/// Use the OnLoad event method to set properties in controls and establish database connections.
/// </summary>
///
/// <param name="sender">sender object</param>
/// <param name="e">EventArgs</param>
//---------------------------------------------------------------------------
protected void Page_Load(object sender, EventArgs e) {
AddDefaultJavascript();
SetModalPageFlag();
if (AllowDirtyFlag) {
AddDirtyFlag();
} }