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.

Bug In How Safari 3.2.1 Renders the Links For RSS Feeds

One of my clients contacted me yesterday to tell me that there was a problem with reading their RSS feed in Safari (and only in Safari).

Over the next hour or so, I learned quite a bit about how the current version of Safari (3.2.1 as of this writing) handles RSS:

  • By default, Safari is configured to open up your default e-mail client to handle/read RSS feeds, resulting in a lot of head-scratching by your truly when I tried to navigate to the feed and ended up with a "Compose New Message" window in Thunderbird. While a lot of people do prefer the RSS-reading capabilities of their mail client over what the browser does with feeds, make that decision for the user is a questionable call on Apple's part, and some sort of alert/notice that this was the deal would have been nice.

  • A lot of browsers these days will apply a style to the RSS feed XML (probably using some sort of built-in XSL, I'm guessing) prior to display so that it's more human-readable and the hyperlinks for each news item are clickable. But you can still view the raw XML using the "View Source" option of the browser. Safari, on the other hand, transforms the feed into an HTML file with JavaScript, leaving no trace of the original XML. Again, another somewhat presumptuous decision by Apple to buck convention in order to enhance the user experience.

...Those two issues are annoyances rather than bugs. The problem affecting my client's RSS feed, however, is a bug in regards to how Safari is transforming the RSS data before displaying it to the user.

Each news item in an RSS feed can contain a number of elements/nodes, two of which are the <link> and <guid> elements. The <link> element is meant to contain the URL where the reader can access the full text of the item. The <guid> element contains a string that uniquely identifies that RSS feed item within the feed (like a primary key in a database).

If the <guid> element contains the "isPermaLink" attribute and that attribute value is set to "true", then that indicates that the <guid> element also contains a URL (a permanent one) to the full text of the item (one that might be different from the URL in the <link> element), and an RSS client could legitimately used the URL in the <guid> as the link to the story instead.

What I discovered, though, was that Safari was creating the hyperlink for each news item by combining the value of the <link> element in the <channel> node of the RSS feed with the value of the <guid> element of each item (which was simply a unique numeric value), even though the <guid> elements did NOT contain the "isPermaLink" parameter. So instead of using the value of the <link> element of each item as per the RSS specs, Safari ended up creating non-existent URLs.

The solution, of course, was simple: I just put the URL for each news item in the <guid> element as well as the <link> element. Point is, I shouldn't have had to.

Once I applied the solution, I did some searching to find out if this is a known problem that was being worked on. I found one mention of it in a generic tech support forum post published in 2008, so it looks like the problem has existed for awhile but hasn't gotten much attention (probably because most people read RSS feeds through actual RSS clients). I used Safari's built-in bug report mechanism to report it to Apple, but I don't hold out much hope for that having an impact.

Still, I thought it worth a post, on the off-chance this information might help someone else.

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.

Applications Are Only as Beautiful as the Processes They Replicate

In an ideal application development process, you work with the client to get an accurate picture of all of the business logic involved in the process the application is supposed to handle, and the end result is a robust system built with clean, understandable code.

But it doesn't always work out that way (some would say it never works out that way). Most of us have had to deal with "scope creep." In fact, one could argue that most modern CFML-coding frameworks and patterns came out of the need to deal with "scope creep" and other reasons for changing our applications.

But sometimes the challenge in creating a clean application comes from the nature of the business "logic" itself, the real-world process that your application is supposed to mimic and replace. It occurred to me the other day that that is often the biggest hurdle I have to overcome with the applications that I'm asked to construct.

When I work with my clients to figure out what exactly what tasks the software needs to perform, I often discover that the processes at work are often riddled with exceptions and conditionals. Sometimes my clients are consciously aware of these exceptions, but other times I have to point them out and we have to figure out how they need to be dealt with.

We humans can handle exceptions within our thought processes very easily. Computer logic, on the other hand, doesn't handle exceptions so casually (which is probably why errors can be referred to as "exceptions"). Coding for even a single exception to an otherwise iron-clad rule can make the code involved twice as complex and perhaps a bit less than pristine.

While we do all we can as responsible programmers to deliver a beautifully-coded application, I think that sometimes there's no avoiding the touch of ugliness that comes from trying to represent and replicate an "ugly" human-driven process.

If You Build the App, Someone Just Might Use It: You Never Know

I was rather surprised to see my colorPicker AIR application included in a list of 10 AIR apps for web designers on the Six Revisions blog this past week. Then Gary Gilbert gave it more exposure by blogging about the Six Revisions post.

After seeing the Six Revisions post, I decided to check colorPicker's download numbers on RIAForge and got another surprise: the download count was just shy of 800.

As of today, four days after the blog exposure, the download count stands at 1119.

I built the colorPicker mainly for myself (and I still use it). I put it up on RIAForge because I thought a FEW people might prefer something a bit simpler than Kuler (Adobe's color palette tool). But given the number of slick color designer AIR apps that are out now, I would never have expected that many people to have given colorPicker even a glance.

It just goes to show that you never know what apps or code other people might find worthwhile.

The new Dreamweaver beta: Subversion, show related files, show code sources

A number of folks have already posted about the availability of the new beta version of Dreamweaver (and Fireworks and Soundbooth) on their blogs, but none of the ones I read talked about any of the new features. Even though I use CFEclipse as my main IDE, some of the features in this new version of Dreamweaver sound promising.

I'll quick paraphrase some of the ones I personally found appealing:

  • Integrated Subversion support.
  • "Live View": you can view your page in a WebKit-powered browser window and make changes to it on the fly.
  • "Related View": these days you usually have several pages working in conjunction that produce the final page view. All of those related files are now listed above the top of your document.
  • "Code Navigator": shows you all of the code sources that affect the code you're currently working on. What isn't clear is whether that will work with ColdFusion code.

Table normalization verses long-term data storage

I'm currently working on an application that involves long-term storage of assessment data. Users submit records of their activities and assess their performance, and then reviewers look over those assessments and denote whether they agree or disagree with them. Each assessment database record is related to a reviewer through the unique reviewer id that is part of the assessment record, and I can use that relationship to retrieve the reviewer's name whenever I display the assessment record.

It's a standard example of table normalization. If the reviewer's name was stored within the assessment record itself, and the reviewer changed their name for some reason (marriage, divorce, mid-life crisis, etc.), the application would have to update the name in both the reviewer's record AND the assessment record. But by using the reviewer's id in the assessment record to establish a relationship between the assessment record and the reviewer record, the reviewer's name only needs to be recorded or updated once.

However, this project will entail keeping the assessment data for an undetermined number of years. With the data arrangement I just described, that means I would have to store the assessment records and all of the related reviewer records if I want to be able to keep showing the name of the reviewer when looking at older assessment records. That could result in keeping a lot of extra data about reviewers (addresses, e-mail addresses, logins, passwords, etc.) who are no longer associated with the program simply because we need to keep their name tied to the assessments.

I think this is one of those situations where it makes sense to repeat a little data. Recording the reviewer's name in the assessment records allows me to let the administrative users of the application delete reviewer user accounts without impacting historical data. It means a bit more work in keeping the reviewer's name the same in both records, but in the long run I think it's worth the effort.

Finish the sentence: "I know I'm in a coding zone/groove when..."

"...I correctly write a recursive algorithm involving nested arrays on the first try."

What about you? When do you know you're in a coding groove such that it feels like you're coding by feel/intuition?

Problem: No Drag-and-Drop On The iPhone/iPod Touch. Solution: Click-To-Click Move

As I mentioned in an earlier blog post, the drag-and-drop functions provided by various JavaScript libraries (jQuery, YUI, etc.) won't work in the iPhone/iPod Touch Safari web browser because the dragging gesture is used for scrolling around the web page.

That's a big problem for those of us who use drag-and-drop in our web applications to allow our users to reorder the items in a list, but I've come up with an alternative method for rearranging items using the jQuery JavaScript library that works on the iPhone/iPod browser as well as regular browsers. I call it the "Click-to-Click Move" method (CTCM).

[More]

New YouTube API= Flex Apps To Manage YouTube Videos?

YouTube announced the release of a new set of APIs today that (from what I've read so far) allow you to use YouTube as a web service. You can use API calls to log into YouTube, upload videos, list videos, edit the metadata about videos, and more.

Flex is obviously well-positioned to make use of these new APIs, given that the videos themselves are done in Flash. I wonder what apps will come out of this new development?

Here's the link to the main YouTube API page:

http://code.google.com/apis/youtube/overview.html

Internet Explorer 8's Webslices Feature: Widgetizing Pieces of Web Pages?

The first public beta of Internet Explorer 8 was released today. In addition to supposedly being fully web standards-compliant, IE 8 comes with two new...well, capabilites: Activities and Webslices.

Curious (and admittedly a bit bored with what I was currently doing), I did a Google search and came up with a page that does a pretty good job of explaining Activities and Webslices:

IE8 Beta Is Out And With It Some Slices & Activities

The Activities capability allows web developers to provide XML code that will add contextual menu options to certain page content when you right-click on that content, allowing you to send that content to another web page or service, like sending an address on the page to a mapping service like Google Maps.

The Webslices capability is even more interesting (if I understand it correctly): using CSS, web developers can tag a piece of the web page as being a slice. End-users can then save this slice in IE, and IE will periodically check that slice for any changes. If the content is changed, the end-user is notified and they can pull up just that part of that web page as a pop-up widget in the browser.

I don't quite know what to make of it...it's like they've made it possible to send a request to a webservice from the page (Activities) and to make part of the page a webservice (Webslices).

It's an interesting idea, but what will the other browsers do with this stuff?

More Entries

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