jwhitlark
jwhitlark

Reputation: 505

Using jquery-ui in ClojureScript with jayq

I'm trying to use jayq with jquery.ui.sortable to make a list on a page sortable. Looking at http://jqueryui.com/demos/sortable/ it seems like it should be as simple as:

(.sortable ($ :#sortable))

Which compiles down to:

jayq.core.$.call(null, "\ufdd0'#sortable").sortable();

And throws:

Uncaught TypeError: Cannot call method 'call' of undefined

when I try to include it in a page. Interestingly, the generated code does work in the page when I paste it into the js console, which implies to me that something necessary is loaded after that line is executed.

I've modified

(def cljs-options {:advanced {:externs ["externs/jquery.js"]}})

to

(def cljs-options {:advanced {:externs ["externs/jquery.js" "js/ui/jquery-ui.js]}})

after reading http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html , which doesn't seem to be sufficient. I'm guessing that jquery.ui modifies the $ Prototype, but I'm not sure how to accomplish this in clojurescript

I'm also using noir and noir-cljs, if it makes any difference.

Looking at using jQueryUI with closure compiler it might just be that jquery-ui needs a hand rolled externs file in order to be used, possibly a major undertaking. Can anyone confirm?

Upvotes: 4

Views: 1445

Answers (1)

jwhitlark
jwhitlark

Reputation: 505

There were two separate aspects to solving this.

  1. To compile in advanced mode, I needed to add the following to my externs file.

    $.prototype.sortable = function (a,b) { };
    $.prototype.disableSelection = function (a,b) { };
    
  2. I'm using noir-cljs, and in my view template, had the following:

    (:require [noir.cljs.core :as cljs])
    (:use [hiccup.page :only [include-js]])
    ...
    (cljs/include-scripts :with-jquery)  
    (include-js "/js/jquery-ui.js")
    

But this can't ever work, since the jquery-ui code needs to be included after jquery but before the generated ClojureScript. The solution is to manually include the libraries in the page:

(include-js "/js/jquery.js")
(include-js "/js/jquery-ui.js")
(include-js "/cljs/bootstrap.js") ;; Generated

Upvotes: 6

Related Questions