Widgets

The frontend detail view consists of sections displayed as tabs containing widgets. Specific nodes produce the output rendered by the frontend into sections and widgets. See Tutorial: Write your own nodes for an introduction to this.

Section nodes are decorated with @marv.node(Section) and push a dictionary with title and a list of widgets:

section = {'title': 'Section title', 'widgets': [widget, ...]}

Widget nodes are decorated with @marv.node(Widget) and push a dictionary with an optional title and one key corresponding to a widget_type (e.g. image) and value with data extracted from a dataset to be rendered by the widget (e.g. {'src': 'img/path'}.

widget = {'title': 'Widget title', widget_type: data}

Widgets are either rendered directly into a section or are used as part of another composite widget, e.g. an image in a gallery (see below).

Valid values for widget_type are given in the following sections. The title key is optional and omitted for brevity.

Image

image = {'image': {'src': img.relpath}}

Example: Image used inside gallery marv_robotics.detail.galleries()

Video

video = {'video': {'src': videofile.relpath}}

Example: marv_robotics.detail.video_section()

Preformatted

Wraps data into an html <pre></pre> tag.

pre = {'pre': 'foo\nbar'}

Custom

Renders custom widgets.

custom = {'custom': {'type': 'foo', 'data': json.dumps(data)}}

Create site/frontend/custom.js and restart your instance to customize widgets and formatters.

window.marv_extensions = {
    formats: {
        // replace default datetime formatter, show times in UTC
        'datetime': function(date) { return new Date(date).toUTCString(); }
    },
    widgets: {
        // rowcount widget displays the number of rows in a table
        'rowcount': [
            /* insert callback, renders the data

               @function insert
               @param {HTMLElement} element The parent element
               @param {Object} data The data to be rendered
               @return {Object} state Any variable, if required by remove
            */
            function insert(element, data) {
                const doc = element.ownerDocument;
                const el = doc.createTextNode(data.rows.length + ' rows');
                element.appendChild(el);

                const state = { el };
                return state;
            },

            /* remove callback, clean up if necessary

               @function remove
               @param {Object} state The state object returned by insert
            */
            function remove(state) {
                state.el.remove();
            }
        ]
    }
};