YUI Styled 'Tip of the Day' Dialog using the PopupControl, DynamicPopulate and DragPanel Extender Controls
So as an R&D task, I created a page that implements a simple 'Tip of the Day' popup control. The functionality is basic - you click a button and the Tip of the Day panel is displayed. Once displayed, you can click that 'Next Tip' button to fetch the next tip and display it to the user. While the next tip is being retrieved, I fade out the text and display an animated gif in the center of the panel. Here is a quick screen shot of what the panel looks like while the next tip is being fetched.
I styled the control based on the YUI Panel control. It includes the following features:
- You can move the panel by clicking and dragging on the 'Tip of the Day' header
- Clicking the 'Next Tip' button will dynamically update the Tip text by using the AjaxControlToolkit's DyanmicPopulateExtender control
- A progress indicator is rendered over the Panel while the contents is being updated
- A shaded border is applied to the panel (IE7 only)
I am still working on these additional features as well
Here is the markup for what I have done so far. Inside the pnlPopup, I have 2 div's, one (class=overlay) for the contents and the other (class=underlay) for the shadow around the border. Within the overlay div I have the a panel for the header text and close button, a panel for the body and another div for the footer contents (the Next Tip and Close buttons). Each of these elements has a CssClass defined where I am specifying the background-image along with the other style rules.
<%// The panel that is popped %> <asp:Panel ID="pnlPopup" runat="server" CssClass="frame" style="display:none"> <div class="overlay"> <asp:Panel ID="pnlHeader" runat="server" CssClass="header"> <asp:Label runat="server" CssClass="msg" Text="Tip of the Day" /> <asp:LinkButton runat="server" CssClass="close" OnClientClick="$find('popup').hidePopup(); return false;" /> </asp:Panel> <asp:Panel ID="pnlBody" runat="server" CssClass="body"> <%= NextTip() %> </asp:Panel> <div class="footer"> <asp:Button ID="btnNextTip" runat="server" Text="Next Tip" OnClientClick="return false;" /> <asp:Button runat="server" Text="Close" OnClientClick="$find('popup').hidePopup(); return false;" /> </div> </div> <div class="underlay"></div> </asp:Panel>
Next, I added 3 toolkit extender controls that supplied some additional behavior. I included the PopupControlExtender to handle displaying and positioning the pnlPopup control. The DynamicPopulateExtender for interfacing with a PageMethod that I created to return the next Tip of the Day. And finally, I added a DragPanelExtender so the user can drag the panel around the page. The DyanmicPopulateExtender is the most interesting of the controls. This control allows you to replace the contents of a control with the string result of a web service or page method ...
So for my Tip of the Day sample, I configure the control to populate the invoke the NextTip PageMethod when the user clicks the btnNextTip button. While this call is be made, the DynamicPopulateExtender applies the updating css class to the pnlBody HTML element and removes it after the call completes. Below is the markup for the DyanmicPopulateControl as well as the other two controls.
<%// The extender that displays and positions the panel %> <ajaxToolkit:PopupControlExtender runat="server" BehaviorID="popup" TargetControlID="btnPopup" Position="Right" PopupControlID="pnlPopup" /> <%// The extender that populates the tip %> <ajaxToolkit:DynamicPopulateExtender runat="server" ClearContentsDuringUpdate="false" PopulateTriggerControlID="btnNextTip" TargetControlID="pnlBody" UpdatingCssClass="updating" ServiceMethod="NextTip" /> <%// The extender that provides drag and drop behavior %> <ajaxToolkit:DragPanelExtender runat="server" DragHandleID="pnlHeader" TargetControlID="pnlPopup" />
Using PageMethod's requires you to add the ScriptMethod and WebMethod attributes to your PageMethod's signature. Here is what my 'NextTip' method looks like. If you are using PageMethods, make sure you mark the method static (I noticed the documentation here is missing this)
As far as implementation details, that's about it. I will say that building this sample took longer than I had initially estimated. Here are a couple of the gotcha's I encountered along the way ...
1. In IE (works fine in FF), the DragPanelExtender display's the 'Copy' and not the 'Move' icon. I half way corrected this (and the DragPanelExtender page does this too) by setting the cursor style on my header element to move.
2. You should be aware that the DynamicPopulateExtender replaces the existing class with the one you specify using the UpdatingCssClass. So it might make sense to apply the same style to both like I have done here. And also define the custom updating style separately.
3. When I was creating this sample, I didn't have much content on my page and the div that contained all of the content was only a few pixels high by a few pixels wide. When trying to drag and drop I kept getting this weird behavior where I would drag the panel and sometimes it would move fine and other times it would revert back to the ordinal location. It turns out the DragDrop script cancels the move if there is not drop target (element to drop onto). You can checked this out here. Try moving the panel outside of the blue box ...
4. There are a handful of slight differences between the ModalPopupExtender and the PopupExtender. The one that got me right away was the minor difference of client side API's for showing and hiding (modalPopup.show() and modalPopup.hide() versus popup.showPopup() and popup.hidePopup()).
That's it. Enjoy!