Code Monkey home page Code Monkey logo

dommy's Introduction

A ClojureScript DOM manipulation and event library.

Usage

Add the following dependency to your project.clj:

[prismatic/dommy "1.1.0"]

Upgrading to 1.0.0+ from 0.X.Y

Version "1.0.0" includes breaking API changes. Here's a quick overview of what's changed:

  • dommy.template namespace and all related templating features (node, deftemplate, etc) have been removed from the library.
  • Simplified namespace structure. Everything in dommy.macros and dommy.attrs has been moved into dommy.core

See CHANGELOG.md or #85 for more details.

If you are looking for hiccup-style templating features, check out https://github.com/jeluard/hipo/

Selection

DOM nodes are selected using macros, which expand to the correct native dom calls. Because selectors don't wrap returned nodes, there is a distinction between single and multiple selections. A selector can be a keyword, string or vector.

(ns foo.bar
  (:require 
    [dommy.core :refer-macros [sel sel1]]))

(sel1 :body) ; => document.body
(sel1 :#header) ; => document.getElementById("header")
(sel1 ".todo") ; => document.getElementsByClassName("todo")[0]

(sel [:#todos :li]) ; => document.querySelectorAll("#todos li")

Sometimes its useful to specify the base node from which the selection takes place.

(sel1 todos-element :.todo)

DOM Manipulation

Inspired by jQuery, but adapted to be functional in order to better fit with ClojureScript core.

(dommy/append! (sel1 :#todos) todo-element)

(doseq [todo (sel :.todo)]
  (dommy/add-class! todo :complete))

(map dommy/text (sel :.todo))

Functions that modify take the target node as their first argument, and return the same modified node, allowing the use of threading macros to accomplish jQuery-like chaining.

(-> (sel1 :#my-button)
	(dommy/remove-attr! :disabled)
	(dommy/add-class! :active)
	(dommy/set-text! "Click me!"))

(->> (sel :.image)
	 (filter #(> (dommy/px % :width) 500))
	 (map #(dommy/add-class! % :big-image)))

Events

Dommy's event API closely resembles the native JavaScript API.

(ns foo.bar
  (:require
    [dommy.core :as dommy :refer-macros [sel1]]))

(defn click-handler [e]
    (.log js/console "You clicked my button! Congratulations"))

(dommy/listen! (sel1 :#my-button) :click click-handler)

(dommy/unlisten! (sel1 :#my-button) :click click-handler)

If the first argument to listen! is a sequence, the handler will delegate events to the selected element defined by the sequence. A special property selectedTarget added to the event specifies the element selected.

(defn todo-click-handler [e]
  (.log js/console "The clicked todo is" (.-selectedTarget e)))

(dommy/listen! [todos-element :.todo] :click todo-click-handler))

Testing

For all pull requests, please ensure your tests pass (or add test cases) before submitting.

$ lein cljsbuild test

License

Copyright (C) 2014 Prismatic

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

dommy's People

Contributors

aamedina avatar aiba avatar aria42 avatar b3nj0 avatar ccfontes avatar cpetzold avatar djpowell avatar ghostandthemachine avatar hsalokor avatar ianconsolata avatar ibdknox avatar ideal-knee avatar jmgimeno avatar justinhj avatar koddsson avatar laughinghan avatar loganlinn avatar malcolmsparks avatar mpenet avatar mva avatar nbeloglazov avatar okal avatar purcell avatar rm-hull avatar starvinraven avatar timvisher avatar w01fe 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  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

dommy's Issues

interested in a dispatch! function?

Was looking for the companion to listen! just now and didn't find it. I'd be happy to write something up if you'd be interested in including that in dommy.

attr sel1 returns old value of input field

When I change the value of an input field the value returned is the original value, not the new value. For example running the js below returns the new value:

document.getElementById("test").value

But the cljs code below returns the old value:

(dommy/attr (sel1 :#test) :value)

Is there something I need to do to refresh it, or am I misunderstanding something?

Android 4.0 stock browser compatibility with Dommy?

We are attaching click handler events but for some reason on older android 4.0 stock browsers they do not seem to attach properly.

On Android 4.1 and higher everything is working fine:

(dommy/listen! elem type callback)

any thoughts or testing/compatibility info for these versions of android?

Yes old versions of android have crufty browser engines!

deftemplate

I'm wondering if deftemplate should explicitly reference the non-compiled version of node, and a sibling macro created defctemplate that explicitly references the compiled version of node. Perhaps these two macros could be put in a separate file?
Right now you can't use deftemplate with the compiled and non-compiled versions of node, which seems like a shortcoming.

Compilation warnings on Clojure 1.7

When I try to compile cljs with Clojure 1.7, I see a bunch of warnings like this:

WARNING: Use of undeclared Var dommy.template/->node-like at line 37 file:/Users/sritchie/.m2/repository/prismatic/dommy/0.1.3/dommy-0.1.3.jar!/dommy/attrs.cljs

I'm guessing that requiring dommy.template in that namespace will fix this up.

Binding

Hi,
is there any one (two) -way binding?
Thanks.

html character entities when constructing node?

I tried something like:

(defn- mk-node []
  (node [:p.flash " "])

then

(replace! (sel1 :body) (mk-node))

I see a literal " " rather than a space. Same with • or ©, etc, etc.

Principal-of-least-surprise suggests those should actually render properly, but I'm okay with there being some other way to do this.

(set-html! (sel1. :.flash) "message • here")

works just fine. However, using set-text! seems to quote the character entities. Might the node macro need to treat that text as HTML or something?

append! requires a DOM node, documentation says otherwise

In the README file the following example is given:

(dommy/append! (sel1 :#todos) [:.todo "Eat some cake"])

This doesn't work since append! expects a DOM Node:

Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.

Either the documentation should be fixed or append! should accept hiccup-like markup.

Suggestion: listen-chan!

listen-chan! could either set up a listen that writes to a provided channel, or create the channel itself. The latter is more convenient in the usual case, the former is more desirable in the general case.

dommy breaks when Polymer is in use

I have no idea whose fault this is, but I want to file the ticket so it's at least known. Whenever I have polymer enabled in Chrome, (dommy/append! (sel1 :body) "foo") fails, with the following error:

"Don't know how to make node from: #<[object HTMLBodyElement]>"

If I use (sel1 :#mybod) (or some other way to get the body), it works.

Maybe Polymer somehow changes the semantics of "document.body"?

To be specific, I'm only including Polymer's platform/platform.js in order to get this behavior.

Delegated event handling

Is there any way to do delegated event handling, a la jQuery .live(), in Dommy? I looked through core.cljs, and live-listener, from the name, looked like it, but my reading of the source suggests that isn't the case.

An unrelated frustration, probably deserving an issue of its own, is the absence of tagged releases. It means I can't go back to v0.1.2 on Github, which my team uses, and look up the implementation of, say, live-listener, for the specific version.

Add support for Custom Elements

Custom Elements is a new w3c specification that introduces a new API to create DOM element: document.createElement(localName, typeExtension). This API reflects a new html syntax <button is="my-button"></button> where button would be the localName and my-button the typeExtension.

The equivalent hiccup syntax [:button {:is "my-button"}] should generate the proper DOM call when used with dommy to support this spec as setting is as an attribute (current behavior) has no effect.

Selector strings need escaping

Query selectors must use css syntax, which means things like semicolons and backslashes need a backslash to precede them.

Example where this causes failure:

(sel "#:0.inp")

This will produce a SYNTAX_ERR (== DOM Exception 12). The crazy-looking ":0.inp" is the typical format of ids produced by goog.ui.Component/makeId which are regularly inserted into id attributes of dom elements (which is how it bit me).

An at least partial fix is to use an escaping function like this (cljs):

(def requires-css-escaping #"(?:^[^a-zA-Z]|[\u0000-\u002c\u002e\u002f\u003a-\u0040\u005b-\u005e\u0060\u007b-\u009f])")
(defn escape-css-char [c] (str \\ (.. c (charCodeAt 0) (toString 16)) \space))

(defn css-escape [s] (clojure.string/replace s requires-css-escaping escape-css-char))

And then patch dommy.core/selector:

(defn selector [data]
  (cond
   (coll? data) (clojure.string/join " " (map selector data))
   (string? data) (name data)
   (keyword? data) (if-let [prefix (some #{\# \.} (aget (name data) 0))]
                             (str prefix (css-escape (subs (name data) 1))
                             (css-escape (name data)))

I think dommy.macros/selector will need a similar transformation.

However you can only safely use this on keywords since strings may use css characters for their intended meaning. This argues for making "css-escape" or "selector-escape" a public function users can use.

Event listener for window "broken"

Previously, with Clojurescript r1853, the following worked:

(listen! js/window :load f)

However as of 1909 (and maybe before) this fails because js/window does not implement the INamed interface:

Doesn't support name: [Object object]

This is as much as I can tell based on a reading of the diff between the two revisions.

Request for CLJS version doc

Hello. Naturally things are continually shifting when using a stack consisting almost entirely of pre-release software... but it would be helpful to have a few words here (or better yet, in the README) about what version(s) of CLJS Dommy is believed to work with.

defnode macro

Can you please add the following macro.

(defmacro defnode [name data]
  `(def ~name
     (node ~data)))

Tagged releases

Would it be possible to do tagged releases, to make navigation of the source code on Github easier? #90

Any plan to cut a release?

Release 0.1.2 is pretty old and there are a number of important fixes in master.
Any plan to cut a release soon?

template.cljs extends prototypes that don't exist in IE8

Is IE8 intended to be supported?

In IE8, js/Document doesn't exist (it uses js/HTMLDocument instead).
Also things like js/SVGElement don't exist, which causes extend-protocol to throw a null pointer exception.
The fix to #28 probably exacerbated this.

Would you be interested in a patch to test for the existence of some of these types before attempting to extend them?

set-style! padding doesn't work with negative values

Hello,

I am trying to do this:

(dommy-attr/set-style! el :padding-top "-3px")

but it doesn't take the negative value, it works only for positive ones, tried as well with margin-top and it worked, so I switched to margin, just wanted to report this behaviour

doesn't recognize identifiers with slashes

id's or classes that have a / character aren't processed. (This is usually caused in clojure by accidentally using name as a generic keyword-to-string function.)

Note this is a legal character in html5: http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute

I'm assuming not all characters can easily be supported, but perhaps this is an easy fix.

A solution would be something a function like (subs (str :abc) 1), but there may be something better.

:style attribute chokes on string value

I'm stumbling across this when I am taking HTML generated by existing code and run it through template/node. Input like [... {:style "background-color: lime"} ...] leads to an exception along the lines of name not supported, because attr/style-str assumes that its input is always a map.

If it's ok with you I can provide a pull request that changes style-str to return its argument unchanged if it is a string.

"PersistentArrayMap.fromArray is not a function" when requiring dommy.core

This is literally my first hour with Clojure*, so I could be doing something stupid, but if I add (:require [dommy.core :as dommy]), I get the following JavaScript error during build: "PersistentArrayMap.fromArray is not a function". This prevents me from testing out dommy/listen! .

I am using lein-cljsbuild 0.3.2, which uses ClojureScript 0.0-1806.

I am able to use the sel and sel1 macros without any issue so far, as long as I leave out that :require.

deftemplate requires dommy.core import

Hi,

I was updating from 0.0.2 to 0.1.0 and noticed some breakage related to the deftemplate macro and inline styles. The compile-add-attr! macro refers to dommy.core/style-str, which leads to:

Uncaught TypeError: Cannot read property 'style_str' of undefined
if(cljs.core.truth_(cljs.core.ObjMap.fromObject(["\ufdd0'width"], {"\ufdd0'width":"100%"}))) {
        dom3877.setAttribute("style", dommy.core.style_str.call(null, cljs.core.ObjMap.fromObject(["\ufdd0'width"], {"\ufdd0'width":"100%"})))

Workaround for this is to require dommy.core somewhere in your application manually. Shouldn't the deftemplate macro work independently, though?

Huge number of warnings

Using the latest version of clojurescript, I get alot of warnings similar to this:

WARNING: Use of undeclared Var dommy.template/->node-like at line 234 file:/Users/skinney/.m2/repository/prismatic/dommy/0.1.3/dommy-0.1.3.jar!/dommy/attrs.cljs

Crate Dependency?

Just started playing with this library, and crate was downloaded. I'm on Leinengin 2. Is that suppose to happen?

Question: Domina and Dommy

Hi,

looking at HTML/DOM libraries I have come across dommy and domina, both of which seem to have similar scopes of application. Is there a reason why they are different projects?

Length of children

Hey guys,

Currently (count (children (dommy/sel1 :body))) throws [object HTMLCollection] is not ISeqable. Is there an easy way to make it so that it is ISeqable?

Cheers!

Prose documentation

Would it be possible to setup a help site, with examples, and detailed description of API functionality? I'd be happy to contribute to that, given the framework for it. I've only been writing Clojure/ClojureScript for about a week now, so I don't know if it's typical in the Clojure community to read the source code when you're getting started with a lib ๐Ÿ˜„

Most of the SVG tags are missed

Your definition

(def +svg-tags+ #{"svg" "line" })

does not include most of the svg tags.

The next definition completes the set.

(def +svg-tags+ #{"svg" "g" "rect" "circle" "clipPath" "path" "line" "polygon" "polyline" "text" "textPath"})

And that's all !!

Thanks,

Juan Manuel

Browser support matrix

Is there a list or matrix anywhere showing which browsers dommy does and does not support, and which features it supports on which browsers (and, more importantly, which it does not)?

Click Events do not work

I just started using dommy the other day, and the first thing I tried to do was use it to detect when a button was pressed and append text somewhere on the page. The problem is, dommy doesn't appear to listen for click events, or at least call the handler for it. My site.cljs looks like this:
(ns site
(:require
[dommy.utils :as utils]
[dommy.core :as dommy])
(:use-macros
[dommy.macros :only [node sel sel1]]))
(defn test [](dommy/append! %28sel1 :#topbar%29 %28node [:p "test"])))
(dommy/listen! (sel1 :#Home) :click test)

And my html file looks like this:
http://pastebin.com/7718eTGV
When I click on the home button, the word test should be added to the

tag, but it is not. However, calling site.test(); from the javascript console makes a new with the same id as the original one and adds the word test to that.

Is this a bug, or simply user error?

Type hinting for predicates

Predicates should have a ^boolean type hint so that they can be properly optimized by the ClojureScript compiler.

Listen to keypress

There is a way to listen for a key{press-down-up} ?

I haven't found it...

Listening to js/window :load breaks with :advanced optimizations

(dommy/listen! js/window :load (fn [_] (println "meow")))

That works fine up to :simple optimizations, but breaks once you go higher. I've found that the issue also happens when selecting the body as well.

(dommy/listen! (sel1 :body) :load (fn [_] (println "meow")))

So far, I haven't found anything in dommy that works, with :advanced, for listening to onload. As a replacement, I've been using a more primitive approach.

(aset js/window "onload" (fn [_] (println "meow")))

Once this has been setup, all other dommy calls I'm making seem to work just fine. The indication here, I gather, is that the issue is with :load listening.

Adjacent nodes

Why is the following not possible?

[[:div#first "first"]
 [:div#second "second"]]

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.