Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dubiousdavid/dominator

Virtual-Dom in ClojureScript
https://github.com/dubiousdavid/dominator

Last synced: 2 months ago
JSON representation

Virtual-Dom in ClojureScript

Awesome Lists containing this project

README

        

# Dominator

[ClojureScript](https://github.com/clojure/clojurescript) + [Zelkova](https://github.com/jamesmacaulay/zelkova) + [Virtual Dom](https://github.com/Matt-Esch/virtual-dom) + ["The Elm Pattern"](http://elm-lang.org/) = Sane Javascript!

Uses [stch-html](https://github.com/stch-library/html) for representing HTML in ClojureScript.

## Features

* Single flow of events.
* Use [core.async](https://github.com/clojure/core.async).
* Use pure functions for updating state and rendering.
* Minimal learning curve (i.e., easier than [Om](https://github.com/swannodette/om)).

## Installation

```clojure
[com.2tothe8th/dominator "0.4.0"]
```

Note: You will need to download the compiled `vdom.js` file to your project directory and reference it in your HTML file.

```bash
wget https://raw.githubusercontent.com/dubiousdavid/dominator/master/vdom.js
```

You will also need to add `:externs ["dominator.js"]` to the compiler options map if using advanced compilation.

## Sample programs

1. [Counter](http://dubiousdavid.github.io/dominator/examples/counter/) ([source](https://github.com/dubiousdavid/dominator/blob/master/examples/counter/src/counter/core.cljs))
2. [Wikipedia](http://dubiousdavid.github.io/dominator/examples/wiki/) ([source](https://github.com/dubiousdavid/dominator/blob/master/examples/wiki/src/wiki/core.cljs))
3. [Mario](http://dubiousdavid.github.io/dominator/examples/mario/) ([source](https://github.com/dubiousdavid/dominator/blob/master/examples/mario/src/mario/core.cljs))

## API Documentation

http://dubiousdavid.github.io/dominator/doc/

## Example Usage

### Overview

In the example below there is a single signal `actions` that all events are put onto. The `sig/reductions` function acts like an unending `reduce` over the `actions` signal. `reductions` takes a pure function, an initial value, and a signal, and produces a signal. `update-model` takes the existing model, the "action" (value from the signal), and returns a new model. The `view` function is mapped over each value from the `model` signal. This function returns a representation of the markup. Finally the markup signal and root element are passed to `render`, which patches the DOM with each value from the signal (uses [requestAnimationFrame](ie.microsoft.com/testdrive/Graphics/RequestAnimationFrame) under the hood).

```clojure
(ns dominator.counter
(:require [dominator.core :refer [render]]
[stch.html :refer [div table tr td input]]
[cljs.core.async :as async :refer [!]]
[dominator.async :as as :refer-macros [forever]]
[dominator.test.util :as util]
[clojure.string :as string]
[cljs.core.match]
[jamesmacaulay.zelkova.signal :as sig]
[jamesmacaulay.zelkova.time :as time])
(:require-macros [cljs.core.match.macros :refer [match]]))

(enable-console-print!)

(def wikipedia-endpoint
"http://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=")

(defn wikipedia [search]
(str wikipedia-endpoint search))

(def query (sig/write-port ""))
(def actions (sig/write-port :no-op))

(defn view [results]
(div
(input :placeholder "Search Wikipedia!"
:oninput #(async/put! query (-> % util/target-value string/trim)))
(ul
(for [result results]
(li result)))))

(def empty-model [])

(defn update-model [model action]
(match action
:no-op model
[:results results] results))

(def queries
(->> query
sig/drop-repeats
(time/debounce 150)
(sig/drop-if string/blank?)
(sig/map wikipedia)
sig/to-chan))

(forever
(let [q (! actions [:results (second result)]))))

(def model (sig/reductions update-model empty-model actions))

(render (sig/map view model) js/document.body)
```