As I extend an ASP.Net application with MVC functionality, I also need to replace some of the components that the AjaxControlToolkit provides. Case in point, the CollapsiblePanelExtender.
The CPE is declared in markup like this:
<ajax:CollapsiblePanelExtender ID=”cpe” runat=”server” CollapseControlID=”paHeader” ExpandControlID=”paHeader” AutoCollapse=”false” AutoExpand=”false” Collapsed=”true” TargetControlID=”paDetail” ExpandedImage=”~/images/collapse_blue.jpg” CollapsedImage=”~/images/expand_blue.jpg” SuppressPostBack=”true” ImageControlID=”imgHeader”>
</ajax:CollapsiblePanelExtender>
paHeader and paDetail are both asp:Panels – clicking on the header toggles the display of the detail panel. The image control is toggled accordingly.
My goal was to create a JavaScript function which uses parameters similar to the markup, omitting those that do not matter in my application.
In MVC, of course, the equivalent of an asp:Panel is a simple HTML <div>.
I started out with a function declaration like this (please forgive non-standard casing):
function CollapsiblePanelExtender(ID, CollapseControlID,
TargetControlID, ImageControlID) { }
but then noticed that I needed to distinguish between initial states expanded and collapsed, as well as an additional callback after expanding/collapsing.
var CollapsiblePanelExtenders = {};
function CollapsiblePanelExtender(ID, CollapseControlID,
TargetControlID, ImageControlID, expanded, fn) {
var ExpandedImage = '@Url.Content("~/images/collapse_blue.jpg")';
var CollapsedImage = '@Url.Content("~/images/expand_blue.jpg")';
CollapsiblePanelExtenders is our array of all CPEs on the page. Parameters expanded and fn are optional.
First, we register the CPE in the array, and initialize the image and the detail’s overview setting:
CollapsiblePanelExtenders[ID] = { collapsed: !(expanded || false) };
$("#" + ImageControlID).attr("src", (expanded || false) ? ExpandedImage : CollapsedImage);
$("#" + TargetControlID).attr("overflow", "hidden");
Finally, we add a click handler on the header panel:
$("#" + CollapseControlID).click(function (pa) {
if (CollapsiblePanelExtenders[ID].collapsed) {
$("#" + TargetControlID).css("height", "");
$("#" + ImageControlID).attr("src", ExpandedImage);
CollapsiblePanelExtenders[ID].collapsed = false;
} else {
$("#" + TargetControlID).css("height", "0px");
$("#" + ImageControlID).attr("src", CollapsedImage);
CollapsiblePanelExtenders[ID].collapsed = true;
}
if (fn) {
fn(CollapsiblePanelExtenders[ID].collapsed);
}
});
};
The click handler adjusts the detail’s height and sets the expand/collapse image. If a callback function is defined, the function is executed with the collapsed status as parameter.
I was surprised that it only takes a couple of JavaScript lines to implement an ACT control. Note, however, that the presented solution does not invoke any animations – have a look at jQuery Effects, if you need them…