Adsense

Monday, January 29, 2007

Centering an Element via CSS vs JavaScript...

We recently ran into a situation where we were dynamically showing and centering model popup windows in an ajaxified environment. Our initial implementation had one down side.

We were showing and dynamically centering our div/panels via JavaScript. The windows would very briefly show up in its default location before jumping to center. Not a huge problem, but very annoying.

Our initial approach looked something like this. Statically build a hidden div/panel and when the user triggers a pop up dialog, call the CenterPanel method from JavaScript and show the panel. We were calculating the screen height and width and making it available globally.

The JavaScript process looked something like this...


CenterPanel("<%= SendToGeneralQueuePopupPanel.ClientID %>");


function CenterPanel(panelId){
var panel
= document.getElementById(panelId);
if (panel) {
panel.style.top
= ((screenHeight / 2) - (GetSize(panel.style.height) / 2)) + 'px';
panel.style.left
= ((screenWidth /2) - (GetSize(panel.style.width) / 2)) + 'px';
}
}

The result was a panel that would show up, then jump to the center of the screen. (Annoying)

After getting a bit of time to think about the issue, I remembered a much simpler way to center a control with pure CSS rather than dealing with problematic JavaScript at all. I'd used this technique in other projects and it makes things quite a bit more simple and stops the panel from jumping around the screen.

The CSS method...

We define a Panel to use as the pop that applies our modalPopup CssClass. Notice that the panel's Width is 200 and it's Height is 60.

<asp:Panel ID="PanelPopup" runat="server" CssClass="modalPopup" Width="200" Height="60">
<div style="text-align:center;">
Are you sure you wish to continue?

</div>
<div style="text-align:center;">
<asp:Button ID="ButtonYes" runat="server" Text="Yes" OnClick="ButtonYes_Click" />

<input id="ButtonNo"
type="button" value="No"
onclick="return HidePopupPanel('PanelPopup', '<%= PanelPopup.ClientID %>');" />
</div>
</asp:Panel>

The modalPopup CSS...

.modalPopup{
//Other CSS
left:50%;
margin-left:-100px;
top:50%;
margin-top:-30px;
}

The CSS above sets the left edge of the panel to be aligned with the center of the browser and then adjusts the left margin of the panel by subtracting 100 pixels (which happens to be half of the panel's width.) This centers the panel horizontally. In the same way, the panel is centered vertically by setting the top of the panel to the middle of the screen and then adjusting the top margin by subtracting 30 pixels which is half of the panel's height.

You can do a lot of fun stuff by using this technique. Setting the left, top, right or bottom of a control and then modifying the margins. Play around with it...

Friday, January 26, 2007

Session Management - Facade Pattern - C# .Net VS2005

State Management is a big part of any web application and using the session variable in ASP.NET is one way to persist data throughout a user’s session. Interacting with the session variable is fairly straight-forward…
Session["UserId"] = user.Id;
int id = (int)Session["UserId"];
Session[
"FirstName"] = user.FirstName;
string fName = (string)Session["FirstName"];
You can store any object or primitive into the session variable and retrieve the value at any time throughout the user’s session.

As you might imagine, your project could get fairly convoluted if you are accessing the same (or many different) session variable across many different pages throughout your application. Using explicit string values as your keys can also cause problems if you accidentally typo when entering them or decide to change one later. Throw several developers into the mix and this can turn into a nightmare.

You can alleviate some of this frustration by using an enum that contains all of your session key values. This allows you to make changes much easier, provides a quick reference to what objects you have in the session, and makes calls to the session variable consistent. The new session calls (with the help of an enum) would look like this.
enum SessionKeys {
UserId
= 1,
FirstName
= 2
}
Session[SessionKeys.UserId .ToString()]
= user.Id;
int id = (int)Session[SessionKeys.UserId .ToString()];
Session[SessionKeys.FirstName .ToString()]
= user.FirstName;
string fName = (string)Session[SessionKeys.FirstName .ToString()];
Taking this a step further, you could wrap this functionality into a static class in your project and route all session traffic through this class. By wrapping session calls in properties within this class, you can ensure type safety and make it much more easy to work with the session object.
public static class SessionFacade {
public static int UserId {
get {
return (int)Session[SessionKeys.UserId.ToString()];
}
set {
Session[SessionKeys.UserId.ToString()]
= value;
}
}
public static string FirstName {
get {
return (string)Session[SessionKeys.FirstName.ToString()];
}
set {
Session[SessionKeys.FirstName.ToString()]
= value;
}
}
}
Sessions calls would then look like this.
int id = SessionFacade.UserId;
SessionFacade.UserId
= user.Id;
string fName = SessionFacade.FirstName;
SessionFacade.FirstName
= user.FirstName;
The SessionFacade class acts as a Facade between you and the session object and alleviates much of the frustrations mentioned above. No more misspelled keys, no more huge updates if you want to change a key. Type safety... Who could ask for more?