Archive for the 'ajax' Category

Checkbox Range Selection Update

Just a little update to my checkbox range selection jQuery plugin to allow chaining.  I'd forgotten to return 'this' at the end of the function.  Here's the full source, including the mod:

(function($) {
  $.fn.enableCheckboxRangeSelection = function() {
    var lastCheckbox = null;
    var $spec = this;
    $spec.bind("click", function(e) {
      if (lastCheckbox != null && e.shiftKey) {
        $spec.slice(
          Math.min($spec.index(lastCheckbox), $spec.index(e.target)),
          Math.max($spec.index(lastCheckbox), $spec.index(e.target)) + 1
        ).attr({checked: e.target.checked ? "checked" : ""});
      }
      lastCheckbox = e.target;
    });
    return $spec;
  };
})(jQuery);

You can check the project page as well, for full history and updates.

Prototype and jQuery

Since I discovered it a few years ago, I've been a big Prototype fan.  It's simple, and gets the job done with a minimum of fuss.  It's not without warts, of course.  I still occasionally forget to put 'new' in front of Ajax.Request, and some of the Ruby-like methods share their lineage's arcane naming.  When it was new, it was the best thing around, and while it now has competitors, it's certainly not lagging behind.

At work, however, jQuery has been adopted as the standard (and I've no power to change it).  The lack of the $() function is annoying; several times I've debated adding this function (or one of various similar ones) to our library:

function $(id) {
  return jQuery("#" + id)[0];
}

I haven't, of course, as it's not the jQuery way.  jQuery also lacks any sort of class assistance, so we still use the Prototype class framework for our class-based JS.  That seems to work fairly well, except for the fact that we have to use two frameworks where one could suffice.

jQuery is not without it's benefits, of course.  The plugin architecture is a nice aspect that Prototype didn't really offer an equivalent of.  It means the core stays lighter (good), but if you want additional functionality you're stuck managing files from a bunch of different projects (annoying).  Event handling is a bit more straightforward, in some ways.  "Magically" acting on collections of elements with a single call (i.e. no .each(function(o){…}) garbage) definitely makes for more readable code as well.

Because of this shift at work, I've been porting some of my personal apps over to jQuery as well.  I've actually been using a couple jQuery plugins (both self-written and external) for specific tasks for a while now, but not the core framework.  What I've found, however, is that jQuery can be prone to slow code.  To avoid a huge amount of extra work on the part of the JS interpreter, using temporary variables for jQuery objects is essential.  If you do strictly id-based queries, the degradation isn't huge, but if you do CSS-based queries, it can be significant.  With Prototype's focus on id-based queries (at least until $$() came about in 1.5), that was less of an issue.

This need to query a minimum number of times can provide a fair amount of complexity when you have more than a handful of closures hanging about and/or a dynamic DOM.  You end up doing a lot of state management work because you're, in effect, caching DOM lookups and have to ensure you never have stale cache.

Other than that issue and the lack of an equivalent to document.viewport, porting has been relatively painless.  Still very id heavy, so not leveraging jQuery as much as could be, but most of what I'm doing wouldn't benefit from other selectors.

Which one is better?  Hard to say.  jQuery seems to make you work harder to type less code, while Prototype seems to cost you a few more characters for a bit less density.  With the exception of Prototype's class support, their feature sets are fairly equivalent, especially with jQuery UI now available to "compete" with Scriptaculous.  For the moment, I'm choosing to use jQuery on new stuff, but wishing for Prototype every few minutes.  Until I come up against some sort of significant wall, it'll probably stay that way, just to stick with the same tooling professionally and personally.  And over time it'll probably get better as the Prototype-ness fades from apps.

Ajaxian on Prototype vs JQuery

Ajaxian posted a little blurb on benchmarking Prototype and jQuery today. I've been a Prototype guy for years, but at the office we've gone from all-Prototype to all-jQuery, and performance degredation was one of the things I noticed. I never did any actual benchmarking, just went by feel, but it's interesting to see that my perceptions were well founded.

Whether performance of JS libraries should be a huge determinant in picking one to use is up for grabs. Unless the client-side is doing a hell of a lot of work, these days' computers have plenty of CPU hanging about unused.  However, in the past couple months we've spent a lot of time working around JS performance issues at the office. I can't say that using Prototype instead of jQuery would have eliminated the bottlenecks, but clearly performance matters.

JavaScript. At Last.

Working on gpsracr.com this evening, and whipped open my favorite chunk of JS: Prototype. It just gets better all the time. They've added support for automatically executing text that is returned from an Ajax.Request with an appropriate MIME type (like text/javascript), which means you don't even need result handlers. Just dispatch to your URL with whatever parameters you need, and let CF emit back whatever JS should run as a result of the submission (error, failure, success, whatever). Talk about sweet.

Now that might not sound like a big deal, but it really is. I use Fusebox. So all my links are parameterized with XFAs. But XFAs are server-side. Client-side JS (especially static JS in *.js files) can't really access XFAs very well, so URL building is a pain for remoting endpoints and/or hard context switches, But if you're generating the JS server-side….

The specific use case was a login form. I want to "submit" it asynchronously and either display a "denied" message if there's a failure, or forward to the inside of the app if it succeeds. Ordinarily, you'd have to submit the credentials, get some sort of status back from the server, and then use JS to do something with it. Now I can just submit the credentials and let CF emit the JS that I want to execute as a result. I love it.

Improved ComboBox Demo

After Koen (a coworker) pointed out that my online ComboBox demo was rather user-unfriendly (like how you just had to "know" to type an 'a' in the fields), I threw some instructions around it. It's available at /web/widgets/, as before. There's also a new distro at /web/widgets/widgets-b2231.zip, and the project page has been updated as well.  The actual code is unchanged, only the demo file has been updated.

ComboBox Widget Update

I've been making tweaks to my ComboBox widget (first published in July 2005) in various apps of mine that use it, and figured it was time to publish an update. You can download the archive at /web/widgets/widgets-b2218.zip, play with the online demo (which is just the expanded archive) at /web/widgets/, or visit the project page for most info.  I believe I've fixed every bug that people have brought to my attention, but if I missed something, let me know.

New and notable features (in no particular order):

  • multiple delimited values (defaults to comma delimited)
  • the ESC key will now close the dropdown, if it's open
  • the TAB key will select the current value and move focus off the combobox
  • automatic hiding of SELECT, APPLET, and EMBED elements under the dropdown (for IE)
  • automatic setting of autocomplete="off"
  • changed to update only ever 250ms, rather than on every key press, which greatly reduces needless churn with JS remoting-based dropdowns
  • added "Loading …" message while waiting for dropdown values (for JS remoting-based dropdowns)
  • removal of already-selected items from the dropdown (only useful for multi-select)
  • added wrapping with the arrow keys (pressing 'up' when the first item is selected will move the selection to the last item)
  • support for arbitrary HTML in the dropdown values that will be stripped to create the actual form field value

There are a few known issues:

  • if your dropdown is larger than it's allowed side, scrollbars will appear, but the scrolling won't reset when new items are loaded
  • untested on IE aside from a few spot checks. However, except for the hiding of SELECT/APPLET/EMBED elements (which is fixed), I've not received any IE-specific complaints, so I'd say it's pretty sound.
  • documentation is somewhat lacking.

I'm sure I'm missed some, but those are the high points. As always, it's MIT licensed so you can basically do whatever. If you find it useful (or think it's a piece of garbage), I'd love to hear about it.

