Adzerk
DiscourseIRCSlackWikiCode
Hoplon, a ClojureScript Web Framework

Hoplon

ClojureScript Web Framework

Get Started

Clojure and ClojureScript, everywhere.

Hoplon is a set of Clojure and ClojureScript libraries that pave over the web's idiosyncrasies and present a simpler way to design and build single-page web applications. Learn more on our wiki.

  • Custom Elements iconCustom HTML elements are regular functions and can be created and composed functionally with HLisp
  • Spreadsheet IconSpreadsheet-like dataflow with the Javelin ClojureScript library. Intuitively model reactive behavior using cells and formulas.
  • Castra IconInteract with the server with the Castra Clojure and ClojureScript library. Define functions on the server, call them from the client.

A simple custom element

Elements and custom elements are regular functions. The function below, loud, accepts any number of children. It constructs and returns a div containing the uppercased children.

(defn loud [& children]
  (div :css {:text-transform "uppercase"} children))

(loud "Lisp Can Do It")
Lisp Can Do It

A stateful custom element

In this example, the timer function initializes a Javelin input cell and schedules it for periodic update using window.setInterval. The text of the returned div is attached reactively to seconds through a formula cell created using cell=.

defelem is a convenience macro for creating functions that handle attribute arguments naturally.

(defelem timer [attrs children]
  (let [start   (or (:start attrs) 0)
        seconds (cell start)]
    (.setInterval js/window #(swap! seconds inc) 1000)
    (div attrs (cell= (str "Seconds Elapsed: " seconds)))))

;; our first timer will start at 0 and count up
(p (timer :style "color: green;" :start 0))

;; start 3 more timers, each with different starting values
(apply ol (map li (for [r (range 1 4)] (timer :start r))))

Seconds Elapsed: 0
  1. Seconds Elapsed: 1
  2. Seconds Elapsed: 2
  3. Seconds Elapsed: 3

An application

In this final example, todo-list is a function that returns an instance of a simple todo list application. The application responds to user input by updating input cell values when DOM events occur.

The :change event on the text input is attached to a function that updates the new-item input cell as keystrokes occur.

The :click event on the button is attached to a function that appends the value of new-item to the end of todo-items inside a dosync. dosync is a transactional construct that suspends the propagation of new values through the cell graph while updating multiple cells.

todo-items are rendered as li elements using the loop-tpl macro. loop-tpl efficiently maps dynamically-sized collections to DOM nodes.

(defelem todo-list [{:keys [title]} _]
  (let [todo-items (cell [])
        new-item   (cell "")]
    (div
      (h3 (or title "TODO"))
      (ul
        (loop-tpl :bindings [todo todo-items]
          (li todo)))
      (input :type "text"
             :value new-item
             :change #(reset! new-item @%))
      (button :click #(dosync
                       (swap! todo-items conj @new-item)
                       (reset! new-item ""))
        (text "Add #~{(inc (count todo-items))}")))))

(todo-list :title "TODO List")

TODO List

    Adzerk
    Made at Adzerk | Ad serving infrastructure for awesome companies
    Adzerk on GithubSite Source
    Copyright © 2015 Alan Dipert, Micha Niskin, Joshua Smith