Animating the ModalPopupExtender

I recently stumbled upon this site again.  I remember on my first visit, I thought it was pretty cool how the modal popup's incorporate subtle animation effects that give the pages a little extra pop.  If you go to the site you can check it out for yourself.  Try clicking on any of the 3 images on the page and watch closely for the animation. 

[Update: 9/20/2007]

I followed up with Ted Glaza on his comment and he provided some additional information.  I included the email thread at the bottom of this post.

Live Demo | Download

This page appears to be using PHP, but I thought it might be interesting to re-engineer the modal popup using ASP.NET AJAX plus the ModalPopupExtender control from the AjaxControlToolkit.  I figured there should be some way to run an AjaxControlToolkit Animation when the dialog is displayed ...

It turned out this was a little more difficult that I had originally thought.  I was anticipating the ModalPopupExtender had an Animation section that I could define the animation to run when the dialog is shown.  I has hoping for something like this ... 

<ajaxToolKit:ModalPopupExtender>
    <Animations>
        <OnShown>
            <% -- Fade in when first displayed %>
            <FadeIn Duration=".75" Fps="20" />                
        </OnShown>
    </Animations>
</ajaxToolKit:ModalPopupExtender>     

Unfortunately the ModalPopupExtender control doesn't natively support any animations, so clearly this solution isn't going to work.  My next approach was to see if I could use to generic AnimationExtender control.  After reading through the documentation, the Animations for this extender only run OnLoad (when the page is loaded), OnClick, OnMouseOver/Out and OnHoverOver/Out.

My solution was to implement a new extender control - the ModalPopupAnimationExtender.  This new control would be implemented in the same vain as the UpdatePanelAnimationExtender, but instead of running Animation's for OnUpdating and OnUpdated, my new extender control would run Animation's for OnShown and OnHidden.  The rest of this post discusses the implementation details of the new extender control.  I have not yet re-implemented a modal popup like the ones in the aforementioned site, but I believe this control has laid the ground work to make it a relatively simple task.

Create the ModalPopupAnimationExtender Project

First, I created a new project and added the Behavior, Designer and Extender files to it.

Implement the ModalPopupAnimationExtender Class

Next, I added the code for the ModalPopupAnimationExtender class.  As you can see, all I have really done is added attributes to make sure the required animation scripts are included with the component, as well as exposing properties for the OnShow and OnHidden animations.  Finally, you will notice that my extender control also inherits from the AnimationExtenderControlBase class instead of the regular ExtenderControlBase class.  If you have the source handy for the UpdatePanelAnimationExtender control, you will notice these classes are almost identical.

/// <summary>
/// Extender used to play animations just before and after an ModalPopup is displayed
/// </summary>
[Designer(typeof(ModalPopupAnimationDesigner))]
[ClientScriptResource("todo", "todo.js")]
[RequiredScript(typeof(CommonToolkitScripts), 0)]
[RequiredScript(typeof(AnimationScripts), 1)]
[RequiredScript(typeof(AnimationExtender), 2)]
[TargetControlType(typeof(Control))]
public class ModalPopupAnimationExtender : AnimationExtenderControlBase
{
    // Animations
    private Animation _shown;
    private Animation _hidden;

    /// <summary>
    /// 
    /// </summary>
    [DefaultValue(null)]
    [Browsable(false)]
    [ExtenderControlProperty]
    public Animation OnShown
    {
        get { return this.GetAnimation(ref this._shown, "OnShown"); }
        set { this.SetAnimation(ref this._shown, "OnShown", value); }
    }

