YUI Styled 'Tip of the Day' Dialog using the PopupControl, DynamicPopulate and DragPanel Extender Controls

The web application I am currently developing has a fair number of popup windows.  Some are modal, some aren't.  All open new browser windows and this annoys more than a few of our users (I hate popup's too, so I guess it shouldn't be that surprising).  So as a team we are looking into replacing our popup windows with the ModalPopupExtender and PopupExtender AjaxControlToolkit controls.  This is just fine by me - I have worked with the toolkit's popup controls on other projects and they worked quite well (It also saves me the pain of writing custom JavaScript for communicating between browser windows). 

Live Demo (IE6, IE7, FF) | Download (Uses Toolkit Version 1.0.10920.0)

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:

  1. You can move the panel by clicking and dragging on the 'Tip of the Day' header
  2. Clicking the 'Next Tip' button will dynamically update the Tip text by using the AjaxControlToolkit's DyanmicPopulateExtender control
  3. A progress indicator is rendered over the Panel while the contents is being updated
  4. A shaded border is applied to the panel (IE7 only)

I am still working on these additional features as well

  1. Resizing with the ResizableControl 
  2. Replacing the shadow with the DropShadow 

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!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/84

Comments


Everytime i see a new feed on your blog I get excited. Your topics and attention to detail is perfect! Great Job Matt! Keep the yui stuff coming.

Posted by: guilherme holdack on November 8, 2007 07:11 PM

hey matt, it is me again, from brazil.
another cool sample, great job!
i'm get addicted to your blog!
thanks a lot, matt!

Posted by: Swami K on November 8, 2007 11:02 PM

Hi Matt:
Your blog is very impressive. You bring about very nice articles on AJAX. Keep up the good job

Regards,
Swami

Great site with working examples and full explanation has helped a lot.

Keep looking on your blog daily for new ajax examples.....wondering if will ever see a gridview inside a modal window.

cheers and keep up the good work, I'm trying to remember how i came across your examples in the first place!!! And how do you get the time to do this.

Richard

Posted by: Pasha on November 13, 2007 12:46 PM

As always GOOD stuff.

Posted by: Steve on November 18, 2007 08:35 AM

Thanks Matt, v useful

Posted by: Max on November 18, 2007 12:25 PM

Another great post as usual. Quck question though - does it bother anyone else that doing something like this with asp.net ajax and the control toolkit requires such a large (KB) of js? I mean your example requires 149KB of javascript alone and 13 different JS files.

Howdy, nice blog though I wonder if you've tested the library of my employer?
http://ajaxwidgets.com
An alternative to ASP.NET AJAX who's USP is exactly that developers don't need to write custom JavaScript themselves.
BTW (to Richard) we have a working example of a DataGrid inside a Window, to make it modal is just a switch on one of the properties of the Gaia Ajax Window object.

Thomas

Hi Matt,,

After surfing this blog everyday for 3 days now,, its really amazing the job you are doing, and the articles samples are greate !!!

thanks for your effort ..

Posted by: haijian on December 28, 2007 05:19 AM

dose it for jsp??

Posted by: Gavin on January 7, 2008 11:01 PM

Hey Matt! Great Blog! I had a difficult time getting the ajax ModalPopupExtender to play nice with this panel.
I added a ModalPopupExtender with this set as the style:
.modalBackground {
background-color:Gray;
filter:alpha(opacity=70); opacity:0.7;}

Posted by: Gavin on January 8, 2008 12:12 AM

Sorry, please disregard my last post. I was able to use one of your other examples to get a working modal. THANKS!!!

Posted by: Tu Dang Tuan on January 22, 2008 11:20 AM

Hi Matt,

Your articles are very useful for me. Thank you very much

Posted by: Terry on March 11, 2008 05:29 PM

When I run you sample (from your site), and resize the browser to be much narrower, the help tip correctly repositions to the left some so as to show up on the page. However, when I download and run this code on my box, it is always 'fixed' to the right of the button. Any idea why my dynamic positioning isn't working?

Posted by: Rain Man Alex on March 27, 2008 10:58 AM

This is one of the best article i have read on using the AJAX Control Toolkit. It has changed the way i see toolkit and its uses. I was using the ajax roadmap webpage for communicating to webservices. This article changed everything. Thank you ever so much.

Rain Man ALex

Posted by: Troy Gerton on July 10, 2008 02:39 PM

Sweet. I used the PopupControlExtender and the DynamicPopulateExtender on the same panel. I already had the PopupControlExtender working using the DynamicServiceMethod property, but there is no UpdatingCssClass property for the PopupControlExtender!!! Why is this? What am I missing? So, I used the DynamicPopulateExtender simply for the UpdatingCssClass property.
Thanks for your blog. It helped me out...Troy

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Sponsor

Recent Comments

  • Troy Gerton wrote: Sweet. I used the PopupControlExtender and the DynamicPopulateExtender on the same panel. I alread...
  • Rain Man Alex wrote: This is one of the best article i have read on using the AJAX Control Toolkit. It has changed the wa...
  • Terry wrote: When I run you sample (from your site), and resize the browser to be much narrower, the help tip cor...
  • Tu Dang Tuan wrote: Hi Matt, Your articles are very useful for me. Thank you very much...
  • Gavin wrote: Sorry, please disregard my last post. I was able to use one of your other examples to get a working ...
  • Gavin wrote: Hey Matt! Great Blog! I had a difficult time getting the ajax ModalPopupExtender to play nice with t...
  • haijian wrote: dose it for jsp??...
  • Nasser wrote: Hi Matt,, After surfing this blog everyday for 3 days now,, its really amazing the job you are d...

Sponsor