I swear radio buttons pucker up the closer my mouse gets to them.  Aside from the lack of good CSS options for radio buttons, they demand a certain level of commitment from the user. Unlike our promiscuous friend the checkbox, once you manage to jab the tip of your mouse into the pinhole of a radio button that's it. There's no unpoking that hole. Sure, you might be able to move it around in a group of radio buttons but, you're pretty much committed to an option.

So, to un-suck the radio button, we need:

  • Free will.  The users should be able to unselect their answer.
  • Mutual exclusiveness.  If we don't have this, we've got nothing but checkboxes.  Only one answer can be selected.
  • Potential beauty: Why be limited to puckered pinholes if we can pretty it up a bit.

By creating a little mash-up using some controls from the AJAX Control Toolkit, maybe we can make something a little better than the standard HTML inputs.  Let's be honest.  This is not a lightweight approach.  I'm not going to tell you what to do but, I would only do this only where the UI bang is worth the page load buck.Don't click on this.  It's just a screenshot.

Let's tackle mutual exclusiveness first. In case you aren't familiar with the terminology, mutual exclusiveness is the idea that by selecting one item, you exclude yourself from selecting something else. For example, if you chose life, you cannot choose death.  To chose death you must not choose life.  So, how do we assure a monogamous answer using a bunch of promiscuous checkboxes? For this task, we'll need a chaperone and, fortunately, the Toolkit also has a little thing called a MutuallyExclusiveCheckBoxExtender--just rolls off the tongue doesn't it.   This control can make check boxes behave like radio buttons! Yes! No, wait...radio buttons suck, right? A square pinhole is really not that much more fun to poke than a round one, is it?

Enter the ToggleButtonExtender.  This AJAX Control Toolkit control allows you override the default HTML checkbox with your own custom images.  Sweet! If we use this with some checkboxes, we have achieved "free will" and "potential beauty" in one shot.

By combining a couple of ready-made tools, we can un-suck the radio button by using checkboxes.  Hmmm...Maybe I should have titled the article "Checkbox Performance-Enhancing Controls". It doesn't really matter.  The goal is to create a better user interface for a task and that's what un-sucking is all about.

 

Reality Check!

Why NOT to do this:

  • The complexity and page size increases exponentially the more options you add so, use wisely.
  • You are a Javascript wizard and don't want to add the Toolkit's baggage.
  • Getting the selected value for the pseudo-RadioButtonList and validation is trickier. So what? You're a great programmer and can handle it, right?
  • It makes it easier for users to see what is selected and not selected.  So, if you rely on users not seeing which puckered pinhole they may or may not have selected, don't do this.

Recently, I blogged about my favorite file upload technique for web applications--the free flash/JavaScript-based SWFUpload.  While this library is not the perfect solution for all circumstances, it certainly provides a very nice user experience and is worth seeing if it matches your project's requirements.

I have a project I'm working on that needs a graceful file upload process. The environment is compatible with the flash/JavaScript requirements so I made myself a .NET control for the library.  The control contains all the necessary JavaScript and you can set the properties (allowed file types, file size, etc.) just like a normal control so you don't have to mess with any of the scripting. 

The features of this control include:

  • Multiple file upload (queuing)
  • Upload progress indicator
  • Ability to cancel queued files
  • NO visible PostBack (uses AJAX)

For those of you who may be wondering if you just stumbled onto the the "holy grail" of file uploads here, hold y'er horses...

This is my first customer server control ever. I'd never made one before and this was my "learning project".  It's probably not a highly tested and production-ready control. That said, you have the source and it's not that complicated so maybe you can customize it or clean it up if necessary. I would like to know what you think--good or bad, so let me know if you find problems or have some ideas to share.

I love multiple monitors.  I made everyone at work start using multiple monitors last year. At first they were afraid...they were petrified...but now they don't like working at home if they only have one monitor.  If you're looking to justify multiple monitors in your organization, here's a report outlining some productivity research regarding monitor size, aspect ratio, and multiple displays.

Okay, so don't be surprised that display company (NEC) found that larger and more displays improves productivity, but it would appear there is a limit to productivity gains. What's your optimal layout?  Check out the report and see for yourself:

 

On a related note...Here's a gotcha I banged my head into with Vista and multiple monitors...

