Tuesday, February 12, 2008

Data Storage Forecast: Only Partly Cloudy

Over the past few weeks, the idea of moving data off of desktops and locally-controlled database servers and "into the cloud" (onto shared data hosting services like Amazon's S3) has been gaining more attention. A guy named Nicholas Carr went so far as to predict the demise of the IT department as businesses essentially outsource their data processing/data retention (NetworkWorld, 1/7/08).

There's no doubt that individuals store more data online these days than they used to because of the rise of applications like Facebook, Flickr, and Google Calendar. Any data that has a social aspect to it gains value by being "out there" for others to view and interact with.

There are also business processes that involve collaboration with other business partners, where arrangements are made to exchange information or tangible goods via a buyer/seller dynamic. Again, it makes sense that the data and even the applications that power such collaborations could be managed and hosted by a third party.

But there will always be a desire to keep certain data close to the vest, even if that means maintaining an internal hardware and network infrastructure. Colleges and universities are not going to outsource their student data to a third party, and medical institutions are obligated by law to safeguard medical information. Banks will probably take a pass on shared data hosting as well. Even if cloud computing becomes more accepted and reliable, there will always be groups and individuals unwilling to give up that control despite any cost savings.

Thursday, February 7, 2008

Switching Between Sets of Database Tables On The Fly

Ever need to tell your ColdFusion app to run select queries against a different set of tables while you do something to the original set (like perform a batch update)?

I did. Here's how I did it.

First, I gave each table in each set a two-part name, two words separated by an underscore. The first part of the name was descriptive of the data in the table ("chapters","sections", etc.) while the second part of the name identified the data set the table belonged to ("live", "archive", whatever). So the "chapters_live" and the "chapters_archive" tables were exactly the same in structure.

Then I created an application variable called "application.tableSuffix" and set its initial value to "live".

(Can you see where this is leading?)

Finally, I changed my select queries to use table names comprised of the first, data-descriptive part of the table name, the underscore, and the value of application.tableSuffix:

<cfquery name="showChapters" datasource="ds">
   select chapterTitle, chapterIntro
   from chapters_#application.tableSuffix#
   order by chapterOrder ASC
</cfquery>

Once that was done, I could change the table set my select queries ran against at any time by simply changing the value of application.tableSuffix. Two things worth noting:

  • This technique only makes sense if only one set of tables can be updated by the user: if users can make changes to either set, you'll have to figure out how to resolve the differences between the data in each set.
  • If the switch could potentially be in place for awhile, you might want to store the current tableSuffix value in a database record or a file and then retrieve that data in the onApplicationStart method of your Application.cfc file so that the current value is preserved even if the application scope expires.

Tuesday, January 22, 2008

Techniques for Providing Instructions Within a Web Application

Some of the processes you find in web applications are fairly standard. Most folks can fill out a contact form, or fill out a survey, or make a calendar entry without the need for too much explanation. But what do you do when the form involves business rules that the user may or may not know, or presents the user with a number of options?

I always try to make sure the tools and the pages I put in my web applications are fairly self-explanatory, especially those tools and pages that only the administrative users of the application interact with.

The folks who end up using and administering my applications (my clients) are almost never technical people, so I start off each administrative page with a brief explanation of what the page does and how you save any information entered on the page. Once they've used the page, they can always skip over the intro and go right into the form or tool.

If the overall form requires a bit of explanation, something that can fit into a few short sentences, I'll put that explanation right after the basic description. If certain form fields require special instructions (like the requirements for choosing a sufficiently-strong password), I'll put the instructions right next to or under the input field, so that they focus on the instructions right when they need them.

Sometimes, though, there's too much to explain and still fit on the page without using up a lot of screen real-estate. In those cases, I'll present the explanation via a JavaScript pop-up window that comes up when the user clicks on a help symbol like a question mark icon.

I try not to use too many of the help icons on a single page, but it's a great way to present additional information to only those folks that need help, without getting in the way of experienced users.

Up until now, those techniques were sufficient to provide my clients with the guidance they needed to use their new application. But my latest project has taken help documentation one step further.

This project allows my clients to create news articles for the web using a JavaScript WYSIWYG editor, so in the prototype I added a few help icons to the editing page in order to explain how to use the editor, how to upload images files, etc. When I showed my clients the editing page and the help icons, I told them I would give them the ability to edit the help text that was displayed in the pop-up windows (so they could phrase the help in a way that made the most sense to them).

They liked that idea, but they had an even better one: they wanted to write their own in-application user manual, so that the primary users of the application could write procedural instructions (instructions not necessarily pertaining to the use of the application) that would guide other users in the office whenever they needed to fill in for the primary users.

So I built a tool to let them write chapters for their manual: they have a simple text field for entering a chapter title and a WYSIWYG editor box for entering the chapter content. They can also rearrange the order of the chapters on the master page using a variation of my jQuery-powered list rearrangement tool (see related entry). The header of the application hosts the "uber" help icon they click to bring up their manual in a large pop-up window, where the chapters are listed as hyperlinks that load the corresponding chapter content into the right-hand content area via an AJAX call.

Only time will tell if they actually write their own manual, but if they do, I may include a manual-writing tool in future applications. If your clients are willing to write some of the documentation for an application, it's a good way to get them further invested in the project, and it can end up saving you some work in the process.

Saturday, December 29, 2007

How to Use the Same Server-Side Code to Validate Form Data With or Without AJAX Using jQuery

In any web application, if the user submits information to be stored in a database using a form, you always want to validate that information before it's stored in the database. The majority of users have JavaScript enabled in their web browser, allowing you to use JavaScript functions to validate the data on the client-side before the submission is allowed to proceed. However, there are those rare individuals who have JavaScript turned off, so a conscientious developer will also validate the submitted data on the server side as well as a backup.

The problem with this is that you end up having to maintain two sets of validation functions, which means twice the work if you have to make a change to the submission form or the validation rules themselves. In addition, if you're not experienced with JavaScript, you may find it harder to write the JavaScript validation code than similar code in your server-side programming language of choice.

In an earlier blog post, I wrote about how the latest version of ColdFusion, ColdFusion 8, provides a new tag called <cfajaxproxy> that allows you to make JavaScript calls to functions contained in ColdFusion Component (CFC) files on the server, enabling you to write your validation code within CFC functions and call them for either client-side or server-side validation.

But what if you're not running ColdFusion 8 yet, or you're using another web programming language (like PHP)? Here's a technique I came up with using the jQuery JavaScript library and the jQuery Form plugin that lets you write your validation and database-update code on the server-side in such a way that you can either call it via AJAX if JavaScript is enabled or run it server-side if JavaScript isn't available.

First, here's the code for the HTML form:

It's a very simple form, with only two text inputs (firstName and lastName). The JavaScript files and the CSS stylesheet used with the form are included in the <head> block. At the beginning of the form is a hidden text field called "submitType." Below the form are two <div> blocks that both have the class "hideElement."

Here's the code for the submitDemo.css file:

The very first entry is for the "hideElement" class, which contains a single style declaration ("display:none;"). So the two <div> blocks at the end of the form are not displayed.

The first two JavaScript files referenced by the HTML form page are the core jQuery file and the jQuery Form plugin, which you can simply download and place somewhere within your web application's directory structure. The third JavaScript file, submitDemo.js, has the custom functions that apply to the HTML form:

These functions are the key to how this technique works. The first function, the "ready" function, is a special jQuery function that runs as soon as the HTML elements on the page are able to be acted upon by JavaScript. The "ready" function assigns two event handlers. The first one defines the actions that occur when the the submit button of the HTML form (which has an id attribute of "submitButton") is clicked: when it is clicked, the value of the hidden text field at the start of the form is changed to "ajax." If JavaScript is disabled in the user's browser, this event will not fire and the value of the submitType hidden text field will remain "regular".

The second event handler executes when the HTML form (which has an id attribute of "submitDemoForm") is submitted. The form is submitted via AJAX using the ajaxSubmit function in the jQuery form plugin with the parameters contained in the submitOptions JavaScript object, which is declared and defined right below the second event handler. Again, if JavaScript is disabled in the user's browser, this event will not fire and the form with be submitted in a normal HTTP POST action to the server.

The submitOptions JavaScript object defines certain aspects of the AJAX submission. The "target" value is the id of the HTML element that will receive the HTML content returned by the server-side page that answers the AJAX call, and in this case the target is the second currently-hidden <div> block beneath the HTML form (the "ajaxResult" <div>). The "beforeSubmit" and "success" values denote JavaScript functions that should be called just before the AJAX call is made and after the AJAX call has completed, and in this case the showProcessing and hideProcessing functions are called. The "URL" value is the server-side page where the AJAX call should be directed, and in this case it is the same page defined in the "action" attribute of the HTML form.

The showProcessing function uses jQuery calls to disable the submit button of the HTML form (so the user cannot submit the form twice), hides the ajaxResult div (in case it was revealed during a previous form submission attempt) by adding the "hideElement" class, and displays the "processingMessage" <div> to alert the user that something is happening by removing the "hideElement" class from that <div>. The hideProcessing function performs the opposite actions: hides the processing message, reveals the ajaxResult <div>, and re-enables the form's submit button.

Finally, here is the code for the server-side page (serverSubmit.cfm) that handles the form validation and, if there are no errors, records the form information to the database:

This example uses ColdFusion to process the validation and submit the data to the database, but you could use any web programming language for this page.

The code starts by defining a variable ("errorList") to contain all of the validation problems found in the submission (if there are any). In this example, the only two validation rules are that the user must submit a first name and a last name. If the user omitted either or both names, the relevant error messages are added to the error variable, which I chose to create as a list (you could just as easily store the error messages in an array).

If, after all of the validation checks have been applied, there are no validation errors, the form information can be stored in the appropriate database table.

What happens next depends on whether or not the form was submitted via AJAX. If the value of the hidden form field "submitType" was changed to "ajax", that indicates that the form was submitted via AJAX. If there were no validation errors, a simple success message is generated and will be displayed in the "ajaxResult" <div> below the HTML form (as per the submitOptions attributes of the ajaxSubmit function in the submitDemo.js file). If there were validation errors, a list of the errors is generated using the <cfloop> block and that result is displayed in the "ajaxResult" <div>.

If, however, the form was submitted via a regular POST action, a different action takes place. In this case, a short error or success message is displayed as the visual output of the serverSubmit.cfm page itself, but you could just as easily redirect the user to another page and display the errors there.

The end result of all this, in a nutshell, is this...

If the user has JavaScript enabled:

  • The user enters the information into the form.
  • They click the submit button.
  • The submit button is disabled and the "Saving changes..." messages appears briefly below the submit button.
  • The server-side page processes the submitted data.
  • A message indicating a successful submission or a failed submission (with the reasons why it failed) is displayed, the "Saving changes..." message disappears, and the submit button is re-enabled.

If the user has JavaScript disabled:

  • The user enters the information into the form.
  • They click the submit button.
  • The server-side page processes the submitted data.
  • The server-side page displays the results of the form submission.

Again, this is a very simple example, but it demonstrates how you can write one set of validation code and write it in the server-side language you're most comfortable with.

 

Monday, December 10, 2007

My First AIR Application: colorPicker

In my most recent web application project, my clients asked for the ability to change the color of certain HTML elements without having to actually write or change any HTML code. So I used ColdFusion and the jQuery JavaScript library to create a color grid similar to the one that pops up in Adobe Dreamweaver when you type a color-related HTML or CSS attribute, allowing them to choose a color simply by clicking on it.

After I finished the grid, it occurred to me how I could use a similar tool for my coding work: CFEclipse doesn't have a selectable color grid (most likely a limitation of Eclipse itself), and it's a pain to open up Dreamweaver or Fireworks just to get a color. So I decided to try and make my color grid into an AIR application.

The result is colorPicker, a widget-like AIR application that lets you either select a color from a grid of "web-safe" colors or design a color using sliders to change the red, green, and blue values of the color. Once you have the color you want, you can click on the corresponding "Save to Clipboard" button to copy the hex color code to the clipboard and then paste it into your HTML code in your IDE of choice. It also saves all of the colors you've copied to the clipboard during your session so you can repeat a color.

It actually uses very little of the AIR API: just the clipboard copy function and the description file needed to run it. Everything else is done with JavaScript, HTML, and CSS.

You can view screenshots of colorPicker and download it from RIAforge.org at:

http://colorpicker.riaforge.org

Tuesday, December 4, 2007

Perfection Isn't Mandatory

I came across this blog post, and even the blog itself is geared towards the .Net crowd, I thought the message was true for all coders who strive to hone their craft:

You are NOT inadequate

Wednesday, November 7, 2007

When Experience Tells You It Can't Be True, It Probably Isn't

Today I was trying to troubleshoot a design tool I created that worked perfectly in FireFox but not in Internet Explorer. There was an element on the page, a <div>, that IE would not apply the CSS style to if the style was applied based on the id attribute of the <div>. I could however apply styles to it if I added a class attribute to it and wrote the class in my CSS stylesheet.

It made no sense. I'd assigned styles based on the id attribute all the time, and had never seen this problem in any modern browser. What the heck was going on?

Finally I saw my mistake: I had left off the closing bracket of the <div> that was the parent of the <div> I was having trouble with. FireFox was "kind" (aka presumptive) enough to close that tag at runtime, and IE was not.

Had I trusted my experience a little quicker, I'd have looked at the HTML code for structural problems first before trying to figure out a way around the problem.