Update Panel animation extender with multi update panel - asp.net

Q:
I use Update Panel animation extender
,, it works so good but unfortunately
,,when i have more than update panel
on the same page and any partial post
back for any update panel on the page
the extender works (animate)..
How to make the extender works with
the intended one (the one i add the
extender to Only)..please sample if possible
The Script:
<script type="text/javascript" language="javascript">
function onUpdating() {
// get the update progress div
var updateProgressDiv = $get('updateProgressDiv');
// make it visible
updateProgressDiv.style.display = '';
// get the gridview element
var gridView = $get('<%=this.pnl_courseImg.ClientID %>');
// get the bounds of both the gridview and the progress div
var gridViewBounds = Sys.UI.DomElement.getBounds(gridView);
var updateProgressDivBounds = Sys.UI.DomElement.getBounds(updateProgressDiv);
// do the math to figure out where to position the element (the center of the gridview)
var x = gridViewBounds.x + Math.round(gridViewBounds.width / 2) - Math.round(updateProgressDivBounds.width / 2);
var y = gridViewBounds.y + Math.round(gridViewBounds.height / 2) - Math.round(updateProgressDivBounds.height / 2);
// set the progress element to this position
Sys.UI.DomElement.setLocation(updateProgressDiv, x, y);
}
function onUpdated() {
// get the update progress div
var updateProgressDiv = $get('updateProgressDiv');
// make it invisible
updateProgressDiv.style.display = 'none';
}
</script>
My ASPX:
<asp:Panel ID="pnl_courseImg" runat="server" HorizontalAlign="Center">
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<contenttemplate>
<br />
<asp:ListView ID="lv_showCourseImages" runat="server" ItemPlaceholderID="a"
onitemcommand="lv_showCourseImages_ItemCommand">
<LayoutTemplate>
<table ID="Table1" runat="server" cellpadding="2" cellspacing="2"
>
<tr ID="a" runat="server">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr ID="Tr1" runat="server">
<td>
<asp:Image ID="img_news" runat="server" ImageUrl='<%# "CourseImages" + "/" + Eval("FK_CourseCode") + "/"+ Eval("photoName")%>' BorderWidth="4px" Height="355px"
Width="410px"/>
</td>
</tr>
<tr id = "tr2" runat ="server">
<td>
<asp:HiddenField ID="hf_newsImage" runat="server" Value ='<%#Eval("photoId")%>'/>
<asp:Button ID="btn_deleteImg" runat="server" Text="Delete" CommandName ="deleteImage" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
<asp:DataPager ID="dp_CourseImages" runat="server"
PagedControlID="lv_showCourseImages"
PageSize="1" onprerender="dp_CourseImages_PreRender">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button" NextPageText=">>"
PreviousPageText="<<" ShowFirstPageButton="True"
ShowLastPageButton="True" />
</Fields>
</asp:DataPager>
</contenttemplate>
</asp:UpdatePanel>
<cc3:updatepanelanimationextender id="UpdatePanel2_UpdatePanelAnimationExtender"
runat="server" enabled="True" behaviorid="animation" targetcontrolid="UpdatePanel2">
<Animations>
<OnUpdating>
<Parallel duration="0">
<%-- place the update progress div over the gridview control --%>
<ScriptAction Script="onUpdating();" />
<%-- disable the search button --%>
<EnableAction AnimationTarget="btn_deleteImg" Enabled="false" />
<%-- fade-out the GridView --%>
<FadeOut minimumOpacity=".5" />
</Parallel>
</OnUpdating>
<OnUpdated>
<Parallel duration="0">
<%-- fade back in the GridView --%>
<FadeIn minimumOpacity=".5" />
<%-- re-enable the search button --%>
<EnableAction AnimationTarget="btn_deleteImg" Enabled="true" />
<%--find the update progress div and place it over the gridview control--%>
<ScriptAction Script="onUpdated();" />
</Parallel>
</OnUpdated>
</Animations>
</cc3:updatepanelanimationextender>
</asp:Panel>
i have one more update panel when click the button in it it fires the extender in this update panel how to fix this problem.
Thanks in advance..

