Giter Club home page Giter Club logo

dommy's Introduction

dommy

Dommy is no-nonsense ClojureScript templating based on Clojure's Hiccup html templating library. It is similar to Crate, but is much faster (3-4x, see the performance comparison test dommy.template-perf-test). It also has a compile-time macro component that is significantly (5x) faster, but requires most of your DOM structure to be expressed as nested vector literals (see 'Compile Macros' below).

Templating Usage

(ns awesome-webapp
 (:require [dommy.template :as template]))

(template/node
  [:div#id.class1
    (for [r (range 2)] 
      [:span.text (str "word" r)])])
      
=> [object HTMLElement]

(.-outerHTML *1)

=> "<div id=\"id\" class=\"class1\"><span class=\"text\">word0</span><span class=\"text\">word1</span></div>"

Classes as a vec/sec

(template/node [:div {:classes ["foo" "bar" "baz"]}])

(.-outerHTML *1)

=> "<div class=\"foo bar baz\"></div>"

Inline style as a map

(template/node
  [:span
    {:style
      {:color "#aaa"
       :text-decoration "line-through"}}])

(.-outerHTML *1)

=> "<span style=\"color:#aaa; text-decoration:line-through;\"></span>"

Extensible

Thanks to @ibdknox you can have custom view logic for your deftype or defrecord by implementing the PElement protocol:

(defrecord MyModel [data]
   dommy.template/PElement
   (-elem [this] [:p (str "My data " data)]))

(dommy.template/node (MyModel. "is big"))   
=> "<p>My data is big</p>"

Compile Macros (Experimental)

There is a also a macro DOM building function which can be significantly faster if most of your template structure can be expressed nested vector literals. It's really worth taking a look at the code and understanding what will and won't be done at compile time (see ns dommy.template-compile). Here's an example:

(defn simple-template [word]
  (dommy.template-compile/node
    [:div#id.class1
	  [:span.text word]]))

Alternatively, you can use the deftemplate macro:

(deftemplate simple-template [word]
  [:div#id.class1
	  [:span.text word]])

These macros will compile this template data into much more efficient JavaScript

function simple_template(word) {
 var dom56633 = document.createElement("div");
  dom56633.className = "class1";
  dom56633.setAttribute("id", "id");
  dom56633.appendChild(function() {
    var dom56634 = document.createElement("span");
    dom56634.className = "text";
    dom56634.appendChild(dommy.template._elem.call(null, word));
    return dom56634
  }());
  return dom56633
}
  

The node macro will 'compile' the structure to efficient JavaScript recursively as long as data is expressed as literals.

Type-Hinting Template Macros

One caveat of using the compile-macro is that if you have a compound element (a vector element) and want to have a non-literal map as the attributes (the second element of the vector), then you need to use ^:attrs meta-data so the compiler knows to process this symbol as a map of attributes in the runtime system. Here's an example

(dommy.template-compile/node  [:a ^:attrs (merge m1 m2)])

Again this is not necessary when the attribute map is a literal (that map can even contain symbolic keys or values).

You can also type-hint a symbol as ^:text which will enusre the macro appens the symbol as a text node and doesn't use the runtime templating.

For instance, this template

(deftemplate simple-template [[href anchor]]
    [:a.anchor {:href href} ^:text anchor])

Will generate the following Javascript:

function simple_template(p__13888) {
    var vec__13891 = p__13888;
    var href = cljs.core.nth.call(null, vec__13891, 0, null);
    var anchor = cljs.core.nth.call(null, vec__13891, 1, null);
    var dom13892 = document.createElement("a");
    dom13892.className = "anchor";
    if(cljs.core.truth_(href)) {
        dom13892.setAttribute("href", href)
    }else {
    }
    dom13892.appendChild(document.createTextNode(anchor));
    return dom13892
}

License

Copyright (C) 2013 Prismatic

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

dommy's People

Contributors

aria42 avatar cpetzold avatar ghostandthemachine avatar ibdknox avatar mpenet avatar mva avatar purcell avatar

Watchers

 avatar  avatar

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.