We all use JS functionality handlers that will trigger for different attached DataGrid events.
More frequent JS handlers are:
Mouse Over, Mouse Out,
On Click,
On Double Click,
Validate (for different grid buttons),
Check client Is Dirty flag
And other...
Here is what I did in order to write it in once:
Server Side:
I wrote a method that should be called from the ItemCreatedCommand event handler. Its purpose is to attach the grid current row to the different JS event handlers. The method gets the grid client ID. This will be use in the client side JS as parameter to the different client side functions. This will enable us, to use single copy of JS functions that will be use by all the Grids within the page.
private void GridOnItemCreated(object sender,
System.Web.UI.WebControls.DataGridItemEventArgs e, string gridClientID)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) //handle the items that not in edit mode
{
//get the type of the row - regular or alternate
string sIsAlternate = (e.Item.ItemType == ListItemType.Item?"false":"true");
//Attach to each grid row the events - onclick, onmouseover, onmouseout
e.Item.Attributes.Add("onclick","OnRowClicked('" + gridClientID + "',this," + sIsAlternate + ");");
//Attach on mouse over event to each grid row
e.Item.Attributes.Add("onmouseover","OnRowOver('" + gridClientID + "',this," + sIsAlternate + ");");
//Attach on mouse over event to each grid row
e.Item.Attributes.Add("onmouseout","OnRowOut('" + gridClientID + "',this," + sIsAlternate + ");");
}
//if its footer - hide it (only when we use a custom stand alone pager control)
if (e.Item.ItemType == ListItemType.Footer)
e.Item.Visible = false;
if (e.Item.ItemType == ListItemType.Pager)
e.Item.Visible = false;
}
The JS functionality is:
First - we need to initialize an array (at the page level) of Marked Grid Row records that will be use to keep the last Marked (pressed by the user) row.
Each Marked Row record contains the Row object itself and indication if it’s alternating row or regular row - this is helpful when we use different ALTERNATINGITEMSTYLE and ALTERNATINGITEMSTYLE layouts
JS Marked Row global array definition:
//set global array - each entry represent a grid in the screen
var oGridsMarkTr = new Array(2);
oGridsMarkTr["dgGridAnother"]=GetGridMarkedTrRecord();
oGridsMarkTr["dgGridBilling"]=GetGridMarkedTrRecord();
function GetGridMarkedTrRecord()
{
this.SelectedRow = null;
this.IsAlternate = false;
return this;
}
We will use this array within the other JS handlers as follow -
//------------------------------------------------------
function OnRowClicked(sGridID, oRow, isAlternate)
{
if (typeof(oGridsMarkTr) == "undefined" || oGridsMarkTr==null || typeof(oGridsMarkTr[sGridID])=="undefined")
return true;
//change the style while the user select item
if (oGridsMarkTr[sGridID].SelectedRow!=null)
{
if (oGridsMarkTr[sGridID].IsAlternate)
oGridsMarkTr[sGridID].SelectedRow.className = 'AlternatingItemTable';
else
oGridsMarkTr[sGridID].SelectedRow.className = 'ItemTable';
}
oRow.className = 'SelectedItemTable';
oGridsMarkTr[sGridID].SelectedRow = oRow;
oGridsMarkTr[sGridID].IsAlternate = isAlternate;
return true;
}
//------------------------------------------------------
function OnRowOver(sGridID, oRow, isAlternate)
{
if (typeof(oGridsMarkTr) == "undefined" || oGridsMarkTr==null || typeof(oGridsMarkTr[sGridID])=="undefined")
return true;
if (oGridsMarkTr[sGridID].SelectedRow!=oRow)
oRow.className = "OverItemTable";
}
//------------------------------------------------------
function OnRowOut(sGridID, oRow, isAlternate)
{
if (typeof(oGridsMarkTr) == "undefined" || oGridsMarkTr==null || typeof(oGridsMarkTr[sGridID])=="undefined")
return true;
if (oGridsMarkTr[sGridID].SelectedRow!=null && oGridsMarkTr[sGridID].SelectedRow==oRow)
return true;
if (isAlternate)
oRow.className = "AlternatingItemTable";
else
oRow.className = "ItemTable";
}
//------------------------------------------------------
We attach JS Functionality to the Grid Edit/Save/Cancel/Delete Events as follow (we use icons):
You can see I sign with bold fonts the different JS event handlers
For example: Cancel icon button click will raise EditGridLine_Cancel handler. The function gets as parameter the name of the Is Dirty hidden flag. When ever the user click on the cancel button and is Dirty has a value then appropriate JS message will be display
DoValidate function gets as parameter the name of the caller dataGrid specific DoValidate function name
<ASP:EDITCOMMANDCOLUMN ButtonType="LinkButton" UpdateText="<img src='Images/save.gif' width=11 height=12 onclick='return DoValidate("dgGridBilling_Validate()")' alt='Save Week' border=0>" CancelText="<img src='Images/cancel.gif' width=11 height=12 alt='Cancel' onclick='return EditGridLine_Cancel("hdnIsDirty");' border=0>" EditText="<img src='Images/edit.gif' width=11 height=12 onclick='EditGridLine_Edit("hdnIsDirty");' alt='Edit this row' border=0>">
<ITEMSTYLE Width="3%" HorizontalAlign="Center"></ITEMSTYLE>
</ASP:EDITCOMMANDCOLUMN>
<ASP:BUTTONCOLUMN Text="<img src='Images/delete.gif' width=11 height=12 onclick='return IsConfirmDelete()' alt='Delete Region' border=0>" ButtonType="LinkButton" CommandName="Delete">
<ITEMSTYLE Width="3%" HorizontalAlign="Center"></ITEMSTYLE>
</ASP:BUTTONCOLUMN>
The aquivelent JS handlers are:
//------------------------------------------------------
function DoValidate(gridValidateCustomFunction)
{
alert(gridValidateCustomFunction);
if (gridValidateCustomFunction!="" && gridValidateCustomFunction!=null)
{
alert("in validate");
return eval(gridValidateCustomFunction);
}
return true;
}
//------------------------------------------------------
//Change to edit mode in a specific grid
//Warn the user if Is dirty flag point that changes where made and not saved
function EditGridLine_Edit(sDirtyId)
{
if (IsDirty(sDirtyId))
{
if (confirm("Pressing on edit button might couse the lost of your latest editing action/s.\n Do you want to Continue?"))
return true;
else
return false;
}
else
return true;
}
//------------------------------------------------------
//Change to view mode in a specific grid
//Warn the user if Is dirty flag point that changes where made and not saved
function EditGridLine_Cancel(sDirtyId)
{
alert(sDirtyId);
if (IsDirty(sDirtyId))
{
if (confirm("Pressing on cancel button might couse the lost of your latest editing action/s.\n Do you want to Continue?"))
return true;
else
return false;
}
else
return true;
}
//check if one or more grid input elements were change
function IsDirty(sId)
{
alert("check is dirty");
var oDirty = document.getElementById(sId);
alert("dirty = " + oDirty.value);
if (typeof(oDirty)=="undefined")
{
alert("Is dirty does not defined");
return false;
}
return (oDirty.value==""?false:true);
}
We need to call the function that change the Is Dirty hidden input element when ever its possible that the user change something in the edit row mode elements.
The JS function is:
//------------------------------------------------------
//Edit line change event
//change Is dirty flag to true
function EditRowChanged(sId)
{
if (!IsDirty(sId))
{
var oDirty = document.getElementById(sId);
//error handler - check if is dirty exists
if (typeof(oDirty)=="undefined")
{
alert("Is dirty does not defined");
return false;
}
//set Is dirty flag
oDirty.value = "yes";
}
}
We call it from the different EditItemTemplate inner input elements as follow:
<ASP:TEXTBOX id=txtText1 CssClass="textboxPercent" Runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "HIERARCHY_LEVEL_DESC")%>' onchange="EditRowChanged('hdnIsDirty');">
</ASP:TEXTBOX>
</EDITITEMTEMPLATE>
For this set of functionality we usally add JS function that open a calendar picker and other different pickers...