Layering Modal Popups using CSS Z-Index

24 07 2008

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

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

 

 

 

 





It’s going to be one of those days…

14 07 2008

VS2008 has crashed 20+ times today.  Reboots aren’t helping.  I’m slowly uninstalling plug-ins at the moment.  Ugh.

Obviously a Monday

I broke'd it...

Tags: ,




Wrapping TabPanel Tabs With A Simple CSS Change

10 07 2008

The last few weeks have been filled with taking an old ASP legacy application and updating it to ASP.NET.  Fun stuff and not to challenging.

However, a “feature” of the AJAX Control Toolkit’s TabContainer finally hit a nerve.  In the past, I’ve ignored the fact that I couldn’t “wrap” the tabs or set how many rows of tabs to create.  I chalked it up to an annoyance and designed applications with this in mind.

After hunting through the Control Toolkit’s source code, the problem is simple.  There’s a line in the CSS explicitly telling it not to wrap.

Well, recompiling the toolkit can get annoying and hurts mobility of your applications—it’s no fun to bundle “custom” copies for a simple styling change.

.ajax__tab_header

{

    white-space: normal !important;

}

That will override the nowrap that is built into the Toolkit’s CSS.

Hopefully, someday, this will be a boolean property on the TabContainer control.





FIX: Printing ANYTHING Locks Up Windows Server 2003

12 06 2008

A few days ago, I installed Visual Studio 2008 SP1 Beta and all the goodies that came along with that.  Since then, printing just didn’t work.  If I tried to print, it’d hang up the application for a few minutes (felt like hours) until it’d error out that the printer was not operational.  I could print DIRECTLY from the printer (the test page).  Meh.

Trust me, while trying to prototype a reporting application and print examples there is no happiness when you can’t print.

After several hours of hunting, testing drivers, trying fixes, etc… I finally came across a TOTALLY unrelated MS KB article, #948046.

The article is for Windows Server 2003 with SP2 and XP with SP2–-both x64 and x86 editions.  It focuses on Microsoft Word and not being able to print if the EU Font pack is installed.  The scenario of “Word document is not printed as expected” is pretty vague.

Now, I’ve been using the same HP printer drivers (an 8150 DN and 5550 DTN Color) for ages without any problems, so I can’t fathom that caused the problem, but who knows.  The problem started after installing VS2008 SP1 Beta (I haven’t combed the install logs to see if it reinstalled Unidrv.dll).

Anyway, the fix to this problem, so far (after testing in several applications including Adobe Acrobat, Word, Excel, Visual Studio, and SQL Management Studio), is to download the hotfix in the #948046 article

Install, reboot, and things work perfect.





Deep Copy Cloning of LINQ Entity Objects - Not Deep Enough

5 06 2008

Yesterday, I wrote about a great IL solution to deep copying LINQ objects.  Unfortunately, it’s not quite deep enough. :(

The problem lies in the entity sets related to LINQ objects.  For example, in what I’m working on, the Report object contains Marks (grades) based on a foreign key relationship.  The previously discussed IL cloning method copies the records, but because it doesn’t generate new primary keys for those, it throws:

“An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.  This is not supported.”

I’ve tried zeroing out the PK fields just as I did with the report object iself—no dice.  Removing the Marks (by setting them equal to either null or new EntitySet<Mark>()) and no dice.

The only way I think I can get around it would be to break the FK relationship, clone the report (which would return a new Id), and then copy each of the Marks objects separately with some sort of loop (similar to below):

foreach (var mark in

new MarksController().SelectAll(oldReport.Id))

{

var newMark = new Mark {

              IndicatorId = mark.IndicatorId,

ReportId = newReport.Id,

             ResponseChoiceId = mark.ResponseChoiceId

});

}

That defeats the purpose though… ugh.

Back to the drawing board!

Tags: , , , ,




ReSharper 4.0 is now RC!

5 06 2008

The first RC for ReSharper 4.0 is out—pick it up! Nice!





Deep Copy Cloning of LINQ Entity Objects

4 06 2008

Unfortunately, there’s no real slick way (built into LINQ) to clone LINQ entity objects. 

My need was simple:  Take a record, duplicate it, change a few select values, and then dump it back into the data source to generate a new primary key.

But I couldn’t find a good way to get a deep copy using ICloneable and sure as heck didn’t want to do it manually. 

After a bit of searching, I came across a great blog posting that discussed using direct IL to make deep copies of objects.  The blog post looked promising.  As the author explains, “[t]he basic thing that it does is, create a DynamicMethod, get the ILGenerator, emit code in the method, compile it to a delegate, and execute the delegate.”  Sounds simple enough.

NOTE: Check out the blog post (here) for the full source code; the modifications I made are mostly domain specific—the implementation works great as it is.

I added the method into the GenericController that I use to implement LINQ and the results were brillant!

// Clone the entity based on the original report.

var newReport = this.Clone(SelectOne(originalReportId));

           

// Remove the ID to make it generate a new primary key.

newReport.Id = 0;

           

//  Change the necessary information.

newReport.EnteredBy = enteredBy;

newReport.Quarter = quarter;

 

// Insert the imported report into the system and save changes.

Insert(newReport, true);

 

// Now that the imported report has a primary key, return it.

return newReport;

Because .Clone is a virtual method of my Controller’s base class (public virtual T Clone<T>(T entity)), it applies to any type that I happen to pass into it.  In the code example above, this Import method is in the ReportsController and SelectOne returns a Report object, so Clone generates a clone based on the constructor and fields of that type.  Implementation with any other LINQ controller works just the same—excellent for reuse.

Since an integer primary key, Id in the code above, cannot be null, setting it to zero (0) will force the SQL processor to generate a new primary key when the record is entered into the database—which is exactly what we want.

Very pleased with the implementation of this and how slick (and quickly) it works.

Tags: , , , ,




Adding Multiple System Monitors ala Perfmon

22 05 2008

I use Perfmon a LOT. 

The logging and diagnostic software provided to us is, well, it’s just not that great.  Very slow to use and get around and every time I want a specific counter, I have to go ask for it because it’s someone’s “job” to add those. Ugh.  That’s no way to live.

Until now, I typically have a Perfmon console for each of my major application and SQL servers.  Why?  Because I was never smart enough to figure out how to add additional System Monitor controls into a single performance console.

Well, now I figured it out!

  • File > Add/Remove Snap-in
  • Click Add…
  • Select the ActiveX Control

ActiveX Control

  • A Wizard will start; scroll down and select System Monitor Control

System Monitor ActiveX Control

  • Give your new counter a name!
  • Repeat this until you’ve added your servers.  From there, configure each System Monitor control as needed.

Perfmon with all the servers!

From here, you can either add counters manually or use this brilliant PowerShell script.





TIP : Extracting Files from an MSI File

13 05 2008

Ever had an MSI file that you needed a library or something out of, but didn’t want to install it?  Amazingly enough, you CAN get to those files.

The Windows Installer (msiexec.exe) can be ran at the command line to extract files directly using an administrative install.

How?

msiexec /a “YourMSIPackage.msi” /qb TARGETDIR=”DRIVE:\YourTargetPath”

Switches used:

/a – Administrative installation
/qb – Basic UI (simple GUI progress bar)

This is a lot easier than hacking it using WinRAR. :)





FireFox 3.0 Beta 5 - DEP’d?

13 05 2008

Anyone else having Windows Server 2003 throw up on FireFox 3b5 with DEP errors?  I’ve excluded it for now, but it makes me a bit leery.

Firefox DEP'd.

Somewhere, there’s a bit of irony here.  I think Windows is just cranky that I have IE 7 disabled and have FireFox set as my default browser.