Accessibility and all these JavaScript frameworks

I use a js-framework (spine.js in my case) in my latest site. Still I make sure that non-js browsers (certainly not over zealous: think SEO) can navigate my site and digest the contents.

As an example I’m going with a search-page with products being shown. Products can be paged, filtered, sorted. Of course this is an example of the generalized idea.

PREREQ: use a template-engine that can both render server-side and client-side. (I use Mustache) . This makes sure you can render models without js- through server-side templating, and render models with js through client-side templating.

  1. Initially: render the products using server-side mustache-template. Also include a ‘bootstrapJSON’-object which contains the same products in JSON-format.

  2. Initially: all links (product-detail page, paging, sorting, filtering) are real server-side urls (no hashbang urls)

  3. The end-result is a page which can be navigated 100% with paging, sorting, filtering without the use of JS.

  4. all paging,sorting, filtering urls result in a request to the server, which in turn results in a new set of products being rendered. Nothing special here.

  5. JS-enabled – on domload:

    • fetch the bootstrapJSON and make product-models from it (use your js-framework features to do this) .
    • Afterwards rerender the products using the same mustache-template but now doing it client-side. (Again using your js-framework).
    • Visually nothing should change (after all server-side and client-side rendering was done on same models, with same template), but at least now there’s a binding between the client-side model and the view.
    • transform urls to hashbang-urls. (e.g: /products/#sort-price-asc ) and use your js-framework features to wire the events.
  6. now every (filtering, paging, sorting ) url should result in a client-side state-change, which would probably result in your js-framework doing an ajax-request to the server to return new products (in JSON-format) . Rerendering this again on the client should result in your updated view.

  7. The logic part of the code to handle the ajax-request in 6. on the server-side is 100% identical to the code used in 4. Differentiate between an ajax-call and an ordinary request and spit out the products in JSON or html (using mustache server-side) respectively.

EDIT: UPDTATE JAN 2013
Since this question/answer is getting some reasonable traction I thought I’d share some closely-related aha-moments of the last year:

  • Spitting out JSON and rendering it client-side with your client-side mvc of choice (steps 6. and 7. above) can be pretty costly cpu-wise. This, of course, is especially apparent on mobile-devices.

  • I’ve done some testing to return html-snippets on ajax (using server-side mustache-template rendering) instead of doing the same on the client-side as suggested in my answer above. Depending on your client-device it can be up to 10 times faster (1000ms -> 100ms) , of course your mileage may vary. (practically no code changes needed, since step 7. could already do both)

  • Of course, when no JSON is returned there’s no way for a client-side MVC to build models, manage events, etc. So why keep a clientside MVC at all? To be honest, with even very complex searchpages in hindsight I don’t have much use for client-side mvc’s at all. The only real benefit to me is that they help to clearly separate out logic on the client, but you should already be doing that on your own imho. Consequently, stripping out client-side MVC is on the todo.

  • Oh yeah, I traded in Mustache with Hogan (same syntax, a bit more functionality, but most of all extremely performant!) Was able to do so because I switched the backend from java to Node.js (which rocks imho)

Leave a Comment