Entries Tagged as 'jQuery'

My First Mozilla Jetpack Add-On For Firefox: browseTimer

JavaScript , jQuery , Miscellaneous No Comments »

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

CSS , JavaScript , jQuery , Miscellaneous , RIAs 3 Comments »

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

JavaScript , jQuery 1 Comment »

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

JavaScript , jQuery , Web development 11 Comments »

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

JavaScript , jQuery No Comments »

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/