NOTE: As of July 12, 2009, this blog has been discontinued and replaced by the new Thought Delimited blog. All of the entries in this blog can be found there, along with new posts.

My First Mozilla Jetpack Add-On For Firefox: browseTimer

As I previously mentioned on my blog last week, Mozilla has launched a new means of creating add-ons for Firefox called Jetpack, which allows would-be plugin developers to build add-ons with HTML, CSS, and Javascript functions that include all of the jQuery functions.

As it happens, the first two functions listed in the Jetpack API were the clearInterval() and clearTimeout() functions, and that gave me a idea. My most recent AIR application, focusTimer, is a desktop widget inspired by time management techniques like Pomodoro, where you basically shut out/off all distractions and work on a task for a set amount of time. Once that time is up, the idea is to take a short break before starting another distraction-free period.

So my Jetpack add-on, browseTimer, is a timer built into the status bar of Firefox that lets you set how much time you want to spend browsing the web before getting back to work. Once the timer expires, the add-on uses the Jetpack API functions for the Firefox tabs to blank out the content of all of your open Firefox tabs and turn the body of the now-blank pages red (in other words, you KNOW when the timer has run out!).

It's certainly not the most useful add-on in the world, but it didn't take long and it helped me learn the basics of Jetpack.

If you're interested in checking it out, visit the following page...

http://www.swartzfager.org/blog/mozillaJetpack/browseTimer/installBrowseTimer.html

...for the link to the Jetpack add-on need to run all Jetpack-based add-ons, links to the Macintosh and Windows versions (there were slight differences in how the input elements were displayed in the status bar that warranted two separate versions), and instructions on how to uninstall it if you don't like it/need it.

Mozilla Announces Jetpack, an API For Writing FireFox Adds-On with jQuery, HTML, and CSS

I found out about this last night from a tweet sent out by the jQuery Twitter account (which is probably a good indication that they like the idea).

The subject line pretty much says it all: Jetpack is designed to let current web developers use their existing skills with HTML, CSS, JavaScript, and jQuery to build Firefox add-ons/plugins without the need to mess with Firefox's XUL mark-up language. While JavaScript has always been part of the add-on development process, the inclusion of jQuery should make performing certain actions a whole lot easier.

You can learn more about Jetpack via the following URLs:

...the tutorials in the final link give you a good idea of the kinds of things Jetpack will allow you to do: the last example is a Jetpack add-on that will count and display the number of unread e-mails in your Gmail Inbox.

I want to give Jetpack a whirl, but I honestly can't think of any functionality I want to add to Firefox that I can't get from an existing plugin. Anyone have any suggestions for something to try with Jetpack?

It's interesting how web technologies keep being repurposed as a development option in other technologies (Adobe AIR, the upcoming Palm Pre's WebOS, and now Jetpack). Even though I'm not particularly interested in delving into all these different areas, I must say that I like the trend. :)

Using jQuery Manipulation Functions (Append, Prepend, After, Before) To Reorder Items

I discovered something interesting quite by accident today. I was trying to figure out the best way to reorder certain <li> items based on the value of a particular trait (while ignoring those <li> items that didn't have that particular trait at all). I figured the best way to accomplish this was to:
  1. Select all of the items that had the trait and store them in an array
  2. Resort the contents of the array into a new array.
  3. Delete the selected items from the list (so as not to replicate them)
  4. Loop through the new array and add the items back into the list using the jQuery prepend() function to put them at the top of the list.

When I ran my first test of my code, I left out the deletion step so I could compare the original item order with the new item order, figuring I would have duplicates of the selected items.

However, I was surprised to discover that prepend() removed the original instances of the selected list items, leaving only the prepended copies. Essentially, it ended up moving the items rather than duplicating them.

There's nothing on the official documentation page that says that if you're prepending an item to a collection that already contains an instance of that item that it will remove the original item for you, but that's apparently what it's programmed to do.

I ran a quick test of some of the other related Manipulation functions (append(),after(),before()), and they all seem to behave that way as well.

Thought it was worth sharing. Certainly makes my reordering task a bit easier.

Using jQuery UI Sortables To Move Items From One List To Another

During my most recent project, my clients asked me to build a web-based tool that would help them place volunteers into various standing committees. Placements would be made based on the preferences of the volunteers (who were asked to choose up to three committees they would like to serve on), the vacancies created in each committee by outgoing members, and the desire to have a diversity of units and divisions represented in each committee.

I decided pretty quickly that the most natural way to represent this placement process on a web page would be to let them "physically" move a volunteer into a committee. I had built similar tools before (even before I started using jQuery), but never with more than two lists or collections, so I went to the jQuery UI site to see what my options were.

I started with the most obvious place to start, the Droppable interaction, but soon realized that a better choice for this task was the Sortables interaction.

The primary focus of the Sortable interaction is to let you reorder a collection of DOM elements by dragging them up-and-down through the collection. It's extremely easy to implement in its most basic form. If you wanted to make all of the <li> elements in a <ul> with an "id" attribute "listA" sortable, you can do it in one line:

$(document).ready() {
  $("#listA").sortable();
});

