Giter Club home page Giter Club logo

enfocus's Introduction

Enfocus

Enfocus is a DOM manipulation and templating library for ClojureScript. Inspired by Christophe Grand's Enlive, Enfocus' primary purpose is providing a base for building rich interfaces in ClojureScript.

If you are unfamiliar with enlive I also recommend taking a look at these links.

David Nolen wrote a nice tutorial

Another tutorial by Brian Marick.

Documentation & Examples

Documentation & Demo Site

Example Website

Where do I get support?

On the group

Quick Start

Setup

From any leiningen project file:

Clojars Project

For the best development experience, use lein-cljsbuild

The Basics

Every great journey starts with "Hello world!"

(ns my.namespace
  (:require [enfocus.core :as ef]
            [enfocus.events :as events]
	    [enfocus.effects :as effects])
  (:require-macros [enfocus.macros :as em]))

(defn start []
  (ef/at js/document
    ["body"] (ef/content "Hello enfocus!")))

(set! (.-onload js/window) start)

See hello-enfocus repo.

The at form

At the core to understanding Enfocus is the at form used in the "Hello world!" example above. It comes in two basic flavors listed below:

A single transform

(at a-node (transform arg1 ...))

;or with implied js/document

(at selector (transform arg1 ...))

and a series of transforms

(at a-node
    [selector1] (transform1 arg1 ...)
    [selector2] (transform2 arg1 ...))

;or with implied js/document

(at [selector1] (transform1 arg1 ...)
    [selector2] (transform2 arg1 ...))

In the first case at is passed a node, node set or selector and a transform. This form of at calls the transform on each element in the node set.

A transform is nothing more than a function that takes a set of arguments and returns a function that takes a set of nodes. In case of the "Hello World!" example above, we see the use of (em/content "Hello world!") this call returns a function that takes node or node set and replaces the content with "Hello world!"

In the second case, we see at is optionally passed a node or node set and a set of selector/transform pairs. The selectors are scoped by the node, node set or js/document, if a node is not passed in, and the results of each selector is passed on to its partner transformation.

A selector is a string representing a CSS3 compliant selector

Handling Events

Enfocus has event handling. Below is a simple example to add an onclick event handler to a button.

(em/defaction change [msg]
  ["#button1"] (ef/content msg))