Ajax (sigh) Pet Peeve

I've finally given up and added 'ajax' to my vocabulary as a synonym for "JS remoting".  But I've got a bone to pick with people building ajax apps: neat UI trickery has to leave the UI in a consistent state or you're making the UI worse instead of better.

The particular example that is continually annoying is WordPress.   The authors have done a good job of integrating ajax bits to speed up the UI, like when you delete a comment, it just fades out of the table instead of reloading.  But what they don't do is update status information (like the number of pending comments) in other parts of the page to reflect that a comment has been deleted.  So you see a link that says there is one pending comment and click it, only to be presented with a page that says there are zero pending comments.  Argggghhhh.  I'd so much rather wait for a page reload on the comment deletion.
Flex wins hands down in this area, because you can do data bindings for all that stuff, and the Flex compiler will build all the event listeners/observers to make sure everything is always updated and therefore consistent.  Building that framework in JS isn't terribly difficult, but it does depend on having raw data structures client-side, rather than using the server to render HTML for injection.

DHTML ComboBox Widget

With the wife and kid out of town, I didn't have much to do, so I spent the afternoon building a simple DHTML combobox widget. Yes, I'm that much of a geek. I haven't done a lot of testing, but I built it exclusively in FireFox, aiming for compatibility, and IE6 behaved exactly as expected on the first try, so I'm hoping other browsers will behave as well.

It's available for download at widgets.zip, a demo is available at /web/widgets/ (try entering the letter 'a'), and there is a project page as well. The demo is included in the zip file as well.

The architecture will likely seem a bit odd at first, but it's built the way it is for good reason. In a nutshell, you put an INPUT in your document, and pass it's ID and a callback function to the ComboBox constructor, and the rest happens by magic. You'll notice that you don't pass in any options, but that's where the callback function comes in. That function will be called any time the value entered in the field changes and the field has focus, and will be passed the current value. It's responsibility is to return an array of strings that should be displayed.

The demo just uses a simple array of names for the values, but I set it up in the seemingly overflexible way specifically to allow for JS remoting calls to be used for generating the dropdown list. Currently, you only get synchronous processing (since the callback has to return the values), but I might add async capabilities (so your can pass in an array of options at any time).

As always, download and run with it, and give me any feedback you have along the way.