...you can see that code in action on the home page of the Sortables interaction.

What I discovered was that it was almost as easy to connect one Sortable list to another, so that in addition to being able to move reorder items within each list, you could drag items from one list to the other, simply by using the "connectWith" option:

$(document).ready() {
  $("#listA").sortable({
    connectWith: ['#listB']
  });

  $("#listB").sortable({
    connectWith: ['#listA']
  });
});

...In the code above, the first sortable() function call makes listA sortable and uses the "connectWith" option to allow items from listA to be dragged into listB. The second sortable() function call lets you sort items in listB and drag items from listB over to listA (even items that originally belonged to listA). If you wanted the movement to only go in one direction (from listA to listB but not back again), you could leave out the "connectWith" option for listB.

Again, the jQuery UI site has a nice ready-made demo of this.

All well and good, but right now all this code does is create the visual effect of moving an item from one list to another. Actually recording the fact that a particular item was moved from one list to the other requires more code, code that is invoked whenever such a move takes place. Being the smart guys and gals that they are, the jQuery UI team built a couple of custom events into the Sortables interaction so you can run additional functions when a certain event has taken place. For my purposes, I only needed to utilize two of these events: receive and remove:

$(document).ready({
  $("#listB").sortable({
    connectWith: ['#listA'],
    receive: function(event, ui) {
      //Run this code whenever an item is dragged and dropped into this list
      var itemText= ui.item.text();
      alert(itemText + " just joined this list");
    },
    remove: function(event, ui){
      //Run this code whenever an item is dragged and dropped out of this list
      var itemText= ui.item.text();
      alert(itemText + " just left this list");
    }
  });
});

...The code is, for the most part, self-explanatory, save for one line (repeated twice):

var itemText= ui.item.text()

The ui object is a "prepared" object created by jQuery UI that holds a number of objects and data associated with the event that just took place. The item object within the ui object represents the item that was moved in or out of the list, so I can treat it as a jQuery object and retrieve the text of the item using the standard text() function. You can find a full list of the data contained in the ui object by clicking on the "Overview" tab at the bottom of the main Sortables interaction web page.

I created my own demo page to illustrate how this code works (with a homage to the Fox TV show "Fringe"):

http://www.swartzfager.org/blog/demoFiles/connectedSortables/connectedSortableEvents.cfm

Two things worth mentioning at this point:

  • If one of your lists starts off empty, or if there's any chance that a user might remove all of the items from a list and then try to put items back into the now-empty list, you need to set a minimum height for that <ul>, so that even when empty, the <ul> is large enough to accomodate a single list element. In Firefox and Safari, you can set the minimum height using the min-height CSS style, but if you have to support IE 7, you'll have to add two additional height styles (like so):
    • min-height:50px;
      height:auto !important;
      height:50px;
  • In my demo, you'll notice that as you drag a person out of the Candidates list, the list item's width gets shrunk to the width of the longest unbroken string of text in the list item. I'm not sure why it does that, but you can negate that effect by either defining a set width for the <li> elements, or by defining a "helper" with a set width (a helper is a visual representation of the item being moved, using something graphical like an icon).

So, armed with this knowledge about the Sortables interaction, I was able to build the tool required by my clients. Every time a volunteer was moved into or out of a committee, the receive or remove event would make an AJAX call to update the volunteer's record (either providing the id of the committee they were placed in or removing it), and it would run a function that updated the vacancy count for that committee specific to that type of person and counted the overall number of vacancies for that committee (to determine if the committee had been "filled"). I also added a few toggles allowing them to hide extraneous information when they only wanted to see the data pertinent to doing placements for a particular committee. The final challenge was to scale everything so that the tool could be viewed with a projector, so that the members of the group responsible for making the placements could work on it collaboratively.

