Drab: Phoenix library for server-side DOM access

Tags: #<Tag:0x00007fc830347038> #<Tag:0x00007fc830346ea8> #<Tag:0x00007fc830346d68> #<Tag:0x00007fc830346c28>


@Eiji - I’ve finished the toggle. But it does more - does not just switch between two values, but you can specify more than two. Every time it is launched, it changes the value to the next on the list (or first if it reach the list end).

socket |> update(:class, set: ["btn-success", "btn-danger", "btn-primary"], on: "#btn")

Check out the live examples here: https://tg.pl/drab/docs#Drab.Query


Your API looks great!
Did you think about writing JS library with similar API (without socket as first argument)? I think it’s really clear and easy to learn. I can do this too if you don’t have any copyrights restrictions.


Drab 0.2.0, just released, is now modular. This means that Drab.Query and Drab.Modal are not obligatory - you may specify the list of modules to use on the Commander:

use Drab.Commander, modules: [Drab.Query]

In your case, when you need to have only basic functions execjs, you’ll use:

user Drab.Commander, modules: []

This will load the Drab.Core (which is neccessary and is always included) only.

Check out more here https://tg.pl/drab/nojquery - the small description or download the sandbox project (https://github.com/grych/drab_example_nojquery).

There is more: this architecture is open for extending Drab. You may create your own module (for example for react) with corresponding JS template and put it in your project. Let’s make Drab growing!


Go on! Just give a note that the idea is borrowed from Drab. I am not planning to do any JS libraries myself :wink:


@grych, those Drab modules look really nice, looking forward to play a bit with this and improve my react-poc this weekend.

Thank you very much!


@grych: I have new idea.
Did you already have implemented events?
You could do something like:

alias Drab.Event

Event.add(:method, [target_name: "target value"], [attr_name: "attr value"], &callback/3)

# Examples:

Event.remove(callback: &callback/3) # remove all events with specified callback
Event.remove(target: [id: "#my_special_btn"]) # remove all events that affects specified element
# ...

defmodule MyApp.Callbacks.MySpecialBtn do
  # maybe GenStage consumer?

  def on_delete_btn_class(socket, btn, changes) do
    # btn is map/struct for target button - struct from HTML element
    # changes is for example: {:deleted, :css, "btn"}

Event.add(:delete, [class: "btn"], [id: "#my_special_btn"], &MyApp.Callbacks.MySpecialBtn.on_delete_btn_class/3)

Add force: true (default to false) if our target matches another selector

alias Grab.Event

Event.add(:update, [], [class: "btn"], &callback/3, force: true)
# add event for all updates on elements with class: btn
update(socket, style: "font-size", set: 6, unit: :px, on: "#button")

so if element with #btn has class btn and we set force: true then we should start callback


@grych this looks neat!

One thing, however, your SSL seems broken. The demo/web site shows scary warning in Chrome :wink:


Thanks for info, looks like StartCom certificates are no longer on the Chrome Root CA list - https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html

Does anyone know any other free certificate issuer?

BTW the reason why I use SSL with the demo page is that some proxy servers does not allow websockets over http.


StartCom is utterly horrible horrible horrible, never use them!

For SSL there is no reason not to be using Let’s Encrypt. :slight_smile:


@OvermindDL1, thanks! I am going to update my certs.


It is pretty high security, has to be renewed every month, but there are automation things galore for that for every web server or even just to add as a cron job. :slight_smile:

/me is lazy and just uses a cron job one to update nginx certs.


I think the longest you can set it is 3 months nowdays.


@grych I like both the API and the idea very much. It’s like the RJS templates from good 'ol days Rails 2.x, but on steroids thanks to persistent nature of Phoenix sockets.

One must think of limitations and downsides of going with this approach before choosing it over say API + React, however I think it’ll do well for most applications. And I guess you can throw in some JavaScript where it does not do good enough job.

I usually deal with a lot of forms, and the dynamic bits on these forms can be like inputs that format say phone number, or postcode as you type. I think writing those as tiny react components would be great fit. Drab would still treat those as normal input when collecting the data server-side.

On a positive side, I am mostly thinking about the code you no longer have to write. Less code == less bugs.

On a negative side, I see that the coupling between back-end event handlers and UI will make stuff like UI upgrades slightly more complex. I also have a hunch you can easily write really bad spaghetti, unmaintainable code this way. I remember the problems we had with RJS and how eventually the Rails community decided to abandon the idea.

Either way, I will give it a shot really soon. The current front-end situation is ridiculous. This is a step back, but a tactical retreat rather than escape :).


thanks for the idea! I need to think about it. It is quite easy to implement it on the server side, but to be consistent it should work on the client side as well. So event should be launched after change in javascript as well.


the big picture is to keep everything on the server side. I started with DOM interfaces, Drab.Query module simple translates Elixir functions (select, update etc) to corresponding jQuery methods and executes it on the client side.

Why not to create a similar module for, for example, React? So you could build the whole interface in Elixir.


@grych the demo site throws 404 at the exact moment I started showing drab to my coworkers… :wink:


Ops, sorry my fault. I’ve changed the server over the weekend and have an issues with elixir/erlang installed from the package (Debian) - memory is leaking like hell. I am installing it from the source now. Please check in 1/2 hour, should be working again.


no worries, it was quite funny when colleague asked “I wonder how reliable it will be” and then bang ;D


It is back now, but be warned it may crash again :slight_smile:


This is what concerns me as well.
In theory, its reliability should be the same as Phoenix/Websockets, but you never know. This software still needs a lot of work and test. Anyway, enjoy!