Best practice - incrementally Adding JS to web page

51 views
Skip to first unread message

Warren Strange

unread,
Dec 12, 2011, 7:26:48 PM12/12/11
to clj-...@googlegroups.com

Let's say you are defining a page - and the page needs some special javascript include or script in the header - one that is unique to the page. 

I know some Java frameworks have the concept of "contribute this fragment to the header".    

What would be the best way to accomplish this with Noir?  

I suppose one can pass a parameter to your common layout logic 
(common/layout   (javascript ...)   .. rest of content)

Is that the best approach? I am just wondering if I am missing anything obvious


Thx

Andrew Cholakian

unread,
Dec 12, 2011, 8:16:27 PM12/12/11
to clj-...@googlegroups.com
Passing a parameter is exactly what I've done. For something like a master layout a single destructured map works well since the number of variables can grow quite large.

Chris Granger

unread,
Dec 12, 2011, 8:20:25 PM12/12/11
to clj-...@googlegroups.com
I typically just pass in a map with page specific css + js if there is any. It wouldn't take much to come up with a more interesting solution if you wanted, like binding *js* in middleware and having the (defpages) use (set-js ..) or some such function to add their content to an atom. Probably not worth it though :)

Cheers,
Chris.

Keith Irwin

unread,
Dec 13, 2011, 1:39:03 AM12/13/11
to clj-...@googlegroups.com
I had this very same issue. I figure I'll solve it a different way with every noir app I write, because, you know, why not? If every problem you solve looks the same, you might as well have fun trying different hammers.

I'll probably over explain my dorky solution, but what the hell, eh?

After digging around in the source I discovered (or misunderstood) that "include-js" can take a list of strings as well as a single string so it seemed like a good idea to have a function that takes a list of the default script and (optionally) appends the one customized for just that particular page.

List of defaults:

  (def ^:private default-scripts
       "/myapp/js/common.js"])

Custom script per page:

  (def ^:private custom-scripts
    {:user "/myapp/js/user.js"
     :login "/myapp/js/login.js"
     :reports "/myapp/js/reports.js"})

Then an optional conj:

  (defn- javascripts
    [page]
    (if-let [custom (page custom-scripts)]
       (conj default-scripts custom)
       default-scripts)))

and in the actual layout code:

  (defpartial layout-page [title page & content]
    (html5
      [:head
         [:title title]
         (apply include-js (javascripts page))
         (apply include-css styles)]
      (layout-body page content)))

or some such thing. Works for navigation links (highlighting the one you're on) and CSS, too, I imagine. I might have misread the source code of include-js: but apply seemed to do the trick and once it did, I moved on to something else without further exploration. After the above, I figured I could unify all these maps and lists into a simple page description kind of structure that made all the unique bits of the pages declarative, but thought I'd resist the temptation.

Keith

Warren Strange

unread,
Dec 13, 2011, 10:05:59 AM12/13/11
to clj-...@googlegroups.com

Keith 

Thanks for sharing - this gives me some great ideas.
Reply all
Reply to author
Forward
0 new messages