defromeo

First steps with Hoplon

Hoplon is great framework. I hope it will change our standart way in building web.

In next a few blog posts I will create Kalah game, and I’ll post my adventure here. To be prepared you should read excellent Getting Started Hoplon.io.

So today our task is create main menu and some blocks which we will see when certain menu chosen. These menu items will be connected with hash. Result is here.

HTML

We start with simple template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/hoplon">
  (page "index.html"
    (:require
      [tailrecursion.hoplon.util :as hutil]))
</script>
<html>
<body>
  <ul>
    <li>
      <a href="#/">Home</a>
    </li>
    <li>
      <a href="#/about">About</a>
    </li>
  </ul>

  <div>Home</div>
  <div>About</div>
</body>
</html>

Notice, we require tailrecursion.hoplon.util and will use route-cell from it for creating cell updated with current hash:

route-celllink
1
2
3
4
(defn route-cell [msec default]
  (let [hash  #(.-hash (.-location js/window))]
    (with-let [ret (cell (hash))]
      (interval #(let [h (hash)] (reset! ret (if (empty? h) default h))) msec))))

In our case with-let macro first create cell with current hash (cell (hash)), then run setInterval with function which will update our cell, after hash cell will be returned.

with-letlink
1
2
3
4
5
(defmacro with-let
  "Binds resource to binding and evaluates body.  Then, returns
  resource.  It's a cross between doto and with-open."
  [[binding resource] & body]
  `(let [~binding ~resource] ~@body ~binding))
intervallink
1
(defn interval  [f msec]  (.setInterval js/window f msec))

So with this library we only need in our index.html.hl:

1
(def route (hutil/route-cell 100 "#/"))

Links highlighting

I’m using bootstrap, and we need set active class for current menu item. So we should use do-class atribute which takes cell with hash-map like {:active true}do-class='{ { (cell {:active true}) }}'.

To depend on current hash we change it to formula cell:

1
2
3
<li do-class='{ {  (cell= {:active (= "#/" route)})  }}'>
  <a href="#/">Home</a>
</li>

We can make a little easy by creating boolean help-cell (there also example of macro defc=):

1
2
(def is-home? (cell= (= "#/" route)))
(defc= is-about? (= "#/about" route))

So now we can write links like this:

1
2
3
<li do-class='{ {  (cell= {:active is-about?}) }}'>
  <a href="#/about">About</a>
</li>

Hidden Content

Now we need only hide with hidden class our div which is not connected to current hash path.

And this is exactly like in above code with menu items (with and without our helper):

1
2
3
4
5
6
7
<div do-class='{ {  (cell= {:hidden (not= "#/" route)}) }}'>
Home
</div>

<div do-class='{ {  (cell= {:hidden (not is-about?)}) }}'>
About
</div>

That is all for now.

All sources