    /// <summary>
    /// 
    /// </summary>
    [DefaultValue(null)]
    [Browsable(false)]
    [ExtenderControlProperty]
    public Animation OnHidden
    {
        get { return this.GetAnimation(ref this._hidden, "OnHidden"); }
        set { this.SetAnimation(ref this._hidden, "OnHidden", value); }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPreRender(System.EventArgs e)
    {
        base.OnPreRender(e);

        this.ResolveControlIDs(this._shown);
        this.ResolveControlIDs(this._hidden);
    }

    /// <summary>
    /// 
    /// </summary>
    [ExtenderControlProperty]
    [DefaultValue("")]
    public string ModalPopupBehaviorID
    {
        get { return this.GetPropertyValue("ModalPopupBehaviorID", ""); }
        set { this.SetPropertyValue("ModalPopupBehaviorID", value); }
    }
}

Implement the ModalPopupAnimationBehavior JavaScript Behavior

My next task is to implement the JavaScript behavior for this control.  Fortunately, the regular ModalPopupExtender control already exposes a client side API for being notified when the popup is displayed and hidden.  All my behavior does is hook into these events and run the animations. 

Here is a little JavaScript snippet from my behavior.  Again, this code is almost identical to the UpdatePanelAnimationExtender's behavior.  First, I initialize the _shown and _hidden animations, then I fetch the ModalPopup's behavior so I can subscribe to the shown and hidden events.  All of this is done within the behavior's initialize function.  In the event handlers, I invoke the play methods for the animation.

initialize : function() {
    
    // Initialize the generic animation behaviors
    this._shown.initialize();
    this._hidden.initialize();

    //  fetch the component
    this._modalPopupBehavior = $find(this.get_ModalPopupBehaviorID());

    //  create and attach the onShown handler
    this._shownHandler = Function.createDelegate(this, this._onShown);
    this._modalPopupBehavior.add_shown(this._shownHandler);

    //  create and attach the onHidden handler
    this._hiddenHandler = Function.createDelegate(this, this._onHidden);
    this._modalPopupBehavior.add_hidden(this._hiddenHandler);        
},

_onShown : function(sender, args) {
    this._hidden.quit();
    this._shown.play();
},

_onHidden : function(sender, args) {
    this._shown.quit();
    this._hidden.play();
}, 

Add it to Your Page

Now for the fun part, adding it to your page.  To add support for running an Animation when the ModalPopup is displayed, you just include the ModalPopupAnimationExtender control and use the markup to define whatever Animations that should run right after the popup is displayed.  Here is a simple example.  Below is a ModalPopup with a fade's Animation that is run right after it is shown ... 

<% // Fade In %>
<asp:Panel 
    ID="pnlFadeIn" runat="server" BackColor="white" Width="300px" 
    HorizontalAlign="Center" style="display:none; padding:20px;">
    Did you notice how the popup faded in?<br />
    <asp:Button ID="btnOkFadeIn" runat="server" Text="OK" Width="50px" />
    <asp:Button ID="btnCancelFadeIn" runat="server" Text="Cancel" Width="50px" />
</asp:Panel>

<ajaxToolKit:ModalPopupExtender ID="mdlPopupFadeIn" BehaviorID="mdlPopupFadeIn" runat="server" 
    TargetControlID="btnFadeIn" PopupControlID="pnlFadeIn" 
    OkControlID="btnOkFadeIn" CancelControlID="btnCancelFadeIn" BackgroundCssClass="modalBackground" />

<mb:ModalPopupAnimationExtender 
    runat="server" ModalPopupBehaviorID="mdlPopupFadeIn" TargetControlID="pnlFadeIn">
    <Animations>
        <OnShown>
            <FadeIn Duration=".75" Fps="20" />                
        </OnShown>
    </Animations>
</mb:ModalPopupAnimationExtender>

Quirks

Of course there are a couple of quirks.  The first is that the ModalPopupAnimationExtender doesn't actually extend the ModalPopupExtender control.  I don't believe AjaxControlToolkit Extender controls were designed to support extending other extenders.  To work around this, the ModalPopupAnimationExtender needs to have the TargetControlID set to the popup panel (the sample panel the ModalPopupExtender is pointing to) as well as having its ModalPopupBehaviorID set to the BehaviorID for the ModalPopupExtender so it can find the correct Behavior and attach to its events.

The second quirk is that depending upon your animation, you might need to run a little code after the dialog is closed that resets the style elements back to their original values.  If you still have the original site open, try doing this:

