Mod teleview provides live updating server rendered views.
📺
Teleview makes it possible to have server side rendered views, which update on the client. The communication between the teleview and its client-side viewport is done via MQTT topics. Client side teleview viewports subscribe to a renderer, the renderer sends a video like update stream which allows the viewport to gradually update its part of the dom-tree.
{% teleview
type = "<type-name>"
template = "_a_template.tpl"
topic = <an mqtt topic to listen to>
teleview_param = ...
vary = %{
renderer_param: x
...
}
%}
When this scomp is placed on a page, the scomp will ensure the teleview and renderer are started. A teleview can have multiple renderers depending on the situation. A different renderer could be started because of authorization levels. This means different admin and visitor views. Or different views per user id, language and other possibilities.
The scomp will sent a notification ensure_teleview
. An observer can then make sure a teleview process and
a renderer is started. When the renderer is already started, the current renderer state will be added to the
html output of the teleview scomp.
A piece of javascript code will subscribe itself to the update topic of the teleview renderer. This will keep the view updated.
Put a teleview scomp into your tempate
{% teleview
type = "example"
template = "_example_teleview.tpl"
topic = "model/example/event/#"
extra_parameter_a = 100
extra_parameter_b = "hello world"
vary = %{ user_id = m.acl.user }
%}
In the above example a teleview will be started with the parameters given.
A teleview process will subscribe itself to the supplied topics, and a renderer process will be started. It will take care of rendering and sending updates to the client side viewer.
Each renderer can have different parameters so they can render the interface in different languages, for different users, or with a special set of acl settings.
In order to support that two different notifications can be setup on the server side.
The client side teleview component is build with Cotonic. This is a javascript library which acts as middleware. Different components can be added. These components can then communicate by using its broker. The broker provides a MQTT publish subscribe model. Cotonic makes it possible for a page to connect to multiple mqtt brokers. Zotonic uses the Cotonic library. Normally a page opens one mqtt connection to the server from which the page was loaded. This is called the origin.
Teleview Runs as a zotonic module.
Each teleview has its own id and consists of a state process, which manages the subscription to the topics it listens too, and one or more renderer processes which can hold private vary properties used for rendering.
Zotonic High Level Architecture
Anatomy of a Zotonic Module
Teleview Module
[TODO]
observe_teleview_state_init({teleview_state_init, #{ type := <<"example">> }=Args}, Context) ->
%% Return a context which is allowed to subscribe the topics.
Context;
observe_teleview_state_init(_InitArgs, _Context) ->
undefined.
observe_teleview_renderer_init({teleview_renderer_init, #{ type := <<"example">> }=Args}, Context) ->
%% Return a context which allows rendering things.
Context;
observe_teleview_renderer_init(_InitArgs, _Context) ->
undefined.
Returns the current state of a renderer of a teleview.
A teleview with id id
was started.
A teleview with id id
was stopped.
The teleview was reset, possibly because of a crash. It was restarted, meaning that the current state of the teleview viewer has to be reset.
A renderer will send still-watching
messages to its viewers. When it does not
receive a response, the renderer assumes that nobody is interested in updates,
and will stop itself. When a teleview has no more renderers, it will be stopped
too.
The topic on which a renderer broadcasts its update.
patch_type | description |
---|---|
keyframe | A complete rendered tree element. |
cumulative | A diff against the last keyframe. |
incremental | A diff against the last frame. |
A keyframe is the complete, text representation of a teleview. The view can be made visible by a teleview viewport on the client side by placing it in the DOM-tree.
{
"sn": <serial-number>,
"frame": <text>
}
An cumulative update is a patch against the last keyframe of a teleview. It is short for cumulative patch. The view of this frame can be made visible by applying the patch against the text representation of the keyframe with the specified serial number. It will result in a new text representation which can be placed in the DOM-tree. The patched keyframe document is the current frame.
Note Because the patch is made against the keyframe it is possible to skip cumulative updates when the client is too busy. The view will then not be updated. The next cumulative patch can be used to update the view.
{
"sn": <serial>,
"patch": <patch>
}
An incremental update is a patch against the current frame. The view of this frame can be made visible by applying the patch against the text representation of the current frame, and placing it in the DOM-tree. After applying the patch, the resulting text representation will be the new current frame.
Note incremental updates must be applied, when they are skipped, it will not be possible to construct a new current frame by applying patches. The teleview viewer will have to wait for a new keyframe. Because of this drawback, teleview renderer will try to send cumulative updates as often as possible. Only when the patch against the keyframe becomes too complex, or the minimum time between keyframes is passed, an incremental patch will be sent.
{
"sn": <timestamp>,
"patch": <patch>
}
The diff is a list of instructions.
- "c" for copy
- "s" for skip
- "i" for insert
Example:
["c", 100, "s", 51, "i", "<b>Hello World</b>", "c", 57]
Which means, copy 100 characters from the current document to the new, skip 51 characters from the current document, insert "Hello World", and copy 57 characters from the current document to the new one.
The teleview zotonic module is a supervisor. It can start televiews. Televiews are a process which manages the state, and a collection of renderers. The renderers take care of producing a render. Each renderer can have its own ACL and language settings. The state process selects the right renderer for the client side of the teleview.