Could anyone tell me how to produce a right-click event handler in Clojure? I am familiar with ":on-click" for simple clicks but not right or double clicks. Can't seem to find any helpful resources online. Thanks!
Frequently in ClojureScript the Google Closure library (Event Handling | Closure Library | Google Developers) is used instead of raw JS. The events (Closure Library API Documentation - JavaScript) namespace contains the goog.events.EventType enumeration which specifies each individual event type:
(ns test.core
(:require [goog.dom :as dom]
[goog.events :as events]))
(letfn [(menu-listener [event]
(.log js/console (str "contextmenu " (.-button event))))
(click-listener [event]
(let [btn (.-button event)
msg (if (= btn 2) "Right-click" (str "Button " btn))]
(.log js/console msg)))]
(events/listen (dom/getElement "click-target") "contextmenu" menu-listener)
(events/listen (dom/getElement "click-target") "click" click-listener))
;; src/test/core.cljs
.
<!DOCTYPE html>
<html>
<head>
<title>contextmenu</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<p id="click-target">Right click on me</p>
<script src="out/test.js" type="text/javascript"></script>
</body>
</html>
<!-- index.html -->
Observe:
A right-click (button 2) fires the contextmenu listener. The click listener doesn't get to see it (even if there is no contextmenu listener).
A second right-click will dismiss the context menu but neither listener is fired.
Using om I got right click as context-menu event. Button number is 2 for right button:
{:onContextMenu (fn [e]
(prn e (.-button e)))}
or in plain html+cljs:
<div id="btn">Click me</div>
(.addEventListener (.getElementById js/document "btn")
"contextmenu" (fn [e] (prn e (.-button e))))
https://developer.mozilla.org/en/docs/Web/API/MouseEvent
Related
How would I render an async script tag in hiccup?
<script src="demo_async.js" async></script>
I think you should just code it as
(use 'hiccup.core)
(html
[:script {:src "demo_async.js" :async "async"} ] )
=> <script src="demo_async.js" async="async" ></script>
Reference: http://www.w3schools.com/tags/tag_script.asp
Trying out OM, ReactJS and ClojureScript. I am trying to add a classname to my dom element. Ideally I want something like this:
<div>
<i class="icon-alert">Contact list</i>
</div>
right now: It writes like:
<div>
<i>Contact list</i>
</div>
This is my core.clj
(defn new-view [data owner]
(reify
om/IRender
(render [this]
(dom/i #js {:class "icon-alert"} "Contacts list")
)))
(om/root new-view app-state
{:target (. js/document (getElementById "row1"))})
This is the relevant part from my index.html
<div id="row1">
<h2>Figwheel template</h2>
<p>Checkout your developer console.</p>
</div>
Any ideas of what I am doing wrong?
Playing around with my code, make me realise: I was writing class instead of className. Feel so dumb. It works now. I will let it here so people with the same issues can get the help they need.
(defn new-view [data owner]
(reify
om/IRender
(render [this]
(dom/i #js {:className "icon-alert"} "Contacts list")
)))
I have a dead simple ClojureScript/Om application. It seems a little broken.
This is the core file:
(ns demo.core
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [goog.events :as events]
[cljs.core.async :as async :refer [>! <! put! chan]]
[om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[goog.events.EventType :as EventType]
[clojure.string :as string]))
(defn layout
[app owner]
(reify
om/IRender
(render [_]
(dom/div {:id "some-id"} "Pumpkin"))))
(defn main []
(om/root
layout
{}
{:target (. js/document (getElementById "app"))}))
It renders this HTML:
<div id="app">
<div data-reactid=".0">Pumpkin</div>
</div>
Why doesn't the div have the id #some-id?
You need to use the #js {} reader literal to specify a JS object rather than a plain-old map:
(dom/div #js {:id "some-id"} "Pumpkin")
This is elaborated a bit in the Om Tutorial.
I'm new to Enlive. I found that I can iterate with clone-for, however, it works for single element. I want to generate a list of a pair of elements like the following:
<div>
item 1<br>
item 2<br>
...
</div>
I tried to select <a> and use clone-for, but end with following result:
<div>
item 1item 2......<br>
</div>
What do I do to repeat <a> with <br> in each iteration?
I think fragments will work in this case.
Try something along these lines:
(html/sniptest "<div>Label<br/></div>" {[:a] [:br]}
(clone-for [{label :label url :url} [{:label "Google" :url "http://www.google.com" }
{:label "Stack Overflow" :url "http://www.stackoverflow.com"}]]
[:a] (do-> (content label)
(set-attr :href url)))))
;; =>
<div>
Google<br />
Stack Overflow<br />
</div>
If you always want the full content of the div to be cloned (not just the fragment :a -> :br) then you can use first-child and last-child. Just change the {[:a] [:br]} selector above to {[:div first-child] [:div last-child]}.
I have this html snippet. I want parse that snippet and emit html without javascript tags
<html>
<body>
<div class="content">lorem ipsum</div>
<script src="/js/jquery.js" type="text/javascript"></script>
<script src="/js/bootstrap.min.js" type="text/javascript"></script>
</body>
</html>
become this
<html>
<body>
<div class="content">lorem ipsum</div>
</body>
</html>
I couldn't found enlive helper function to remove tags.
I have found the solution thanks for the example. So I write this code and the js disappeared
(html/deftemplate template-about "../resources/public/build/about/index.html"
[]
[:script] (fn js-clear [& args] nil)
)
My usual approach when I need to conditionally remove some tags of the rendered page is to use a nil returning function.
For instance
(html/defsnippet upgrade-plan "page_templates/upgrade-plan.html" [:#upgradePlanSection]
[pending-invoice ... ]
...
[:#delayedPlanWarning] #(when pending-invoice
(html/at %
[:#delayedPlanWarning] (html/remove-attr :style)
[:.messagesText] (html/html-content (tower/t :plans/pending-invoice
(:id pending-invoice)))))
...
In that particular case if pending-invoice is nil the delayedPlanWarning element is removed from the rendered html since the function returns nil.
If you don't mind the extra parsing and emitting, the following would do nicely:
(def orig (html-resource (java.io.StringReader. "<html>
<body>
<div class=\"content\">lorem ipsum</div>
<script src=\"/js/jquery.js\" type=\"text/javascript\"></script>
<script src=\"/js/bootstrap.min.js\" type=\"text/javascript\"></script>
</body>
</html>")))
(def stripped (transform orig [(keyword "script")] (substitute "")))
(apply str (emit* stripped))
When removing whole tags, you only need to use nil as your transformation.
(deftemplate tester1
(java.io.StringReader. "<html><body><div class=\"content\">...")
[]
[:script] nil)
(template1)
In your case, you would replace the StringReader with the resource you are using.