I don't like doing a lot of client side Javascript (or Coffeescript) development. pjax is a way to minimize client side Javascript while maintaining fast page load times.

I became interested in pjax after reading an article on the development of Basecamp Next. DHH indicated that they looked at pjax but then rolled their own similar system.

Here is a github repo with a Clojure and Noir example web app using pjax that I wrote this morning. There were a few non-obvious aspects to using pjax with Noir so hopefully this will save you some time.

If you don't want to grab the github repo, here are a few interesting code snippets. First, we need to run a little Javascript to process links to set up for AJAX calls setting a "X-PJAX" header:

// Activate PJAX test links
// Response will be loaded into #wrapper element
I put this code in resoures/public/js/application.js which is loaded in the common Clojure page wrapping code (in common.clj):
(ns noir-pjax-example.views.common
(:use [noir.core :only [defpartial]]

(defpartial layout [& content]
(println "\n**** layout\n")
[:head [:title "noir-pjax-example"]
(include-css "/css/reset.css")
(include-js "/js/jquery.js")
(include-js "/js/jquery.pjax.js")
(include-js "/js/application.js")]
[:body "<h1><b>Demo of pjax with Clojure and Noir</b></h1><br/><br/>"
"<div id=\"wrapper\">"
The trick is that this wrapper code only gets executed one time and the browser only needs to set up the page one time. Only the div with id "wrapper" gets replaced by the standard pjax Javascript file jquery.pjax.js.

Sure, there is still Javascript using pjax, but you don't have to write much at all. In this case, I am "pjax-ifying" all HTML links with the small Javascript snippet in application.js; in a real application, you would be more selective and perhaps also set up multiple page elements that pjax updates. The following code snippet shows the file welcome.clj:

(ns noir-pjax-example.views.welcome
(:require [noir-pjax-example.views.common :as common]
(:require noir.request)
(:use [noir.core :only [defpage]]
[hiccup form-helpers page-helpers]

(defpage "/" []
(if (nil? (((noir.request/ring-request) :headers)
[:p "Welcome to noir-pjax-example /"]
[:a {:href "/"} "foo 1"])
"<p>Welcome to noir-pjax-example /</p>"
"<a class=foo href=\"/foo\">foo 2</a>")))

(defpage "/foo" []
(if (nil? (((noir.request/ring-request) :headers)
[:p "Welcome to noir-pjax-example /foo"]
[:a {:href "/"} "home 4"])
"<p>Welcome to noir-pjax-example /foo</p>"
"<a class=foo href=\"/\">home 3</a>")))
There is not much of a trick here: I check to see if there is a "x-pjax" header and if there is I don't call the common layout page wrapper function.