Using UWA Controls

What is a UWA Control?

A UWA Control is a UWA class that extends the UWA Control Abstract class, as defined in: UWA.Controls.Abstract. It can be either a simple (Accordion, Calendar, DatePicker) or a complex control (FeedView, TabView) UX Control. The only requirement being that it provides a UI to the end user. No business logic should be embedded in controls since it is only a view.

Loading Controls inside an App

By default a UWA app includes what we call the emulation files, so that in standalone mode (outside of Netvibes), the application uses the UWA environment and look-and-feel.

<!-- Application Standalone emulation files -->
<link rel="stylesheet" type="text/css"
    href="//uwa.netvibes.com/lib/c/UWA/assets/css/standalone.css" />
<script type="text/javascript"
    src="//uwa.netvibes.com/lib/c/UWA/js/UWA_Standalone_Alone.js"></script>

However, in order to reduce the size, not all the Controls and Services that are available in the UWA JS Runtime are included in these emulation files.

When you want to use UWA.Controls or UWA.Services classes, you need to insert the JavaScript files <script> tags for the required Controls into the <head> of your UWA app's XHTML file.

<!-- Application extra control file -->
<script type="text/javascript"
        src="//uwa.netvibes.com/lib/c/UWA/js/UWA_<NameSpace>_<ClassName>.js"></script>

To determine a UWA Control or Service JavaScript file url, first determine the name of the NameSpace, then the ClassName:

NameSpace - The type of the class (e.g Controls, Services)
ClassName - The name of the class (e.g TabView, Lightbox, Scroller...)

Simple UWA.Controls usage

UWA Controls usually extend UWA.Controls.Abstract. In this case, create an instance of the control by passing a hash of options to the constructor, then inject the control into the widget body or another element of your choice.

The following example uses the UWA.Controls.Segmented control.

  1. Insert the control script:

Insert the required script tag in the <head> of your UWA app file in order to load the

<UWA.Controls.Segmented> class.

<script type="text/javascript"
        src="//uwa.netvibes.com/lib/c/UWA/js/UWA_Controls_Segmented.js">
  1. Create the control class instance:

Then create the UWA.Controls.Segmented control instance and inject it into the widget body or an existing module:UWA/Element.UWA.Element instance into your widget.onLoad event

var myWidget = {

    myControl: null,

    onLoad: function () {

        // Create your control instance, and store a reference to
        // it for future manipulation.
        myWidget.myControl = new UWA.Controls.Segmented({
            data: {
                option_a: {text: 'a'},
                option_bb: {text: 'bb'},
                option_ccc: {text: 'ccc'},
                option_dddd: {text: 'dddd'}
            }
        });

        // Example 1. Inject into the widget.body
        myWidget.myControl.inject(widget.body);
        // OR
        widget.setBody(myWidget.myControl);

        // Example 2. Inject into an element
        var myElement = UWA.Element('div', {
             'class': '.mySegmentContainer',
             html: {
                 tag: 'h1',
                 text: 'My Segmented example'
             }
        }).inject(widget.body);

        // Inject the control into myElement
        myElement.setContent(myWidget.myControl);
        // OR
        myWidget.myControl.inject(myElement);
    }
}

widget.addEvent('onLoad', myWidget.onLoad);

You can explore the following controls classes for more examples and documentation about UWA.Controls classes.

Create a custom UWA.Controls

You can create custom controls extending UWA.Controls.Abstract Class, the advantage of using UWA.Controls.Abstract is that it will implement the options (setOptions, setOption), inject and events (addEvent, dispatchEvent) methods.

To create a custom UWA.Controls:

  1. Create a JavaScript file with your control's source that implements UWA.Controls.Abstract using {@link module:UWA/Class.UWA.Class.extend|UWA.Class.extend}.
  2. Create a sample app to test your control that includes this javascript file.

Example: For this example we will create a simple button control.

First is the JavaScript file for this button control:

We will consider it hosted at the following url "http://example.com/lib/js/MyCompany/Controls/Button.js". See "NOTE" inside the JavaScript source for explanations.

