ckirkendall / enfocus Goto Github PK
View Code? Open in Web Editor NEWDOM manipulation and templating library for ClojureScript inspired by Enlive.
Home Page: http://ckirkendall.github.com/enfocus-site/
DOM manipulation and templating library for ClojureScript inspired by Enlive.
Home Page: http://ckirkendall.github.com/enfocus-site/
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
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.
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.
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.
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
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
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?
Is there an equivalent to the "this-node" selector from enlive?
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
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.
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?
There is considerable duplication of code between Domina and Enfocus. Domina is a lower level abstraction that can be used as a base layer for Enfocus.
We need some form of syntax validation on the major forms. This validation should provide the developer with easy to understand error messages.
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!
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.
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.
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.
Like so:
(em/select js/document (em/trans [node] (set! (.-scrolltop node) 0))
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;")}))
If an object has padding non-nul, the resize animation starts with the wrong dimensions.
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
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
;; 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))
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)
The current status of 2.0.0-snapshot looks pretty stable. Any plan to upload a 2.0.0 to clojars soon?
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.
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"]]
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.
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.
(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)
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
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?
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.
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.
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
/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.
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.
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
}
};
htmlToDocumentFragment function, used in enfocus.core/load-local-dom
has a known bug, which doesn't allow rendering <table />
elements. Maybe we should provide our own implementation, since Google is clearly not going to fix this?
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?
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
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.
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.
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.
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] [])
(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.
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"] ...)
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: :
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
)
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
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.