Entries Tagged as 'JavaScript'

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/

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

JavaScript , jQuery 1 Comment »

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

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

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.