Wednesday, July 30, 2008

My first jQuery plugin: textCounting

I've blogged about things I've done with jQuery before, but this is the first jQuery plugin I've developed.

My textCounting plugin lets you show users how much text they've entered into a <textarea> box and/or how much text they can still enter before reaching a set limit. The plugin can be configured to count either the number of words or number of characters entered or still available.

The plugin is designed in a way that a single call of the plugin can affect all of the <textarea>s on the same page if you follow certain element ID naming conventions. There are a number of different configuration options, and it can be used with another jQuery plugin, the Metadata plugin, to retrieve settings and data from a metadata block within the class attribute of the <textarea>s.

To see a demonstration of the plugin in action and to download the plugin, visit:

http://bcswartz.github.io/textCounting-jQuery-plugin/

I want to point out that one thing that the plugin does NOT do is enforce the word/character limit set for each <textarea>: you can apply a CSS class to the HTML element containing the count as a visual notice to the user that they've exceeded the limit, but it doesn't actually prevent them from continuing to type. I was originally going to provide that option, but I realized that a lot of users tend to paste content from another source in <textarea>s, especially when the content is expected to be verbose, and making the user count the words or characters in their text prior to copying it into the <textarea> defeats the purpose of providing the counter in the first place.

If any of you are interesting in writing your own jQuery plugins, I highly recommend you read Mike Alsup's blog post "A Plugin Development Pattern" on the Learning jQuery site. It was an invaluable resource and taught me a lot.

Thursday, July 10, 2008

Google's new virtual room service (Lively) may have potential

Yesterday Google launched a new beta project called Lively. Lively lets you create virtual rooms that people can join and then interact with each other via avatars. The concept is similar to virtual reality systems like The Sims or Second Life, but the difference is that you can put the rooms that you build on your own web page(s).

When I first heard about it, I thought the idea was a bit over-the-top, but I decided to at least try it out last night.

For a first version beta, it's pretty slick. You start off with a basic set of room layouts and room items (furniture, decorations, accessories) to build your room with, but you can choose to add different items from an on-line catalog (currently, all of the items are "free," which seems to imply a virtual currency may be established later when they let folks create their own stuff). Once you add an item to the room, you can move the item by dragging it and then rotate it as needed. You can also add mood music, either from the catalog of music or by uploading your own music file.

