Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

events/listen! does not work with :optimizations :advanced (??) #57

Closed
deg opened this issue May 22, 2013 · 11 comments
Closed

events/listen! does not work with :optimizations :advanced (??) #57

deg opened this issue May 22, 2013 · 11 comments

Comments

@deg
Copy link

deg commented May 22, 2013

This seems weird enough that I assume the problem lies in my code, but I don't see what I'm doing wrong...

My code works correctly until I compile it with :optimizations :advanced. Then, the domina event listener seems to return a raw object, rather than the DOM node I expected:

(defn dbg1 [x]
  (log "1: " (by-id "tabbar"))
  (log "2: " x))

(defn ^:export init []
  (events/listen! (by-id "tabbar") :click #(dbg1 %)))

I click on the page, and the console shows:

1: [object HTMLDivElement]
2: [object Object]

@ddellacosta
Copy link

deg, you've probably resolved this by now, but this looks like normal behavior to me. Domina returns a wrapped event object to the listen! function argument. Have you tried calling anything like "raw-event" or whatnot on the object in your function, and examining that output?

https://github.com/levand/domina#event-objects

For example, to get the clicked element, you would call (current-target event-obj).

EDIT: the perplexing thing to me is that this works at all when you don't have advanced compilation on, because as far as I can tell this is proper behavior...

@deg
Copy link
Author

deg commented Sep 9, 2013

(Whoops, I thought I answered this a few days ago, but I apparently never hit send, or something)

I'll need to look at this more carefully tomorrow, but I've just confirmed that the problem still occurs. The relevant code has morphed a bit since I first submitted the report; it's now:

(defn ^:export init []
  ...
  (events/listen! (dom/by-id "tabbar") :click
    #(-> % events/target (. -id) ...))
  ...)

Works fine with :optimizations :simple, but :advanced gives

Uncaught Error: No protocol method Event.target defined for type object: [object Object] 

@deg
Copy link
Author

deg commented Sep 10, 2013

Ok, I've looked at this a bit more carefully. I've verified that when I compile :advanced, the object that is passed to my listener does not respond to domina.events/target, .../raw-event, etc. In all cases, I get the error Uncaught Error: No protocol method Event.xxx defined for type object: [object Object]

So, I guess the key question is:
Am I doing something wrong in my project.clj and/or my call to listen!, or does Domina not yet fully support :advanced mode?

...
The rest of this message is my attempt to debug the obfuscated JS code. Ignore if I've gone off-track:

It looks like the problem is something in the compilation of Domina's Event defprotocol that goes awry in advanced mode.

First, for reference, here is the code generated in :simple mode:

domina.events.target = function(a) {
  if(a ? a.domina$events$Event$target$arity$1 : a) {
    return a.domina$events$Event$target$arity$1(a)
  }
  var b;
  b = domina.events.target[goog.typeOf(null == a ? null : a)];
  if(!b && (b = domina.events.target._, !b)) {
    throw cljs.core.missing_protocol.call(null, "Event.target", a);
  }
  return b.call(null, a)
};

Here is the code generated in :advanced mode:

function zj(a) {
  if(a ? a.Vc : a) {
    return a.ca.target
  }
  var b;
  b = zj[p(null == a ? null : a)];
  if(!b && (b = zj._, !b)) {
    throw v("Event.target", a);
  }
  return b.call(null, a)
}

In simple mode, the first line succeeds, and the target is returned immediately.

In advanced mode, a.VC seems to be undefined.
a itself seems to the object jQuery.fn.jQuery.init[1]
(But, big caveat, I'm a complete newbie at debugging JavaScript, so I may be misreading the debugger here).

@ddellacosta
Copy link

a itself seems to the object jQuery.fn.jQuery.init[1]

Why is jQuery in there? This should be straight domina/Google Closure objects that you're dealing with. This is starting to smell like namespace collisions in advanced mode...

What other javascript/Clojurescript libs are you using? Assuming you're not--do you get the same issues when you isolate this bit of code to a separate project, with nothing but Domina included?

@ddellacosta
Copy link

Sorry to not answer this: Am I doing something wrong in my project.clj and/or my call to listen!, or does Domina not yet fully support :advanced mode?

Domina most definitely supports advanced mode--I'm using it now in a production app. So there is probably something going on with the collection of libs you are including/namespaces you're importing into your code/etc. (based on my own experiences getting advanced compilation working w/domina and other libs).

@deg
Copy link
Author

deg commented Sep 11, 2013

Thanks; good to know that the problem is contained. I'll start pruning/testing my project.clj later today -- have to run to a few meetings first. I'll let you know what I find; hope it's just some simple collision to add to the readme.

Meanwhile, here's my project.clj, in case something obvious catches your eye. (Sorry, it's a bit of a mess, assembled from too many different sources and failed experiments. I'm aiming to clean it up too, in this round of testing).

(defproject receipts "0.1.0-SNAPSHOT"
  :description "HTML5 web-app to manage our receipts."
  :url "https://bitbucket.org/degeldeg/receipts"
  :license {:name "Proprietary software - this is not open-source"
            :url "http://nonesuch/com/no-license.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]

                 ;; Degel's Clojure utility library
                 [degel-clojure-utils "0.1.12"]

                 ;; Degel's Redmapel state tree library
                 [redmapel "0.1.7"]

                 ;; Parser tools
                 [instaparse "1.2.2"]

                 ;; Needed, I think, in order to build a runnable uberjar with compojure
                 [ring/ring-jetty-adapter "1.1.8"]

                 ;; Routing library for Ring web application library
                 [compojure "1.1.5" :exclusions [ring/ring-core org.clojure/tools.macro]]

                 ;; DOM manipulation library for ClojureScript
                 [domina "1.0.2-SNAPSHOT"]

                 ;; HTML templating.
                 ;; [TODO] {FogBugz:139} Compare with Hiccup. Maybe choose just one
                 [enlive "1.1.1"]

                 ;; HTML generation for Clojurescript (Ported from Clojure Hiccup)
                 [hiccups "0.2.0"]

                 ;; Ring/Compojure RPC
                 ;; [TODO] {FogBugz:139} Look at the other Shoreleave libs too. Support for
                 ;;        local storage, browser history, repl, etc.
                 [shoreleave/shoreleave-remote-ring "0.3.0"]
                 [shoreleave/shoreleave-remote "0.3.0"]

                 ;; Clojure/ClojureScript validation
                 [com.cemerick/valip "0.3.2"]

                 ;; Clojure interface to AWS SimpleDB
                 [com.cemerick/rummage "1.0.1" :exclusions [commons-codec]]]

  :plugins [[lein-cljsbuild "0.3.2" :exclusions [org.clojure/clojure]]
            [lein-ring "0.8.3" :exclusions [org.clojure/clojure]]
            [com.cemerick/austin "0.1.0"]

            ;; Not supported in lein 2.2.0, but here as a reminder to get features
            ;; mentioned in https://groups.google.com/forum/#!msg/clojure/9cA5hvFJTkw/fnWwxvALd64J
            #_[lein-pedantic "0.0.5"]
            ]

  :min-lein-version "2.0.0"

  :source-paths ["server-src"]
  :test-paths ["test"]
  :ring {:handler degel.receipts.server/app}
  ;:profiles {:dev {:hooks [leiningen.cljsbuild]}}
  :main degel.receipts.server

  :cljsbuild {:crossovers [valip.core
                           valip.predicates
                           degel.cljutil.utils
                           degel.redmapel
                           degel.redmapel.node
                           degel.receipts.db
                           degel.receipts.static-validators]
              :builds {#_ :dev
                       #_
                       {:source-paths ["client-src"]
                        :compiler {:output-to "resources/public/js/receipts-dev.js"
                                   :optimizations :whitespace
                                   :libs [""] ;; See https://github.com/cemerick/pprng/
                                   :pretty-print true}
                        :jar false},
                       :production
                       {:source-paths ["client-src"]
                        :compiler {:output-to "resources/public/js/receipts.js"
                                   ;; TODO {FogBugz:134} No :advanced until dom issue resolved;
                                   ;;      No :advanced so REPL will work, until :dev is
                                   ;;      usable again (per 'lib ""' bug)
                                   :optimizations #_ :advanced :simple
                                   :libs [""] ;; See https://github.com/cemerick/pprng/
                                   :pretty-print #_ false true}
                        :jar true}}})

@deg
Copy link
Author

deg commented Sep 11, 2013

Problem found; the clue was your comment about jquery.

My project uses bootstrap.js which, in turn, requires the inclusion of jquery.js.
I pulled those two lines out of my html file and the problem went away.

Fortunately, the only features of bootstrap I actually use are in the css, so this change has near-zero impact on my project.

The control that showed the problem was a bootstrap button. So, I assume that the only connection to domina is that the domina call happened to be the first interesting access of that object. Looks like this issue can be closed as a red herring. Sorry!

But, for my future reference, do you happen to know if either jquery or bootstrap are known not to work with advanced compilation?

@ddellacosta
Copy link

Oh, great! Glad to hear that you figured it out.

But, for my future reference, do you happen to know if either jquery or bootstrap are known not to work with advanced compilation?

Well, I can't speak to bootstrap, but considering that jayq does (we have it in our project, although we deprecated it in favor of domina...for now), and bootstrap is mostly jQuery code (right?) it should work. Assuming you've got the right externs (https://developers.google.com/closure/compiler/docs/api-tutorial3#externs) set up it should be okay.

@deg
Copy link
Author

deg commented Sep 12, 2013

Yeah, umm, about those externs... (embarrassed grin). No, I didn't have any, but discovered the need yesterday when I Googled for jquery and closure. But, since I don't actually need the bootstrap or jquery js files at all, I just diked out the two references and don't need to learn the extern syntax until next time.

Thanks again. All's well that ends.

@ddellacosta
Copy link

Yeah--I've really only ever needed the externs in a limited way, when I'm calling JS code in my CLJS, and most of the time I wrap stuff up in a function or two and that does it.

In any case, glad to hear things are working.

@ckirkendall
Copy link
Collaborator

I am closing this issue because the resolution was outside of domina.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants