Archive

Archive for the ‘AJAX’ Category

Populating Select Lists in ASP.NET MVC and jQuery

September 25, 2009 Comments off

I’ve been working the last bit to find the best way to create/populate select (option) lists using a mixture of ASP.NET MVC and jQuery.  What I’ve run into is that the “key” and “value” tags are not passed along when using Json(data).

Here’s what I’m trying to pull off in jQuery: building a simple select drop down list.

var dd_activities = “<select id=’dd_activities’>”;
var count = data.length;
for (var i = 0; i < count; i++) {
 dd_activities += “<option value='” + data[i].Key + “‘>” + data[i].Value + “</option>”;
}
dd_activities += “</select>”;

$(“#activities”).before(dd_activities);

Using some very basic key/value data:

[
 {“3″,”Text Value”},
 {“4″,”Another Text Value”},
 {“1″,”More boring values…”},
 {“2″,”Running out of values”},
 {“5″,”Last value…”}
]

Without any sort of name, I was at a loss on how to access the information, how to get it’s length, or anything.  FireBug was happy to order it up… but that didn’t help.
 
My first attempt was to use a custom object, but that just felt dirty—creating NEW objects simply to return Json data.
 
My second attempt matched the mentality of newing new anonymous Json objects and seemed to work like a champ:
 

[Authorize]

[CacheFilter(Duration = 20)]

public ActionResult GetActivitiesList()

{

    try

    {

        var results =

        _activityRepository

            .GetAll()

            .OrderBy(x => x.Target.Name).OrderBy(x => x.Name)

            .Select(x => new

                {

                    Key = x.Id.ToString(),

                    Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

                })

            .ToList();

 

        return Json(results);

    }

    catch (Exception ex)

    {

        return Json(ex.Message);

    }

}

 
Well, not beautiful, but returns a sexy Key/Value list that Json expects—and that populates our select list.
[
 {“Key”:”3″,”Value”:”Text Value”},
 {“Key”:”4″,”Value”:”Another Text Value”},
 {“Key”:”1″,”Value”:”More boring values…”},
 {“Key”:”2″,”Value”:”Running out of values”},
 {“Key”:”5″,”Value”:”Last value…”}
]
The next step was to get that out of the controller and into the data repository… pushing some of that logic back down to the database.
 

var criteria =

    Session.CreateCriteria<Activity>()

    .CreateAlias(“Target”, “Target”)

    .Add(Restrictions.Eq(“IsValid”, true))

    .AddOrder(Order.Asc(“Target.Name”))

    .AddOrder(Order.Asc(“Name”))

    .SetMaxResults(100);

 

var data = criteria.List<Activity>();

var result =

    data

        .Select(x => new

            {

                Key = x.Id.ToString(),

                Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

            })

        .ToList();

tx.Commit();

return result;

 
A bit of formatting, restrictions, push the ordering back to the database, and a tidy SQL statement is created.
 
The last touch is the return type.  Since we’re returning a “List” of anonymous types, the return type of GetActivitiesList() must be an IList.
 
That shrinks down my ActionResult to a single call.
 

try

 {

     return Json(_activityRepository.GetActivitiesList());

 }

 catch (Exception ex)

 {

     return Json(ex.Message);

 }

 
That works… and will work for now.  Though, I’ve marked it as a HACK in my code.  Why?  I’m honestly not sure yet.  Just a feeling.

Html.Grid Rendering as Plain Text?

September 23, 2009 1 comment

Notice: Stupid, stupid moment described ahead.  Proceed with caution.

I spent a good half hour trying to figure out why my MVCContrib Html.Grid<T> wasn’t rendering.  It wasn’t throwing an error, it was simply returning the HTML code as Plain Text.

  • The AutoMapper code looked good,
  • The Html.Grid<T> code looked good (it’d be templated off another page anyway and that page was working),
  • The view model code looked good.

So why was I being greeted with garble junk?

${Html.Grid(Model.Details) .Attributes(Id => “RoutineDetails”) .Columns(column => { column.For(c => this.Button(“EditDetail”).Value(“Edit”).Id(string.Format(“edit_{0}”, c.Id))).DoNotEncode(); column.For(c => c.Activity.Target.Name).Named(“Target Area”); column.For(c => c.Activity.Name).Named(“Activity”); column.For(c => c.Sets); column.For(c => c.Weight); column.For(c => c.Repetitions); column.For(c => c.Duration); })}

Html.Grid that is not… well, at least not properly.

Encoding issue? Maybe. Data issue? Perhaps.

No, the issue was typing too quick and not paying attention.

public ActionResult New()

 {

     var viewModel = BuildRoutineNewViewModel(new Routine());

     return View();

 }

Yeah, that’s the problem… right there.  I’d forgotten to pass the view model into the View.  Apparently the Html.Grid<T> helper simply panics if the model you’re reading from is empty or null—rather than throwing an error.

Oddly enough, this is one of those times I’d wish the screen would have lit up red.  Lessons learned.

Rendering the Web Equally on Mobile Devices

June 26, 2009 Comments off

I’ve been digging through the Interwebs for a while now and, I thought, had worked out all of the “kinks” of rendering on a mobile device—specifically iPhones.

The special ‘viewport’ meta tag means the world to iDevices.

meta name=“viewport” content=“width = device-width” />

I’m faced with a new challenge—the Palm Pre’s built-in web browser.  My shiny new phone is great, but it isn’t without glitches.

The first glitch I’ve found appears to be a DNS issue— http://myserver/web won’t resolve; however, http://123.45.67.89/web will.  It seems to be touchy.  Most of our webs work just fine, others don’t.  I haven’t narrowed it down to a single server or architecture as it seems to be a bit of everything.  Wonky.

The next glitch is more important—the rendering.  One of our tools is a simple form-based tool that looks great on the iPhone; however, renders partial screen and “garbles” when you move around the screen.

Palm Pre:

Garbled image

iTouch/iPhone:

I’ve also found that anything in an ASP.NET Update Panel (like those Select buttons) are unusable.  Other webs I’ve used (Bank of America, etc) use AJAX just fine, so I don’t think it’s that—probably a coding issue I need to dig into and resolve.

UPDATE: Explicitly adding “LoadScriptsBeforeUI=’true’” to the ASP.NET ScriptManager seems to help with this.. a little.

Anyone else worked specifically with the Pre devices and rendering?  I’d appreciate any meta tags or layout ideas that worked. ๐Ÿ™‚  The Pre isn’t a common device in our organization—yet.

Implementing IEPNGFix as a Reusable Control

January 30, 2009 4 comments

Even with IE 8.0 on the horizon, a great deal of our internal users are still using IE 5.5 and 6.0.  While, for the most part, our current coding techniques are unaffected, we did move to using PNG files quite a while ago and are faced with rendering issues as the target audience for a few of our produces expands.

To solve those issues, I’ve been using TwinHelix’s IE PNG Fix behavior with a great deal of success; however, I dislike keeping track of multiple files and references between projects.  It made more sense to make it a reusable control and include it in our shared architecture library.  When Angus releases a new implementation, then I only need to update the control and push out the updated libraries rather than touching HTML in each project.

Here’s how:

1. Download the latest version of IE PNG Fix from here.

2. Add the IEPngFix.htc, blank.gif, and IEPngFix_tilebg.js (if using 2.0 Alpha 3) into your project.  Mark all three files as Embedded Content.

3. Create a basic CSS file that can be added to pages and call the IEPngFix behavior.  Use the full path to the Web Resource (we’ll add those in the next step).  It’s sensitive to the namespace of your project.

img, div, .pngfix, input {

    behavior: url(‘<%=WebResource(“Resources.IEPngFix.htc”)%>’);

}

3. Modify the Properties/AssemblyInfo.cs file and add the approprate Web References.

[assembly: WebResource(“Resources.IEPngFix.css”, “text/css”,

       PerformSubstitution = true)]

[assembly: WebResource(“Resources.IEPngFix.htc”, “text/x-component”,

       PerformSubstitution = true)]

[assembly: WebResource(“Resources.IEPngFix_blank.gif”, “image/gif”)]

[assembly: WebResource(“Resources.IEPngFix_tilebg.js”, “text/javascript”)]

Notice that the HTC behavior file is an “x-component”.  For a full list of MIME references, check out the w3schools.com.  Also, perform substitution allows us to use dynamic calls of resources—within resources, such as in our CSS file.

4. Create a new class that inherits from CompositeControl.  This control will add the javascript and CSS references into our projects.  Override the OnPreRender method and populate the calling Page’s header with the links to our two files.

protected override void OnPreRender(EventArgs e)

{

       // Base Code: http://www.twinhelix.com/css/iepngfix/

       // Include JavaScript for tiled background support.

       string javascriptInclude =

              Page.ClientScript.GetWebResourceUrl(GetType(),

             “Resources.IEPngFix_tilebg.js”);

           

       var jsLink = new HtmlLink

              {

                     Href = javascriptInclude

              };

       jsLink.Attributes.Add(“type”, “text/javascript”);

       Page.Header.Controls.Add(jsLink);

           

       // Include Css file that calls HTC.

       string cssInclude =

              Page.ClientScript.GetWebResourceUrl(GetType(),

             “Resources.IEPngFix.css”);

           

       var cssLink = new HtmlLink

              {

                     Href = cssInclude

              };

       cssLink.Attributes.Add(“rel”, “stylesheet”);

       cssLink.Attributes.Add(“type”, “text/css”);

       Page.Header.Controls.Add(cssLink);

 

       base.OnPreRender(e);

}

That’s it.  Build and add the new control to your project.  You can then add a new forms page and drop the control into the page.  I prefer, however, to keep a “DefaultPage” and inherit my pages from it—add once, apply to all. ๐Ÿ™‚

protected void Page_Load(object sender, EventArgs e)

{

       Page.Controls.Add(new IEPngFix());

}

Here we can see the rendered control. The PNG has a transparent background and without IEPngFix shows up as a white box rather than seeing the black background of the page.  Works like a champ!

IEPngFix in Action

Thanks again to Angus Turnbull for this excellent behavior!

Tags: , , , ,

Using xUnit.net in ReSharper 4.1 and MVC

September 11, 2008 1 comment

Ben Taylor has saved us all a HUGE load of frustration by releasing a patched version of the xUnit.net installer and libraries that works with ReSharper 4.1.

There’s a final step, however, if you want it to work with the MVC Framework (this is for Preview 5).

The default xUnit.net MVC template package includes a 3rdParty directory for the xUnit.dll file.  The Test project also references that same library for the context of the tests.  To take advantage of Ben’s new 4.1’esque library, you need to update the 3rdParty file with his or you’ll be seeing red.

Steps:

1. Open your MVC Test project.

2. Remove (delete) the 3rdParty/xunit.dll.

3. Add an Existing File to the 3rdParty directory, pointing to the new library from Ben.

4. Under the Test project’s References, refresh the xunit reference and be sure it’s picking up the new file (the caution icon should disappear).

5. Run your tests in ReSharper and be very happy. ๐Ÿ™‚

Working MVC tests with xUnit and Ben's Patch.

VS2008 and .NET 3.5 SP1 Success

August 12, 2008 Comments off

Danger, danger!Well, I’m 1/4 now upgrading the VMs to SP1.  The “one” that worked is the one I least expected.

Machine 1:

A simple VM used for a basic web project.  C#, Web Developer Tools installed—not even joined to the network.  No “hotfixes” were installed, but I ran the tool anyway just to be sure.  It chugged for a while and then threw an exception.  Feeling daring, I went ahead and tried to upgrade to SP1 and it didn’t even detect Visual Studio or .NET 3.5.  Hah.

Machine 2:

A prototyping VM that I copy web apps onto to run and test—nothing major, just VS2008, C#, web test tools, etc.  This one did have SP1 beta on it that I was dinking with as well as various Silverlight tools.  The patch removal tool worked just fine.  After a reboot, the SP1 installation got about 20% complete then McAfee (mcshield.exe) threw about 70 exceptions all at once and flooded the task bar.  The system then BSOD’d and reboot.  I tried another couple times to install SP1 (I can’t disable McAfee, ePO prevents it) with no success.

Machine 3:

This VM provides a test system for our customers to connect to, evaluate applications, and such.  VS2008 and .NET 3.5 (no SP1 beta) was installed more for convenience than anything else.  The system isn’t in use for the next few weeks, so worth a shot on this one.  I didn’t run the patch removal tool (perhaps that was my mistake) on this workstation and proceeded with installing SP1.  About 80% through the installation, devenv.exe crashed and asked to be debugged—of course, when I tried to debug, it crashed.  Hah.

Machine 4:

This is the one that worked; however, it’s the oddest, most broken of the bunch.  It’s had SP1 beta on it, various MVC preview builds, Astoria, bunches of Silverlight tools as well as various libraries and code bunches I have for newsgroup and forum posts.  The patch removal tool found a bunch of stuff and remove it without any issues.  After the reboot, SP1 installed (took about 45 minutes) and the system reboot.

And it works…

It works!

Seriously… why?

I still have a few VMs left to dink with and plan to throw it on my development workstation later this week after I wrap up a few projects and have some down time (I had planned to rebuild the entire workstation anyway—so good opportunity).

I hope, after I find some basic installation method, to have time to dig in to the features…

Wrapping Up CrossBrowserUpdateProgress Into a Control

August 11, 2008 Comments off

Download the Source.

A few weeks ago, I wrote about the joys of trying to create a cross browser UpdateProgress panel (or more to the point, work around oddities with IE6 CSS).

The post was fine, and the method works quite well; however, it’s not easily reproducable in it’s current form.  A custom web control; however, would solve that in a snap.

In this custom control, I’ll:

  • Determine if it’s IE6 or not and apply the approprate CSS
  • Accomodate the glitch where DropDownLists shine through in IE6
  • Provide public properties for the AssociatedUpdatePanelId and the text to appear in the UpdateProgress

Later on, I’ll probably tweak this to simply make the ProgressTemplate a public property—just like a standard UpdatePanel; however, for now, this meets the needs—a basic update progress control.  Simple is good. ๐Ÿ™‚

Basic CBUP

On the ASPX side, the code usage is quite simple:

<ts:CrossBrowserUpdateProgress runat=”server” ID=”cbup”

AssociatedUpdatePanelID=”UpdatePanel1″
DialogText=”Please wait…” />

Behind the scenes, the code is pretty spartan.  The WebControl renders an UpdateProgress control, applies the DialogText and AssociatedUpdatePanelID properties, creates the ProgressTemplate with the IFrame (to fix IE6 drop down lists), modal background, and the dialog itself.  Let’s take a look at the code.

There are three methods that are overridden: OnPreRender (to set the CSS), RenderContents (to create the controls and set a final ZIndex for IE6), and the actual CreateChildControls.

OnPreRender

Thankfully, the Request object has a helpful HtmlBrowserSpecifications array that keeps track of properties such as the browser, versions, javascript compatibility, etc.  From this, we can determine our IE 6 users and provide the approprate CSS.

protected override void OnPreRender(System.EventArgs e)

{

if (this.Context.Request.Browser.Version == “6.0” &&

this.Context.Request.Browser.Browser == “IE”)

{

       var ie6Css =

Page.ClientScript.GetWebResourceUrl(GetType(), “ie6.css”);

var iis6CssLink = new HtmlLink { Href = ie6Css };

       iis6CssLink.Attributes.Add(“rel”, “stylesheet”);

       iis6CssLink.Attributes.Add(“type”, “text/css”);

       this.Page.Header.Controls.Add(iis6CssLink);

}

 

var generalCss =

Page.ClientScript.GetWebResourceUrl(GetType(), “general.css”);

var generalCssLink = new HtmlLink { Href = generalCss };

       generalCssLink.Attributes.Add(“rel”, “stylesheet”);

       generalCssLink.Attributes.Add(“type”, “text/css”);

       this.Page.Header.Controls.Add(generalCssLink);

 

       base.OnPreRender(e);

}

The CSS files are included as embedded resources (and should be approprately marked in the AssemblyInfo.cs) with the control.

RenderContents

RenderContents is nice and simple—set the ZIndex of the entire control, make sure that everything is in place, and render!

protected override void RenderContents(HtmlTextWriter output)

{

output.AddStyleAttribute(HtmlTextWriterStyle.ZIndex, “99999999”);

       EnsureChildControls();

       base.RenderContents(output);

}

Is the ZIndex necessary?  Quite frankly, I’m not sure.  For IE6, 3/5ish tests failed WITHOUT it—the drop down lists still shined through in spite of the IFrame.  Having it in there seemed to guarantee it working.  Your mileage may vary. ๐Ÿ™‚

CreateChildControls

The CreateChildControls method is responsible for generating the actual UpdateProgress control and adding it to the WebControl for rendering.

protected override void CreateChildControls()

{

base.Controls.Clear();

 

       if (!ChildControlsCreated)

       {

              var baseProgress = new UpdateProgress

             {

                     DisplayAfter = 100,

DynamicLayout = false,

AssociatedUpdatePanelID = AssociatedUpdatePanelID,

ProgressTemplate = new ProgressTemplate()

};

this.Controls.Add(baseProgress);

 

}

base.CreateChildControls();

}

Seems a bit to easy, huh?  It is.  Notice that the ProgressTemplate is creating a new ProgressTemplate?  ProgressTemplate is a Template (or ITemplate) and to dynamically assign it, I had the best luck creating an internal class to handle rendering the template—this is where the guts of the control actually fall.

ProgressTemplate

The only required method of an ITemplate is InstanciateIn(Control) and I’m more than happy to accomdate.

/// <summary>

/// Fake ProgressTemplate for the UpdatePanel.ProgressTemplate.

/// </summary>

internal class ProgressTemplate : ITemplate

{

public void InstantiateIn(Control container)

       {

// Create IFrame for IE6 “coverups” of drop down lists.

       if (HttpContext.Current.Request.Browser.Version == “6.0” &&

HttpContext.Current.Request.Browser.Browser == “IE”)

{

var iFrame =

new LiteralControl(@

<iframe id=’UpdateProgressHideSelect’>

</iframe>”);

container.Controls.Add(iFrame);

 

       }

       var progressBackground =

new LiteralControl(@

<div id=’UpdateProgressModalBackground’>

</div>”);

 

var progressDialog =

new LiteralControl(@

<div id=’UpdateProgressPanel’>

<div id=’UpdateProgressText’>” +

_dialogText +

“</div></div>”);

 

                container.Controls.Add(progressBackground);

                container.Controls.Add(progressDialog);

}

}

To access the _dialogText inside the internal ProgressTemplate class, you can either pass it as a variable when you create ProgressTemplate OR set your private field to static.

Put that all together and the output HTML is nice and tidy:

<span id=“cbup”>

<div id=“ctl03”

style=“z-index: 99999999; visibility: hidden; display: block;”>

<div id=“UpdateProgressModalBackground”/>

<div id=“UpdateProgressPanel”>

<div id=“UpdateProgressText”>Please wait…</div>

</div></div>

</span>

There’s still work to do, but it provides a nice base to toss in my controls library.

IE6 Causes Z-Index Nightmares…

Rather than update the post from yesterday, this chaos deserves it’s own post.

Yesterday, I discussed layering Modal Popup Extenders with the Update Progress controls.  In IE7, FF3, and, well, most everything except IE6, it works like a champ as-is.

The “bug”?  After quite a bit of research, the problem revolves around the following issues:

  • lack of support for the { position: fixed } property,
  • lack of support for the { right; bottom} properties,
  • … unreliable suport for {height: 100%, width: 100% } properties,
  • general pain and suffering
  • <SELECT> tags (or ASP:DropDownList objects) exist above any other z-index,

I’m sure there were other issues.  Really.

After spending a good part of the day trying code, looking it up on QuirksMode, and trying again, I have somewhat of a solution; however, I still greatly dislike how it works in IE6.

On the MasterPage, I have a single UpdateProgress that isn’t associated to a specific UpdatePanel.  Therefore, it’ll catch all Async postbacks (and I only have ONE UpdateProgress control).

<asp:UpdateProgress

runat=”server” DisplayAfter=”100″ ID=”UpdateProgress”>

<ProgressTemplate>

<div class=”UpdateProgressModalBackground”></div>

<div class=”UpdateProgressPanel”>

<h3>Please wait…</h3>

<img src=”Images/ajaxbar.gif”
alt=”Please wait…”

style=”text-align: center; width: 100%; height: 10px; />

</div>

</ProgressTemplate>

</asp:UpdateProgress>

This, again, references our UpdateProgressModalBackground and UpdateProgressPanel styles.  These two styles are unchanged from the post yesterday.  Here they are again for reference:

/* UpdateProgressPanel is above EVERYTHING ELSE,

even other modal popups */

.UpdateProgressPanel

{

       z-index: 99999999;

       background-color:#fff;

       color:#fff;

       width: 200px;

       text-align: center;

       vertical-align: middle;

       position: fixed;

       bottom: 50%;

       left: 45%;

       padding: 10px;

       border: solid 2px #5D7B9D;

}

 

.UpdateProgressModalBackground

{

    z-index: 99999998;

    background-color: #6D7B8D;

    position: fixed;

    top: 0;

    left: 0;

    height: 100%;

    width: 100%;

    min-height: 100%;

    min-width: 100%;

    filter: alpha(opacity=50);

    opacity: 0.5;

    -moz-opacity: 0.5;

}

The UpdateProgress and these two classes work just fine in IE7+, FF2+.  So, now to fix IE6..

So, what’s the difference in IE6?  Well, we can’t use the positioning attributes in the above classes–-they won’t work properly. 

Issue #1 – Fitting the Popup and Background Without Positioning Attributes

Searching the web, I found an article by Damien White discussing his his same pains with this.  His solution involved using the IE-specific CSS “expressions” to calculate the height and width of the window.

height:

expression(

        document.documentElement.scrollTop +

        document.documentElement.clientHeight + “px”);

 

width: expression(document.body.clientWidth + “px”);

However, at least for me, Damien’s expressions wouldn’t handle scrolling down the page.

Damien explains:

The thinking behind this was to take the window height (which document.documentElement.clientHeight gives us) and then add the scroll top position, which will give us the upper portion if the user scrolls up.  The problem shows itself when the user scrolls down; that area is not covered.  The good thing about this is that I didn’t need to mess with the body height, but the solution isn’t optimal in the long haul.

That’s a bad deal because that’s the whole point!  Reading a bit more, there was a comment from Kunal Mukherjee on Damien’s post that solved the problem.

Kunal’s expressions looked at the scrollHeight of the window as compared to the offsetHeight and returned the larger.

height: expression(

document.body.scrollHeight > document.body.offsetHeight
? document.body.scrollHeight
: document.body.offsetHeight + ‘px’ )
;

Actually, that works really well. Cool.

Finally, I’d recommend, as Damien did, breaking out your CSS into two files—one for “IE6” and one for everyone else.  This is easily done using the IE-specific conditional statements.

<!–[if lt IE 7]>
<link rel=”stylesheet” type=”text/css” href=”App_Themes/ie6/ie6.css” />
<![endif]–>

I also included !important flags on each of the properties in the ie6.css file—just to be safe.

Issue #2 – IE6 Pushes <SELECT> tags above everything else…

This is where the solution gets dicey; however, I’m relying on Kunal’s solution again.  In his comment, he pointed out a way to hide <SELECT> tags in IE6 without causing the disappearing act that the ModalPopupExtender causes—cover them with an IFRAME.

To me, this hack seems… sketchy at best, but it works.

In the ProgressTemplate of the UpdateProgress control, add in the IFRAME.

<iframe id=”UpdateProgressHideSelect”></iframe>

In the default.css (or the non-ie6.css, whatever you’ve called it), I recommend setting the iframe’s style to {display: none}—it isn’t needed outside IE6, don’t render it. ๐Ÿ™‚

On the ie6.css, add the UpdateProgressHideSelect in—along with another expression to place the iframe over the entire page (like the standard BackgroundCssClass of a ModalPopupExtender):

#UpdateProgressHideSelect

{

    z-index: 15000;

    position: fixed;

    top: 0;

    left: 0;

    background-color: #fff;

    border: none;

    filter: alpha(opacity=0);

    -moz-opacity: 0;

    opacity: 0;

    height: 100%;

    width: 100%;

    display: inline !important;

}

 

* html #UpdateProgressHideSelect

{

    position: absolute;

    height: expression(

document.body.scrollHeight > document.body.offsetHeight

? document.body.scrollHeight

: document.body.offsetHeight + ‘px’);

}

The z-index of 15000 for the iframe ensures that it appears above the normal 10000 of a ModalPopupExtender panel; however, under our crazy high UpdateProgress control.

Problem solved—for now.

Here’s how they look, side by side.

FireFox 3:

FireFox 3 Output

Nice and clean, properly centered given the size of the box and window size.  Can see drop down lists and MPE behind the UpdateProgress, but cannot access them.

IE 7:

IE7 Output

Output as expected and where expected.  Can see drop down lists and MPE behind the UpdateProgress, but cannot access them.

IE 6:

IE6 Output

Output as expected—basically where expected.  Drop down lists are hidden behind the IFRAME to prevent input.  Other controls are visible, including the MPE, but behind the background.

What fun!

Layering Modal Popups using CSS Z-Index

I really like the Modal Popup Extender (MPE) (see various articles here) and the “feel” that it adds to sites.  It’s useful for collecting information, changing information, or simply informing the user that something has happened.

But what happens when you need two popups at the same time?

In a recent project, I used the MPE to provide options when a user added or imported records into a system.  However, I also wanted to provide an UpdateProgress panel that would appear OVER the modal popup panel.  To do this, I needed to redefine the z-index css attributes to properly layer the controls.

My requirements were simple:

  • The MPE should appear over all “pages”.
  • The MPE “Backgrounds” (the BackgroundCssClass of the MPE) should appear just behind the MPE.
  • The UpdateProgress and it’s background should appear over EVERYTHING else.
  • The UpdateProgress and the MPEs should scroll and resize according to the browser.
  • Everything must be cross-browser (of course).

UPDATE: While this works BEAUTIFULLY in IE7, IE8, FF2, and FF3–-it totally borks out in IE6.  Working on a fix nowIE6 Causes Z-Index Nightmares

The Modal Popup Panel

The MPE

The modal popup panel is pretty standard.  The z-index of 1000 basically puts it above most everything else on the screen.

.ModalPopupPanel

{

    z-index: 1000;

    width: 400px;

    border: solid 2px #5D7B9D;

    background-color: #F5F5DC;

    padding: 10px 10px 10px 10px;

}

The UpdateProgress Popup Panel

The UpdateProgress Popup Panel

The UpdateProgress panel is also quite standard—a white box, border, and animated .gif image to keep users entertained during longer processes.  For this, the z-index is set outrageously high just for safety.  Remember: I want the UpdateProgress above EVERYTHING else.

.UpdateProgressPanel

{

/* UpdateProgressPanel is above EVERYTHING ELSE, even other modal popups */

       z-index: 99999999;

       background-color:#fff;

       color:#fff;

       width: 200px;

       text-align: center;

       vertical-align: middle;

       position: fixed;

       bottom: 50%;

       left: 45%;

       padding: 10px;

       border: solid 2px #5D7B9D;

      

}

The Modal Backgrounds

Behind the MPE and UpdateProgress backgrounds, you see a nice blue slate gray color, that’s handled by the ModalBackground class (the BackgroundCssClass attribute of the ModalPopupExtender control. 

.ModalBackground,

.UpdateProgressModalBackground

{

       background-color: #6D7B8D; /* Blue Slate Gray */

       position: fixed;

       top: 0;

       left: 0;

       height: 100%;

       width: 100%;

       min-height: 100%;

       min-width: 100%;

       filter:alpha(opacity=50);

       opacity:0.5;

       -moz-opacity: 0.5;

}

 

.ModalBackground

{

/* Just below a ModalPopupPanel */

    z-index: 999;

}

 

.UpdateProgressModalBackground

{

/* Above everything else, except an UpdateProgressPanel */

    z-index: 99999998;

}

To save some reuse, the ModalBackground and UpdateProgressModalBackground share the same attributes; however, I’ve specified the z-index separately to ensure that the UpdateProgressModalBackground appears ABOVE the regular ModalBackground. 

 

These combine to create a nice layered effect.  Now, even when a MPE is visible, the UpdateProgress still appears over it and prevents user entry.

 

UpdatePanel over MPE

 

 

 

 

A lull…

July 24, 2008 Comments off

As projects wind down, it’s been quite the administrative lull lately.  Projects are done and rolling out the door; paperwork is ramped up and covering my desk. ๐Ÿ˜ฆ  Hopefully, over the next few weeks, some new fun and excitement will jump in the door—including a new project involving mobile devices (yay!).

If not, maybe it’ll give me time to get back into experiment mode and kick around the new ASP.NET MVC Preview 4 and ASP.NET AJAX 4.0 Preview.  I haven’t had nearly enough time to dink at home—all this newfound housework takes a LOT of time and energy. Heh.