I recently upgraded my home/office PC.  My old system had three monitors under Windows XP and ran great.  I used a nVidia AGP card and added an ATI dual-video PCI card to create my surround video. 

Enter crotchety ol' Vista with it's fancy-smancy new way of handling multiple graphics cards...  Up until now, I've been pretty happy with Vista but this just chaps my hide. If you are planning to use more than two monitors with Vista, you need to read this article first.

It all started with my upgrade to VS 2008.  I've been using the trial version and only had 3 days left...time to do the deed.

IMPORTANT SIDE NOTE: If you are using the trial version, you don't need to do a full uninstall/reinstall.  I saw this option the very second I clicked the "uninstall" button.  That cost me an hour and a half.  Live and learn.

Back to the story...at the end of the Visual Studio upgrade I got the option to check for updates which I always do.  I am reckless with updates and proud of it.  I seem to be addicted to see what's going to happen. Will it work? Will it fail? If it fails, will it be spectacular?  OMG, what have I done!...It's so exciting.

For the most part the installation was quite uneventful and I spent most of it daydreaming about my vacation next week. 

Then comes the REBOOT!  This is the best part of any major update.  This is where it can go really really bad, really really fast.  I love this part.

System loads.  It pauses before the login screen to install the final 3 parts of Service Pack 1. In big bold letters is the warning, "Do not turn your computer off".  I'm starting to sweat and my pulse races as it finishes part 1 and moves to part 2 (like I should care what part it's on--but I do!).

Part 2 is almost done then...BAMMMM! It's the final episode of Sopranos!

My screens goes black.  The only thing displayed in all three monitors is a cryptic message only a machine could produce.

"!! 0xC00000 !! 255/73694 (_000000000000000.cfg-ms)"

I knew the exclamation points could only mean something tremendous had happened.  Clearly, to tremendous to put into words.

I sit there, trembling.  I wonder, "Is it dead? Should I leave it and just go home? Should I turn the computer off? No, it said not to. Computers know best, right?"

My hand shook as I held in the power button. Not from fear--from excitement!  It's been a long time since I've had this much fun with an update.

I held my breath as it began to restart. My heart was pounding.  I'm given a choice "Repair Windows Startup" or "Start Windows Normally".

What's the logical choice?  "Repair", you say?  As I selected "Start Windows Normally" (honestly, why wouldn't I want it to start anything but "normally"), I sat frozen, hoping it would be okay but at the same time hoping for some kind of explosion.

The update finished normally, and my machine seems none the worse for wear. 

Now, isn't there an IE8 Beta out there somewhere...

I recently happened upon this intriguing little API that provides a nice interface for displaying events on a timeline.  It was pretty easy to get my head around it and it's pretty easy to setup and use.  It's got a Google Maps-like scrolling interface that is very intuitive.  If you're not sure what a timeline looks like, you might want to jump straight to an example before continuing.

I've don't really like the standard options for browsing a blogs history which typically looks like this:

  • January (10)
  • February (5)
  • March (11)
  • ...

Kind of boring, right? So, as a proof of concept, I created a little test project to see what an RSS feed would look like in a timeline.  Here's what it looks like for a busy RSS feed like Techmeme (or, view live demo):

RSS feeds don't typically output an entire history so this example isn't all that practical.  However, if I had access to the database I could pull in all the posts to create a full blog timeline. As far as practical applications go, I can think of a number of other scenarios for using an interactive timeline over a plain old list:

  • Displaying event logs
  • Order tracking
  • Live event blogging
  • New user registration
  • News tickers
  • Twitter?
Take a look at the Simile Timeline page if you would like more information, documentation, or some better examples.  You can also download my little test project/demo.

Apparently not much.  According to the product pricing page, all you need is "Any other developer tool".  Here is the full eligibility statement found at the bottom of this page:

Upgrade Pricing Eligibility

To qualify for upgrade pricing, you must be a licensed user of one of the following products:

  • An earlier version of Microsoft Visual Studio
  • Any other developer tool

The free Visual Web Developer 2008 Express edition binds you to a license and is a developer tool. Hmmm...seems to qualify. Can anyone confirm/debunk this assumption?

How about Dreamweaver or my dusty copy of FrontPage 97?  Any Netscape Composer 4.0 users still out there? 

UPDATE: This is now available as a free ASP.NET control. 