  1. Click on the top Screenshot (notice there is a slight scale animation)
  2. Click CLOSE
  3. Click on the top Screenshot again - what happened to the scaling?

I am not sure, but I am guessing this might be because the popup wasn't restored to its original sizing after it was closed.  Here is another sample Animation that illustrates this.  This sample scales the ModalPopup out using the following markup ...

<OnShown>
    <Sequence>
        <Parallel Duration="1" Fps="50">
            <Scale ScaleFactor="1.5" Center="true" />
        </Parallel>
    </Sequence>
</OnShown>

With this Animation, a problem will occur when the dialog is opened more than once.  Because the original height and width are not reset, the dialog starts scaling from where the previous scale left off.  The screenshots below show this.  The first one is a how the dialog looks initially, the second one shows what it looks like after it has been displayed twice.

 

 

To overcome this, you can use the OnHidden Animation (which runs after the dialog has been hidden) to reset any style values back to their original values like so ...

<OnShown>
    <Sequence>
        <%-- Show the flyout --%>
        <Parallel Duration="1" Fps="50">
            <Scale ScaleFactor="1.5" Center="true" />
        </Parallel>
    </Sequence>
</OnShown>
<OnHidden>
    <Sequence>
        <%-- Reset the width/height --%>
        <StyleAction Attribute="width" Value="150px" />
        <StyleAction Attribute="height" Value="50px" />
    </Sequence>
</OnHidden>    

That's it. Enjoy!

 

[Update: 9/20/2007] From email with Ted:

From: Ted Glaza
To: Matthew Berseth <matt@mattberseth.com>
Sent: Thursday, September 20, 2007 8:37:05 AM
Subject: RE: Animating the ModalPopupExtender

Hi Matt,
Sorry – I wrote that a little too quickly.   Since it doesn’t utilize PopupExtender, you would need to modify ModalPopupExtender’s source.  Somewhere around eight extenders in the Toolkit make use of PopupExtender (look for _popupBehavior member variables in their behaviors) so they were able to trivially take advantage when it received generic animations.  ModalPopupExtender doesn’t use PopupExtender anymore because (if I’m remembering correctly) its display logic became too complicated once support for dragging, scrolling, etc., was added.  To add animations directly to ModalPopupExtender, you’ll want to modify its source and not perform the regular show/hide if animations are present.  Here’s an excerpt from PopupBehavior (making it visible and hidden again was a cross-browser positioning concession):.

        // Either show the popup or play an animation that does
        // (note: even if we're animating, we still show and position
        // the popup before hiding it again and playing the animation
        // which makes the animation much simpler)

        this._visible = true;
        var element = this.get_element();
        $common.setVisible(element, true);
        this.setupPopup();        // Position the popup (so if the user just fades it in, etc., they’re ready to go)

