levand / domina Goto Github PK
View Code? Open in Web Editor NEWA DOM manipulation library for ClojureScript
A DOM manipulation library for ClojureScript
Currently, keywords passed to listen!
& co are restricted to builtin-types
, which is a set constructed from goog.events.EventType. Unfortunately, this approach doesn't allow to use keywords for subscribing to events, dispatched by goog.ui.Component subclasses, for example goog.ui.TabBar:
(listen! :active tabbar #(...))
;; ^^^ this won't work
What are the options here? I think domina
could:
builtin-types
with keys from all possible EventType
enums or provide a way for a user to do it.Here's something odd I noticed about the domina 1.0.1 jar on clojars. The tree structure of the extracted jar looks like this:
.
├── cljs
│ ├── domina
│ │ ├── css.cljs
│ │ ├── events.cljs
│ │ ├── macros.clj
│ │ ├── support.cljs
│ │ └── xpath.cljs
│ └── domina.cljs
├── domina
│ ├── css.cljs
│ ├── events.cljs
│ ├── macros.clj
│ ├── support.cljs
│ └── xpath.cljs
├── #domina.cljs#
├── domina.cljs
├── META-INF
│ ├── leiningen
│ │ └── domina
│ │ └── domina
│ │ └── project.clj
│ ├── MANIFEST.MF
│ └── maven
│ └── domina
│ └── domina
│ ├── pom.properties
│ └── pom.xml
└── project.clj
As you can see, all clojurescript files in the domina/
folder are duplicated in the cljs/
folder. Is there a reason for this duplication?
I'm having the same issue as emezeske/lein-cljsbuild#145, and it seems to go away if I remove domina from the project.
Our team loves Domina, would love to see it working properly - how can I help? I'm not sure how to track this error down.
domina/nodes always returns an empty collection in :optimizations :simple, but works as expected in optimizations :advanced
To see the issue, for some page with a few divs, run the following code
(js/alert (domina.css/sel "div"))
(js/alert (domina/nodes (domina.css/sel "div")))
The first line
works fine in both :optimizations :simple and :optimizations :advanced
The second line
With :optimizations :simple, an empty collection is displayed
With :optimizations :advanced, a collection of htmlelements is displayed
[domina "1.0.2"]
[org.clojure/clojurescript "0.0-2234"]
[lein-cljsbuild "1.0.3"]
I just started testing Domina, and as soon as I compile it using lein cljsbuild once
I am getting the following warnings:
Compiling "resources/public/test.js" from ["src/cljs"]...
WARNING: clone already refers to: /clone being replaced by: domina/clone at line
147 file:/C:/Users/Proprietaire/.m2/repository/domina/domina/1.0.2/domina-1.0.2
.jar!/domina.cljs
WARNING: No such namespace: XPathResult at line 30 file:/C:/Users/Proprietaire/.
m2/repository/domina/domina/1.0.2/domina-1.0.2.jar!/domina/xpath.cljs
WARNING: No such namespace: XPathResult at line 41 file:/C:/Users/Proprietaire/.
m2/repository/domina/domina/1.0.2/domina-1.0.2.jar!/domina/xpath.cljs
The XPathResult warning appears when I include xpath: [domina.xpath :only [xpath]]
I use the latest ClojureScript. I did some reasearch and I haven't found anything regarding this issue, so I am wondering if it is my setup that is wrong or an actual issue with Domina.
I thought it might be worth mentioning Android support in the documentation.
Android 2.x (which has a 95% share on Android devices), doesn't implement XPath, but it erroneously claims that it does via the document.implementation.hasFeature mechanism. This causes xpath.js to refuse to install.
Android doesn't have document.evaluate. By detecting this, and setting the useNative: false config option, prior to loading xpath.js, android will use the xpath.js implementation and work fine.
<script type="text/javascript">
/* Android 2.x claims XPath support, but has none. Force non-native
XPath implementation in this case */
if (document.implementation
&& document.implementation.hasFeature
&& document.implementation.hasFeature("XPath",null)
&& !document.evaluate) {
window.jsxpath = {
targetFrame: undefined,
exportInstaller: false,
useNative: false, /* force non-native implementation */
useInnerText: true
};
}
</script>
<!-- Non-native XPath implementation for IE and Android 2.x -->
<script type="text/javascript" src="js/xpath.js"></script>
So, three things are currently an issue in preventing Android 2.x from working:
I am trying to use domina to extract information from html received from another website (which I don't control, and which doesn't have a proper API). The basic issue is this:
If I do:
(html-to-dom "<img src=\"foo.jpg\">")
the browser will do a request to whatver.url/foo.jpg. The same applies to nodes and single-node, of course. Is there a way around that, or should I use a different library? I know enlive uses its own, more abstract representation of nodes, which is also nice for examining and doing arbitrary stuff on them, but I would be happy with just avoiding the side effects.
If a form element does not contain 'name' attribute domina has trouble selecting it because array-like? returns '0' instead of false. It looks like you have detected the same issue with select boxes and that is why you added the -name check. Maybe it would be better to check these types of nodes in some other way. Maybe a hash list of node-types with these properties.
(defn- array-like?
[obj]
(and obj ;; is not nil
(not (.-name obj)) ;; is not an element (i.e, <select>)
(.-length obj))) ;; has a length
Creighton
Consider the following code:
(listen! (sel "body") :keypress (fn [evt] (println "Keypress" (:keyCode evt))))
On Chrome, I see ASCII codes printed out properly for alphanumeric keys, but no event is received and thus nothing is printed for arrow keys.
On Firefox, I see codes printed out properly for arrow keys, but all alphanumeric keys print a keyCode of 0.
By using lein-cljsbuild 0.2.10 and adding a domina > 1.0.0 (i.e. 1.0.1 or 1.0.2-SNAPSHOT) $ lein cljsbuild once
produces a very long waiting time after last CLJS to JS compilation before returning.
Following is a repo sample
By including domina 1.0.2-SNAPSHOT instead of 1.0.0, by-class does not work any more with the following JS message:
Uncaught Error: Doesn't support name: modern_dbg.js:17727
name modern_dbg.js:17727
domina.t3861.domina$DomContent$nodes$arity$1 modern_dbg.js:25216
nodes modern_dbg.js:25094
destroy_BANG_ modern_dbg.js:25301
remove_help modern_dbg.js:32687
(anonymous function) modern_dbg.js:26173
goog.events.Listener.handleEvent modern_dbg.js:24464
goog.events.fireListener modern_dbg.js:24798
goog.events.handleBrowserEvent_ modern_dbg.js:24919
(anonymous function)
But it works using .getElementsByClassName
interop.
You can check this behaviour with the following source code included in a repo:
https://github.com/magomimmo/modern-cljs/blob/domina-by-name/src/cljs/modern_cljs/shopping.cljs
The following does not work in any browser I tested.
(listen! :click (fn [evt] (log "button clicked!")))
Nor does
(listen! js/document :click (fn [evt] (log "button clicked!")))
Attempted to use [domina "1.0.0-beta4"], but 'lein deps' fails because:
[INFO] Unable to find resource 'org.clojure:clojurescript:pom:0.0-1069' in repository central (http://repo1.maven.org/maven2), etc
The project.clj for the beta4 version of domina has this version of Clojurescript as a dependency. I tried excluding it in my project file, e.gl.
[domina "1.0.0-beta4 :exclusions [org.clojure/clojurescript]]
guessing that domina could just use the version from cljsbuild, but that didn't work.
Is there a workaround? This version of Clojurescript doesn't seem to be available in any publc repository.
Hi,
I'm trying to get the selected option from a drop down list:
`
`(ns foo
(:require [domina :as dom]
[goog.dom.forms :as forms]))``
If I try get the value of the drop down using the Domina 'value' function:
(dom/value (dom/by-id "day_of_week"))
I get nil/null
If I go instead direct to the google closure getValue function:
(forms/getValue (dom/by-id "day_of_week"))
it works.
Any ideas?
There is an issue selecting styles when the value has a :
in it.
The regex match only returns the initial match before the first :
.
So something like background-image: url(http://www.something.com/image.jpg)
will result in a map that is {:background-image "url(http"}
I think you should take out the line of https://github.com/levand/domina/blob/master/src/cljs/domina.cljs#L385
I think you should leave the events as they are, because let us say you had the following:
<div id="top-div">
<!-- child content -->
</div>
If you have an event listener on #top-div and you call set-html! on #top-div, those event listeners are wiped out. It seems like this doesn't need to be the case, because it's just the inner html that is getting changed, not #top-div.
Determine how to write a function that takes a CSS selector string and returns a DomContent
. I'd like to avoid pulling in Dojo as a third party dependency, but it might be the only cross-browser way. Investigate this.
The underlying Google Closure listen method take a string or an array of strings for the event type when registering an event listener. That way, one can register the same listener function to fire on several different event types at once. This can be easily done in a (doseq), but might be nice here, too.
(listen! js/document :DOMContentLoaded (fn [] (.log js/console "symbol")))
(listen! js/document "DOMContentLoaded" (fn [] (.log js/console "string")))
The second log will execute correctly when DOMContentLoaded
fires (can be verified by adding a third handler using .addEventListener
), the first one gets lost in an unknown void. The readme only uses symbols (even for custom events) and gives no hint that strings and symbols aren't equivalent
Hello, is it really required to have clojure and clojurescript as dependencies in project.clj
? I mean, since domina
is a clojurescript library the library user will surely have both of them in their own project.clj
.
I am getting this when I try to load the ns:
WARNING: domina is a single segment namespace at line 1 file:/home/master/.m2/repository/domina/domina/1.0.3/domina-1.0.3.jar!/domina.cljs
WARNING: domina is a single segment namespace at line 1 out/domina.cljs
Hey Luke, would you mind tacking a license on this bad boy? Thanks! -Alan
(.log js/console (single-node "<tr><td>Foo</td></tr>"))
to print to the console:
<tr><td>Foo</td></tr>
i.e. a Table Row Element
(.log js/console (single-node "<tr><td>Foo</td></tr>"))
printed to the console:
Foo
i.e. a Text Node Element
This discrepancy is due to a known bug in goog.dom.htmlToDocumentFragment: http://code.google.com/p/closure-library/issues/detail?id=210. The TR and TD (as well as TH, THEAD, TBODY, TFOOT) tags are stripped out when converting from a string to DOM elements, leaving only concatenated text nodes.
This issue impacts a use case that I think is quite common -- A string containing a table row is used as a template for each element of a collection, it is manipulated and inserted into the DOM.
I have included domina in my project.clj as follows:
[domina "1.0.0-alpha2"]
At a cljs repl I can do:
(load-namespace 'domina)
which produces:
WARNING: satisfies? already refers to: #'clojure.core/satisfies? in namespace: domina.macros, being replaced by: #'domina.macros/satisfies?
So far so good. But:
(domina/by-id "fun")
Gives me:
"Error evaluating:" (domina/by-id "fun") :as "domina.by_id.call(null,"fun");\n"
Oddly enough:
(load-namespace 'domina.xpath)
(domina.xpath.xpath "//body/p[@Class='fun']")
gives:
Also if I do:
(load-file "domina.cljs")
(domina/by-id "fun")
I get:
Any ideas what could could be causing this? I thought it might be a class path issue, but since I can reack domina.js using load-file, this does not appear to be the case.
Domina's set-value!
doesn't work to change the value
attribute of a checkbox. Looking at the code, I see this is because it's implemented by calling Google Closure Library's goog.dom.forms/setValue
, whose code does not set the value of the value
attribute of checkboxes, but it adds or removes the checked
attribute (see the setInputChecked_
function in the same file, which, BTW, it has this comment "This seems potentially unintuitive since it doesn't set the value property").
On the other hand, Domina's value
function only returns a checkbox value
attribute if the checkbox is checked. Again, this is because value
relies on Closure Library's equivalent function (getValue
) which has this behavior for checkboxes.
I find these set-value!
and value
behaviors for checkboxes very uintuitive (besides, they made me waste a lot of time!) as they change the semantics of value
in the HTML spec apparently for no reason.
I've raised the issue in Closure Library's mailing list but nobody replied as of now. I wonder... don't you agree that the current behavior is not correct? If so, should this be fixed in Domina, or should we wait for this to be fixed in Closure Library?
Just finished a long hack session getting touch events to work. Turns out google helpfully strips out the touch information from touch events before domina gets them, and then the touch events don't really support any of the stuff documented here:
https://developer.mozilla.org/en-US/docs/DOM/TouchEvent
My solution is here - basically getting the original browser event and accessing its touch stuff.
http://stackoverflow.com/questions/15732028/clojurescript-touch-events-and-domina/15745781#15745781
It would be nice if domina could make up for google's shortcoming by making the touch information available in the domina event structures.
I was having a problem with leiningen trying to resolve a dependency for org.clojure/clojurescript 0.0-1069 which couldn't be found, changing this to version 0.0-1011 in the pom file seemed to solve that issue. I know someone on google groups was having this issue as well.
When compiling a ClojureScript project I get this warning
WARNING: domina is a single segment namespace at line 1 file:/Users/user/.m2/repository/domina/domina/1.0.3/domina-1.0.3.jar!/domina.cljs
It would probably be better to move to a multi segment namespace, single segment namespaces are generally avoided
The function remove-extraneous-tbody!
uses two undeclared vars, namely tag-name
and start-wrap
. These two (among others) show as warnings when running e.g. lein cljsbuild once
. The function remove-extraneous-tbody!
was introduced in commit 7e2d04c.
Hi,
I am trying to dispatch a click event on a button -
(defn enter-to-click
"It captures the enter event on the given element selector (s1) and triggers a click event on the element selector (s2)"
[s1 s2]
(let [el1 (sel s1) el2 (sel s2)]
(listen! el1 :keydown (fn [ev]
(when (= (:keyCode ev) 13)
(dispatch! (sel "#sign_in") "click" {}))))))
The listen! event works, I am even able to log messages from the when block , however the dispatch doesnt work. I am however able to trigger a click event using jquery from the browsers console.
Any help will be appreciated.
Thanks,
Murtaza
In the documentation there's just a typo, I believe—
"De-registering Event Handlers
There are several ways to de-register an event handler.
If you have they key returned"
should read
"De-registering Event Handlers
There are several ways to de-register an event handler.
If you have the key returned"
so basically just removing a y
I spent a few hours today tracking down this issue, so thought I'd write it up as a gotcha.
I was trying to listen to submit events on a form.
<form id="myform">
<input type="text"></input>
<input type="submit"></input>
</form>
This was my first attempt.
(events/listen!
(by-id "myform") "submit"
(fn [ev] (.log js/console "Submit")))
It doesn't work.
But this works :-
<button id="test"/>
(events/listen!
(by-id "test") "click"
(fn [ev] (.log js/console "OK")))
And, going back to the previous example, this works too :-
(events/listen!
(domina.css/sel "#myform") "submit"
(fn [ev] (.log js/console "Submit")))
So does this.
(events/listen!
[(by-id "myform")] "submit"
(fn [ev] (.log js/console "Submit")))
Notice that I've wrapped the node in a vector.
But this doesn't :-
(events/listen!
(by-id "myform") "submit"
(fn [ev] (.log js/console "Submit")))
And I think it should.
Why doesn't it work?
If we look at the events/listen! function we see it is wrapper the node with domina/nodes. That's what you want if you're passing a NodeList (perhaps found using a selector). But in the case of an HTML form, it returns the 2 child nodes (the input text and submit button).
So
(events/listen!
(by-id "myform") "submit"
(fn [ev] (.log js/console "Submit")))
adds the event listener to both inputs, but not to the form.
I think the DomContent protocol is complects the notion of parenthood with the notion of a collection of nodes. They are not the same thing.
Can you please help me understand the prolific use of a bang symbol at the end of function names. In Clojure proper this is very rarely used.
David
Thank you for this great library. I use it extensively. The problem I am having boils down to this:
Using Leinengen 2.0 and a project.clj with dependencies:
[[org.clojure/clojure "1.5.0"]
[org.clojure/clojurescript "0.0-1586"]
[domina "1.0.0"]
[org.clojure/google-closure-library-third-party "0.0-2029"]]
From the prompt provided by "lein trampoline cljsbuild repl-rhino" and the namespace created with "(ns testing (:require [goog.db :as db]))" the command "(type goog.db.openDatabase)" returns an "undefined" error, apparently in reference to the goog.db namespace.
But when I remove the domina dependency from the above project.clj, the same series of commands properly finds and evaluates the goog.db reference.
This seems weird enough that I assume the problem lies in my code, but I don't see what I'm doing wrong...
My code works correctly until I compile it with :optimizations :advanced. Then, the domina event listener seems to return a raw object, rather than the DOM node I expected:
(defn dbg1 [x]
(log "1: " (by-id "tabbar"))
(log "2: " x))
(defn ^:export init []
(events/listen! (by-id "tabbar") :click #(dbg1 %)))
I click on the page, and the console shows:
1: [object HTMLDivElement]
2: [object Object]
I'm not really sure how to structure this issue, but basically I'm curious about the thinking behind get-data and set-data!. It seems that, rather than returning/modifying data attributes, they modify a custom "__domina_data" attribute. If one expects to be able to do something like retrieve or add/update an HTML data attribute, they don't work.
Can you give a use-case for get-data/set-data! ?
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.