LRBlog

Logical Reality Design: Web Design and Software Development

Archive for the ‘Projects’ Category

NinjaScript: Javascript so unobtrusive, you’ll never it see coming

October 13, 2010

NinjaScript LogoWe're happy to announce NinjaScript: a jQuery plugin for unobtrusive scripting.
NinjaScript provides:

  • CSS-like language for web page behavior
  • Define rich behaviors that include both event handlers and transformations.
  • Durable behaviors that survive DOM alteration, with performance comparable to jQuery's live() method.
  • Handy built-in behaviors for AJAX.

Motivations

Unobtrusive Javascript is one of the coming movements in web design for a reason. Separation of concerns is generally a good thing, and the idea of separating behavior from semantics is pretty obvious once you think about it. If nothing else, it makes it much easier to think about how you structure your site. Just build it out as if this were still 1998 and you couldn't trust a browser to open an alert box, much less submit AJAX, then come back and mark everything up.

On the other hand, one hears a lot about "Unobtrusive Is Hard" and how a graceful degrade takes twice as long, etc etc. At the same time, software exists to encapsulate skills.  Could be you'll be seeing a Rails plugin from LRD soon to convert the big Rails helpers into degrading versions.

Therefore: NinjaScript. Unobtrusive Javascript in a tidy package so that you can get on with your day.

What's it look like?

Here's a very simple example. Suppose you have an existing

that POSTs and reloads the page, and you would like it to submit to the same URL, but via AJAX.

If you have NinjaScript loaded, this all you need:

$.behavior({
  '#coolness': $.ninja.submits_as_ajax() 
})

In addition to the pre-defined behaviors like submits_as_ajax(), you can build your own rich behaviors, specifying both transforms (alterations to an element that will be applied as soon as the element appears in the doms) and event handlers at the same time:

$.behavior({
  '.date_entry': { transform: function(elem){ $(elem).datepicker() }},
  '#work_unit_select_all': { click: selectAllWorkUnits },
 
  '#timeclock form.edit_work_unit':    $.ninja.ajax_submission({
    busy_element: function(elem){ return $('#timeclock')}
  }),
 
  '#messages .flash': {
    transform: function(elem) {
      $(elem).delay(10000).slideUp(600, function(){$(elem).remove()})
    }
  },
  '#timeclock input#work_unit_hours': {
    click: function(evnt, elem) {
      $(elem).val(hours_format(task_elapsed))
    }
  }
});

That's direct from an LRD project.

Basically, it's meant to look like a stylesheet - as much as possible within jQuery.  This snippet:

  • adds a datapicker to the date entry fields
  • binds a click handler (defined elsewhere) to allow for selecting all work units
  • makes a form into an AJAX submitter - complete with busy overlay
  • makes the #messages list decay - items live for 10 seconds and then go away
  • sets up automatic calculation of hours for certain fields

Pretty simple, but powerful.

What you're seeing there are CSS-style selectors (strictly speaking: jQuery selectors) used to pick elements, and behaviors applied to the elements. $.ninja.ajax_submission() is a prepackaged behavior, which are pretty easy to write.

The ad hoc behavior applied to '#messages .flash' defines a transformation. Transformations are basically the code you'd throw into a document.ready block, pre-sorted to go to their respective elements, with the added bonus that they'll survive later modifications of the DOM.

Behaviors can also define event handlers by adding an events clause, with the events they respond to as keys. In other words:

$.behavior({
  '.fun': {
    events: {
      click: function(ev, elem){ $(elem).sing_and_dance(); }
      mouseover: function(ev, elem) { $(elem).shiver_in_anticipation(); }
      //yes: mouseover.
    }
  }
});

What the app needs to do

To start, pretend that there is no AJAX. Build everything with full round trip HTTP.

Next, come back and make sure that your app responds to requires for javascript with scripts to do whatever you need them to do. Replace elements, usually.

Finally, add behaviors to your pages with NinjaScript. For AJAX, you don't need to change the HTML at all. All straightforward forms and GET links can be converted into to AJAX forms just by specifying the submits_as_ajax() behavior as shown in the top example above. Since you wrote them without AJAX originally, they will continue to work and degrade gracefully without AJAX.

How it works

The short answer is: rebinding. Event delegation is well and good, and if that's all you need, you probably can look elsewhere. My advice is to stick around, though. You get plenty of goodness from NinjaScript, without too much pain.

There are some problems with bubbly delegation though.  Event delegation doesn't solve the problem of modifying elements. You can't delegate watermarking.  And you can't (easily) store data on an element-by-element basis while you're delegating.

NinjaScript builds and applies behavior objects to all the elements selected in the $.behavior block. When they're applied, behaviors modify their host with their transform function (adding tooltips, changing no-input forms into links, pulling input labels in as watermarks, etc.) and apply event handlers directly to the element. They also mark the element as having been enriched with behavior, so that we don't try to re-apply behavior.