Stolen from the ASP.NET Forums (sorry, didn't know how to get a link directly to the specified thread post):
Okay I solved it. here is my solution:
Just add the following javascript to your page
<script type="text/javascript">
var currentPostBackElement;
function pageLoad()
{
var manager = Sys.WebForms.PageRequestManager.getInstance();
manager.add_initializeRequest(OnInitializeRequest);
}
function OnInitializeRequest(sender, args)
{
var manager = Sys.WebForms.PageRequestManager.getInstance();
currentPostBackElement = args.get_postBackElement().parentElement;
}
</script>
and use the ConditionScript in the UpdatePanelAnimationExtender as followed:
<ajaxToolkit:UpdatePanelAnimationExtender ID="MyExtender" runat="server" TargetControlID="updPanel">
<Animations>
<OnUpdating>
<Condition ConditionScript="currentPostBackElement.name == 'updPanel' ">
<FadeOut AnimationTarget="updPanel" minimumOpacity=".1" Fps="30" />
</Condition>
</OnUpdating>
<OnUpdated>
<Condition ConditionScript="currentPostBackElement.name == 'updPanel' ">
<FadeIn AnimationTarget="updPanel" minimumOpacity=".1" Fps="30" />
</Condition>
</OnUpdated>
</Animations>
</ajaxToolkit:UpdatePanelAnimationExtender>
Its important to have the trigger (in my case a timer) in the update panel which should be refreshed. so you can get the parent
I didn't test this solution by I hope it will help you.

The Ajax Control Toolkit is now maintained by DevExpress, and this bug has been resolved. I updated my DLL to version 18.1, and I'm no longer experiencing the problem.

Related

Do a Button Click from Code behide

I have a gridview which lists Tools and Access values. To edit I have an edit imagebutton on each row. I have an OnRowBound method which assigns an OnClick attribute to each button so that I will know which record I need to edit.
The code is
Protected Sub ChangeFirstRowIcon(ByVal Sender As Object, ByVal e As GridViewRowEventArgs) Handles gv_AccessRights.RowDataBound
'This sub fires on each gridview row created...
'It first checks that the row is a data row (as opposed to Header, Footer etc.)
'If ib_Edit is true then change add an attribut to button with aid, tid and ac values attached.
If e.Row.RowType = DataControlRowType.DataRow Then
Dim ib_Edit As ImageButton = e.Row.FindControl("ib_Edit")
Dim lb_AccessID As Label = e.Row.FindControl("lb_AccessID")
Dim hd_ToolID As HiddenField = e.Row.FindControl("hd_ToolID")
Dim hd_AccessCode As HiddenField = e.Row.FindControl("hd_AccessCode")
If ib_Edit IsNot Nothing Then
ib_Edit.Attributes.Add("onClick", "proxyClick('" & lb_AccessID.Text & "', '" & hd_ToolID.Value & "', '" & hd_AccessCode.Value & "')")
End If
End If
End Sub
I'm using a hidden proxy button to show a modal popup which the user will use to edit a record... (the same popup will be used to add a new access record... but that will come later). So having passed my details to proxyClick I set values to controls within the modal popup. The javascript is....
<script type="text/javascript">
function proxyClick(aid, tid, ac) {
document.getElementById('hd_AccessID').value = aid;
document.getElementById('hd_ToolIDMod').value = tid;
document.getElementById('hd_AccessCodeMod').value = ac;
document.getElementById('but_SetModalDetails').click();
}
</script>
For reference the main bits of the markup are....
<table class="border">
<tr>
<td>
<asp:Button ID="but_SetModalDetails" runat="server" Style="display: none" Text="Set modal details" ClientIDMode="Static" UseSubmitBehavior="true" />
<asp:Button ID="but_HiddenProxy" runat="server" Style="display: none" Text="Hidden Proxy Button for Modal Popup" ClientIDMode="Static" />
</td>
<td class="rt">
<asp:Button ID="but_AddTool" runat="server" AccessKey="A" CssClass="butGreen" Text="Add Tool" ToolTip="Add Tool - Alt A" />
</td>
</tr>
</table>
<asp:ModalPopupExtender ID="mpx_AddEditAccess" runat="server" CancelControlID="but_Cancel"
BehaviorID="pn_AddEditAccess" PopupControlID="pn_AddEditAccess" TargetControlID="but_HiddenProxy"
BackgroundCssClass="modalBackground" />
<asp:Panel ID="pn_AddEditAccess" runat="server" Width="500px" CssClass="modalPopup"
Style="display: block">
<div class="box">
<h2>
<asp:Label ID="lb_ModTitle" runat="server"></asp:Label>
</h2>
<asp:HiddenField ID="hd_AccessID" runat="server" ClientIDMode="Static"></asp:HiddenField>
<div class="block">
<asp:UpdatePanel ID="up_Access" runat="server" UpdateMode="Always">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddl_ToolName" EventName="SelectedIndexChanged" />
</Triggers>
<ContentTemplate>
<table>
<tr>
<th class="p66 rt">
Tool Name:
</th>
<td class="p66">
<asp:HiddenField ID="hd_ToolIDMod" runat="server" ClientIDMode="Static" />
<asp:DropDownList ID="ddl_ToolName" runat="server" AutoPostBack="true" AppendDataBoundItems="True"
DataSourceID="SqlDS_Tools" DataTextField="ToolName" DataValueField="ToolID" OnSelectedIndexChanged="ddl_ToolName_SIC">
<asp:ListItem Text="Please Select..." Value="0"></asp:ListItem>
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDS_Tools" runat="server" ConnectionString="<%$ ConnectionStrings:ToolsConnString %>"
SelectCommand="SELECT [ToolID], [ToolName] FROM [tbl_Tools] WHERE ([Redundant] = #Redundant)">
<SelectParameters>
<asp:Parameter DefaultValue="False" Name="Redundant" Type="Boolean" />
</SelectParameters>
</asp:SqlDataSource>
<asp:RequiredFieldValidator ID="rfv_ddl_ToolName" runat="server" ControlToValidate="ddl_ToolName"
CssClass="error" Display="Dynamic" ErrorMessage="Please Select Tool Name" InitialValue="0">
</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<th class="p66 rt">
Access Rights:
</th>
<td class="p66">
<asp:HiddenField ID="hd_AccessCodeMod" runat="server" ClientIDMode="Static" />
<asp:DropDownList ID="ddl_AccessCode" runat="server" Enabled="false">
<asp:ListItem Text="No Access" Value="0"></asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td class="p66">
<asp:Button ID="but_Cancel" runat="server" Text="Cancel" />
</td>
<td class="p66 rt">
<asp:Button ID="but_Save" runat="server" Text="Save" />
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
</asp:Panel>
As you can see I have implemented two hidden buttons but_SetModalDetails and but_HiddenProxy. but_SetModalDetails has some codebehind which sets a couple of dropdown lists (one populated from a datasource, the other is populated dynamically based on the value of the first. The codebehind is...
Protected Sub but_SetModalDetails_Click(ByVal sender As Object, ByVal e As EventArgs) Handles but_SetModalDetails.Click
If hd_AccessID.Value = "0" Then
lb_ModTitle.Text = "Assigning Access Rights to:"
ddl_ToolName.SelectedIndex = 0
ddl_AccessCode.SelectedIndex = 0
ddl_AccessCode.Enabled = False
Else
lb_ModTitle.Text = "Edit Access Rights to:"
ddl_ToolName.SelectedValue = hd_ToolIDMod.Value
ddl_ToolName.Enabled = False
SqlStr = "SELECT AccessID AS ddlValue, AccessText as ddlText FROM tbl_AccessCodes WHERE ToolID = " & hd_ToolIDMod.Value
PopulateDDLvalue(ddl_AccessCode, SqlStr)
ddl_AccessCode.SelectedValue = hd_AccessCodeMod.Value
ddl_AccessCode.Enabled = True
End If
'NOW I NEED TO SIMULATE but_HiddenProxy Click
End Sub
As you can see at the end I need to simulate a click of but_HiddenProxy so that the modalPopup is shown populated with the correct data.
Any Ideas? Thanks
After all that... I was able to do everything in codebehind...
I only needed one hidden button but_HiddenProxy.
In the gridview instead of setting an onClick attribute for each edit image button I just set a commandname of 'AccessEdit' (don't use 'Edit'). I then had a method that handled the gridview.RowCommand event. This found the various info I needed by using findControl on the selected row. These values were then used to populate the dropdowns in the popup and then use the show command to make the popup visible.
One bit that did stump me for a while was why my RowCommand was not triggering when an imagebutton was clicked. I'd forgotten that I had validation in the modal which stopped the RowCommand being executed. I stuck a CausesValidation="false" in the imagebutton and all was OK.
Talk about using a hammer to crack a nut!

AutoComplete with service and Masterpage

I've been struggling with getting all these components to work correctly, but when I get to the js it cannot find the TextBox control on the Student page.
The MasterPage ScriptManager:
<body>
<form id="MainForm" runat="server">
<asp:ScriptManager ID="ScriptManagerMain" runat="server">
<Services>
<asp:ServiceReference Path="~/AutoComplete.asmx" />
</Services>
</asp:ScriptManager>
Masterpage ContentPlaceHolder:
<asp:ContentPlaceHolder ID="ContentPlaceHolderStudent" runat="server">
</asp:ContentPlaceHolder>
Student (child) page:
<asp:Content ID="Content" ContentPlaceHolderID="ContentPlaceHolderStudent" runat="server" >
<asp:UpdatePanel ID="StudentSearchPanel" runat="server" ViewStateMode="Inherit">
<ContentTemplate>
Search by student ID:
<br />
<asp:TextBox ID="StudentIDSearchTextBox" runat="server" OnTextChanged="StudentIDSearchTextBox_TextChanged" Wrap="False" MaxLength="6" ClientIDMode="Static" ViewStateMode="Inherit"></asp:TextBox>
<br />
<asp:Label ID="StudentIDEntryError" runat="server" Visible="false" Font-Bold="True" ForeColor="Red" Text="Please enter a 6-digit student ID number."></asp:Label>
<br />
Or, begin typing student last name:
<br />
<asp:TextBox ID="StudentNameSearchTextBox" runat="server"
CssClass="StudentNameSearch"
ViewStateMode="Inherit"></asp:TextBox>
The Autocomplete Extender on the Student page:
<ajaxToolkit:AutoCompleteExtender ID="StudentNameSearchTextBox_AutoCompleteExtender" runat="server"
TargetControlID="StudentNameSearchTextBox"
ServicePath="~/Scripts/AutoComplete.asmx"
ServiceMethod="GetStudents"
OnClientItemSelected="onStudentSelected"
MinimumPrefixLength="2"
CompletionSetCount="30"
UseContextKey="True"
CompletionListCssClass="autocomplete_completionListElement"
CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem"
CompletionListItemCssClass="autocomplete_listItem" >
</ajaxToolkit:AutoCompleteExtender>
The AutoComplete.asmx is working, so I won't add that code. When I begin typing a student last name, I do get a json response, something like the following (altered to protect student data). I took this from FireBug:
{"d":["{\"First\":\"Lisaaa, Abby E.\",\"Second\":\"610999\"}","{\"First\":\"Lisbbb, Bobby P.\",\"Second\":\"151999\"}","{\"First\":\"Lisccc, Cathy M.\",\"Second\":\"739999\"}","{\"First\":\"Lisddd, David L.\",\"Second\":\"496999\"}","{\"First\":\"Liseee, Emily C.\",\"Second\":\"701999\"}","{\"First\":\"Lisfff, Frank G.\",\"Second\":\"623999\"}"]}
The problem, when I get to OnClientItemSelected="onStudentSelected" in GetStudentJson.js:
function onStudentSelected(sender, e) {
var selectedStudent = eval("(" + e._value + ")");
var StudentIdTextbox = document.getElementById('<%=ContentPlaceHolderStudent_StudentIDSearchTextBox.ClientID %>');
StudentIdTextbox.innerText = selectedStudent;
__doPostBack(StudentIdTextbox, "");
}
I get an error StudentIdTextbox is Null. I've tried adding all levels of placeholders by going to ViewSource to figure out how to find that box and give it the value of the student id, but to no avail. In fact, here is what it looks like:
<input name="ctl00$ContentPlaceHolderStudent$StudentIDSearchTextBox" type="text" maxlength="6" id="StudentIDSearchTextBox" />
Any advice??
I finally discovered that by problem lies in page lifecycle. Instead of referencing the script in the master page, I moved the script itself to the child page. Now, 'FindControl' is looking for a control that actually exists.
<script type="text/javascript">
function onStudentSelected(sender, e) {
var selectedStudent = eval("(" + e._value + ")");
var txtId = document.getElementById('<%= Page.Master.FindControl("ContentPlaceHolderStudent").FindControl("StudentSearchPanel").FindControl("StudentIDSearchTextBox").ClientID %>');
txtId.value = selectedStudent;
}
</script>
I was simply trying to find that control too soon.

Update Panel & Event firing twice

I have an ASPX page with 3 dropdown boxes via Infragistic controls. 1 of them is inside an UpdatePanel and the two outside of the UpdatePanel is suppose to control what is displayed in the 3rd one via AsynPostBack Event. Both dropdown boxes outside of the UpdatePanel call the same function in the code behind but depending on which object I pass to it, it will show something in the 3rd drop-down box. Problem is, the function appears to be getting triggered twice regardless of which dropdown box I select and each call passes its control to the function and the second one is what always being displayed even when I click on the first one. How do I stop that? I'm expecting for the function to just fire once depending on which control I select. I also tried to have each dropdown box point to its own function and still, both of them got triggered...
<td style="width:3px;"><asp:HiddenField ID="pnb_recno" runat="server" /></td>
<td style="width:100px;">Line Of Business:</td>
<td colspan="2" width="150px"><!--OnSelectionChanged="pnb_product_list"-->
<ig:WebDropDown ID="pnb_ddRgn" runat="server" Width="175px" DropDownContainerHeight="100px"
EnableDropDownAsChild="false" TextField="Name" DropDownContainerWidth="175px" Font-Size="11px"
StyleSetName="Windows7" OnSelectionChanged="pnb_product_list" AutoPostBack="true" ClientEvents-SelectionChanged="pnb_chgLOB" >
<Items>
<ig:DropDownItem Text="" Value="" />
<ig:DropDownItem Text="Global Client Access" Value="Global Client Access" />
<ig:DropDownItem Text="Solution Center" Value="Solution Center" />
<ig:DropDownItem Text="Both" Value="Both" />
</Items>
</ig:WebDropDown>
</td>
<td style="width:3px;"></td>
<td style="width:100px;">Problem Type:</td>
<td colspan="2" width="150px">
<ig:WebDropDown ID="pnb_ddPblmTyp" runat="server" Width="175px" DropDownContainerHeight="80px" EnableDropDownAsChild="false" TextField="Name" DropDownContainerWidth="175px" Font-Size="11px" StyleSetName="Windows7" AutoPostBack="true" OnSelectionChanged="pnb_product_list">
<Items>
<ig:DropDownItem Text="" Value="" />
<ig:DropDownItem Text="Infrustructure" Value="Infrustructure" />
<ig:DropDownItem Text="Products" Value="Products" />
</Items>
</ig:WebDropDown>
</td>
<td colspan="2" width="150px">
<asp:UpdatePanel ID="pnb_udtPnlPrdts" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="pnb_ddRgn" EventName="SelectionChanged" />
<asp:AsyncPostBackTrigger ControlID="pnb_ddPblmTyp" EventName="SelectionChanged" />
</Triggers>
<ContentTemplate>
<ig:WebDropDown ID="pnb_ddPrdts" runat="server" Width="175px" EnableClosingDropDownOnSelect="false" TextField="ProductName" EnablePaging="false" DropDownContainerHeight="175px" EnableMultipleSelection="true" MultipleSelectionType="Checkbox" StyleSetName="Windows7" DisplayMode="DropDown">
<ClientEvents SelectionChanged="selectedIndexChanged" SelectionChanging="selectedIndexChanging" />
</ig:WebDropDown>
</ContentTemplate>
</asp:UpdatePanel>
</td>
protected void pnb_product_list(object sender, EventArgs e)
{
try
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
using (SqlCommand sqlCommand = new SqlCommand("dbo.getDdProducts", sqlConnection))
{
sqlCommand.CommandTimeout = 0;
sqlCommand.CommandType = CommandType.StoredProcedure;
if (!String.IsNullOrEmpty(pnb_ddRgn.CurrentValue))
sqlCommand.Parameters.AddWithValue("#lob", pnb_ddRgn.CurrentValue);
else
sqlCommand.Parameters.AddWithValue("#alert_type", pnb_ddPblmTyp.CurrentValue);
using (DataTable dataTable = new DataTable())
{
using (SqlDataAdapter dataAdapter = new SqlDataAdapter(sqlCommand))
{
dataAdapter.Fill(dataTable);
}
pnb_ddPrdts.DataSource = dataTable;
pnb_ddPrdts.DataBind();
}
}
}
}
catch (Exception exception)
{
}
}
I would try looking for AutoPostBackFlags one for selectionChanged and another for valueChanged is it possible it is just infact because both these events are being triggered is why it is posting back twice??

AJAX Control Toolkit MultiHandleSlider readOnly handle

I have a question about AJAX MultiHandleSliderExtender. Code is following:
<form runat="server" id="myForm">
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" CombineScripts="false" />
<asp:TextBox ID="strMinModTB" runat="server" Style="display:none;" Text="80" />
<asp:TextBox ID="strCurModTB" runat="server" Style="display:none;" Text="100" />
<asp:TextBox ID="strMaxModTB" runat="server" Style="display:none;" Text="160" />
<asp:TextBox ID="strSlider" runat="server" Style="display:none;" />
<asp:MultiHandleSliderExtender ID="strModMultiSlider" runat="server"
BehaviorID="strModMultiSlider"
TargetControlID="strSlider"
Minimum="0"
Maximum="300"
Length="600"
EnableHandleAnimation="true"
EnableKeyboard="false"
EnableMouseWheel="false"
ShowInnerRail="true"
ShowHandleDragStyle="true"
ShowHandleHoverStyle="true">
<MultiHandleSliderTargets>
<asp:MultiHandleSliderTarget ControlID="strMinModTB" />
<asp:MultiHandleSliderTarget ControlID="strCurModTB" />
<asp:MultiHandleSliderTarget ControlID="strMaxModTB" />
</MultiHandleSliderTargets>
</asp:MultiHandleSliderExtender>
<asp:Label ID="sliderLabel" runat="server" Visible="true"></asp:Label>
</form>
Now what I want to do is to lock positions of outter handles and allow only the middle one to be dragged in range from the left hanle to the right one thus changing the value in asp:Label (ID="sliderLabel").
I've tried readOnly="true" attribute on TextBoxes but with no result. There is also IsReadOnly Extender property but that blocks all handles.
Also when I add the BoundControlID property (containing ID of label) to the Extender it stops working (all handles on 0 position and I cannot drag them)
Is there a way around this or am I missing something?
Thank you for replies :)
You don't need a BoundControlID for the MHSE do you?
Also, could you not add a class to each Handle and then fix the outer handles positions using CSS?
See below for code example.
ASP Code
<asp:MultiHandleSliderExtender ID="strModMultiSlider" runat="server"
BehaviorID="strModMultiSlider" TargetControlID="strSlider"
Minimum="0" Maximum="300" Length="600"
EnableHandleAnimation="true" EnableKeyboard="false"
EnableMouseWheel="false" ShowInnerRail="true"
ShowHandleDragStyle="true" ShowHandleHoverStyle="true">
<MultiHandleSliderTargets>
<asp:MultiHandleSliderTarget ControlID="strMinModTB" HandleCssClass="handle_outer"/>
<asp:MultiHandleSliderTarget ControlID="strCurModTB" HandleCssClass="handle_inner" />
<asp:MultiHandleSliderTarget ControlID="strMaxModTB" HandleCssClass="handle_outer"/>
</MultiHandleSliderTargets>
</asp:MultiHandleSliderExtender>
CSS Code
.handle_outer
{
//Code to Fix Handle in Place
}
.handle_inner
{
}