Recently, Joe Stagner created some videos and talked about 4 upload scenarios that provide an AJAX-like file upload experience.  I've used or looked at all of those options at least once or twice in the past, but they were never quite what I wanted.  I wanted something sleek and sexy.  Something that really popped. The file upload tool that is my new best friend is SWFUpload.

SWFUpload is a JavaScript/Flash library that degrades to a plain old upload control if there are compatibility problem. It's truly a thing of beauty.  The SWFUpload online demos really don't do it justice as far as demonstrating how pretty you can make it look with a little CSS.  Not that I'm the world's greatest designer, but here's an action screen shot of how I integrated it into an ASP.NET application. The picture is a screen capture of SWFUpload in the process of uploading 4 files. The control is inside of an AJAX.NET ModalPopup inside of an UpdatePanel. You can also see it in action as part of a short demo I did for this project.  It's not the greatest video, but you can see the uploading files and photos example about halfway though the video.

What's broken?  It would appear that there are a couple of problems with consuming Atom feeds using the RSSToolkit.

  1. <pubDate/> shows up empty
  2. <link/> use the the base URL for the channel instead of the URL for each <item/>

I opened up a work item for these issues, and here's what fixed it for me:

  • Download the Source.
  • Open the Resources\AtomToRSS20.xsl file and make the following changes:
    • LINE 25: <xsl:value-of select="//*[name()='modified']"/> should be <xsl:value-of select="//*[name()='updated']"/>
    • LINE 43: <xsl:value-of select="//*[name()='link']/@href"/> should be <xsl:value-of select="child::*[name()='link']/@href"/>
    • LINE 55: <xsl:value-of select="//*[name()='modified']"/> should be ><xsl:value-of select="child::*[name()='updated']"/> *updated 2/1/2008
    • Recompile the .DLL file. Or, I uploaded my recompiled version with the work item.

Follow my erotic tale of "code awakening" as I discover AJAX's raw naked self.  We'll pop the hood and see AJAX as nature intended. This steamy tale of passion, romance, love, and AJAX may leave you breathless and panting for more. Or, it could simply be a ruse to get you to read my article. I'm not above shameless marketing tactics.  Sex sells and you're buying... ;-)

 

"Wam-Bam" AJAX

The following example is not valid, has no error checking, is messy, but it will work in IE7, Firefox, Opera, and Safari. It is the least amount of effort (I think) needed to demonstrate AJAX.  We will use two files for this example to show that a basic html page can pull information from a separate file on the server. No gender roles are defined for either of these files so, just pick your pleasure, open your imagination, and read on...

Content.txt

You're hot!

Default.html

<script type="text/javascript">
        var xmlHttp = null;                
        window.onload = function() {
            xmlHttp = new XMLHttpRequest();
            xmlHttp.open("GET", "Content.txt", true);
            xmlHttp.onreadystatechange = onCallback;
            xmlHttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
            xmlHttp.send(null);            
        }        
        function onCallback() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    alert(xmlHttp.responseText);
                }
            }
        }
    </script>

What's this do?

As Default.html loads in the browser, the JavaScript creates a new HTMLHTTPRequest and then uses it to retrieve the contents of the text file from the server. The results are displayed in an alert box. It sure doesn't feel like the warm snuggly AJAX we're looking for, but it's a nice little piece of AJAX to peak our interest.

 

"Second Date" AJAX

Okay. We got "the deed" done in the first example, but this little quickie just won't cut if we're serious about this little trist. Let's turn the lights on and get a better look at the example in a valid HTML page, with some basic error checking, and a few comments so we know what we are dealing with.

Content.txt

You're hot AND thoughtful!

Default.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>AJAX Example</title>
    <script type="text/javascript">
        var xmlHttp = null;
        
        window.onload = function() { // Begin the request when page loads
            loadXmlHttp(); 
            sendRequest("Content.txt")            
        }
        
        function loadXmlHttp() {
            // Do a little browser detection to see if we can
            // use XMLHTTPRequest or if we are stuck w/ the ActiveX
            // option.
            if (window.XMLHttpRequest) { //IE7, Mozilla, Safari, Opera
                xmlHttp = new XMLHttpRequest();
            } else if (window.ActiveXObject) {
                try{
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); // IE5 & 6
                }
                catch(e) {}
            }
        }
        
        function sendRequest(url) {
            if (xmlHttp) {
                xmlHttp.open("GET", url, true); // "true" creates an async. request
                xmlHttp.onreadystatechange = onCallback;
                xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                xmlHttp.send(null);
            }
        }
        
        function onCallback() {
            // This function will run over and over as the request 
            // goes though processing
            if (xmlHttp.readyState == 4) { // "4" indicates the end of the request
                if (xmlHttp.status == 200) {// "200" indicates a successful request
                    alert(xmlHttp.responseText); //Display the result
                }
                else { //Something went wrong.
                    alert('Error: ' + xmlHttp.status);
                }
            }
        }
    </script>