(em/defaction setup []
  ["#button1"] (events/listen :click #(change "I have been clicked")))

(set! (.-onload js/window) setup)

The defaction construct is use here instead defn. defaction creates a function that calls the at form like discussed above and passes in js/document as the node to be transformed.

Effects

Enfocus has the concept of effects. Effects are nothing more than transformations over a period of time. Below is a simple example of a resize effect. Notice how the effects can be chained.

(em/defaction resize-div [width]
  ["#rz-demo"] (effects/chain
                 (effects/resize width :curheight 500 20)
                 (effects/resize 5 :curheight 500 20)))

(em/defaction setup []
  ["#button2"] (events/listen #(resize-div 200)))

(set! (.-onload js/window) setup)

Actions, templates and snippets

A snippet is a function that returns a seq of nodes, it can be used as a building block for more complex templates or actions.

You define a snippet by providing a remote resource, a selector and series of transformations.

The snippet definition below selects a table body from the remote resource templates/template1.html and grabs the first row. It then fills the content of the row.

(em/defsnippet snippet2 "templates/template1.html" ["tbody > *:first-child"]
               [fruit quantity]
               ["tr > *:first-child"] (ef/content fruit)
               ["tr > *:last-child"] (ef/content (str quantity)))

A template is very similar to a snippet except it does not require a selector to grap a sub section, instead the entire remote resource is used as the dom. If the remote resource is a full html document only what is inside the body tag is brought into the template.

(em/deftemplate template2 "/templates/template1.html" [fruit-data]
                ["#heading1"] (ef/content "fruit")
                ["thead tr > *:last-child"] (ef/content "quantity")
                ["tbody"] (ef/content
                           (map #(snippit2 % (fruit-data %)) (keys fruit-data))))

Normally, snippets and templates are loaded via an AJAX request, but you can also create :compiled templates, which will be inlined in to resulting code at compile time:

(em/deftemplate template2 :compiled "/templates/template1.html" [fruit-data]
                ["#heading1"] (ef/content "fruit")
                ["thead tr > *:last-child"] (ef/content "quantity")
                ["tbody"] (ef/content
                           (map #(snippit2 % (fruit-data %)) (keys fruit-data))))

If, snippets and/or templates are loaded via AJAX it is important to make sure the content has been loaded before calling the template or snippit function. Enfocus provides a convient macro that works like an onload callback but for AJAX driven snippets and templates.

(em/wait-for-load (render-page))

An action is a set of transforms that take place on the live dom. below is a definition of a an action.

(em/defaction action2 []
             [".cool[foo=false]"] (ef/content (template2 {"banana" 5 "pineapple" 10}))
             ["#heading1"] (ef/set-attr :id "new-heading1"))

Enfocus also support hiccup style emitters introduced in enlive "1.1.0".

(defn hiccup-template [arg1]
  (ef/html
    [:h1#hiccup.clazz {:width arg1} "Hiccup Emitters are Cool"]))

Transformations

A transformation is a function that returns either a node or collection of node.

Enfocus defines several helper functions for transformations:

Supported Enlive Transformations

  content            (content "xyz" a-node "abc")
  html-content       (html-content "<blink>please no</blink>")
  set-attr           (set-attr :attr1 "val1" :attr2 "val2")
  remove-attr        (remove-attr :attr1 :attr2)
  add-class          (add-class "foo" "bar")
  remove-class       (remove-class "foo" "bar")
  do->               (do-> transformation1 transformation2)
  append             (append "xyz" a-node "abc")
  prepend            (prepend "xyz" a-node "abc")
  after              (after "xyz" a-node "abc")
  before             (before "xyz" a-node "abc")
  substitute         (substitute "xyz" a-node "abc")
  clone-for          (clone-for [item items] transformation)
                     or (clone-for [item items]
                          selector1 transformation1
                          selector2 transformation2)
  wrap               (wrap :div) or (wrap :div {:class "foo"})
  unwrap             (unwrap)
  replace-vars       (replace-vars {:var1 "value" :var2 "value")

New Transformations

  focus              (focus)
  blur               (blur)
  set-prop           (set-prop :value "testing")
  set-style          (set-style :font-size "10px" :background "#fff")
  remove-style       (remove-style :font-size :background)
  listen             (listen :mouseover (fn [event] ...))
  remove-listeners   (remove-listeners :mouseover :mouseout)
  fade-in            (fade-in time)
                     or (fade-in time callback)
                     or (fade-in time callback accelerator)
  fade-out           (fade-out time)
                     or (fade-out time callback)
  resize             (resize width height ttime)
                     or (resize width height ttime callback)
                     or (resize width height ttime callback accelerator)
  move               (move x y ttime)
                     or (move x y ttime callback)
                     or (move x y ttime callback accelerator)
  scroll             (scroll x y ttime)
  		     or (scroll x y ttime callback)
		     or (scroll x y ttime callback accelerator)
  chain              (chain (fade-in ttime) ;serialize async effects
                            (move x y ttime)
                            (fade-out ttime)
                            ...)
  set-data           (set-data key value)

Currently there is one transformation that is supported by Enlive but not Enfocus. (Patches very welcome!!)

  move               (move [:.footnote] [:#footnotes] content)
                     ;this will be called relocate in enfocus

Selectors

Enfocus supports both CSS3 and XPath selectors:

(ns example
  (:require [enfocus.core :as ef])
  (:require-macros [enfocus.macros :as em]))

(em/defaction action2 []
             [".cool[foo=false]"] (ef/content ....)) ;CSS3
             (ef/xpath "//tr[@id='1']/th[2]") (ef/set-attr :id "new-heading1")) ;XPATH

The from form

The from form is how we get data from the dom in enfocus. It comes in two basic flavors listed below:

This form returns the result of the extractor.

(from a-node (extractor arg1 ...))

;or with selector

(from selector (extractor arg1 ...))

and this form returns a map of the form {:key1 result1 :key2 result2}

(from a-node
    :key1 [selector1] (extractor arg1 ...)
    :key2 [selector2] (extractor arg1 ...))

;or implied js/documnt

(from
    :key1 [selector1] (extractor arg1 ...)
    :key2 [selector2] (extractor arg1 ...))

Extractors

An extractor is a function that takes a node and returns information about.

Enfocus defines several helper fuctions for extractors:

An extractor is a funciton that takes a node and returns information about

  get-attr           (get-attr :attr1)
  get-text           (get-text)
  get-prop           (get-prop :value)
  get-data           (get-data :key1)
  read-form          (read-form)  - returns {:field1 ("val1" "val2") :field2 val}

Contributing

Compile Enfocus

 git clone git://github.com/ckirkendall/enfocus.git
 cd enfocus
 lein do cljx once, compile

Test Enfocus

After having compiled down enfocus as explained above

lein test

bREPLing with Enfocus

After having compiled down enfocus as explained above issue the following lein task:

 lein repl

Then run the http server as follows

user=> (run)
2013-10-15 12:34:33.082:INFO:oejs.Server:jetty-7.6.8.v20121106
2013-10-15 12:34:33.138:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:3000
#<Server org.eclipse.jetty.server.Server@7aed9585>

Next launch the browser-connected REPL as follows:

user=> (browser-repl)
Browser-REPL ready @ http://localhost:55211/4347/repl/start
Type `:cljs/quit` to stop the ClojureScript REPL
nil
cljs.user=>

Finally, visit the http://localhost:3000/ URI

The page is empty and it used for bREPLin only. Wait few moments while the connection is established and then you can start bREPLing with Enfocus.

cljs.user=> (js/alert "Hello, Enfocus!")

Final note

All the Austin use cases should work as expected.

License

Copyright (C) 2012-2013 Creighton Kirkendall

Distributed under the Eclipse Public License, the same as Clojure.

Special Thanks!

Christophe Grand for creating enlive and building a simple api for dom manipulation.

enfocus's People

Contributors

amacdougall avatar ckirkendall avatar eweng avatar fogus avatar gigasquid avatar jamesnvc avatar jsyrjala avatar magomimmo avatar nahuel avatar piranha avatar riffm avatar robert-stuttaford avatar stuarth avatar superbobry avatar underus avatar virvar avatar xavi avatar yantonov avatar zilti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

enfocus's Issues

Documentation/Demo Site Problem with (deftemplate ...) example

I think I found a small problem with the Documentation/Demo site - the first (deftemplate ...) example inserts the new DOM elements in the wrong place. They end up at the bottom of the document, contrary to the "table will appear here" statement.

Warnings when compiling project

When I compile my project I get following warnings when when I use `require? syntax.

WARNING: filter already refers to: #'clojure.core/filter in namespace: enfocus.macros, being replaced by: #'enfocus.macros/filter
WARNING: delay already refers to: #'clojure.core/delay in namespace: enfocus.macros, being replaced by: #'enfocus.macros/delay

Setting the 'value' property on input=text with set-attr is problematic.

With set-attr, I could see the change being applied in the Chrome Dev Tools inspector, but not in the actual page. I suspect setAttribute isn't the right way to do this particular state change.

Had to do this instead:

(defn set-input-value!
  [selector value]
  (set! (.-value (first (ef/nodes->coll (em/select [selector])))) value))

Perhaps you could include something like it in enfocus?

Domina issue when upgraded to latest ClojureScript

I am getting

WARNING: Use of undeclared Var domina/domina at line 128 file:/Users/boriskourt/.m2/repository/domina/domina/1.0.1/domina-1.0.1.jar!/domina.cljs

Here is everything I have added in the project file:

  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/clojurescript "0.0-1889"]
                 [enfocus "2.0.0-beta2"]
                 [org.clojure/core.async "0.1.222.0-83d0c2-alpha"]]
  :repositories {"sonatype-oss-public" "https://oss.sonatype.org/content/groups/public/"}
  :plugins [[lein-cljsbuild "0.3.3"]]

I am using advanced mode to compile and running 'lein cljsbuild auto'.

My test program is just:

(ns ui.core 
  (:require [cljs.core.async :as async
               :refer [<! >! chan close! sliding-buffer put! alts!]]
            [enfocus.core :as ef]
            [enfocus.effects :as effects]
            [enfocus.events :as ev]
            [goog.dom :as dom]
            [clojure.string :refer [join blank?]])
  (:require-macros [cljs.core.async.macros :as m :refer [go alt!]]))

If I remove any reference to enfocus here the warning goes away.

Also if I ignore it and add any enfocus events I get this error in my chrome js console:

Uncaught Error: No protocol method ITransform.apply-transform defined for type string: #<[object Object]> 

Any ideas?

Can't create snippet from the <form> element

When using

    <div id="login-form">  . . . </div>

-- evrything works OK. But if I change that to

    <form id="login-form"> . . . </form> 

-- Enfocus can't create that snippet.

The code looks like this:

    (em/defsnippet login-form "/html/login.html" [:#login-form] [])

Warning on line 262

Hi,

I've got the warning while running 'lein cljsbuild auto':

WARNING: Wrong number of args (1) passed to cljs.core/instance? at line 262 file:/home/dim/.m2/repository/enfocus/enfocus/0.9.1-SNAPSHOT/enfocus-0.9.1-SNAPSHOT.jar!/enfocus/core.cljs
WARNING: Wrong number of args (1) passed to cljs.core/instance? at line 262 file:/home/dim/.m2/repository/enfocus/enfocus/0.9.1-SNAPSHOT/enfocus-0.9.1-SNAPSHOT.jar!/enfocus/core.cljs

It is a function call there: (instance? js/DocumentFragment) which really lacks the second argument.
It seems to me that it should be like this: (instance? js/DocumentFragment frag)

And by the way, how is it going with the issue #9 ?

Thanks for the wonderful library,
Dmitry

Can't get keypress on body of document.

I'm using Enfocus-2.0.00-SNAPSHOT

With the ode block

"body" (efe/listen :keypress (fn [&args](. js/console log args) ))

I can't get key presses on the body of the document. yet, if I do

"#button1" (efe/listen :click (fn [&ags](. js/console log args) ))

everything works fine.

Question: how do I register a global key listener (I want left/right arrow keys to move slides).

Thanks!

Check for existence of node by selector

Is there a better way to check for the presence of a node by selector than this?

(defn exists?
  [sel]
  (> (count (ef/nodes->coll (em/select [sel]))) 0)

; false
(exists? :#foo)
; true
(exists? :body)

I had a look at Domina's CSS selector and it looks to be lazy somehow; nothing stood out to me.

Issue in defsnippet

Hi,

I have been facing this issue since a day, and cant seem to figure out what is wrong. Any help will be appreciated. Here is the function that errors out -

(defsnippet top-navbar "templates/components.html" ["top-navbar"]
  [links]
  ["ul[data-navlinks=\"left\"]"] (content "hello world"))

Below is the components.html -

<html>
<head></head>
<body>
<top-navbar>
<div class="navbar navbar-fixed-top">
    <div class="navbar-inner">
      <div class="container">
        <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </a>
        <div class="nav-collapse">
          <ul data-navlinks="left" class="nav">
            <li><a href="#">Link</a></li>
          </ul>
          <ul class="nav pull-right">
            <li class="dropdown">
              <a href="#" class="dropdown-toggle"
              data-toggle="dropdown">Username<b class="caret"></b></a>
              <ul class="dropdown-menu">
                <li><a href="#">Logout</a></li>
              </ul>
            </li>
          </ul>
        </div><!-- /.nav-collapse -->
      </div>
    </div><!-- /navbar-inner -->
  </div>
<top-navbar>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</body>
</html>

In clojurescript repl whenever I call the above function it hands, so its not helpful. In the Chrome's js console this is the error I get -

Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
goog.dom.appendChildclient.js:19793
enfocus.core.chainable_standard.call.app_func__4802client.js:30634
map__2client.js:9997
lazy_seq_valueclient.js:7366
cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1client.js:7409
_seqclient.js:3318
seqclient.js:4378
dorun__1client.js:17329
dorunclient.js:17363
doall__1client.js:17376
doallclient.js:17386
(anonymous function)client.js:30636
map__2client.js:9997
lazy_seq_valueclient.js:7366
cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1client.js:7409
_seqclient.js:3318
seqclient.js:4378
dorun__1client.js:17329
dorunclient.js:17363
doall__1client.js:17376
doallclient.js:17386
trans__2client.js:30555
transclient.js:30567
trans__1client.js:30551
transclient.js:30565
(anonymous function)client.js:31474
map__2client.js:9997
lazy_seq_valueclient.js:7366
cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1client.js:7409
_seqclient.js:3318
seqclient.js:4378
dorun__1client.js:17329
dorunclient.js:17363
doall__1client.js:17376
doallclient.js:17386
initclient.js:31472
(anonymous function)

Thanks,
Murtaza

Enfocus doesn't work with optimization "advanced"

The cljs code:

(em/defsnippet my-snippet "/html/snippets.html" 
  [:#mytest] []
  [:#this:] (em/content "123"))

(defn mystart []
  (em/at js/document
         [:#here] (em/content (my-snippet))))

(set! (.-onload js/window) mystart) 

Part of the "html/snippets.html" file:

<div id="mytest">
  <div id="this">
  </div>
  Hello from Enfocus!
</div>

With optimizations "whitespace" everything works perfect. Switching to "advanced" kills the Enfocus, the script doesn't work.

lein-cljsbuild warnings

Hi,

The lein-cljsbuild auto gives me the following warnings, I am not sure if these are something that need to be fixed, so just bringing to attention.

However, Thanks for the great library!

WARNING: Wrong number of args (1) passed to cljs.core.instance_QMARK_ at line 262 file:/home/murtaza/.m2/repository/enfocus/enfocus/0.9.1-SNAPSHOT/enfocus-0.9.1-SNAPSHOT.jar!/enfocus/core.cljs
WARNING: Use of undeclared Var enfocus.core/op-handler at line 438 file:/home/murtaza/.m2/repository/enfocus/enfocus/0.9.1-SNAPSHOT/enfocus-0.9.1-SNAPSHOT.jar!/enfocus/core.cljs

upload 2.0.0 to clojar

The current status of 2.0.0-snapshot looks pretty stable. Any plan to upload a 2.0.0 to clojars soon?

Switching to alpha1

I encountered a problem when building:

clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: 
No such var: cljs.compiler/resolve-var, compiling:(domina/macros.clj:13)

I looked at the domina source, and I wasn't able to puzzle out what I could be doing wrong.

Here are the deps I was pulling in:

[[org.clojure/clojure "1.4.0"]
 [compojure "1.0.4"]
 [hiccup "1.0.0"]
 [enlive "1.0.1"]
 [enfocus "1.0.0-alpha1"]
 [amalloy/ring-gzip-middleware "0.1.2"]
 [org.clojars.lypanov/google-closure-library-repackaged "0.0-1376"]
 [org.clojars.lypanov/google-closure-library-third-party-repackaged "0.0-1376"]
 [shoreleave/shoreleave-pubsub "0.2.2-SNAPSHOT"]]

Ability to use 'at' on snippets

(defsnippet sn "..." [])

(let [node (sn)]
  (em/at node (em/set-attr :id "123")) // fails
  (em/at node [".class"] (em/set-attr :id "123"))) // fails too

I don't know if it's intentional or could be fixed maybe?

The problem is — I want to use compiled snippets, but I cannot put much logic inside defsnippet (let definitions etc). So I'm trying to modify snippet after I materialized it, using regular at form inside a fun.

Looks like it's because it tries to call root.getElementsByTagName(query.getTag()) at DocumentFragment.

Maybe there's another way to do this, a workaround?

[enfocus "1.0.0-beta2"]
[org.clojure/google-closure-library "0.0-2029"]
[org.clojure/google-closure-library-third-party "0.0-2029"]
[domina "1.0.1" :exclusions [org.clojure/clojurescript]]
[lein-cljsbuild "0.2.7"]

Thanks.

Allow 'internable' templates

It would be nice if enfocus allowed interning local templates during compilation (similar to what one does in its sample application), instead of loading them via XHR, what do you think?

(deftemplate "path/to/local/template" [...]
    ;; the usual transformation stuff
    )

Problems with snippets when two or more share a common URL

The current cache is based on url path and returns a vector of the id-mask and DocumentFragment. If two snippets have the same url the last one to load will overwrite the first and the Id-mask will be wrong for the first snippet.

How to use the "Hello World" example?

This is a very stupid question, please forgive me. How do I "use" the Hello World example in [1]? I assume this is compiled via cljs and the resulting Javascript file is viewed in a browser in conjunction with an HTML file, but the details of the process are unclear to me. I'm trying to peel back the layers of extra features in the testing example and demo website to get to this understanding.

[1] https://github.com/ckirkendall/enfocus#the-basics

enfocus error while creating DOM

Hi,

I have a html file on my server. In my client code I am using enfocus's deftemplate to read the file and then insert into the DOM.

I do not get an error when I try to insert content generated through hiccup. I also do not get error when I read the same file using enlive on server side and then get the generated file as a string through ajax and then insert into the DOM using enfocus.

However I get error when I both retrieve the template file on client side using enfocus and then insert it into the DOM. The retrieval also works without incident, as I am able to test the deftemplate function on repl.

I have created the gist for the html and the client side code retreiving the file and then inserting it into the DOM. I will appreciate if you can help me resolve this.

The following are 3 gists of the code -

https://gist.github.com/2974225
https://gist.github.com/2974221
https://gist.github.com/2974215

Also below is the error I see in the browser's console -

Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
create_hidden_domclient.js:30530
reg_form_2client.js:34680
renderclient.js:34667
(anonymous function)

Thanks,
Murtaza

clojure.core.Keyword

Whenever I try to use a snippet inside a template I get this javascript error:

TypeError: 'undefined' is not a constructor (evaluating 'new cljs.core.Keyword("\ufdd0'default")')

cljs.core.Keyword doesn't appear to exist, though cljs.core.keyword does.

I'm using enfocus 1.0.0-beta3 and clojurescript 0.0.1552.

Set Focus and Blur

It'd be great if enfocus had transformers for calling focus/blur on elements:

  (.focus <node>)
  (.blur <node>)

Could instead simply be:

  (em/focus)
  (em/blur)

events/listen-live discards original event, disabling .preventDefault in handlers.

Problem

I defined a channel-based listen-live helper like this:

(defn listen-live
  ([selector type] (listen-live selector type nil))
  ([selector type f] (listen-live selector type f (chan)))
  ([selector type f out]
   (at ["body"]
     (events/listen-live type selector
       (fn [e]
         (cond
           (= f :prevent-default) (.preventDefault e)
           (fn? f) (f e))
         (put! out e))))
   out))

I tried to use this function to handle links whose URLs should be used for client-side routing. The idea was the prevent the link navigation, and push the href onto history instead. I discovered that although a pure listen-based version worked, the listen-live version did not: the handler code executed correctly, but the browser navigated to the URL a split-second later.

Analysis

On inspecting the code, I realized that the implementation of listen-live was discarding the original event, executing the handler on a new one with the same type and target:

(defn listen-live [event selector func]
  (fn [node]
    (ef/at node
           (listen event
                   #(doseq [el (get-node-chain node (.-target %))]
                      (ef/at el
                             (ef/filter (ef/match? selector)
                                        (fn [node]
                                          (func (create-event event el (.-target %)))))))))))

Naturally, .preventDefault has no effect on an event created from whole cloth.

Possible Solution

Execute the handler function on the native event before returning a new event. This makes a certain sacrifice in immutability, because the native event may be changed by the handler, but the alternative is worse.

Invalid tbody structure in tables generated with templates

enfocus seems to assume that every table has tbody element. This happens at least in 1.0.0-alpha2 and 1.0.0-alpha3.

snippet.html

<table id="list">
  <tr>
    <td class="elem1"></td>
    <td class="elem2"></td>
  </tr>
</table>
</body>

template.html

  <table id="list">

  </table>
(em/defsnippet my-snippet "snippet.html" ["table#list > tbody > *"]
  [item]
  [".elem1"] (em/content (:elem1 item))
  [".elem2"] (em/content (:elem2 item))
  )

(em/deftemplate my-template "template.html" [items]
  ["#list"] (em/content (let [item (map #(my-snippet %) items)]
                          item
                          )))

Result is:

<table id="list"><tr>
    <td class="elem1">a1</td>
    <td class="elem2"></td>
  </tr><tr>
    <td class="elem1">a2</td>
    <td class="elem2">b2</td>
  </tr></table>

If I change snippet selector to ["table#list > *"] the result is following

<table id="list"><tbody><tr>
    <td class="elem1">a1</td>
    <td class="elem2"></td>
  </tr>
</tbody><tbody><tr>
    <td class="elem1">a2</td>
    <td class="elem2">b2</td>
  </tr>
</tbody></table>

The result has invalid tbody structure even when neither snippet.html or template.html has tbody element at all.

I would expect that the latter selector would give me the first result.

read-form doesn't like elements without name attr

I have a button without a name attribute that submits a form.

<form id="form">
  <input name="test" value="some text">
  <button>Save</button>
</form>

When evaluating:

(.log js/console (ef/from "#form" (ef/read-form))) 

You will find something like the following in the console:

{:test "some text" : ""}

Which edn/read-string doesn't like:

clojure.lang.ExceptionInfo: Invalid token: :

Remote snippet loading sometimes results in nil object instead of a snippet

The problem occurs only in Firefox 21 (running Fedora 18 with all updates). See the project https://github.com/dbushenko/iw . Run it as usually (lein ring server), point your browser to localhost:3000/html/index.html.

At first, only the header and the footer are loaded. But if you push Ctrl-R, then all the inner content also appears. I have tested this issue for a while and thats what I've found. I think that defsnippet doesn't create a blocking call, so the atom tpl-cache is available for reading all the time.

(defmacro defsnippet [sym & body]
  (let [[mode uri sel args & forms] (ensure-mode body)
        dom-key (str (name sym) uri)]
    `(do
       ~(case mode
          :remote `(enfocus.core/load-remote-dom ~uri ~dom-key)
          :compiled (load-local-dom uri dom-key))
       (enfocus.macros/create-dom-action
        ~sym
        #(enfocus.core/get-cached-snippet ~dom-key ~sel)

We can read tpl-cache any time even when the call to the server (which creates a snippet) hasn't completed yet.

(defn get-cached-dom
  "returns and dom from the cache and symbol used to scope the ids"
  [uri]
  (let [nod (@tpl-cache uri)]
     (when nod [(first nod) (html-to-dom (second nod))])))

In my case the snippet main-content-snip is rather large and it takes time to load it. Thats why when I call it first, it returns nil.

That's just my thoughts, I don't insist that I understood everything correctly. But looks like the issue is here, in tpl-cache returning nil.

Alternative syntax for 'deftemplate' and 'defsnippet'

I was thinking -- maybe we can use metadata notation for defining :compiled templates and snippets? this will allow creating private templates, ex:

(deftemplate ^{:compiled true :private true} 
  my-internal-template 
  ["#content"] ...)

at won't select children of a form

In google chrome, debugging generated source,

fel = document.querySelector(dommy.core.selector.call(null, "#contactForm"));

enfocus.core.at.call(null, 
    fel, 
    cljs.core.PersistentVector.fromArray(["input"], true), 
    function(x){console.log(x);})
// logs nothing

enfocus.core.at.call(null, 
    fel.parentElement, 
    cljs.core.PersistentVector.fromArray(["input"], true), 
    function(x){console.log(x);})
// logs each of the form's inputs.

Creating templates/snippets before the DOM is loaded

Hello,

I am getting an error when I try to build templates or snippets before the DOM is loaded. This error is due to the document fragment under construction being attached to the "body" tag of the live DOM which does not exist at that time.
(see the function create-hidden-dom of core.cljs).

I wonder if it would be better (or not?) to attach the document fragment to the "html" tag of the live DOM instead of the "body" tag in order to fix this issue.

Also, what are the reasons for the document fragment being attached to the live DOM instead of being attached to a non-live node.

Thank you.

Ewen.

'content' macro makes it impossible to use apply with a seq of values

I have a function which interleaves defsnippet results with plain-text elements. I'm trying to use its resulting seq as the args to the content call.

In enlive, I can simply do:

;; clojure
; require ([net.cgrand.enlive-html :as em])

(apply em/content '("some" (call-to-a-defsnippet data) "text"))

But in enfocus, I have to drop down to enfocus.core because content is a macro:

;; clojurescript
; (:require-macros [enfocus.macros :as em])
; (:require [enfocus.core :as ef])

; fails, clojurescript has no idea what `em/content` is
(apply em/content '("some" (call-to-a-defsnippet data) "text"))

; fails, "Uncaught Error: NOT_FOUND_ERR: DOM Exception 8" when
; trying to goog.appendChild a child string to a DocumentFragment parent
(em/content '("some" (call-to-a-defsnippet data) "text"))

; this works
(apply ef/en-content '("some" (call-to-a-defsnippet data) "text"))

Is there some way around doing this, so that I can keep my template code identical? Does this macro actually have to be a macro?

clone-for needs to support destructuring

(em/defsnippet template "/templates/components/calendar.html" "#calendar"
[entries]
["tr.week"](em/clone-for [week entries]
["td"] %28em/clone-for [[date entry] week]
%28em/do->
%28em/add-class %28get entry :type))
(em/content (date/format "d" date))
(em/listen :click #(state/set! :calendar/current-date (first info)))))))

Trying to compile that throws this error:

Compiling "resources/public/js/main.js" failed.
Exception in thread "main" java.lang.IndexOutOfBoundsException
at clojure.lang.RT.nthFrom(RT.java:784)
at clojure.lang.RT.nth(RT.java:753)
at clj_stacktrace.utils$quartile1.invoke(utils.clj:52)
at clj_stacktrace.utils$fence.invoke(utils.clj:69)
at clj_stacktrace.repl$find_source_width.invoke(repl.clj:98)
at clj_stacktrace.repl$pst_on.invoke(repl.clj:107)
at clj_stacktrace.repl$pst_PLUS_.doInvoke(repl.clj:129)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at cljsbuild.compiler$compile_cljs.invoke(compiler.clj:56)

ef/html flushes my console.log

whenever I use ef/html, my console is flushed with all the hiccup stuff. I guess there is a way to turn debugging off as suggested in your code:

enfocus.core.debug = true;
enfocus.core.log_debug = function log_debug(mesg) {
if(cljs.core.truth_(function() {
var and__3941__auto__ = enfocus.core.debug;
if(cljs.core.truth_(and__3941__auto__)) {
return!cljs.core.EQ.call(null, window.console, undefined)
}else {
return and__3941__auto__
}
}())) {
return console.log(mesg)
}else {
return null
}
};

snippet selecting ALL children of a Node

/templates/remote.html:

<!DOCTYPE html>
<html>
  <body>
    <div id="content">
      <h1>Hello World</h1>
      <p>Lorem ipsum ...</p>
    </div>
  </body>
</html>

(em/defsnippet remotehtml "/templates/remote.html" ["div#content > *"] []) 

I thought that this snippet should contain all child-nodes of div#content but it contains only <h1>Hello World</h1> not the <p>Lorem ipsum ...</p>.

So i conclude, that it is either a missunderstanding on my side or an issue in domina or an issue in enfocus.

Need load waiting moved from global to individual templates

Currently we use (em/wait-for-load (render-login)) attached to a window onload event to wait for all templates and snippets to load. This however does not give the best user experience. Waiting should be moved to the call for the individual templates.

"'DocumentFragment' is undefined" on IE8

Due to the single check for DocumentFragment here:

enfocus.core.create_hidden_dom = function create_hidden_dom(child) {
  var div__15706 = goog.dom.createDom("div", enfocus.core.hide_style);
  if(cljs.core.instance_QMARK_.call(null, DocumentFragment, child)) {
    goog.dom.appendChild(div__15706, child)
  }else {

My app doesn't load on IE8:

"'DocumentFragment' is undefined" on IE8

Can this check be altered to support IE8, please?

'enfocus.core/hidden-style' breaks some 'goog.ui' widgets

Turns out display: none; causes nasty side effects, when used with some Closure Library widgets, for example: goog.ui.Slider relies on .clientWidth and .clientHeight properties of the underlying element, which are zero, when the parent element has display: none.

Maybe a slightly better way of achieving the same behaviour would be:

(def hidden-style 
  (.-strobj {"style" (str "visibility: hidden;"
                          "position: absolute;"
                          "z-index: -1;"
                          "overflow: hidden;")}))

directly using macros without namespacing

Hi,

This is general question on namespace usage. The enfocus's site has this example-

(ns my.namespace

(:require [enfocus.core :as ef])

(:require-macros [enfocus.macros :as em]))

(defn start [](em/at js/document
[“body”] %28em/content “Hello world!”%29)

However I would like to directly use the "at" and "content" macros, without the namespacing. In clojure this can be done by importing the namespaces using the :use form. Can I do the same in clojurescript?

Thanks,
Murtaza

required "enfocus.effects" namespace never provided

WARNING: 2 error(s), 0 warning(s)
ERROR: JSC_MISSING_PROVIDE_ERROR. required "enfocus.effects" namespace never provided at /Volumes/CAT_Archive_1of2/Users/gzmask/projects/rich-invoice/target/cljsbuild-compiler-0/app/core.js line 3 : 0
ERROR: JSC_MISSING_PROVIDE_ERROR. required "enfocus.events" namespace never provided at /Volumes/CAT_Archive_1of2/Users/gzmask/projects/rich-invoice/target/cljsbuild-compiler-0/app/core.js line 4 : 0

Code:
https://github.com/richever/rich-invoice

compatibility between enlive and enfocus nodes

Hi,

I have server side code which is in enlive. It reads a snippet and passes the information on an ajax call using Chris Ganger's fetch library. The get-navbar is the function that will be called by my client side code and will return enlive nodes -

(def title  "Faiz-ul-Mawaid-il-Burhaniyah - Poona Students")

(def links [{:url "#" :text "Home"} {:url "#" :text "Hisaab"}])

(def templ "faiz/templates/components.html")

(defsnippet nav-link templ [:top-navbar [:ul (attr= :data-navlinks "left")] first-child]
  [{:keys [url text]}]
  [:a] (set-attr :href url)
  [:a] (content text))

(defsnippet top-navbar templ [:top-navbar]
  [links]
  [[:ul (attr= :data-navlinks "left")]] (content (map nav-link links)))

(defremote get-navbar []
   (top-navbar links))

Below are the nodes that are received by the client side -

({:content ("\n" {:content ("\n    " {:content ("\n      " {:content ("\n        " {:content ("\n          " {:content (), :tag :span, :attrs {:class "icon-bar"}} "\n          " {:content (), :tag :span, :attrs {:class "icon-bar"}} "\n          " {:content (), :tag :span, :attrs {:class "icon-bar"}} "\n        "), :tag :a, :attrs {:data-toggle "collapse", :class "btn btn-navbar", :data-target ".nav-collapse"}} "\n        " {:content ("\n          " {:content ({:content ({:content ("Home"), :tag :a, :attrs {:href "#"}}), :tag :li, :attrs nil} {:content ("Home"), :tag :a, :attrs {:href "#"}} {:content ({:content ("Hisaab"), :tag :a, :attrs {:href "#"}}), :tag :li, :attrs nil} {:content ("Hisaab"), :tag :a, :attrs {:href "#"}}), :tag :ul, :attrs {:class "nav", :data-navlinks "left"}} "\n          " {:content ("\n            " {:content ("\n              " {:content ("Username" {:content (), :tag :b, :attrs {:class "caret"}}), :tag :a, :attrs {:data-toggle "dropdown", :class "dropdown-toggle", :href "#"}} "\n              " {:content ("\n                " {:content ({:content ("Logout"), :tag :a, :attrs {:href "#"}}), :tag :li, :attrs nil} "\n              "), :tag :ul, :attrs {:class "dropdown-menu"}} "\n            "), :tag :li, :attrs {:class "dropdown"}} "\n          "), :tag :ul, :attrs {:class "nav pull-right"}} "\n        "), :tag :div, :attrs {:class "nav-collapse"}} {:data " /.nav-collapse ", :type :comment} "\n      "), :tag :div, :attrs {:class "container"}} "\n    "), :tag :div, :attrs {:class "navbar-inner"}} {:data " /navbar-inner ", :type :comment} "\n  "), :tag :div, :attrs {:class "navbar navbar-fixed-top"}} "\n"), :tag :top-navbar, :attrs nil})

This is the client side code -

(defn init []
  (fm/letrem [n (get-navbar)]
             (.log js/console (pr-str n))
             (at (doc)
                 ["body > header"] (content n))))

The above code doesnt work.

However when a html string is returned from server side and inserted on client side using the html-content transformation, it works. So is it possible to return nodes from server side itself rather than a html string ?

Thanks,
Murtaza

em/scroll effect

;; macros.cljs
(defmacro scroll 
  ([xpos ypos] 
    `(enfocus.core/en-scroll ~xpos ~ypos 0 nil nil))
  ([xpos ypos ttime] 
    `(enfocus.core/en-scroll ~xpos ~ypos ~ttime nil nil))
  ([xpos ypos ttime callback]
  `(enfocus.core/en-scroll ~xpos ~ypos ~ttime ~callback nil))
  ([xpos ypos ttime callback accel]
  `(enfocus.core/en-scroll ~xpos ~ypos ~ttime ~callback ~accel))) 

;; core.cljs
(defn en-scroll
  "scrolls selected elements to a x and y in px optional time series data"
  [xpos ypos ttime callback accel]
  (ef/chainable-effect
    (fn [pnod pcallback]
      (let [start (array (.-scrollLeft pnod) (.-scrollTop pnod))
            xpos (if (= :curx xpos) (.-scrollLeft pnod) xpos)
            ypos (if (= :cury ypos) (.-scrollTop pnod) ypos)
            end (array xpos ypos)
            anim (fx-dom/Scroll. pnod start end ttime accel)]
        (util/log (str start) (str end))
        (when pcallback
          (events/listen anim goog.fx.Animation.EventType/END pcallback))
        (. anim (play))))
       callback))

Enlive Selector Syntax

Hey Creighton,

Thanks for this great library!

Given that Enlive's selector syntax isn't supported, how do you currently deal with template sharing between Enlive and Enfocus?

Right now, to test my templates (both when writing them and when writing tests for them), I'm using a JVM REPL and midje.

I'd LOVE to be able to implement all my template code with this great quick feedback loop all within Emacs. The only thing holding me back is that the templates I write there are incompatible with the ones Enfocus uses.

I know you have support for Enlive's syntax planned. What can I do in the mean time? What do you do currently?

To be clear, I'm talking about a whole bunch of defsnippets that I'd like to use in both VMs.

`lein cljsbuild once` failing?

In trying to follow the build instructions [1], lein cljsbuild once fails with the following long error message:

Compiling ClojureScript.
Reloading Clojure file "\enfocus\macros.clj" failed.
java.io.FileNotFoundException: Could not locate enfocus/enlive/syntax__init.class or enfocus/enlive/syntax.clj on classpath: 
                 RT.java:432 clojure.lang.RT.load
                 RT.java:400 clojure.lang.RT.load
               core.clj:5415 clojure.core/load[fn]
               core.clj:5414 clojure.core/load
             RestFn.java:408 clojure.lang.RestFn.invoke
               core.clj:5227 clojure.core/load-one
               core.clj:5264 clojure.core/load-lib
             RestFn.java:142 clojure.lang.RestFn.applyTo
                core.clj:603 clojure.core/apply
               core.clj:5298 clojure.core/load-libs
             RestFn.java:137 clojure.lang.RestFn.applyTo
                core.clj:603 clojure.core/apply
               core.clj:5381 clojure.core/require
             RestFn.java:421 clojure.lang.RestFn.invoke
       \enfocus\macros.clj:1 enfocus.macros/eval1975[fn]
       \enfocus\macros.clj:1 enfocus.macros/eval1975
          Compiler.java:6511 clojure.lang.Compiler.eval
          Compiler.java:6501 clojure.lang.Compiler.eval
          Compiler.java:6952 clojure.lang.Compiler.load
                 RT.java:359 clojure.lang.RT.loadResourceScript
                 RT.java:350 clojure.lang.RT.loadResourceScript
                 RT.java:429 clojure.lang.RT.load
                 RT.java:400 clojure.lang.RT.load
               core.clj:5415 clojure.core/load[fn]
               core.clj:5414 clojure.core/load
             RestFn.java:408 clojure.lang.RestFn.invoke
            compiler.clj:100 cljsbuild.compiler/reload-clojure[fn]
             compiler.clj:99 cljsbuild.compiler/reload-clojure
            compiler.clj:136 cljsbuild.compiler/run-compiler
            NO_SOURCE_FILE:1 user/eval1941[fn]
             LazySeq.java:42 clojure.lang.LazySeq.sval
             LazySeq.java:60 clojure.lang.LazySeq.seq
                 RT.java:473 clojure.lang.RT.seq
                core.clj:133 clojure.core/seq
               core.clj:2725 clojure.core/dorun
               core.clj:2741 clojure.core/doall
            NO_SOURCE_FILE:1 user/eval1941[fn]
            NO_SOURCE_FILE:1 user/eval1941
          Compiler.java:6511 clojure.lang.Compiler.eval
          Compiler.java:6501 clojure.lang.Compiler.eval
          Compiler.java:6477 clojure.lang.Compiler.eval
               core.clj:2797 clojure.core/eval
                main.clj:297 clojure.main/eval-opt
                main.clj:316 clojure.main/initialize
                main.clj:349 clojure.main/null-opt
                main.clj:427 clojure.main/main
             RestFn.java:421 clojure.lang.RestFn.invoke
                Var.java:419 clojure.lang.Var.invoke
                AFn.java:163 clojure.lang.AFn.applyToHelper
                Var.java:532 clojure.lang.Var.applyTo
                main.java:37 clojure.main.main
Compiling "../testing/resources/public/cljs/enfocus.js" from ["cljs-src" ".generated/cljs"]...
Compiling "../testing/resources/public/cljs/enfocus.js" failed.
clojure.lang.ExceptionInfo: Could not locate enfocus/enlive/syntax__init.class or enfocus/enlive/syntax.clj on classpath:  at line 1 cljs-src\enfocus\core.cljs
             core.clj:4227 clojure.core/ex-info
          analyzer.clj:107 cljs.analyzer/error
          analyzer.clj:890 cljs.analyzer/analyze-seq
          analyzer.clj:948 cljs.analyzer/analyze
          analyzer.clj:939 cljs.analyzer/analyze
          compiler.clj:795 cljs.compiler/compile-file*
          compiler.clj:851 cljs.compiler/compile-file
          compiler.clj:912 cljs.compiler/compile-root
           closure.clj:374 cljs.closure/compile-dir
           closure.clj:406 cljs.closure/eval1475[fn]
           closure.clj:276 cljs.closure/eval1404[fn]
           closure.clj:420 cljs.closure/eval1462[fn]
           closure.clj:276 cljs.closure/eval1404[fn]
           compiler.clj:43 cljsbuild.compiler.SourcePaths/fn
             core.clj:2432 clojure.core/map[fn]
           LazySeq.java:42 clojure.lang.LazySeq.sval
           LazySeq.java:60 clojure.lang.LazySeq.seq
               RT.java:473 clojure.lang.RT.seq
              core.clj:133 clojure.core/seq
              core.clj:601 clojure.core/apply
             core.clj:2461 clojure.core/mapcat
           RestFn.java:423 clojure.lang.RestFn.invoke
           compiler.clj:43 cljsbuild.compiler/cljsbuild.compiler.SourcePaths
           closure.clj:900 cljs.closure/build
           compiler.clj:57 cljsbuild.compiler/compile-cljs[fn]
           compiler.clj:56 cljsbuild.compiler/compile-cljs
          compiler.clj:140 cljsbuild.compiler/run-compiler
          NO_SOURCE_FILE:1 user/eval1941[fn]
           LazySeq.java:42 clojure.lang.LazySeq.sval
           LazySeq.java:60 clojure.lang.LazySeq.seq
               RT.java:473 clojure.lang.RT.seq
              core.clj:133 clojure.core/seq
             core.clj:2725 clojure.core/dorun
             core.clj:2741 clojure.core/doall
          NO_SOURCE_FILE:1 user/eval1941[fn]
          NO_SOURCE_FILE:1 user/eval1941
        Compiler.java:6511 clojure.lang.Compiler.eval
        Compiler.java:6501 clojure.lang.Compiler.eval
        Compiler.java:6477 clojure.lang.Compiler.eval
             core.clj:2797 clojure.core/eval
              main.clj:297 clojure.main/eval-opt
              main.clj:316 clojure.main/initialize
              main.clj:349 clojure.main/null-opt
              main.clj:427 clojure.main/main
           RestFn.java:421 clojure.lang.RestFn.invoke
              Var.java:419 clojure.lang.Var.invoke
              AFn.java:163 clojure.lang.AFn.applyToHelper
              Var.java:532 clojure.lang.Var.applyTo
              main.java:37 clojure.main.main
Caused by: java.io.FileNotFoundException: Could not locate enfocus/enlive/syntax__init.class or enfocus/enlive/syntax.clj on classpath: 
               RT.java:432 clojure.lang.RT.load
               RT.java:400 clojure.lang.RT.load
             core.clj:5415 clojure.core/load[fn]
             core.clj:5414 clojure.core/load
           RestFn.java:408 clojure.lang.RestFn.invoke
             core.clj:5227 clojure.core/load-one
             core.clj:5264 clojure.core/load-lib
           RestFn.java:142 clojure.lang.RestFn.applyTo
              core.clj:603 clojure.core/apply
             core.clj:5298 clojure.core/load-libs
           RestFn.java:137 clojure.lang.RestFn.applyTo
              core.clj:603 clojure.core/apply
             core.clj:5381 clojure.core/require
           RestFn.java:421 clojure.lang.RestFn.invoke
              macros.clj:1 enfocus.macros/eval2944[fn]
              macros.clj:1 enfocus.macros/eval2944
        Compiler.java:6511 clojure.lang.Compiler.eval
        Compiler.java:6501 clojure.lang.Compiler.eval
        Compiler.java:6952 clojure.lang.Compiler.load
               RT.java:359 clojure.lang.RT.loadResourceScript
               RT.java:350 clojure.lang.RT.loadResourceScript
               RT.java:429 clojure.lang.RT.load
               RT.java:400 clojure.lang.RT.load
             core.clj:5415 clojure.core/load[fn]
             core.clj:5414 clojure.core/load
           RestFn.java:408 clojure.lang.RestFn.invoke
             core.clj:5227 clojure.core/load-one
             core.clj:5264 clojure.core/load-lib
           RestFn.java:142 clojure.lang.RestFn.applyTo
              core.clj:603 clojure.core/apply
             core.clj:5298 clojure.core/load-libs
           RestFn.java:137 clojure.lang.RestFn.applyTo
              core.clj:603 clojure.core/apply
             core.clj:5381 clojure.core/require
           RestFn.java:408 clojure.lang.RestFn.invoke
          analyzer.clj:670 cljs.analyzer/eval360[fn]
          MultiFn.java:177 clojure.lang.MultiFn.invoke
          analyzer.clj:892 cljs.analyzer/analyze-seq

[1] mentions a directory called "enfocus/sample" which doesn't seem to exist in the repository so maybe the readme is outdated, sorry for not being able to figure this out.

[1] https://github.com/ckirkendall/enfocus#compile-clojurescript

filenotfoundexception with enfocus/macros.clj in latest snapshot jar

My enfocus 2.0.0-SNAPSHOT dep was updated in the last couple of days and now I get:

Caused by: java.io.FileNotFoundException: Could not locate enfocus/macros__init.class or enfocus/macros.clj on classpath:

When I compile my clojurescript. I have a macros file that uses it.

here is the code:

(ns mirv.client.add-release-macros)

;; templates
(defmacro make-release-note-snippets
  []
  (cons 'do (for [selector [".release-fixed" ".release-changed" ".release-notes" ".release-added"]]
              `(enfocus.macros/defsnippet ~(symbol (str (subs selector 1) "-note-snippet")) :compiled "html/add-release.html" [~selector]
                 [note#]
                 [:.note-message]
                 (enfocus.core/content note#)))))

and here is the stacktrace:

Exception in thread "main" clojure.lang.ExceptionInfo: Could not locate enfocus/macros__init.class or enfocus/macros.clj on classpath: {:tag :cljs/analysis-error}
at clojure.core$ex_info.invoke(core.clj:4327)
at cljs.analyzer$error.invoke(analyzer.clj:116)
at cljs.analyzer$analyze_seq.invoke(analyzer.clj:892)
at cljs.analyzer$analyze.invoke(analyzer.clj:950)
at cljs.analyzer$analyze.invoke(analyzer.clj:941)
at cljs.analyzer$eval2931$fn__2933$fn__2935$fn__2936.invoke(analyzer.clj:445)
at clojure.core$map$fn__4215.invoke(core.clj:2485)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.RT.seq(RT.java:484)
at clojure.core$seq.invoke(core.clj:133)
at cljs.analyzer$eval2931$fn__2933$fn__2935.invoke(analyzer.clj:445)
at cljs.analyzer$eval2931$fn__2933.invoke(analyzer.clj:444)
at clojure.lang.MultiFn.invoke(MultiFn.java:241)
at cljs.analyzer$analyze_seq.invoke(analyzer.clj:894)
at cljs.analyzer$analyze.invoke(analyzer.clj:950)
at cljs.analyzer$analyze.invoke(analyzer.clj:941)
at noir.cljs.compiler$__GT_cljs.doInvoke(compiler.clj:48)
at clojure.lang.RestFn.invoke(RestFn.java:423)
at noir.cljs.watcher$init_file.invoke(watcher.clj:50)
at noir.cljs.watcher$start.doInvoke(watcher.clj:115)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at noir.cljs.core$start.doInvoke(core.clj:45)
at clojure.lang.RestFn.invoke(RestFn.java:423)
at mirv.server$_main.doInvoke(server.clj:36)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:411)
at user$eval11047.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6609)
at clojure.lang.Compiler.eval(Compiler.java:6582)
at clojure.core$eval.invoke(core.clj:2852)
at clojure.main$eval_opt.invoke(main.clj:308)
at clojure.main$initialize.invoke(main.clj:327)
at clojure.main$null_opt.invoke(main.clj:362)
at clojure.main$main$fn__6661.invoke(main.clj:440)
at clojure.main$main.doInvoke(main.clj:437)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Caused by: java.io.FileNotFoundException: Could not locate enfocus/macros__init.class or enfocus/macros.clj on classpath:
at clojure.lang.RT.load(RT.java:443)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5028.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4977.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$require.doInvoke(core.clj:5496)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at mirv.client.add_release_macros$eval12141$loading__4920__auto____12142.invoke(add_release_macros.clj:1)
at mirv.client.add_release_macros$eval12141.invoke(add_release_macros.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6608)
at clojure.lang.Compiler.load(Compiler.java:7064)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.loadResourceScript(RT.java:361)
at clojure.lang.RT.load(RT.java:440)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5028.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4977.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$require.doInvoke(core.clj:5496)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at cljs.analyzer$eval3015$fn__3017.invoke(analyzer.clj:672)
at clojure.lang.MultiFn.invoke(MultiFn.java:241)
at cljs.analyzer$analyze_seq.invoke(analyzer.clj:894)
... 39 more

how is this code working?

Hi,

I have the below code working. In this I am generating HTML / DOM object using crate. Then I am inserting that into the DOM using the content macro of enfocus.

However the content macro of enfocus is only suppose to work with enfocus tags, and here I have a DOM object !

(defn layout [c]
"Takes html string as input and inserts it into the DOM"
(log "Layout Content" c)
(at (doc)
[".cljs-main"](content c)))

(defhtml reg-form []
[:div.form-horizontal
[:fieldset
[:legend "Student Registeration"]
[:div.control-group
[:label.control-label {:for "input01" :bind "click: faiz.client.info-collection.hello"} "Text Input"]]]])

(defn render [](layout %28reg-form%29))

Thanks,
Murtaza

ef/set-attr not working

I have an input field:
[:input#field1 {:type "text"}]

then I use (at js/document (set-attr :value "some val")) to set the input field.

This doesn't work. Sometimes it does work when the input field has not been entered anything before. the most of the time it does nothing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.