Creating Modal Windows with Coolite

One of the most popular effects in web development, is the modal dialog.  Using standard CSS we are able to create the appearance of a modal dialog on a webpage that can be used to provide a quick login form, more information, or any of a thousand other things.  Naturally, most UI frameworks have this effect built-in so developers can quickly create this effect without having to worry about cross browser problems; Coolite is no exception.

Generally, the way this is achieved is a

is placed somewhere on the page (usually at the bottom) and is targeted with JavaScript which does some fanciness to give it various look-and-feel properties.  Coolite is slightly different, but in a way that makes more sense.  It leverages the idea of the “viewport” as the main page, that is what the user see’s without the modal.  In Coolite we would define this as such:

<ext:ViewPort ID="vp1" runat="server" AutoHeight="true">
    <Body>
    </Body>
</ext:ViewPort>

The basic idea here is that the viewport serves as a wrapper for your main content.  So we could define our main UI here, for this example we will simple put a button which opens the modal.

<ext:ViewPort ID="vp1" runat="server" AutoHeight="true">
    <Body>
        <ext:Button ID="btnOpen" runat="server" Text="Open"
            Icon="Application">
            <Listeners>
            </Listeners>
        </ext:Button>
    </Body>
</ext:ViewPort>

Next we define the code for our Modal window, for this example, we are going to constrain the width and put some lipsum text

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

<ext:Window ID="Window1" runat="server" AutoHeight="true" Width="400" Constrain="true"
    Modal="true" ShowOnLoad="false" ButtonAlign="Right" Title="Modal Window">
    <Body>
        Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum
        has been the industry's standard dummy text ever since the 1500s, when an unknown printer
        took a galley of type and scrambled it to make a type specimen book. It has survived not
        only five centuries, but also the leap into electronic typesetting, remaining essentially
    </Body>
    <Buttons>
        <ext:Button ID="btnClose" runat="server" Text="Close" Icon="Cancel" />
    </Buttons>
</ext:Window>

So this is fairly simple and straightforward.  We have defined our main layout in a ViewPort and then we have defined external layout elements (the modal) in Windows that are defined outside the ViewPort.  I defined only the essential properties of the modal, but there are quite a few properties, such as X and Y to define the starting location of the modal.

However, we are missing one critical element; with this current code there is no way to show the modal to the user.  There are two ways to do this, and your selection of the means to do this will depend on your scenario.  You can open this with both JavaScript and the .NET code behind.  In JavaScript, we simply add a listener node and listen for the “Click” event.  Thus our buttons definition looks like this:

<ext:Button ID="btnOpen" runat="server" Text="Open"
    Icon="Application">
    <Listeners>
        <Click Handler="Window1.show();" />
    </Listeners>
</ext:Button>

This is the approach I like to take for simple calls, just define the Handler property with the JavaScript you want.  Its a “do it once and throw it away’”.  However, if you’re going to duplicate logic and call it throughout the page, I would then define the Fn property and centralize all that logic in a single function.

In addition, the Window component has many events that you can catch, with JavaScript or Server-side code, though client side will be much easier to understand.  I will list out some of the more useful ones that I have used:

  • BeforeShow – fires just before the modal is shown to the user.  Useful as a means of resetting modal content from an pre-existing operation.
  • BeforeHide – fires just before the modal disappears from the users view
  • Hide – fires after the modal is closed via a call to hide() on the Window element
  • Show – fires after the modal is shown to the user

So as I mentioned the same effect can be accomplished using AjaxEvents.  To do this you would simply update the Button definition removing the node with the note, like such:

<ext:Button ID="btnOpen" runat="server" Text="Open"
    Icon="Application">
    <AjaxEvents>
        <Click OnEvent="btnOpen_Click">
            <EventMask ShowMask="true"
                Msg="This is a Loading Mask" />
        </Click>
    </AjaxEvents>
</ext:Button>

This defines that for the button the Click event raises an AjaxEvent which is handled by the btnOpen_Click method in the page code behind.  From this position you have access to related page elements.  What does it mean to be related?  I honestly dont know, this is one of the aspects of Coolite that is largely undocumented.  From what I can gather, it seems to be the parent container, though you can define a specific form to link to the AjaxEvent, via the FormID attribute.

Notice that we are also defining a mask to be visible when this event is occurring.  Remember that we are going back to the server, so it makes sense to give the user some feedback; thus in the event the operation takes time the user is notified and appropriate interactions can be prevented.  To give you an idea what the code behind method looks like in this case, here is what btnOpen_Click looks like:

protected void btnOpen_Click(object sender, EventArgs ev)
{
    Window1.Show();
}

Very simple and straightforward.  You could imagine having checks in here to prevent the modal from showing if certain conditions were not met, or populating modal elements with server data.

To conclude, the big thing to remember about Coolite modals, is that they must be placed outside a ViewPort component with the Modal property set to true.  There a wide variety of properties that you can configure for the window to improve the look and feel of the modal as well as positioning.  Modals provide a great way to display related information or provide a drill down into data, they can be used to simplify interfaces and provide more elegant ways to access commonly used functionality, while continuing to move the web application closer to the goal of behaving like a desktop application.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s