I wasn't comfortable sharing an exact copy of the tool I created, but I have posted a facsimile that's fairly close to it, minus any real-life data and any AJAX calls to save the placements between page reloads. You can view it here (Note: it doesn't work in IE 7):

http://www.swartzfager.org/blog/demoFiles/connectedSortables/volunteerPlacement.cfm

...I provided instructions at the top, but quite honestly I think most IT-inclined folks could figure it out without them.

It's just one example of some of the really cool (yet practical) user interfaces made possible with jQuery and jQuery UI.

Introducing the tableFormSynch jQuery Plugin

These days, there are a number of options for creating tables where a user can click on a cell and edit the data in that cell using JavaScript (CFML's <cfgfid>, the Jeditable jQuery plugin, etc.). Those work fine for simple tables, but they're not great solutions when you want to:

  • Work with record data you're unwilling or unable to display in the table, lest the table become too long horizontally.
  • Update data related to the row record that could have multiple values (example: the list of skills an employee has).

My new plugin, tableFormSynch, is designed to provide a workable alternative for those situations. It works in conjunction with the jQuery metadata plugin (http://plugins.jquery.com/project/metadata) to bind a table to a form such that you can populate the form with the data stored in a particular row and then use the form to update the data and write it back to the row. It also has functions for creating a new row based on the data in the form, deleting a selected row, and clearing the form of all values. It works with all form elements, including checkboxes, radio buttons, and <select>.

Because the data for each table row is stored in metadata, you don't have to display all of the data in the cells of the row: show only the most important information in the row and show the rest of the information in the form. Values from multiple related records can be stored in the metadata as arrays and viewed/updated via the form using either checkboxes or multi-select <select> boxes.

The only thing you have to watch out for is to make sure that you replace any single-quotes and double-quotes in your data before inserting that data in the metadata string (the plugin documentation covers that in more detail).

The plugin doesn't perform any AJAX operations, so you're free to use your preferred AJAX functions to write and retrieve data from the server. The plugin also isn't particular about how you populate the data in your rows, so you could generate the rows using any server-side technology: CFML using <cfoutput>, <cfloop>, or an IBO, PHP, ASP, etc. You're also free to use your favorite functions for validating the form data.

To view a demo and download the plugin, visit:

http://www.swartzfager.org/blog/jQuery/plugins/tableFormSynch/

jQuery Plugin Fling Lets You Set Up Flex-like Event Listeners

I was checking Twitter on my iPod Touch when I cam across a tweet from the jQuery Twitter account about a plugin called Fling.

The purpose of Fling is to make it easier to manage multiple triggers and cascading events. Fling lets you create a named event, then subscribe multiple functions to that event. When the named event is published, those subscribed events then fire in sequence.

It reminded me of how Flex allows you to set up multiple event listeners and use event bubbling to trigger multiple events based off of a single action.

Leveraging the Ubiquity FireFox Plugin To Access CFQuickDocs Pages

If you're a FireFox user and you haven't tried out the new Ubiquity plugin created by the folks at Mozilla Labs, you should.

What is Ubiquity? The short answer is it's a command-line interface for retrieving and re-purposing web content. For example, the "wikipedia" command built into the plugin takes the word you type in, retrieves data from the top 5 matches for that word (as you type it, no less) in Wikipedia using an API, and displays that data with clickable links to the Wikipedia pages in the command window:

You can see even more interesting uses for Ubiquity by watching the video clip in the Ubiquity blog post.

One of the things about Ubiquity that hasn't been talked about very much is that you can create your own Ubiquity commands using JavaScript and then share those commands with other Ubiquity users (note to jQuery users: Ubiquity commands can use jQuery functions as well as regular JavaScript functions). To that end, I created a very simple command that lets me call up a particular CFQuickDocs page by typing "cfquickdocs" and the name of the CFML tag or function I want to look up:

As Ubiquity commands go, it's not that impressive, but it does let me pull up a particular entry faster than I used to (which involved going into my bookmarks, clicking on the bookmark, waiting for the page to load, and then entering the tag or function I want to read about). And all it took was one function call with four parameters:

makeSearchCommand({
name: "cfquickdocs",
url: "http://www.cfquickdocs.com/?getDoc={QUERY}#{QUERY}",
icon: "http://www.cfquickdocs.com/favicon.ico",
description: "Searches the CFQuickDocs for the CFML tag or function you enter."
});

Sharing a Ubiquity command is simply a matter of putting the command in a JavaScript file and then creating an HTML page that calls that file. If you already have Ubiquity installed, you can install this CFQuickDocs command into your Ubiquity plugin by going to the following URL:

http://www.swartzfager.org/ubiquity/cfquickdocs.html

If you don't have Ubiquity installed but want to learn more about developing Ubiquity commands, there is an online tutorial that explains the basics. Once you have the plugin installed, you'll have access to a command editor that lets you try out your commands as you code them, and you can read the code for all of the functions that come built into the plugin.

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://www.swartzfager.org/blog/jQuery/plugins/textCounting

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.

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? :)

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:

<!---Include the jQuery core file--->
<script type="text/javascript" src="/views/JavaScript/jquery-1.2.2.js"></script>

<script language="javascript">
//Set the typical jQuery ready event handler to fire when the document is ready for manipulation
$(document).ready(function () {

//Assign a click event handler for all of the 'delete' hyperlinks (which all have a CSS class of 'deleteLink')
$(".deleteLink").click(function () {

var linkObj= $(this);
//Take the existing URL in the 'href' value and append an additional URL variable
var ajaxURL= linkObj.attr("href") + "&js=1";

//Remove the li list element (the parent) the link belongs to
linkObj.parent().remove();

//Make the Ajax call
$.ajax({
type: "POST",
url: ajaxURL
}); //end of .ajax function

//This statement will prevent the browser from actually navigating to the address in the link
return false;

}); //end of .deleteLink click function
}); //end of document.ready function
</script>


<h2>Your Messages</h2>

<ul>

<cfoutput query="qryMessages">

<li id="#messageId#">

#message#<br />
<a class="deleteLink" href="index.cfm?fuseaction=#xfa.deleteMsg#&msgId=#messageId#">Delete</a>

</li>

</cfoutput>

</ul>

...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.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.