Show/Hide div tag javascript

I have a gridview column that's gets a large amount of text from the server. So instead of showing all that text after the grid loads I want to show it only if a user clicks an Expand link then closes it with a collapse link. Here is what I have. Please note that I already know that I can put both javascript functions in one; I'm testing right now in two separate functions.
<script type="text/javascript" language="javascript" >
function hidelink() {
var col = $get('col');
var exp = $get('exp');
col.style.display = 'none';
exp.style.display = '';
}
function showlink(){
var col = $get('col');
var exp = $get('exp');
col.style.display = '';
exp.style.display = 'none';
}
<asp:GridView ID="GridView2" Width="400px" runat="server" AutoGenerateColumns="False"
AllowPaging ="True"
BackColor="White" BorderColor="#999999"
BorderStyle="None" BorderWidth="1px"
CellPadding="3" DataKeyNames="APPID"
DataSourceID="SqlDataSource3"
PagerSettings-Mode="NextPreviousFirstLast" EnableSortingAndPagingCallbacks="True">
<PagerSettings Mode="NextPreviousFirstLast" />
<RowStyle BackColor="#EEEEEE" ForeColor="Black" />
<Columns>
<asp:BoundField DataField="stuff" HeaderText="Name" ReadOnly="True"
SortExpression="app" />
<asp:BoundField DataField="Description" HeaderText="Short Descr"
ReadOnly="True" SortExpression="des" />
<asp:TemplateField HeaderText="Long Descr" SortExpression="data">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("data") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<div id="col">
<asp:LinkButton ID="expand" runat="server" OnClientClick ="hidelink();return false;">Expand</asp:LinkButton>
</div>
<div id="exp" style="display:none">
<asp:LinkButton ID="collapse" runat="server" OnClientClick ="showlink();return false;">Collapse</asp:LinkButton>
</div>
<asp:Panel ID="Panel1" runat="server" >
<table>
<tr>
<td> <%#Eval("LongDescription")%>
</td>
</tr>
</table>
My issue is that only the first record does everything it should. (expand/collapse) but the other rows only expand and does not hide the expand link in the div tag. It is only finding the id of the first row because when the expand button is hit on any other row it changes the first row to show the collapse link. How can i fix this?
The problem is that because you have repeating elements, the ids of the DIVs are being reused. This is illegal in HTML. The id property of each element must be unique. A better way to handle it is to pass in a reference to the current element to the handler and have it derive the element that it needs to operate on by traversing the DOM.
<div>
<asp:LinkButton ID="expand" runat="server" OnClientClick ="hidelink(this);return false;">Expand</asp:LinkButton>
</div>
<div style="display:none">
<asp:LinkButton ID="collapse" runat="server" OnClientClick ="showlink(this);return false;">Collapse</asp:LinkButton>
</div>
Note: I'm using jQuery in these functions as it makes it easier to traverse the DOM. You can do the same with your own DOM traversal functions and by setting the style properties if you like.
function hidelink(ctl) {
var myDiv = $(ctl).closest('div');
myDiv.hide();
myDiv.next('div').show();
}
function showlink(ctl){
var myDiv = $(ctl).closest('div');
myDiv.hide();
myDiv.prev('div').show();
}
You need to use unique IDs for each row. IDs can only apply to one element in the page, and your code is applying one ID to all the instances of this large column in the table.
Alternatively, you can just use the DOM methods to locate the right element to show/hide. For example:
<div>
Expand
<table style="display: none;">
<tr>
<td><%#Eval("LongDescription")%></td>
</tr>
</table>
</div>
Then for your script:
function showHideDesc(link) {
var table = link.parentNode.getElementsByTagName("TABLE")[0];
if (table.style.display == "none") {
table.style.display = "";
link.innerHTML = "Collapse";
}
else {
table.style.display = "none";
link.innerHTML = "Expand";
}
}

Resources