-
Notifications
You must be signed in to change notification settings - Fork 104
Make your own widget
Widgets provide access to the variable items using javascript code. They consist of Twig/html macros for static display elements or for integration of existing widgets. Dynamic functions can be added using javascript or jQuery mobile code. You should place your own widgets in the dropins/widgets or pages/(yourpages)/widgets folder. Don't use the dropins/widgets folder if you are using the auto page generation function in smarthomeNG plugin "visu_smartvisu" with enabled widget handling since this plugin empties the folder first before putting smarthomeNG plugins widgets there. In smarthomeNG v1.9 this is solved with the new "smartvisu" plugin putting the widgets into dropins/shwidgets.
You can use
/**
..
*/
for comments in your code.
Be aware that pages and widgets cannot have the same name! So if there is a widget called "multimedia.xxx", you have to avoid a multimedia.html in your pages folder! Otherwise you will receive an "Error loading page". As of smartVISU v3.3 this is solved by implementation of a namespace "@widgets" combining the search paths for the widgets. Widgets should then be imported using the namespace since the old importing method is deprecated and will be removed in a later version.
These widgets assemble standard widgets into combined visualisation elements. Here is a simple dimmer widget as example:
The head ("docstring") describes the macro parameters for documentation purposes.
/**
* Standard dimmer with switching and dimming function
*
* @param {id=} unique id for this widget (optional)
* @param {text=} name of the dimmer
* @param {item} an item for switching
* @param {item} an item for dimming
* @param {value=0} the minimum value if the slider is moved to total left (optional, default: 0)
* @param {value=255} the maximum value if the slider is moved to total right (optional, default: 255)
* @param {value=5} step between two values (optional, default: 5)
* @param {image=light_light} the pic for the 'on' state (optional)
* @param {image=light_light} the pic for the 'off' state (optional)
* @param {color=icon1} the color for the 'on' state (optional)
* @param {color=icon0} the color for the 'off' state (optional)
* @param {text(input,handle,both,none)=none} how should the value be shown; possible options: 'input', 'handle', 'both', 'none' (optional, default 'none')
* @param {value=} the minimum value to display if the slider is moved to total left if this should differ from sent/received value (optional, default like min)
* @param {value=} the maximum value to display if the slider is moved to total right if this should differ from sent/received value (optional, default like max)
*/
Every widget macro must be documented by a preceding docstring comment which is used to generate documentation and contains information for Template Checker and the Widget Assistant.
This has to be right above the macro defintion and starts by /**
and end with */
. Every line has to begin with a *
.
The first line has to contain a short description of the widget.
On the following lines the parameters are described in the same order as they are defined in the macro (the order is essential!).
These lines start with the keyword @param
followed by an expression in {}
which contains the type, form, options and allowed values. This is followed by a description of the parameter. The description may have line breaks, but please note that subsequent lines may not start with a star *
.
The type may be one of the following:
- id: Unique id
- image: An icon of the icons folder
- text: A string
- value: A number
- color: Any css color like #FF0000, rgb(255,0,0), hsl(0, 100%, 50%), red or icon1 (icon0 through icon5 as of v3.3)
- item: A backend item
- image: An icon or a dynamic icon
- type: A type of a button, one of 'micro', 'mini', 'midi', 'icon' or 'text'
- duration: A duration like 1h or 30s
- format: PHP sprint like expression
- formula: A JavaScript expression
- url: Any valid URL (absolute or relative)
Parameters which have to be a list are marked by suceeding square brackets: @param {value[]}
If the list-form is optional (i.e. a single value or a list is accepted) add a question mark in the brackets: @param {value[?]}
A parameter may be marked as optional by adding an equal sign after the type: @param {text=}
If the parameter has a default value, add it after the equal sign: @param {text=hello}
. Remember: This is just for documentation purposes, the default value itself has to be set in your code.
Use the array form to set a list as default value: @param {value[]=[0,1]}
Some types can be limited to discrete values by adding a list of allowed values in parentheses: @param {text(left,right)}
If this is used for formula, color or type the values are allowed in addition to the predefined ones; i.e. @param {type(foo)}
allows 'micro', 'mini', 'midi', 'icon', 'text' or 'foo'
The inline documentation loads docu / example files for custom widgets if they are stored in the same directory as the widgets themselves, i.e. dropins/widgets or dropins/shwidgets. Name the widget files which must include the head shown above <widgetgroup>.html
and <widgetgroup>.js
Then, the widget docu page with examples needs to be called widget_<widgetgroup>.<macroname>.html
Macro definition with parameters
The macro name and parameter field is being defined here. Later, the widget will be called with filename.macro if filename.html is imported as "filename" in your html page. E.g. if the macro is stored in "device.html" the call is "{{ device.dimmer (....) }} "
Other widgets used in the macro must be imported explicitely.
{% macro dimmer(id, txt, item_switch, item_value, min, max, step, pic_on, pic_off, color_on, color_off, value_display, min_display, max_display) %}
{% import "basic.html" as basic %}
/** use {% import "@widgets/basic.html" as basic %} as from v3.3 */
Now the function of the macro is defined. css formats are adressed via the "class" statement and a unique id can be defined. See the inline documentation for standard widget functions and parameters
<div class="dimmer" data-widget="device.dimmer"{% if not id is empty %} id="{{ uid(page, id) }}"{% endif %}>
{{ basic.stateswitch('', item_switch, 'icon', '', [ pic_off|default('light_light.svg'), pic_on|default('light_light.svg') ], '', [ color_off , color_on|default('icon1') ]) }}
<p>{{ txt|e }}</p>
{{ basic.slider('', item_value, min, max, step, 'horizontal', value_display|default('none'), min_display, max_display) }}
</div>
{% endmacro %}
Head section, macro definition and import of other widgets (if necessary) is made like above. Now instead of calling other widgets, the parameter handshake for the jQuery mobile macro is set up:
<div {% if not id is empty %} id="{{ uid(page, id) }}"{% endif %}
data-widget="foo.bar" data-item="{{ item1 }},{{ item2 }}"
data-min="{{ value_top|default('0') }}" data-max="{{ value_bottom|default('255') }}"
data-step="{{ step|default(5) }}">
The HTML tag must have an attribute called "data-widget" which corresponds to the widget name and "initSelector" in the jQuery mobile (jQm) / JavaScript section in "foo.js". The attribute "data-item" carries the item names which appear as "response[0, 1, ...] in the update method on the jQm side. If more than one item are used, data-item should be filled via the Twig-function {{ implode(itemlist) }}. Further options may be defined which appear in the option method in jQm widget.
Methods for item updates etc. are made available in prototype methods provided in "$.sv.widget". A widget is initialized with a name and reference to the prototype widget. The initSelector links the widget to it's html part (data-widget=...). Next, the options are initialized and filled with default values. Option names correspond with the data-<option> names in the html part of the widget.
$.widget("sv.foo_bar", $.sv.widget, {
initSelector: 'div[data-widget="foo.bar"]',
options: {
min: 0,
max: 255,
step: 5,
},
_update: function(response) {
if (response[1] !== undefined) {
var a = response[1];
}
var h = parseInt(Math.min(Math.max((response[0] - min) / (max - min), 0), 1) * 13 * 14);
...
The JavaScript code is used to dynamically change the page contents according to the item values. Most important is the _update method which is called every time an item is changed which the widget is listening to. The composition of the different methods can't be described here in detail. Just view the existing widgets in order to learn more about the different methods.
Any widget in the dropins/widget folder should not only contain the <widgetgroupname>.html and <widgetgroupname>.js, but also a small example html for every widget in your widget group.
Put this part into your example file that should be called widget_<widgetgroup>.<widget>.html
{% extends "custom/widget_custom.html" %}
{% block example %}
your example content
{% endblock %}