Now, when the DOM is modified, the collection of behaviors is told to reapply all the behavior objects. Any elements already enriched get skipped, since we know they were already enriched. One nifty consequence is that elements that weren't around for the initial application get found this time and get behaviors applied.

How do we know the DOM was modified? Believe it or not, there are events that a lot of browsers generate when the DOM is changed, and we listen for those. Plus, when a NinjaScript behavior does an AJAX call, it assumes that the resulting javascript execution changed the page, and it fires it's own event based on that.

Consequences of adopting NinjaScript

Most noticeably, NinjaScript event handlers are a little different from normal event handlers. We assume that events shouldn't bubble and shouldn't fire their normal behavior - you can save a little code not worrying about suppressing those. NinjaScript handlers also are called in the context of the behavior object they're attached to. This means that "this" is not the element receiving the event; "this" is the behavior object that is unique to the element. You can stash information about the behavior in there during the transform step, or maintain state for the element between events. The event handler receives not only the event record (with the original target, etc.) but also the element it's attached to as arguments. All in all, changing a standard event handler over to a NinjaScript handler isn't terribly difficult.

You should also be aware that NinjaScript really does need to know when the DOM changes. Everywhere but IE, you should be okay without doing anything - any DOMNodeInserted or DOMSubtreeModified that reaches the root node should trigger rebinding. To be safe, call $.ninja.tools.fire_mutation_event() and everything should be fine.

There exists a (small) set of utility functions at $.ninja.tools - right now there's only:
$.ninja.tools.perform_ajax_submission(form_or_anchor) - Submits form data over AJAX, evals the response and triggers a rebind.

Directions for the Future

NinjaScript really wants more stock behaviors. Already on the TODO list are:

  • make_watermark
  • Editable table rows - it'd be nice to be able to have AJAX checkboxes and draggable order
  • Fading messages - complete with a backlog and roll back - "Wait, what was that?"
  • Undoable edits - there's likely a lot of backend support this needs.

Behaviors should be mergable. At the moment, the application of two behaviors to the same element is undefined, in that their order isn't predictable.

Convection: self-hosted secure file exchange in Rails

June 8, 2010

Introducing Convection, an open-source (MIT License) project of Logical Reality Design. Need to swap files with clients or collaborators, but don't want to (or can't) trust those files to Amazon or sendbigfiles.com? Want fine-grained control over which users can see which files? Try Convection.

Lots of file exchange services exist, for example SendBigFiles.com etc. However, all of these services are hosted on someone else's hardware, and most of them share files by transferring URLs -- usually via email -- without good access control or authorization schemes.

We built Convection because a client needed to transfer files with other companies, but they needed to host the system themselves because the contracts they hold with their own clients require them not to store data on services that they don't control. The specifications Convection was built around were:

  1. Hosted on our own server.
  2. Downloads require a login, and files cannot be shared by email.
  3. Users must log in to download files or see available files.
  4. User accounts can be grouped, groups can be managed.
  5. Files can be shared with an entire group.
  6. Files uploaded by users default to minimal permission - visible only to the uploader and to admins.
  7. All communications over SSL. (we made this optional)

Installing and hosting Convection

To run Convection, you will need a webserver capable of running a Ruby on Rails application, and a database. Setting such a thing up is beyond the scope of this post. If you have a Dreamhost account, you can set up a Rails-capable domain with a couple of clicks in their web panel. In addition to the server, you will need to set up a database (we have only tested MySQL, but Convection should work with any SQL database for which Rails/ActiveRecord has a supported adapter, including PostgreSQL and Oracle), and initialize the database with these two commands:

  > rake db:migrate RAILS_ENV=production
  > rake db:seed RAILS_ENV=production

This will generate the tables necessary for Convection to run, and create a pair of initial demo users "admin" and "user", both with password "foobar".

If you are setting up a server yourself, there are plenty of guides to deploying Rails on the web. Much of our own guide to deploying CruiseControl.rb can be used to set up any Rails application on Slicehost or any other Ubuntu Linux hosting provider.

Let me know if you're trying to deploy Convection and having trouble: if we know people are using it we may put effort into making it easier to deploy and install, and write a more thorough guide.

A few other links that may help you with deploying a Rails application, depending on your environment:

  1. Using Phusion Passenger to Deploy a Rails Application on Apache
  2. Deploying Rails Applications (book)

If you Google around you may find plenty of other links relevant to your particular environment.

Configuring Convection

If you log into your running Convection application as an administrator (initial user "admin", password "foobar"), an Admin Tools utility will appear in the right hand column. From here, you can access tools for creating users, and groups, and the general site configuration.

In general site config, you can set your site name and logo, set whether or not the site requires SSL access (Note: your server must already support SSL!) outgoing email and email notification preferences, add Google analytics, and an assortment of other site configuration operations that are mostly self-explanatory.

