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 at:

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.

Wednesday, October 31, 2007

Are Mashups a Threat to Web Application Developers?

I read a blog post or an article the other day (can't remember where) in which the author stated his belief that soon mashups would be the biggest job security threat to web application developers instead of outsourcing. His reasoning was that as IT departments leverage existing/external web services to compose their applications, they won't need as many internal developers.

There is some logic to that, but web services and mashups--heck, any existing code or algorithms--can only get you so far. If there's something out there that's exactly what you need, you just acquire it, and there's no need to do any programming of your own.

Recently a client and I discussed redoing an application for them in order to make it more flexible and open to expansion. They don't have any internal programmers, so I've been thinking about how to write administrative tools that would allow them to create new data sets and the interfaces to allow the users to enter data. After spending several hours over the past few days working out the different variations and the complexities involved, I realized today that it wasn't going to happen. There's a point of complexity and customization where no tool is going to let you cover all the bases: you need a programmer to deal with it.

So no matter how sophisticated and easy-to-use these web services and APIs become, someone with some programming-savvy will always be needed to fully leverage those assets and customize the end-result to the needs of their users.

Advantages of the jQuery Ready event

I've been working with jQuery for a few weeks now as part of a project, and I love it. I've always preferred to roll my own JavaScript, but from now on I plan to write all of my JavaScript utilizing the features provided by jQuery.

One of the most significant features of jQuery is it's document ready function:

   // Your code here

It allows you to assign functions that will execute when an event like a mouse click occurs on the selected HTML element(s) (hyperlinks, divs, buttons, etc.). This allows you to separate the JavaScript calls from the HTML code itself--instead of writing:

<input id="mainLink" onclick="showPic();" type="button" value="Show Picture" /> can assign the click event to the mainLink button in a separate JavaScript file (referenced by the HTML file)...

   $("#mainLink").click (function () {

...and leave the button free of that markup:

<input id="mainLink" type="button" value="Show Picture" />

The other benefit to this technique is that if you have a client that likes to alter the HTML code of the pages you wrote for them, but you're afraid they might screw up the JavaScript calls in the page, you can use jQuery to create all of the event handlers and the client won't have to worry about avoiding JavaScript code in the document.

Tuesday, July 31, 2007

ColdFusion 8 is Here

Adobe released the much anticipated ColdFusion 8 yesterday.

Most of the new features of CF 8 were announced in various presentations and analyzed in numerous blogs, so the biggest news besides the announcement itself was the pricing of the Standard and Enterprise editions (U.S. pricing): $1,299 for Standard ($649 if upgrading), $7,499 for Enterprise ($3,750 if upgrading).

I was hoping that maybe Adobe would make the Standard edition free in the hopes of drawing developers away from PHP and Java. However, Adobe has always said that they sold more copies of ColdFusion 7 than any previous release of ColdFusion, so I can certainly understand why they wouldn't want to give up that revenue: they are a business, after all.

A number of ColdFusion developers were upset about the pricing, especially the pricing of the Enterprise edition. They're concerned that they'll be unable to convince their potential clients to go with ColdFusion when languages like PHP and Java are free in terms of initial cost.

My hope is that Adobe will take some of the revenue generated by CF 8 sales and put that money into a solid advertising campaign, something that will bring attention to CF in the business community and in the larger Internet company. Ideally, such a campaign should include demonstrations of just how easy it is to accomplish certain tasks in CF. And they shouldn't be afraid to make comparisons between how CF lets you accomplish those tasks and how PHP or Java does those same tasks (if they even can!). I also think those demos should be publicly available on Adobe's web site, along with other marketing materials, so that these developers who are trying to convince clients to go with ColdFusion can point to these examples to make their case.

Maybe Adobe can even provide some technically-savvy marketing staff whom these developers can call for help with convincing clients. One of the strengths of ColdFusion is that there is a company that is solidly behind the development and support of the product, and that strength should be leveraged to the utmost.

As for attracting more developers to ColdFusion, that's more of a problem for Adobe to tackle than it is for ColdFusion developers. A strong advertising campaign will help generate interest, but Adobe may need to come up with new ways to make ColdFusion appealing to potential developers who probably feel they'd have better job security learning PHP or Java. I guess time will tell.

There is one other thing I'd like to see happen...the removal of that Warhol-esque portrait of Tim Buntel on the Adobe ColdFusion product page. The fact that it's a portrait of Tim is okay; the fact that it looks like a browser image rendering error is not. Please, somebody fix that!

Thursday, May 17, 2007

Some Notes from the D.C. Scorpio Presentation

(WARNING: Long post!)

I was at the Scorpio presentation in Washington D.C. last night. While the presentation didn't reveal any Scorpio features that haven't been covered in blog posts from earlier presentations (like here and here), I did pick up a few more details about certain things:

<cfajaxproxy>: As I mentioned in my last post, this tag will automatically created JavaScript code to call CFC methods via AJAX, like so:

<cfajaxproxy cfc="com.fooclass" jsclassname="cfFoo" />

<script language="javascript">
  var myFoo= new cfFoo();
  if (!myFoo.isEmailAddress(email))
  { alert("Please enter a valid e-mail address"); }

What I learned last night was that you can define a callback method for the calls to the CFC, so when data is returned asynchronously from the CFC, a particular JavaScript function will execute. It goes something like this (in JavaScript):


<cfdbinfo>: This feature was only mentioned recently. It's a tag that allows you to introspect any database ColdFusion can access via a datasource. You can retrieve the following information:

  • A list of the tables in the datasource
  • The version (of the database, I think)
  • A list of columns in the table (hopefully details about the column datatype, not mentioned)
  • The primary key, all foreign keys, and all indexed columns in a table
  • "Details" about stored procedures (whatever that means).

...I think this tag could drastically impact how ORM tools are developed.

<cfpresentation>, <cfpresentationslide>, and <cfpresenter>: When I first heard about the presentation and presentation slide tags, I envisioned that the result of using these tags would be a simple Flash slideshow, like the ones you see for viewing a series of pictures.

I was way off.

These tags generate a full-blown, full-window, Breeze-like presentation. In the example they showed us, the slides took up the left 2/3rds of the window. Below the slides were the usual slide controls (stop, start, pause, forward, backwards). On the right 1/3 of the window was a block of information about the presenter generated by the <cfpresenter> tag, which included a picture of the presenter, and below that were 3 tabbed columns providing access to other information (like notes and comments).

You can put pretty much anything within a <cfpresentationslide>: calls to external resources, movies, even operational Flex forms. The tag has a duration attribute that lets you set how many seconds the slide will display before moving to the next slide, and you can provide narration for the slide (narration is probably another attribute; they didn't use it in their example) via an MP3 file (they didn't say if other audio formats were supported). They also said that slide content was indexed, apparently to allow for searching.

You can define multiple presenters simply by using multiple <cfpresenter> blocks, and you can assign one presenter per slide by pointing the presenter attribute of the slide with the name of a <cfpresenter> block.

They pointed out two advantages to using these tags instead of simply uploading or converting a static presentation: the content of the slides can be updated dynamically (i.e. your sales chart could represent current data even if the presentation was built months ago), and you could use business logic to determine which slides a user could see.

Reaction options for an unresponsive server: I don't administer our CF Server (though I run my own locally), but I was interested in how the new alert functions in CF 8 could help my server admins, so I took in as much about that as I could.

They showed us the interface for configuring an Alert response to an "Unresponsive Server" (defined as a server that is exceeding its permitted thread count, I believe). There were several options for what the server should do if that condition arose, and I'm fairly certain you could choose all of them:

  • Send e-mail (there is another page tab where you define where that e-mail is sent to).
  • Dump snapshot (this will generate a text file containing a full statistical and status dump of the server in its present state for troubleshooting purposes).
  • Kill threads running longer than __ seconds.
  • Reject any new requests.
  • (Run) Processing CFC: ____. You can call a CFC you create. That CFC must contain two methods: onAlertStart() and onAlertEnd(). The page contained some guidance instructions on what you could do with those methods, but the text was a bit too small for me to read.

Other Alert conditions (besides Unresponsive Server) were Slow Server, JVM Memory, and Timeouts. They didn't really show those page tabs to us, so I don't know if the same response options are available for those (though I suspect they are).

onMissingMethod: You can now include this method in your CFCs to execute whenever something calls your CFC asking to run a function that doesn't exist. The onMissingMethod provides you with the name of the function that was called and the arguments that were passed in the call.

Obviously, it can be used as a means of error prevention/error handling, but it can be used for other purposes as well. Adam Lehman was running the demo part of the presentation, and he told us (and showed me later) an interesting use for it.

As tempted as I am to talk about it, I don't want to steal his thunder. I was hoping he had a blog and he written about it so I could just point folks to that, but if he has a blog I couldn't find it.

I will say this about it: it involves accommodating the erroneous request (think "controller").

Public beta: Maybe this was mentioned in someone's blog already and I missed it, and if I missed it then maybe others did as well. They said a public beta would be available: I believe the exact words Tim Buntel used were "very soon."

So keep an eye on Adobe Labs: I'm betting it'll be up there right after the Scorpio tour concludes (the start of June), if not sooner.

Wednesday, May 9, 2007

cfajaxproxy: No More Validation Duplication

ColdFusion 8 is going to include a huge new set of tools and features. How huge? Let's just say ColdFusion bloggers do not lack for material these days. And every few days another feature is revealed as Adobe folks tour the country with their preview demo.

It was recently revealed that ColdFusion 8 would contain a new tag called <cfajaxproxy> as part of a number of tags in support of AJAX functionality. Details are vague, but apparently the idea is that this tag lets you call the functions in a ColdFusion CFC file from JavaScript via an AJAX call and return the results of the functions back to the JS function.

That's a tremendously powerful tool. Most modern CF applications perform all of their business logic and database transactions through CFC functions, and now all of those algorithms can be made available via AJAX.

The area where this will really help is input validation. A good web developer knows that data input by a user should be validated before submission to the server by JavaScript, but that the server should also validate the data upon submission in case JavaScript is unavailable/turned off.

That used to mean maintaining two sets of validation functions: one in JS and one in ColdFusion.

Not anymore. Now you can write one set of validation routines in your CFC methods and use it for both client-side and server-side validation. A single set of routines, easy-to-maintain and, because they are written in ColdFusion and not JavaScript, browser-independent.

I can't wait!

Sunday, April 22, 2007

Blueprint for An Emergency SMS Messaging System

An hour or two after my last post, I talked with the members of my group about possibly implementing an alert system that would send out an SMS text message to faculty, staff, and students at the university, something that would help get the word out should a shooting occur at our university. That was Tuesday morning.

By Friday afternoon, I had finished two ColdFusion-powered portlets for our still-relatively new university portal: one that let members of the university enter their SMS information, and another that let select individuals send out an alert message using that information.

The code is unremarkable, but I wanted to share the ideas behind those portlets as inspiration or guidance for others.

We decided to design the system to use the SMS gateways provided by the cell phone service providers themselves: almost all of the major providers allow you to send an SMS to someone via an e-mail address comprised of the recipient's cell phone number and an e-mail domain specific to the cell phone provider (for example: would be the e-mail address to send an SMS to a T-Mobile user with a cell phone number of 555-555-5555). My manager found a list of these gateways on a LiveJournal page, and I found a similar page at Wikipedia.

The sign-up portlet (if put into production) will appear in everyone's portal page. The portal takes care of authentication, so the portlet retrieves the unique portal ID of the user from the portal without requiring additional authentication. The portlet window contains some text explaining the service and how it will be used followed by a simple form: a select box containing the names of the different cell phone services that provide cell service in the area, and a text box for the user to provide their cell phone number or their cell service username.

The form is followed by three form buttons. The first button, the "Save" button, submits the form data to be saved to a database table. Basic JavaScript validation is used to make sure that the user has selected a cell service provider and has provided a phone number or username: if the user has JavaScript disabled, similar server-side validations will take place.

If the data is valid, it will be recorded in the user's database record. The record will contain the user's unique ID, the unique ID of the cell service provider (which matches up with a record in the table containing the service providers and their SMS gateway addresses), an encrypted copy of their cell phone number/username (so that data is protected if the database table itself is compromised), and the current date signifying the last time the information was updated. Once the information is recorded, the user will see a message at the top of the portlet indicating whether the data submission was successful or not.

The second button, the "Save and Test" button, triggers the same actions as the regular "Save" button but also executes code to send the user a test SMS message using the SMS information they provided. The message is sent using a tag directed to the e-mail address comprised of the phone number/username and the SMS gateway of the cell service provider. The message contains a unique test message ID number that corresponds to the primary key value of a test message log table. The records in that log table also contain the ID of the user who generated the test message, the IP address of the user's computer, the SMS gateway and an encrypted form of the number/username the message was sent to, and the date and time the test message was sent. This log can be used to determine if anyone is misusing the test mechanism to send spam SMS messages to other individuals. The user's own database record is also updated with the date they sent a test message so that we can determine if the user has tested (and therefore verified) their SMS information. Again, once the information has been saved and the test message has been sent, the user will receive a feedback message, and will be told that they should receive the test SMS shortly.

The third button is a "Removal" button so users can remove their SMS information if they no longer wish to use the service or if they are leaving the university. The button triggers code that removes the SMS gateway and phone/username data from the user's database record, but it does not remove any data the user generated in the test log (to ensure that anyone abusing the testing tool cannot cover their tracks). Again, the user will see a message indicating whether or not the action was successful.

Once users have submitted their SMS information, they will see that information populated in the form on subsequent visits to the portlet. If the "last updated" date in their database record is over 6 months old, they will see a message at the top of the portlet window indicating that they should review their information to make sure it is current and to click the "Save" button to indicate this (thereby resetting the "last updated" date).

The administrative portlet, like the sign-up portlet, retrieves the unique portal ID of the user from the portal without requiring any additional action from the user. However, it then compares that portal ID with the records in a database table that lists the authorized users of the administrative portlet. That table contains the records for two types of users: technical administrators who can only use the portlet to send test messages to users who have agreed to be testers of the service (such users have an additional data field populated in their user database record), and emergency administrators who are allowed to send an alert SMS to all users of the system in an emergency.

If the portal user is a technical or emergency administrator, the portlet redirects them to the appropriate starting page, while unauthorized users are prevented from proceeding (technically, unauthorized users would not have access to the portlet at all anyway). Technical administrators are presented with a single hyperlink that gives them the option to compose and send a test message to the test users. Emergency administrators have that hyperlink as well as the hyperlink to the form for sending a true alert message.

Even though the processes for sending a test message and sending an emergency message are very similar, separate submission forms are used as a security measure to ensure that only emergency administrators can send an emergency message. Each form also checks the user's credentials to make sure they are authorized to perform those particular actions.

The forms for composing a test message and composing an emergency message both consist of a textarea control and a submit button. The directions preceding the forms are slightly different: emergency administrators using the emergency message form are reminded that while they can send more than one message, a second or third message may be delayed by increased cell traffic generated in response to the first message, and to keep that in mind when composing the initial message. Technical administrators (and emergency administrators using the test message form) are reminded that their test message should clearly indicate that the message is a test message and not a real one.

Beneath the textarea control are two text blocks, one that indicates the number of characters in the textarea and one that counts down the number of characters used from a starting number of 110. The number of characters an SMS message can contains varies between cell service providers. Based on the information we had on the SMS gateways our users would use, we decided that 110 characters was the number of characters almost all users would be able to receive, and that 140 characters was the upper limit of characters we would allow.

As the user types, a JavaScript function fires every time a key is released that counts the number of characters currently in the textarea and then uses that information to update both counters. Any user with JavaScript enabled will know exactly how long their message is and whether it exceeded the safe 110 character limit. If the message exceeds 140 characters when they submit the form, a JavaScript alert box will inform them that they need to shorten the message. If JavaScript is disabled, server-side validation code will perform a similar task.

Each of the form pages is followed by a confirmation page, where the user is asked to confirm their decision to send the test message or emergency message. The user is shown the message they composed one more time. Any characters beyond the 110 safe character limit in the message are shown in red to indicate to the administrator what text might be truncated and therefore not received by some recipients. Following the message are two form buttons, a confirmation button and a cancellation button.

If the user clicks the cancellation button, they will be sent back back to the composition screen along with the text of the message (so the contents of the message are not lost if the user merely wants to make some changes to the content).

The confirmation button for sending a test message retrieves the SMS data for all of the users identified as test users, while the confirmation button for sending the emergency message retrieves that information for ALL users. The code then loops through those query results. During each loop iteration, the user's cell phone number/username is decrypted and the message is sent via to the address comprised of the decrypted number/username and the SMS gateway of the user's cell service provider. Once all of the messages have been sent, a new record is recorded in a database table that logs all messages sent by technical and emergency administrators: each record contains the administrator's ID number, the text of the message, the date and time the message was sent, and a value indicating whether the message was a test message (that only went to test users) or not. These log records ensure that anyone who sends out an unauthorized message can be identified.

Once the message has been processed, the administrative user will be returned to the appropriate composition form and will see a message indicating whether or not the message was successfully sent out. The user can then opt to send another message or return to the initial portlet screen. there you have it.

A stand-alone application designed to perform similar tasks would have to include an authentication system, and might have to run a scheduled task to check the age of each user's SMS data and send them an e-mail if their data was old, but I think everything else could be designed to work in a similar manner to the system I just outlined.

Tuesday, April 17, 2007

Twitter as Alert System?

Yesterday's tragedy at Virginia Tech underlined the importance of sending out warnings regarding dangerous situations as quickly as possible and through as many channels as possible.

Listening to the news last night, it sounded like the VT administration used every channel of communication at their disposal: the campus website, mass e-mails, broadcast phone messages to all campus phones, and a siren system. The university I work at (the University of Maryland) also has all of those means of getting the word out.

The one communication channel that wasn't mentioned, however, was cell phones. That's not surprising: I suspect few universities specifically collect cell phone numbers from their students, and most students would probably be hesitant to give their cell number to the university out of privacy concerns.

But in light of yesterday's events, maybe universities should rethink that issue. Messages sent to land-line phones and e-mail addresses are only received if the recipient is at their phone or is actively checking e-mail. A message sent to a cell phone, which folks usually carry with them, has a much better chance of getting the recipient's attention immediately, even if they are walking between classes. While not every student owns a cell phone, those that did and received the message could spread the word to the people around them, getting the word out much faster.

So let's assume universities offered to send emergency messages (and only emergency messages) to students who provided a cell phone number to contact: how would the university broadcast an alert to those phones?

A long-term solution would be to put a SMS messaging system in place at the university designed specifically for this purpose (universities like mine that run ColdFusion 7, for example, could build an application using the SMS Gateway service provided by the ColdFusion server).

A short-term solution could be Twitter. Twitter is a social networking tool where you can receive short messages from friends via a web page, IM, or via SMS.

A university could set up a Twitter account to use to send out emergency messages, then instruct students to get a Twitter account (which is free) and "follow" the university Twitter account. The students can then control whether they receive updates from the university Twitter account via their phone or not.

Granted, this is not what Twitter was designed for, but I think it could serve as a stop-gap measure for getting warnings out until a more robust system is put in place.

Friday, March 16, 2007

Tired of the Open Source/Closed Source Conflict

Yesterday I ran across Ryan Stewart's blog post Open web advocates: Get off your high horse, where he took another blogger, Brendan Eich, to task about a post he wrote, The Open Web and Its Adversaries, defending standard web technologies against the perceived encroachment of proprietary technologies like Flex.

A number of folks took Ryan to task for daring to defend those proprietary technologies. I was so annoyed over the whole discussion that I had to take the time to express my thoughts. This is what I wrote:

This isn't Good vs. Evil, people.

I hate how most discussions comparing "open" source to "closed" source end up as a "right" verses "wrong" debate. Injecting a nonexistent dimension of morality into these arguments makes for a confrontational discussion rather than an analytical one, and it doesn't really benefit anyone. It seems like the main concern of many of my fellow posters is that there's a danger of Adobe or Microsoft dictating how web sites and web applications will be built because their web application technologies (Flash/Flex and WPF/E) are not open to change and modification by developers. I can see where such a concern would cause supporters of open source software to view Adobe and Microsoft as potential adversaries, but is that concern really valid? Could Adobe or Microsoft really take over the web if they wanted to?

How could they? Neither company has a monopoly on the core/base technologies that make the web possible: the network of wires and cables, networking hardware and software, TCP/IP, DNS, and web browsing software (granted, Microsoft is a strong player in the browser world, but I think it's clearly been demonstrated that they cannot dictate terms to the browser industry as a whole). Without that level of control, they cannot stop the use of traditional web technologies (HTML/CSS/JavaScript).

So what's really the concern here? That developers will abandon HTML/CSS/JavaScript for Flash and WPF, perceiving these technologies as the "next generation" of the web, in such numbers as to give Adobe and Microsoft a strong influence over web technologies in general? Well, yes, that could happen. That's the nature of a free market: people are free to choose the technology/methodology that they believe works best for them, and sometimes the end result is that one product or process ends up being the front runner. Does that mean its competitors are doomed to extinction? Heck no: it just means they need to innovate and offer something the front runner cannot.

One of the basic tenants of the open source movement is that open code allows a product or technology to benefit from the creativity of countless developers, leading to more and faster innovations. If that tenant is true in practice, then on a level playing field an open source product should be able to out-innovate and out-evolve a proprietary product, and therefore active competition between an open source product and a proprietary product works in favor of the open source product.

There's plenty of room on the web for all of these technologies. Developers should feel free to use whatever technology (at whatever cost) they deem is best suited to meeting the needs of their particular project. Limiting their options by strict adherence to an ideal or concept is a disservice to themselves and to their clients, paying or otherwise.

I do have one question for the open source community regarding their view of HTML/CSS/JavaScript: other than the fact that one organization makes money and the other (I assume) does not, what is the difference, in the eyes of an individual developer, between having conventions and standards for Flash controlled by Adobe, and having conventions and standards for HTML/CSS/JavaScript controlled by the W3C? Unless you are a high-level member of either organization, your ability to use their technologies is subject to their authoritative decisions, is it not?

Friday, January 5, 2007

Using Conditional CSS Selectors

The CSS I use in my applications is pretty straightforward. I stick with the basics, assigning styles based on element id, classes, and pseudo-classes.

When situations arise that require similar page elements to utilize differnet styles, I use ColdFusion or JavaScript code to evaluate the condition and assign the appropriate CSS class.

This article I found today is an excellent description about how to use CSS selectors to act only on page elements that meet a certain description--no JavaScript or server-side coding required:

Showing Hyperlink Cues with CSS

Since he makes a point of saying these selectors will work in IE 7, I can only assume that they won`t work (or at least not well) in IE 6, so you may not want to use these selectors unless you have a backup plan for mimicking the end-result using another method or you know your audience has upgraded to IE 7. Still, something worth knowing and a feature to look forward to as IE 6 rides off into the sunset.

Thursday, January 4, 2007

Catching Errors When Consuming RSS Feeds

Yesterday, Ben Forta blogged about an article by Ben Cortese on Consuming RSS Feeds with ColdFusion.

The article does a great job of providing simple, straightforward code for accessing an RSS feed and displaying it to the user. However, a few more lines of code would shield the user from errors caused by the feed not being available or by the malformed content within the feed.

As the article pointed out, you can retrieve the RSS feed from the remote site through the use of the tag, and then you can convert the XML in the feed to an XML object using the xmlParse function. If you enclose each of these steps within a block, you can intercept the errors and give your user a simple error message that explains there`s a problem with the feed.

For example, say you wanted to consume the main news feed from ( Here`s how you would retrieve the feed and then convert it to an XML object with error-handling:

It`s a good idea to include this kind of error-handling whenever your application relies on external data in order to function properly so that the user knows that the problem lies with the source of the data rather than the application itself. And in the case of RSS feeds, the problem with the feed could be resolved within the next few minutes or so: the server providing the feed could come back up, or the problem entry in the feed could be removed (this is especially true of Web 2.0 user-driven sites where the feed content is updated frequently).