README.md

# Drab, the Server-side jQuery

Manipulate browser DOM objects directly from Elixir/Phoenix. No Javascript programming needed anymore!

## Teaser

* Client side:

```html
<div class="progress">
  <div class="progress-bar" role="progressbar" style="width:0%">
  </div>
</div>
<button drab-click="perform_long_process">Click to start processing</button>
```

* Server side:

```elixir
def perform_long_process(socket, dom_sender) do
  steps = MyLongProcess.number_of_steps()
  for i <- 1..steps do
    MyLongProcess.perform_step(i)
    # update the progress bar after each of MyLongProcess steps
    socket 
      |> update(
          attr: "style", 
          set: "width: #{i * 100 / steps}%", 
          on: ".progress-bar")
      |> update(
          :html,         
          set: "#{Float.round(i * 100 / steps, 2)}%", 
          on: ".progress-bar")
  end
  socket |> insert(class: "progress-bar-success", into: ".progress-bar")
end
```

## Warning: this software is still experimental!

### See [Demo Page](https://tg.pl/drab) for live demo and description.

## Installation

  So far the process of the installation is rather manually, in the future will be automatized.

  1. Add `drab` to your list of dependencies in `mix.exs` in your Phoenix application and install it:

```elixir
def deps do
  [{:drab, git: "https://github.com/grych/drab.git"}]
end
```

```bash
$ mix deps.get
$ mix compile
```

  2. Add `jquery` to `package.json`:

```json
"dependencies": {
  "jquery": ">= 3.1.1"
}
```

  3. Add jQuery as a global at the end of `brunch-config.js`:

```javascript
npm: {globals: {
  $: 'jquery',
  jQuery: 'jquery'
}}
```

  4. And install it:

```bash
$ npm install && node_modules/brunch/bin/brunch build 
```

  5. Initialize Drab client library by adding to the layout page (`web/templates/layout/app.html.eex`)

```html
<%= Drab.Client.js(@conn) %>
```
    
    just after the following line:

```html
<script src="<%= static_path(@conn, "/js/app.js") %>"></script>
```
    
  6. Initialize Drab websockets by adding the following to `lib/endpoint.ex`:

```elixir
socket Drab.config.socket, Drab.Socket
```

Congratullations! You have Drab installed and you can proceed with your own Commanders.

## Usage

All the Drab functions (callbacks, event handlers) are placed in the module called `Commander`. Think about it as a controller for the live pages. Commanders are similar to Phoenix controllers and should be placed in `web/commanders` directory.

To enable Drab on the specific pages, you need to add the directive `use Drab.Controller` to your application controller. 

Remember the difference: `controller` renders the page while `commander` works on the live page.

  1. Generate the page Commander. Commander name should correspond to controller, so PageController should have PageCommander:

```bash
$ mix drab.gen.commander Page
* creating web/commanders/page_commander.ex

Add the following line to your Example.PageController:
    use Drab.Controller 
```

  2. As described in the previous task, add `Drab.Controller` to your page Controller (eg. `web/controllers/page_controller.ex` in the default app):

```elixir
defmodule DrabExample.PageController do
  use Example.Web, :controller
  use Drab.Controller 

  def index(conn, _params) do
    render conn, "index.html"
  end
end    
```

  3. Edit the commander file `web/commanders/page_commander.ex` and add some real action - the `onload` callback which fires when the browser connects to Drab.

```elixir
defmodule DrabExample.PageCommander do
  use Drab.Commander, onload: :page_loaded

  # Drab Callbacks
  def page_loaded(socket) do
    socket 
      |> update(:html, set: "Welcome to Phoenix+Drab!", on: "div.jumbotron h2")
      |> update(:html, 
          set: "Please visit <a href='https://tg.pl/drab'>Drab</a> page for more examples and description",
          on:  "div.jumbotron p.lead")
  end
end
```

Function `update/3` (shorthand for `Drab.Query.update/3`) with `:html` parameter sets the HTML of DOM object, analogically to `$().html()` on the client side.

Finally! Run the phoenix server and enjoy working on the Dark Side of the web.

### The code above is available for download [here](https://github.com/grych/drab-example)

## Drab Events

* Client-side: assign the events directly in HTML, using `drab-[event]='event_handler'` attribute, when `event` is the event name (currently: click, change, keyup, keydown) and `event_handler` is the function name in the Commander. This function will be fired on event. Example:

```html
<button drab-click='button_clicked'>Clickme!</button>
```

* Server-side: when clicked, this button will launch the following action on the corresponding commander:

```elixir
defmodule Example.PageCommander do
  use Drab.Commander

  # Drab Events
  def button_clicked(socket, dom_sender) do
    socket 
      |> update(:text, set: "alread clicked", on: this(dom_sender))
  end
end
```

As you probably guess, this changes button description (`Drab.Query.update/3` used with `:text`).

## What now?

Visit [Demo Page](https://tg.pl/drab) for a live demo and more description.

Visit [Docs with Examples](https://tg.pl/drab/docs) - documentation with short examples.

## Contact

(c)2016 Tomek "Grych" Gryszkiewicz, 
<grych@tg.pl>