        if (this._onShow) {
            $common.setVisible(element, false);
            this.onShow();        // Play the animation
        } else {
            this.raiseShown(Sys.EventArgs.Empty);
        }

We have an existing work item to add animation support to ModalPopupExtender (and several other work items for other extenders), but we focus our efforts primarily on the highest voted items each release (and only 5 people have voted for this one).  Our next release will fix over 950 votes.
Thanks,

Ted

From: Matthew Berseth [mailto:matt@mattberseth.com]
Sent: Thursday, September 20, 2007 5:16 AM
To: Ted Glaza
Subject: Animating the ModalPopupExtender

Hi Ted -

Thanks for the feedback.  I have a couple of quick questions. 

- Are you suggesting to modify the source of the ModalPopupExtender?  When I first read you comment, I thought there was a way to use a combination of PopupExtender + ModalPopupExtender to get the functionality I was after. 

- Do you know why the ModalPopupExtender doesn't support OnShow and OnHide like all of the other controls you mention? 

Thanks Again,

Matt


TrackBack

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

Listed below are links to weblogs that reference Animating the ModalPopupExtender:

» September 23rd Links: VS, ASP.NET, ASP.NET AJAX, Silverlight, WPF from Top ASP.NET Items
Here is the latest in my link-listing series . Also check out my ASP.NET Tips, Tricks and Tutorials page [Read More]

» September 23rd Links: VS, ASP.NET, ASP.NET AJAX, Silverlight, WPF from ScottGu's Blog
Here is the latest in my link-listing series . Also check out my ASP.NET Tips, Tricks and Tutorials page [Read More]

» September 23rd Links: VS, ASP.NET, ASP.NET AJAX, Silverlight, WPF from Programming
Here is the latest in my link-listing series . Also check out my ASP.NET Tips, Tricks and Tutorials page [Read More]

Comments


Great post Matt!

As you hinted, it would also be possible to add animation directly to the ModalPopupExtender instead of using a second extender. If you crack open the source for PopupExtender (not PopupControlExtender), youll see how it has support to show and hide the popup element using generic animations. These animations were then leveraged by all the controls using PopupExtender like AutoCompleteExtender, DropDownExtender, PopupControlExtender, etc. The sample page for AutoCompleteExtender contains a live example.

Posted by: John Oswalt on September 20, 2007 12:00 AM

I believe that the site that you found is using the Lightbox JS library. It appears to be using a version 1 over the newest version 2. This library can be found at http://www.huddletogether.com/projects/lightbox/

Posted by: Alex Aspinall on September 21, 2007 12:00 AM

Although your way is probably more practical, a quick fix is to animate the popup by using the OnClick of the button (or a hidden button) that launches the popup (where btnLaunchPopUp is the target button and divSelection is the Panel that represents the Pop Up).









Posted by: Daniel on September 23, 2007 12:00 AM

This works great, though in practice it seems the values for the animations are interpreted differently in IE vs. Firefox using your extender, for example the fade in in IE is much slower than Firefox; have you experienced this or could it be a result of other controls at work?

Posted by: Pankaj on September 24, 2007 12:00 AM

Hey Matt....
nice work...
I also tried, using animations with modal popup and was successful also in achieving it, but can you please check if we can use ajax validator callout extender with animated popup???I tried it and after using animation, only that part of callout is visible which is inside popup boundaries...anything outside is getting cut???

Great post. I dont comment often but I am a regular reader of your blog.

@Daniel -

I havent seen this issue. Has anyone else encountered this?

Matt.

Posted by: Dan on November 20, 2007 12:00 AM

If you use the modalPopupAnimationExtender and have the target panel inside an update panel. If your doing a partial update in the panel when you show the popup..the animation doesnt account for this. Any suggestions?

Posted by: Praneet on January 10, 2008 12:00 AM

Great post Matt. I have implemented the modalpopup with flyout, resize and fade-in animation. Works great, but there is an issue with IE(v6 and v7). I have used a wireframe to resize and then faded-in the Modalpopup.The initial opacity of panel containing the popup is zero, and then it is faded-in. It works fine in firefox, i.e. the popup is displayed only at the end of other animations, but in IE the popup is displayed right from the start of other animations at the opacity of 10-20% even though it is completely transparent. I think there are transparency issues when i apply animations to popup. Is there a fix for it?

Posted by: Mahmood Sultan on January 20, 2008 12:00 AM

hi Matt:
I have used modalpopup animation extender but facing problem when I used update panel inside modalpopup, on partial update it set whole panel to its orignal value,
e. g, I set initially Div Width:0 after executing animation its width changes to 300px but after partial update its value reset to zero(which was initial value).
any suggestion will be appreciated.
Thanks

Posted by: Thomas on March 25, 2008 12:00 AM

Hi Matt,
I was using your modal popup animation control in my application with the AjaxToolKit 10301 release. When I tried using the new toolkit 3.5 I got errors regarding the modal popup animation. Any suggestions or perhaps a new version of the dll using the new toolkit.
Thank you in advance.

Posted by: benjib98 on July 22, 2008 12:00 AM

Hi Matt.
I have found your resourceful blog and decided to extend your modal popup animator. Unfortunately, when used a newer version of the AJAXControlToolkit, I got some conflicts and when replaced the assembly used in your control with a newer assembly, the control crashed.Can you advise me how it would be possible to fix this error?
thanks

Posted by: Sandeep Sachan on August 1, 2008 08:04 AM

Hi Matt,
Actually we are trying to use modalpopupextender in dotnetnuke cms, but when i tried to configure the controll with that page it got some serous issue.
My main intention is to call a modalpopup sort of things on Load of any page..
So will that be done?

Posted by: Prathamesh Dalvi on September 10, 2008 01:12 AM

Hi,

I am using ModalPopUpAnimationExtender for animating a popup which is user control. I am facing problems with the height and width of the popup.Please help me.

I've tried to use ModalPopupExtender in DotNetNuke site? but it's jammed in the top left corner, half of it cut off.

Posted by: Neetu on September 27, 2008 03:21 AM

hello
when i use this on linkbutton inside datalist...its throwing the error that linkbutton not found....and when i user button click event to show popup....page is posting back...please tell me the solution....how to use this for a button inside datalist......

Thank You

Hey Matt,

Great post.

I encountered the same problem as Neetu.
If you embedd the extender in a DataList or ListView there is a javascript error saying: 'this._modalPopupBehavior' is null or not an object.

Any idea to fix that?

Cheers,
Michael

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.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • Michael Ulmann wrote: Hey Matt, Great post. I encountered the same problem as Neetu. If you embedd the extender in a Dat...
  • Neetu wrote: hello when i use this on linkbutton inside datalist...its throwing the error that linkbutton not fou...
  • BLER wrote: I've tried to use ModalPopupExtender in DotNetNuke site? but it's jammed in the top left corner, hal...
  • Prathamesh Dalvi wrote: Hi, I am using ModalPopUpAnimationExtender for animating a popup which is user control. I am facing...
  • Sandeep Sachan wrote: Hi Matt, Actually we are trying to use modalpopupextender in dotnetnuke cms, but when i tried to con...
  • benjib98 wrote: Hi Matt. I have found your resourceful blog and decided to extend your modal popup animator. Unfortu...
  • Thomas wrote: Hi Matt, I was using your modal popup animation control in my application with the AjaxToolKit 10301...
  • Mahmood Sultan wrote: hi Matt: I have used modalpopup animation extender but facing problem when I used update panel insid...