/// NOTE: UWA JS Runtime 1.3+ provides full AMD support,
// use define to create a JavaScript Module.
define('MyCompany/Controls/Button', [
    'UWA/Core',
    'UWA/Controls/Abstract',
], function (Core, Abstract) {

    // NOTE: add use strict for good practice and
    // avoid global usage or missing var.
    'use strict';

    /*
      Class: MyCompany.Controls.Button

        Display a customizable button.

      Extends:
        <UWA.Controls.Abstract>
    */
    var Button = Abstract.extend({

        /* Group: Properties */

        /*
          Property: defaultOptions
            The default controls options.
        */
        // NOTE: Use defaultOptions to define the default value of options.
        defaultOptions: {
            text: '',
            className: 'MyCompany-button',
        },

        /* Group: Methods */

        /*
          Method: init

            Set the options for the current controls instance,
            creates observers and elements object.

          Parameters:
            * Object options: options hash or a option/value pair.

          Returns:
            * Nothing.
        */
        init: function (options) {

            // NOTE: if you override init, you may need to call
            // the parent method to handle options and events.
            this._parent(options);

            // NOTE: Isolate your DOM creation into
            // a sub method that you call inside the init.
            this.buildSkeleton();
        },

        buildSkeleton: function () {

            var options = this.options;

            // NOTE: Create DOM for the control using <UWA.createElement>
            // then store it into this.elements.container.
            this.elements.container = Core.createElement('a', {
                'class': options.className,

                // NOTE: use html options instead of raw HTML
                html: {
                    tag: 'span',
                    text: options.text
                },

                // NOTE: Style your basic control design inside JavaScript
                // not in a separate stylesheet for good practice. It is still
                // possible to overide it inside the widget using stylesheet or style tag
                // later for more customizations.
                styles: {
                    padding: '5px',
                    background: 'blue',
                    color: 'white',

                    // NOTE: UWA supports CSS3, and will add prefixes, if required, using
                    // feature detection.
                    borderRadius: '5px',
                    boxShadow: '5px 5px 2px #888'
                },

                // NOTE: Plug the events using <UWA.Controls.Abstract.dispatchAsEventListener>
                // to allow event attachement from contrusctor and default events.
                events: {
                    click: this.dispatchAsEventListener('onClick'),
                    mouseover: this.dispatchAsEventListener('onMouseOver'),
                    mouseleave: this.dispatchAsEventListener('onMouseLeave'),
                }
            });
        },

        /* Group: Events methods */

        // NOTE: Add some default event behavior to the control.
        // These will be triggered because we are using <UWA.Controls.Abstract.dispatchAsEventListener>.

        onClick: function () {
            this.elements.container.addClassName('clicked');
        },

        onMouseOver: function () {
            this.elements.container.addClassName('over');
        },

        onMouseLeave: function () {
            this.elements.container.removeClassName('over');
        },
    });

    // Create the Namespace
    MyCompany = window.MyCompany = window.MyCompany || {};
    MyCompany.Controls = MyCompany.Controls || {};
    MyCompany.Controls.Button = Button;

    return Button;
});

Next, is the source of the UWA App that will use this custom control:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:widget="http://www.netvibes.com/ns/">
    <head>

        <!-- Application Metas -->
        <title>Title of the App</title>
        <meta name="author" content="John Doe" />
        <meta name="description" content="A descriptive description" />

        <!-- Application Standalone emulation files -->
        <link rel="stylesheet" type="text/css"
            href="//uwa.netvibes.com/lib/c/UWA/assets/css/standalone.css" />
        <script type="text/javascript"
            src="//uwa.netvibes.com/lib/c/UWA/js/UWA_Standalone_Alone.js"></script>

        <!-- Application Custom files -->
        <script type="text/javascript"
            src="http://example.com/lib/js/MyCompany/Controls/Button.js"></script>

        <!-- Application JavaScript Source -->
        <script type="text/javascript">
        //<![CDATA[

            /*
                We create the global MyWidget object (it could be any other name).
                This object will be used to store variables and functions.
            */
            var MyWidget = {

                /*
                    The onLoad() function is first,
                    it will be triggered by the widget "onLoad" event.
                */
                onLoad: function() {

                    // Here we update the content of the widget body.
                    var defaultText = 'Hello World!',
                        myButton = new MyCompany.Controls.Button({
                        text: defaultText,
                        events: {
                            onClick: function (event) {
                                var textContainer = this.getContent().getElement('span');
                                textContainer.setText('clicked');
                            },

                            onMouseOver: function (event) {
                                var textContainer = this.getContent().getElement('span');
                                textContainer.setText('Over');
                            },

                            onMouseLeave: function (event) {
                                var textContainer = this.getContent().getElement('span');
                                textContainer.setText(defaultText);
                            }
                        }
                    });

                    // Clear the widget body content,
                    // then inject control into body
                    myButton.inject(widget.body.empty());
                }
            };

            /*
                The "onLoad" event is the very first event triggered when
                the widget is fully loaded or when the preferences are validated.

                Here, we add MyWidget.onLoad() function as an "onLoad" event
                listener on the widget.
            */
            widget.addEvent('onLoad', MyWidget.onLoad);

        //]]>
        </script>
      </head>
      <body>
            <p>Loading...</p>
      </body>
</html>