Friday, March 13, 2009

ASP.NET Session Timeout Control + jQuery Dialog

For quite awhile now I've been a big fan of the ASP.NET Session Timeout Control by Travis Collins.

I really like the way he designed it - and by also implementing partial postback capability (see his post's comments) - it really takes care of everything I need in a timeout control... except for one thing.. visibility. That's the only complaint I've ever heard is that when the template div is made visible - it's not always the most eye-catching element.

'Enter jQuery UI's Dialog (modal) plugin. I'd thought it'd be really nice to easily have a ui-themed dialog popup upon session timeout instead of simply showing a div. That'd definitely grab their attention instead of just a scrollTo + div.show() kind of approach.

This is my (work-in-process) solution.

We edit Travis's javascript file with the following changes:

At the bottom of the initialize: function() {.... section, we add the following code (simply so we can override it if desired):

this.initDialog();

That will allow the initialize routine to call our new initDialog function we're about to add (that we can easily override from the using application).

So now we add our new initDialog function (I added mine just after the _resetTimeout function):

// this will be the default Dialog if not overriden
initDialog: function(e) {
if (typeof jQuery.ui != 'undefined') {
var tsc = this;
$("#" + this._clientId).dialog({
autoOpen: false,
bgiframe: true,
modal: true,
buttons: {
Ok: function() {
$(this).dialog('close');
CallServer();
tsc._resetTimeout();
}
}
});
}
},

Now Initialize will call this function and setup our default dialog if we don't bother to override it. (Notice we're not going to do anything if the jQuery.ui isn't loaded.)

Next we change the existing showAboutToTimeout function to look like this:

showAboutToTimeout: function(e) {
if (typeof jQuery.ui != 'undefined')
$("#" + this._clientId).dialog('open');
else {
$get(this._clientId).style.display = 'block';
ScrollToElement($get(this._clientId));
}
window.focus();
},

So basically if jQuery.ui is loaded, we'll open our dialog (it should be initialized by now). If no jQuery.ui - we revert to Travis's original design.

One more slight change to the _resetTimeout function and we're done:

if (typeof jQuery.ui == 'undefined')
$get(this._clientId).style.display = 'none';

This just takes care of fully reverting to Travis's original design in case the jQuery UI isn't loaded. (Because our UI Dialog is going to close on it's own using the OK button function.

So that's it! Now the timeout control is capable of detecting if you have the jQuery IU loaded - and if so - display a dialog upon timeout. If no UI detected - it reverts back to Travis's original show/hide div design.

Here's an HTML example to use the new version of the Timeout control. Notice it still uses the original Template design for the dialog contents. *You have to add the title property to the Timeout control to set the Dialog window title:


<tsc:Timeout ID="Timeout1" runat="server" title="Session Expiring" Enabled="true" TimeoutURL="~/TimeOut.aspx" DisplayButton="false">
<Template>
<p>
<span class="ui-icon ui-icon-alert" style="float:left; margin: 1px 10px 20px 0;"></span>
Your session is about to Expire.
</p>
<br style="font-size:x-small;" />
<p>Click <b>OK</b> to continue your session.</p>
</Template>
</tsc:Timeout>

* Notice the dialog will be theme using whatever jQuery UI theme you are using.

And lastly, an example of how you'd override the default Dialog from the using application's HTML (if you wanted to):

<script type="text/javascript">
TSC.Timeout.Timeout.prototype.initDialog() {
if (typeof jQuery.ui != 'undefined') {
var tsc = this;
$("#" + this._clientId).dialog({
autoOpen: false,
bgiframe: true,
draggable: true,
modal: true,
buttons: {
Ok: function() {
$(this).dialog('close');
CallServer();
tsc._resetTimeout();
}
}
});
}
};
</script>

So there you have it - a fully jQuery UI Dialog enabled ASP.NET Session Timeout control! Thanks again to Travis Collins for his original design.

Click below for full Timeout Control project (source, dll's, etc).


NEW! Full working Web App solution demonstrating usage:

Friday, March 6, 2009

Async Error Handling Changes in .NET 3.5

I was recently surprised to learn about a very subtle, yet important change in asynchronous error handling that Microsoft implemented in ASP.NET AJAX 3.5.

I'd noticed that async errors in a new 3.5 app I'm currently working on no longer resulted in the 2.0-style alert popup - but I just assumed it was some change in IE8RC1 causing the different behavior. It finally bugged me enough that I spent a few minutes researching the topic and ran across a very interesting post on David Barkol's blog explaining the situation.

It seems Microsoft decided to let us handle the error ourselves so we can do whatever we want with it (maybe use a cool jquery modal or something) instead of forcing us to use the vanilla alert box.

David's blog also provides a great code example on how to catch the exception and reinstate the alert box behavior from .NET 2.0.

Tip: For a more descriptive error message, I will sometimes concatenate the usual e.Message text with the InnerException.Message text.

Sunday, January 25, 2009

Sorting Textbox contents with jQuery TableSorter

I recently needed to add client-side sorting to a table having one column of textboxes. I wanted the client to have the same sorting capabilities for this column as they did for the rest of the columns in the table.

Although I love the jQuery TableSorter plugin – the built-in parsers don’t really accommodate this type of thing.

After a bit of javascript debugging, I realized as long as there wasn’t any other markup in the cell besides the textbox itself – it’d be pretty simple using a bit of jQuery to extract the value.

This is the custom parser I came up with:

$.tablesorter.addParser({
id: "textbox_text",
is: function(s) {
return false;
},
format: function(s) {
return $($.trim(s)).val().toLowerCase();
},
type: "text"
});
The format function takes the raw html of the input element passed in via the s argument and basically just uses jQuery to extract the val().

Just remember the is function always returns false so you have to explicitly set the parser on a particular column like this:
$('#table1').tablesorter({
headers: {
0: { sorter: "textbox_text" }
}
});
The cool thing is that although this illustrates the concept of extracting text from an input element, you could use this technique to obtain a value/attribute/childnode/etc from any type of element.

Thursday, November 20, 2008

Basic jQuery Examples for ASP.NET Controls

Well it’s official - I’m the newest member of the jQuery fan club. Since Microsoft announced their partnership with the jQuery team and it’s integration with Visual Studio – I’ve been all over it.

I am amazed at how fast it’s taken off in the short time it’s been around. People are writing and publishing plugins like crazy.

As my first jQuery post, I thought I’d show a few basic examples of interacting with some of the common ASP.NET server controls.

DropDownList SelectedValue:

GET:   $('#<%=DropDownList1.ClientID%>').val()
SET: $('#<%=DropDownList1.ClientID%>').val("value_to_set")

DropDownList SelectedIndex (2 options):

GET: $('#<%=DropDownList1.ClientID%>').attr("selectedIndex")
GET: $('#<%=DropDownList1.ClientID%>')[0].selectedIndex

SET: $('#<%=DropDownList1.ClientID%>').attr("selectedIndex", "0")

SET: $('#<%=DropDownList1.ClientID%>')[0].selectedIndex = 0

RadioButtonList SelectedValue:

GET:   $("input[name='<%=RadioButtonList1.UniqueID%>']:checked").val()
SET: $("input[name='<%=RadioButtonList1.UniqueID%>'][value='value_to_set']").attr("checked", true)

Button Enable/Disable

$('#<%=Button1.ClientID%>').attr("disabled", true/false);

Label Text

GET:  $('#<%=Label1.ClientID%>').text()
SET: $('#<%=Label1.ClientID%>').text("value_to_set")

TextBox Text (also HiddenField Value)

GET:  $('#<%=TextBox1.ClientID%>').val()
SET: $('#<%=TextBox1.ClientID%>').val("value_to_set")

Check Visibility

if ($('#<%=Button1.ClientID%>').is(':visible'))


That’s it for now. More to come-

Friday, October 17, 2008

Visual Studio 2008 PowerCommands Add-In

UPDATE: 3/7/2009 - Make sure you follow the instructions in this forum thread to prevent some very bizarre disappearing (AKA crashing) studio issues after installing this addin.


I’m not sure how I missed this great, free add-in for Visual Studio 2008 called PowerCommands.

It adds several handy features that I’ve grown quite fond of such as Collapse Projects, Open Containing Folder, Email CodeSnippet, etc.

‘Several truly useful functions.

See the website for full details.

Tuesday, September 9, 2008

SQL 2005 Management Studio Color Schemes

If you're into Visual Studio Color Schemes, you'll want to check out Tomas Restrepo's utility to port your current color scheme from Visual Studio into SQL Management Studio.

It basically just copies all the applicable registry settings from VS to SMS - but it turned out well for me.

Check it out-

Saturday, September 6, 2008

Full (Bulk) Edit Dynamic ASP.NET ListView (AKA Spreadsheet in a Web Page)

Inspired from Matt Berseth's awesome Bulk Insert ListView, I present a slightly modified version that is in essence an auto-saving, dynamic row, viewstate-based listview.


It functions basically just like a blank spreadsheet. You start out with one blank row. Need more rows? Click Add. Add too many? Click Delete.

The nice thing is that anytime you click anything, the contents are saved to viewstate via an ObjectDataSource.

After you've entered everything you need, click Submit and do whatever you need to do with the data (send it to a database, etc).

The ListView's ItemTemplate is made up of input controls (TextBoxes, DropDownLists, etc) - so it's basically always in edit mode.. there's just no Edit/Update/Cancel clicking required.

I also demonstrate the use of special-case bindings like the DropDownList that you can't simply %# Bind % like normal TextBoxes.

Saving state is accomplished somewhat similar to Matt's, only mine saves via an overriden OnItemCommand event in an extended ListView class. This makes saving state *almost* completely automatic.

The elegance is in the simplicity. There's nothing quirky or magic about it. It's just a combination of simple concepts that result in an intuitive bulk input grid. And obviously you could also use it to Edit existing data in a dynamic way - just load the ListView on Page_Load.

Again, a huge thanks to Matt Berseth for the original concept/stylings/etc.

Full source is available below: