drab v0.6.0-pre.1 Drab.Core
Drab Module with the basic communication from Server to the Browser. Does not require any libraries like jQuery, works on pure Phoenix.
defmodule DrabPoc.JquerylessCommander do
use Drab.Commander, modules: []
def clicked(socket, payload) do
socket |> console("You've sent me this: #{payload |> inspect}")
end
end
See Drab.Commander
for more info on Drab Modules.
Events
Events are defined directly in the HTML by adding drab-event
and drab-handler
properties:
<button drab-event='click' drab-handler='button_clicked'>clickme</button>
Clicking such button launches DrabExample.PageCommander.button_clicked/2
on the Phoenix server.
There are few shortcuts for the most popular events: click
, keyup
, keydown
, change
. For this event
an attribute drab-EVENT_NAME
must be set. The following like is an equivalent for the previous one:
<button drab-click='button_clicked'>clickme</button>
Normally Drab operates on the user interface of the browser which generared the event, but it is possible to broadcast
the change to all the browsers which are currently viewing the same page. See the bang functions in Drab.Query
module.
Event handler functions
The event handler function receives two parameters:
socket
- the websocket used to communicate back to the page byDrab.Query
functionssender
- a map contains information of the object which sent the event; keys are binary strings
The sender
map:
%{
"id" => "sender object ID attribute",
"name" => "sender object 'name' attribute",
"class" => "sender object 'class' attribute",
"text" => "sender node 'text'",
"html" => "sender node 'html', result of running .html() on the node",
"value" => "sender object value",
"data" => "a map with sender object 'data-xxxx' attributes, where 'xxxx' are the keys",
"event" => "a map with choosen properties of `event` object"
"drab_id" => "internal"
"form" => "a map of values of the sourrounding form"
:params => "a map of values of the sourrounding form, normalized to controller type params"
}
The event
map contains choosen properties of event
object:
altKey, data, key, keyCode, metaKey, shiftKey, ctrlKey, type, which,
clientX, clientY, offsetX, offsetY, pageX, pageY, screenX, screenY
Example:
def button_clicked(socket, sender) do
# using Drab.Query
socket |> update(:text, set: "clicked", on: this(sender))
end
sender
may contain more fields, depending on the used Drab module. Refer to module documentation for more.
Form values
If the sender object is inside a
Link to this section Summary
Functions
Asynchronously executes the javascript on all the browsers listening on the given subject
Bang version of Drab.Core.broadcast_js/3
Synchronously executes the given javascript on the client side
Exception raising version of exec_js/2
Returns the value of the Plug Session represented by the given key
Returns the value of the Plug Session represented by the given key or default
when key not found
Returns the value of the Drab store represented by the given key
Returns the value of the Drab store represented by the given key or default
when key not found
Saves the key => value in the Store. Returns unchanged socket
Helper for broadcasting functions, returns topic for a given controller
Helper for broadcasting functions, returns topic for a given URL path
Helper for broadcasting functions, returns topic for a given topic string.
iex> same_topic("mytopic")
"topic:mytopic"
Finds the DOM object which triggered the event. To be used only in event handlers
Like this/1
, but returns object ID, so it may be used with broadcasting functions
Link to this section Functions
Asynchronously executes the javascript on all the browsers listening on the given subject.
The subject is derived from the first argument, which could be:
socket - in this case broadcasting option is derived from the setup in the commander. See
Drab.Commander.broadcasting/1
for the broadcasting optionssame_path(string) - sends the JS to browsers sharing (and configured as listening to same_path in
Drab.Commander.broadcasting/1
) the same urlsame_commander(atom) - broadcast goes to all browsers configured with :same_commander
same_topic(string) - broadcast goes to all browsers listening to this topic; notice: this is internal Drab topic, not a Phoenix Socket topic
First argument may be a list of the above.
The second argument is a JavaScript string.
See Drab.Commander.broadcasting/1
to find out how to change the listen subject.
iex> Drab.Core.broadcast_js(socket, "alert('Broadcasted!')")
{:ok, :broadcasted}
iex> Drab.Core.broadcast_js(same_path("/drab/live"), "alert('Broadcasted!')")
{:ok, :broadcasted}
iex> Drab.Core.broadcast_js(same_controller(MyApp.LiveController), "alert('Broadcasted!')")
{:ok, :broadcasted}
iex> Drab.Core.broadcast_js(same_topic("my_topic"), "alert('Broadcasted!')")
{:ok, :broadcasted}
iex> Drab.Core.broadcast_js([same_topic("my_topic"), same_path("/drab/live")], "alert('Broadcasted!')")
{:ok, :broadcasted}
Returns {:ok, :broadcasted}
Bang version of Drab.Core.broadcast_js/3
Returns subject.
Synchronously executes the given javascript on the client side.
Returns tuple {status, return_value}
, where status could be :ok
or :error
, and return value
contains the output computed by the Javascript or the error message.
Options
timeout
in milliseconds
Examples
iex> socket |> exec_js("2 + 2")
{:ok, 4}
iex> socket |> exec_js("not_existing_function()")
{:error, "not_existing_function is not defined"}
iex> socket |> exec_js("for(i=0; i<1000000000; i++) {}")
{:error, "timed out after 5000 ms."}
iex> socket |> exec_js("alert('hello from IEx!')", timeout: 500)
{:error, "timed out after 500 ms."}
Exception raising version of exec_js/2
Examples
iex> socket |> exec_js!("2 + 2")
4
iex> socket |> exec_js!("nonexistent")
** (Drab.JSExecutionError) nonexistent is not defined
(drab) lib/drab/core.ex:100: Drab.Core.exec_js!/2
iex> socket |> exec_js!("for(i=0; i<1000000000; i++) {}")
** (Drab.JSExecutionError) timed out after 5000 ms.
(drab) lib/drab/core.ex:100: Drab.Core.exec_js!/2
iex> socket |> exec_js!("for(i=0; i<10000000; i++) {}", timeout: 1000)
** (Drab.JSExecutionError) timed out after 1000 ms.
lib/drab/core.ex:114: Drab.Core.exec_js!/3
Returns the value of the Plug Session represented by the given key.
counter = get_session(socket, :userid)
You must explicit which session keys you want to access in :access_session
option in use Drab.Commander
.
Returns the value of the Plug Session represented by the given key or default
when key not found
counter = get_session(socket, :userid, 0)
You must explicit which session keys you want to access in :access_session
option in use Drab.Commander
.
Returns the value of the Drab store represented by the given key.
uid = get_store(socket, :user_id)
Returns the value of the Drab store represented by the given key or default
when key not found
counter = get_store(socket, :counter, 0)
Saves the key => value in the Store. Returns unchanged socket.
put_store(socket, :counter, 1)
Helper for broadcasting functions, returns topic for a given controller.
iex> same_controller(DrabTestApp.LiveController)
"controller:Elixir.DrabTestApp.LiveController"
Helper for broadcasting functions, returns topic for a given URL path.
iex> same_path("/test/live")
"same_path:/test/live"
Helper for broadcasting functions, returns topic for a given topic string.
iex> same_topic("mytopic")
"topic:mytopic"
Finds the DOM object which triggered the event. To be used only in event handlers.
def button_clicked(socket, sender) do
set_prop socket, this(sender), innerText: "already clicked"
set_prop socket, this(sender), disabled: true
end
Do not use it with with broadcast functions (Drab.Query.update!
, Drab.Core.broadcast_js
, etc),
because it returns the exact DOM object in exact browser. In case if you want to broadcast, use
this!/1
instead.
Like this/1
, but returns object ID, so it may be used with broadcasting functions.
def button_clicked(socket, sender) do
socket |> update!(:text, set: "alread clicked", on: this!(sender))
socket |> update!(attr: "disabled", set: true, on: this!(sender))
end
Raises exception when being used on the object without an ID.