Upload progress bar: experimental feature.

If your site hosts large uploads that take a while to transfer, you can try our experimental tools to provide an upload progress bar to the user. This tool will only work if your site is served by Apache, and requires installing and configuring an optional module for Apache.

To enable this tool, follow the instructions in the README file and associated links, and turn on the progress bar setting in site preferences.

Helping us improve Convection

Convection is currently in version 1.1.4 and has been in production in two places (that we know of) for about five months as of June 8, 2010.

Please let us know if you are using Convection and enjoy it (or don't). Feel free to request features or alterations, but Convection is open source, so also please consider contributing if you have ideas!

RailsTutorial.org launched

December 14, 2009

rails-tutorial-logo-2The new Ruby on Rails Tutorial book and website by Michael Hartl has launched at RailsTutorial.org.   Hartl is the author of RailsSpace and cofounder of the Insoshi Ruby on Rails social networking platform.

Logical Reality did the logo and layout design work for Rails Tutorial.

 

New York Times article about UniThrive

June 13, 2009

One of my clients, UniThrive, was just written up in the New York Times. Go check it out!

An excerpt:

In the photo, the young person’s eyes are brown and kind-looking. She is in need of financial help. A new Web site that brings together the charitable minded and those in need has posted the details of her request.

This is not one of those arrangements where donors can sponsor a needy child or a sorghum farmer in the developing world. The person asking for help is a 21-year-old neurobiology major at Harvard, and she is requesting a loan from Harvard alumni.

New Project Launch: UniThive.org

May 5, 2009

Where have I been the last few months?

Busy building and launching UniThrive.org!

UniThrive LogoUniThrive.org is a fantastic new non-profit startup that seeks to help reduce the cost of higher education by networking college students with alumni, and facilitating direct, zero-interest loans between alumni and students to defray tuition costs.

Technologically, UniThrive is a Rails application that began as a fork of the open-source social networking application Insoshi. Since forking Insoshi, we've nearly doubled the size of the code.

Today, UniThrive is in a live beta test available to students and alumni of Harvard University. Take a look, and check out the UniThrive Blog!

Site launch: CordobaSzekely.com

July 10, 2008

This morning we launched a refreshed site and an all-new online store for one of my clients, CordobaSzekely Productions.

Robert Cordoba and Deborah Székely are dance instructions and multiple-time national champions at the U.S. Open West Coast Swing Championships. They teach West Coast Swing and other dances all around the US and the world, and market a line of dance instructional DVDs.

Their former site had gotten a bit long in the tooth, so this was a just a quick refresher, keeping the former graphics design but bringing the HTML and CSS up to contemporary standards. Their online store was completely reimplemented using the open-source Zen Cart, where formerly they'd used the proprietary (and often difficult to use) Miva Merchant.

Another new design for LRDesign.com

May 29, 2008

Apparently I can't stop playing, because today I built and uploaded a third design for the LRDesign main site: "Blue Art". This one required the IE PNG fix from Twin Helix for IE 6.0 compatibility.

I think there are still a few annoying bugs in the stylesheet switcher on IE; once I clean those up I plan to write a post explaining how to easily set up this kind of stylesheet switcher in a Rails project.

New theme added to LRDesign.com

May 29, 2008

For quite a while I've wanted to decorate the main Logical Reality site with multiple, switchable themes, implementing each with pure CSS on top of semantic HTML markup, a la the CSS Zen Garden. Last night I finally got a start on that, implementing a simple stylesheet switcher and a grunge theme with textures from Urban Dirty.

To check it out, load the main site and click the "Change Skin" link in the upper left.

New LRDesign Site Launched

May 15, 2008

The Logical Reality main site has been badly neglected for far too long: for several months it's just been a plain-text site with no theme, listing a bare portfolio. It's so hard to prioritize working on my own site when there is plenty of work to do for my clients!

A custom Ruby on Rails portfolio display engine is in the works (patterned after the one I did for La Cañada Design Group). My goal is to make it skinnable with switchable themes, implemented entirely in CSS on semantic markup, a la the CSS Zen Garden. In the meantime, though, I've uploaded a basic site (written in RoR, but with only static pages for the moment) with a new minimalist theme.

Website Launch: Insoshi Social Networking Platform

April 30, 2008

The Insoshi Open-Source Social Networking Platform project was just launched yesterday! Logical Reality designed both the Insoshi logo, and landing/informational site that leads new users to the project itself.

Insoshi is built with Ruby on Rails, and is the first major social networking tool to be released completely open-source. Here's an article on Insoshi and the launch at TechCrunch.

The site was a rapid-development Web-2.0 style project, developed using the blueprint CSS framework and other standards-compliant techniques. The logo was chosen to represent Insoshi's core functionality in social networking: communication between people. The lowercase i's on the ends invoke iconified people, with the "broadcast" arcs indicating communication from one to the other.