Getting Started with UION


UION stands for User Interface Object Notation is a highly customizable, simple, testable JSON UI framework.


UIkit


UION uses UIkit components, so it's kind of like a wrapper on top of UIkit that allows JSON ot be used instead of HTML.

An example of a modal:

var modal = UI.new({
  "view": "modal",
  "header": {
    "view": "label",
    "htmlTag": "H3",
    "label": "Stale coffee is exquisite!"
  },
  "body": {
    "view": "label",
    "label": "Medium brewed, dripper to go filter iced..."
  },
  "footer": {
    "flexAlign": "right",
    "cells": [
      {
        "view": "button",
        "label": "No way!",
        "margin": "right"
      },
      {
        "view": "button",
        "type": "primary",
        "label": "Yup."
      }
    ]
  }
}, document.body);

// Opens the modal
modal.open();

If you want to see an more in-depth example, checkout the source code for this site. It's built almost entirely using UION.


Usage


For release, use:

<link rel="stylesheet" href="css/uikit/uikit.css">
<script src="jquery.min.js" type="text/javascript"></script>
<script src="uion.min.js" type="text/javascript"></script>

For debugging, use:

<link rel="stylesheet" href="css/uikit/uikit.css">
<script src="jquery.js" type="text/javascript"></script>
<script src="uion.debug.js" type="text/javascript"></script>

Flexible and Extensible


Many paid-to-use similar frameworks such as Kendo UI or Webix do not offer the flexibility of UION.

UION allows you to control every aspect of components, allowing you to even create custom components. For examples on how to create your own components, see the documentation on Github.


Highly extensible JSON UI Components


To understand how to create your own custom components, lets take a look at an example from the library itself.

exports.def({
    __name__: "toggle",
    $setters: exports.setCSS({
        type: {
            "success": "uk-toggle-success",
            "danger": "uk-toggle-danger",
            "warning": "uk-toggle-warning",
            "": ""
        }
    }),
    $defaults: {
        htmlTag: "LABEL",
        tagClass: "uk-toggle"
    },
    __after__: function () {
        exports.event(this._html, "change", this._onChange, this);
    },
    _onChange: function () {
        this.dispatch("onChange");
    },
    template: function (config) {
        return exports.replaceString('<input type="checkbox"{{checked}}><div class="uk-toggle-slider"></div>',
            {checked: config.checked ? " checked" : ""});
    },
    getFormControl: function() {
        /**
         * Get the HTML input element.
         * @returns {Element}
         */
        return this._html.firstChild;
    },
    reset: function () {
        /**
         * Reset the toggle.
         */
        this.getFormControl().checked = false;
    },
    getValue: function () {
        /**
         * Get the value of the toggle.
         * @returns {boolean}
         */
        return this.getFormControl().checked;
    },
    setValue: function (value) {
        /**
         * Set the value of the toggle.
         * @paramm value
         */
        this.getFormControl().checked = value;
    }
}, exports.components.element)

The above toggle component is a fine example of how to define your own components. Any functions on the JSON object will be integrated into the component itself. With `this` referring to the component.

this.config

This refers to the configuration or JSON data initially used to initialize the component.

this.element

This is the underlying HTML element.

__init__

This function will be called when the coomponent is instantiated with `UI.new`. This method should be used to create the HTML elements and initializing variables, nothing else.

__after__

At this point the HTML elements should be initialized and is usually where event listeners are attached to the elements. UION uses it's own dispatcher system, and elements can inherit it from UI.Dispatcher Mixin object.

A number of useful Mixins exist within the library. All components are just plain old JavaScript objects, and nothing more. You can even write your own Mixins are integrate them using UI.extend.

template

This defines the template string for your component. This is set using the `innerHTML` attribute during a `render()` call. You can overwrite render to define your own rendering behavior if you don't want to use the default template protocol.

$setters

This is used for properties that require special handling when they are set using the `set` function. Any initial configuration properties are taken and ran through its $setter function if possible. This is how most CSS properties are set in the default components.

$defaults

These are the default fields that are fed into the $setter functions if nothing is provided.

Inheritance


You can chain previously defined components or Mixins at the end of the `UI.def(config, ext1, ext2, ...)`, please note that overriding occurs from right to left, with the right-most object being the ancestor. It's properties can be overridden by anything left of it.

I hope you get the essence of how to write custom components from the introduction above. I plan to extend this guide into a full step by step thing in the future.


Testability


Writing UI as ordinary components actually makes things very testable. As UION uses its own event dispatching system, you can simulate button clicks, select elements and create components all within headless unit testing.

Below is an example of what can be done with UION components:

it("someToggle onChange", function () {
    spyOn(self, "someAction");
    $$("someToggle").setData([{label: "someLabel1", value: 1}, {label: "someLabel2", value: 2}])
    $$("someToggle").setValue(1);
    $$("someToggle").dispatch("onChange");
    expect(self.someAction).toHaveBeenCalledWith(1);
    $$("someToggle").setValue(2);
    $$("someToggle").dispatch("onChange");
    // And so on...
});

After writing lots of E2E tests using Nightwatch, I found testing is very, very slow. For test driven development, it makes a minor code change takes an extra few minutes. As more and more tests pile up, the full suite of E2E tests can take 5-20 minutes to run.

In general, Chrome just runs code more slowly than PhantomJS or other headless browsers, even for unit tests it can be up to 10x slower.

It's much faster to write lots and lots of unit test which run quickly and catch mistakes in the UI logic.


Maintainable


UION aims to be an extremely simple, maintainable library, that anyone can fork and take over themselves. There is no worry about framework lock in, as once you understand the basis of how to define components, you could create your own set of components yourself.

The test coverage right now for UION is pretty poor. Writing a full test suite for each and every UI component is an item on the project's todo list.