Once you've decided an avatar to represent you, you can enter the room and interact with the items (if there's a couch, you can choose to sit down on it). If there are other people/avatars in the room, you can chat with them just like you would in a normal chatroom and your words will appear in a conversation block over your head for everyone to see (or you can whisper privately to a single fellow occupant). Right-clicking on your avatar brings up a menu of gestures and animations you can have your avatar perform, like clapping, laughing, or dancing like John Travolta in "Pulp Fiction" (yes, it's as bizarre-looking as you might think).

I threw together a very simple room and then embedded the code to access the room on a very simple web page on my site. You can check it out if you like, but since you'll need the Windows-only plugin to enter the room, which is the same plugin that lets you create your own room and avatar, you're probably better off trying Lively out by creating your own room.

The need for the plugin to even enter a room is probably one of the biggest drawbacks of the service. The visual evidence strongly suggests that Lively runs off of Flash and was built using Flex (I once saw the standard Flex "Initializing..." dialog box while loading my room) so it's unclear as to why a separate plugin is needed. Maybe Adobe can work with Google to redo the plugin in AIR so it's at least cross-platform.

The other challenge facing adoption of Lively is, well, its usefulness. Right now, it's essentially an enhanced chat room. Some folks have said that businesses could use it to hold virtual meetings, but I don't see that happening unless Lively is upgraded to allow one or more room participants to speak via a microphone and provides a means of working with a presentation (Lively does allow you to display Flash videos within your room but I didn't explore that feature).

And while the idea of having a virtual room up on your home page or blog is kinda neat, it's not going to do you much good unless there's a compelling reason for people to come and hang out in groups in YOUR room. Centralized virtual realities like Second Life are never empty because there's just one world for people to go to: certain areas might be emptier than others, but there's always someone around to interact with. Still, I do see some potential uses for it with established communities. Popular online forums could replace their existing chat rooms with Lively rooms. Businesses could create a guest room or visitor room where website visitors could hang out before interacting with customer service avatars. Conferences like cf.Objective() or CFUnited could have virtual discussions rooms that allow conference-goers to discuss the day's events with non-conference goers ("Folks, the in-person BOFs will be from 8pm to 9pm, followed by the online BOF free-for-all in the Lively room from 9pm to...whenever.")

Heck, the folks on the RIA cruise in February could take the Lively "tropical island" room template and make a place to meet up with non-cruise landlubbers at some point during the cruise if they wanted to.

Who knows if people would make use of these rooms, but the beauty is that it doesn't take long at all to create a basic Lively room, so if it doesn't work out the time lost in trying isn't painful.

It'll be interesting to see if this goes anywhere. My guess is that it'll depend on how much time and effort Google decides to invest in it and whether it will scale effectively (I heard that there were load issues when it first went public yesterday, but I didn't have any real problems with it last evening).

Saturday, June 28, 2008

A list of jQuery plugins I use

As part of his blog post today, Ray Camden and a number of the folks who posted comments pointed out that while it was great that there are a lot of plugins available for jQuery, the downside is that it's hard to know which plugins are any good. I'm not a heavy plugin user, but I'd thought I'd list the few plugins and jQuery UI libraries that I've found to be very useful:

  • jQuery Form Plugin: this plugin appears in every project I've done since I started using jQuery. It makes it dead simple to submit forms via AJAX.

    (Oooh, it looks like the author's added some new features since the last time I download it...I'll have to check that out).

  • Tablesorter: this plugin was actually incorporated into version 1.0 of the jQuery UI library, but I don't see it listed in the current version of the UI library. This plugin lets you sort a table in ascending or descending order based on a selected column.

  • Sortables UI library: this part of the jQuery UI library lets you rearrange items on the page using drag-and-drop (something I've mentioned a number of times here on my blog).

  • TableDnD (Table Drag-and-Drop): the Sortables UI library I just mentioned does not work on table rows (tables are just "different," apparently), but this plugin lets you grab a row and move it up or down within the table.

  • curvyCorners: after trying a few different plugins aimed at letting you create curved corners for certain HTML elements (like <div>s), this plugin, although not perfect, seemed to work best.

    I must say that I couldn't get it to work right in IE, but that might have been because of the way I was using it. And it looks like the author has released a few updates since I last downloaded it, so that may not be an issue anymore.


Anyone else have any jQuery plugins they'd recommended using? Or recommend avoiding? :)

Saturday, June 21, 2008

Some random post CFUnited thoughts

Now that CFUnited's over (at least for me) and I've had some time to rest and mull over things, I wanted to post a few random thoughts and opinions:

  • The entire L'Enfant Plaza Metro station (columns, walls, even some of the Metro railcars that passed through) was one big ad for Adobe LifeCycle. The message: LifeCycle can help the government manage and distribute PDF forms. Unusual? I don't get down into DC too often, but I'd never seen any one company take over an entire station like that before. I want to see more of this high-visibility marketing from Adobe, especially for ColdFusion.

  • Sean Corfield's new asynchronous event-driven framework, Edmund, looks very cool. Being able to fire off events and have them bubble up through the framework much like what you can do in Flex is a very appealing idea.

  • Twitter once again proved to be a useful tool. I found it a lot easy to "tweet" what was going on instead of writing it up on the blog, and thanks to Nafisa Sabu and Elliot Sprehn of TeraTech, anyone who visited the CFUnited website could read the tweets of the conference-goers who had "friended" the CFUnited Twitter account. Hopefully a few folks found my tweets to be useful.

  • While the proposed integration of Hibernate in ColdFusion 9 sounds neat, I think Transfer is still going to be the ORM of choice for many developers, both now and in the future, for some of the reasons Mark listed in his blog and because Transfer works/will work on a larger number of CFML platforms (CF7, CF8, and probably OpenBD and Railo).

  • The discussion about whether or not ColdFusion and ColdFusion development is becoming too Java-like isn't over yet. I met a developer who made the point that it seemed strange (and stupid) to him that we're trying to entice Java developers to use CFML because it makes development faster and easier while we seem to be gravitating towards adding complexity to our development process and our code.

    I made the usual argument that regardless of the focus on OOP in the ColdFusion blogging community, no one was advocating removing those aspects of ColdFusion that make CFML easy to learn and use, and that even OO-style programmers will admit that there are some situations where using an OO application framework is overkill, but he wasn't entirely convinced.

    It made me wonder: if Adobe does develop a teaching curriculum as part of their effort to get ColdFusion adopted in schools, will that curriculum take advantage of CFML's traditional low learning curve, or will they emphasize an OO-style of programming from the get-go?

  • Some promising ideas came out of Brian Meloche's session on promoting ColdFusion/CFML outside of the community. The existence/promise of OpenBD and Railo and Adobe's decision to make ColdFusion free for educational use has opened up a whole new world of possibilities. You should be hearing about these ideas soon, either via the CFConversations podcast or some other channel.

  • Which reminds me, you should check out the CFConversations podcast if you haven't done so already. And I would say that even if I wasn't involved with the project. :)

Friday, June 6, 2008

Going to CFUnited tomorrow

Well, CFUnited begins tomorrow, so I'll be getting up a bit earlier than usual so I can drive to the nearest Metro station and head down into D.C.

The last time I attended CFUnited was back in 2005, so it'll be interesting to see if the conference has changed any in terms of atmosphere and organization since then. Certainly the venue will be different; hopefully that means the wireless network will be more robust/reliable.

And this time I won't be ducking out of lunch to settle on a new house (but hey, I did make it back in time for the next round of sessions).

I probably won't post any new blog entries during the conference (it takes me too darn long to come up with what I really want to say), but I might post a snippet or two about what's going on via Twitter. If you're interested in listening in on those "tweets", you can just follow me on Twitter for the next few days: my Twitter handle is bcswartz.

As for any of my fellow conference-goers (if you're listening), if you don't already use Twitter, you might want to make use of it during the conference. I don't know if Twitter is going to serve as a communications channel for what's going on and where people are meeting up like it did at cf.Objective(), but I imagine if nothing else the CFUnited folks will be making use of the CFUnited Twitter account to send out notices and what not. You can either use Twitter via the Twitter website and refresh the page occasionally, or you can use a Twitter desktop app like Twhirl (built with Adobe AIR).

Of course, that's all moot if we manage to overload the wireless network at the conference. :)

Anyway, looking forward to seeing everyone there!

Monday, May 26, 2008

Using a Transfer decorator to get related records within the same table

 

One of the benefits of using the Transfer ORM in your application is that if you define the relationships between your tables in the Transfer XML configuration file, you can retrieve any objects related to your current object through a variety of functions.

However, sometimes you need to relate records within the same table. For example, in my current project, I have a table of item records which need to be arranged in a hierarchy of unknown depth: one set of items could have two levels of hierarchy, another three levels. Each item, therefore, can have one parent item above it (identified by a parentId field in the record) in the hierarchy and any number of children below it (and all the child records have the current item's ID as their parentId value).

How can you use Transfer to access these in-table relationships? One way is by using a decorator object. As the Transfer documentation explains, a decorator is a CFC file you write yourself that extends the TransferDecorator CFC that comes with Transfer. You associate your decorator with the Transfer object that represents the table in your Transfer configuration file so that when a Transfer object for a record in that table is generated, the functions you define in your decorator become part of that object. So say I define a Transfer object called "Item" in the package "example". Here is the XML in the Transfer configuration file:

The decorator to be called is the itemDecorator.cfc in the "com" directory. I want to have two new functions in the decorator, one that returns a Transfer object for the parent record, and one that returns an array of Transfer objects representing each child record. Here's the code:

In a decorator CFC that extends the TransferDecorator CFC, you can access the current item's Transfer object all of its functions via the getTransferObject() function, and you can access the main Transfer object via the getTransfer() function. So the single statement in the getMyParentItem() function in the decorator CFC is equivalent to:

 
<cfset parentItemObject= transfer.get("example.Item",currentItemObject.getParentId())>

The getMyChildItems() function is slightly more complicated because it needs to retrieve a recordset of child objects first, using the listByProperty() function of the main Transfer object (again, provided via the getTransfer() function within the decorator), then loop through those records, creating a Transfer object for each child record and appending it the array returned by the function.

What if the item record in question is either at the top of the item hierarchy or at the bottom? If there is no parent item, the Transfer object returned by the getMyParentItem() function will have an itemId of 0 (the default value for an empty numeric primary key) and empty values for all of the other properties, so you can test for that condition. If there are no child items, the array returned by the getMyChildItems() function will simply be empty.

This is only the second Transfer decorator I've ever written, so there may be a better way of going about it, but it gets the job done with just two short functions added on to existing object functions provided by Transfer. I like it when things are this easy.

Friday, May 23, 2008

Creating a hyperlink that works with or without AJAX

The current project I'm working on includes a display page where users can see a list of messages generated for them by the system. Each message consists of an <li> element containing the text of the message followed by a hyperlink labeled "Delete". I wanted to make it such that you could delete each message without refreshing the page, but still accommodate users who had JavaScript turned off, and without a lot of extra work. How did I do it? Like so:

...The only other thing you need to do is put a conditional statement in the page/event that is called by the hyperlink that looks for the presence of the additional URL variable ("js" in this case). If JavaScript is turned off, that additional variable will not be defined and the page/event will redirect the action back to the calling page once it's done deleting the message data from the database. If JavaScript is turned on, the page/event will simply delete the message data (no action redirect), and the user simply sees that message item disappear from the list.