</head>
<body></body>
</html>

What's this do?

Basically, we took a "drunken one-night stand" of an example, and took it out for dinner.  The output is the same, but you can see that we are being a little more careful by loading the correct request object and checking to see if the request was successful. It's still pretty shallow and not something worth committing to, but it's starting to get interesting.

 

"Falling in Love" w/ AJAX

Now that we have the mechanics down, we can get a little adventurous and begin to spice things up. Let's add some of that hot AJAX interactiveness everyone's talking about and see what happens.  For this example, we will ask a question on the HTML page, wait for a response, and then see the response from the text file without any of that flacid postback action. The juicy bits have been highlighted in the code for your veiwing pleasure.

Content.txt

Of course I love you, AJAX!

Default.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>AJAX Example</title>
    <script type="text/javascript">
        var xmlHttp = null;
        
        function askBigQuestion() {
            var l = document.getElementById('Loading'); // Find the loading object
            l.innerHTML = "I'm thinking..."; // Display some feedback during the process
            loadXmlHttp(); 
            sendRequest("Content.txt")            
        }
        
        function loadXmlHttp() {
            // Do a little browser detection to see if we can
            // use XMLHTTPRequest or if we are stuck w/ the ActiveX
            // option.
            if (window.XMLHttpRequest) { //IE7, Mozilla, Safari, Opera
                xmlHttp = new XMLHttpRequest();
            } else if (window.ActiveXObject) {
                try{
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); // IE5 & 6
                }
                catch(e) {}
            }
        }
        
        function sendRequest(url) {
            if (xmlHttp) {
                xmlHttp.open("GET", url, true); // "true" creates an async. request
                xmlHttp.onreadystatechange = onCallback;
                xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                xmlHttp.send(null);
            }
        }
        
        function onCallback() {
            // This function will run over and over as the request 
            // goes though processing
            if (xmlHttp.readyState == 4) { // "4" indicates the end of the request
                if (xmlHttp.status == 200) {// "200" indicates a successful request
                    var r =document.getElementById('Result');
                    r.innerHTML = xmlHttp.responseText; // Display the result
                    var l = document.getElementById('Loading');
                    l.innerHTML = ''; // Clear the feedback
                }
                else { //Something went wrong.
                    alert('Error: ' + xmlHttp.status);
                }
            }
        }
    </script>
</head>
<body>
    Do you love me?
    <input type="button" onclick="askBigQuestion();" value="Ask"/>
    <br /><br />
    <span id="Loading"></span>
    <span id="Result"></span>
</body>
</html>

What's this do?

When the user clicks on the button, the request begins, a status message is displayed while the request is processed, and then the contents of the text file are rendered on the page. Hmmm...maybe not as sexy as we were hoping for, but the potential is definitely there for some very hot action.

 

The "Big Commitment"

It's decision time. How much farther do we want to go with this AJAX thing?  After this point, it's a big commitment (at least for me) to learn more JavaScript, understand the DOM, meet the relatives (JSON, REST, SOAP, etc), and a whole host of other freaky-deaky things. 

Personally, I am not ready for a full on commitment just yet. I am just going to finish reading my new book that I won from Dave Ward on his blog, "ASP.NET AJAX in Action" so I know how my "AJAX framework de jour" really works. Other than that, I'll and keep "playing the field" with some other technologies I've been flirting with--I'm such a tech whore--and let the smart people keep creating great frameworks that are so easy, even I can use them. 

Whew...I don't know about you, but I need a nap...

It's the burning question that's been haunting me for years.  Where did this little ambiguous icon come from? What was the inspiration for this symbol of information subscription? What great mind dove deep into their soul and returned with this gem?

I may have uncovered the mystery...See it for yourself.

More Posts Next page »