"Hello World" using UWA

The following guide will introduce you to the basics of Universal Web App (UWA) application development.

With each chapter, you will learn something new about UWA.

Step 1 - UWA application skeleton

This is a basic UWA skeleton file, it will display the text "Hello World!" in the body element once the app is loaded, just as any web page would do.

<?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 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 the first one,
                    it will be triggered by widget "onLoad" event.
                */
                onLoad: function() {

                    // Here we update the content of the widget body.
                    widget.setBody('Hello World!');
                }
            };

            /*
                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 "onLoad" event
                listener on the widget.
            */
            widget.addEvent('onLoad', MyWidget.onLoad);

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

Note that a UWA file is a web page with 4 main characteristics:

  • MUST feature the Netvibes widget namespace on the html element, this way:
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:widget="http://www.netvibes.com/ns/">
  • SHOULD include the emulation JavaScript and CSS 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>
  • MUST be made of well-formed XML/XHTML code
  • MUST be encoded in UTF-8

Step 2 - Using user preferences

You can define preferences that the user will be able to edit. This is done using the UWA's <widget:preferences> element.

You can get the preference value using UWA's JavaScript function widget.getValue(name) and set the value of the preference using widget.setValue(name, val) function.

Values are stored on the Netvibes server or in a cookie for example, depending of the platform.

In this example, one preference is defined, named "hellowho". It is a text string that the user can edit to define their name with a default value "World".

<?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 Preferences -->
        <widget:preferences>
            <widget:preference name="hellowho" type="text" label="Hello who ?" defaultValue="World"></widget:preference>
        </widget:preferences>

        <!-- 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 function.
            */
            var MyWidget = {

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

                    var who = widget.getValue('hellowho');

                    // The function "widget.setBody()" replaces the content
                    // of the widget body.
                    widget.setBody({
                        tag: 'p',
                        text: 'Hello ' + who + '!'
                    });
                }
            };

            /*
                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 "onLoad" event
                listener on the widget.
            */
            widget.addEvent('onLoad', MyWidget.onLoad);

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

This way, if the user enters "Richard" instead of the default "World" in the preference, the message will be updated accordingly once the preference is validated.

Step 4 - Handle preference validation

By default when the user edits the preferences it triggers the UWA.Widget.onLoad event again.

You may want to handle it in a separate event listener, in order to build your app layout in your "onLoad" listener and only partially update the layout when the preference changes. You can do so using an onRefresh listener.

If there is a UWA.Widget.onRefresh listener, it will be triggered instead of UWA.Widget.onLoad when the user edits the preferences.

<?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 Preferences -->
        <widget:preferences>
            <widget:preference name="hellowho" type="text" label="Hello who ?" defaultValue="World"></widget:preference>
        </widget:preferences>

        <!-- 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 function.
            */
            var MyWidget = {

                whoElement: null,

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

                    // Use widget.setBody() to replaces the content of the body element
                    // in order to initialize the layout of your app
                    widget.setBody({
                        tag: 'h1',
                        text: 'My App Title'
                    });

                    // Inject whoElement into the body
                    MyWidget.whoElement = widget.createElement('p').inject(widget.body);

                    // Update whoElement
                    MyWidget.updateWho();
                },

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

                    MyWidget.updateWho();
                },

                updateWho: function () {

                    var who = widget.getValue('hellowho');

                    // widget.setBody() replaces the content of the body element
                    MyWidget.whoElement.setText('Hello ' + who + '!');
                }
            };

            /*
                The "onLoad" event is triggered when the widget is loaded and
                "onRefresh" when the preferences are validated.

                Here, we add the MyWidget.onLoad() and MyWidget.onRefresh() functions
                as "onLoad" and "onRefresh" event listeners on the widget.
            */
            widget.addEvents({
                onLoad: MyWidget.onLoad,
                onRefresh: MyWidget.onRefresh,
            });

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

Step 5 - Retrieving data through an Ajax request

You can easily interact with web services, whether it is your own or an open API even if it's not hosted on the same domain than your app.

If you don't have access to an API yet, it is very easy to build one for test purposes, just build a server-side, dynamic file (PHP, ASP, etc.) that would respond to certain requests with the appropriate data, packaged in one of the supported formats: XML, JSON, HTML, RSS or plain text.

Let's say you already have an API, which sends back the plain text answer "World" to any request. This service would be located at "http://api.example.org/request".

Remember that the data sent to and retrieved from the app MUST be UTF-8 encoded.

The appropriate UWA function in this case is UWA.Data.getText.

Here is what the app source code could look like:

<?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 Preferences -->
        <widget:preferences>
            <widget:preference name="hellowho" type="text" label="Hello who ?" defaultValue="World"></widget:preference>
        </widget:preferences>

        <!-- 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 = {

                toWhom: "no one",

                onLoad: function() {

                    // the URL should return 'World' in plain text
                    UWA.Data.getText('http://api.example.org/request', MyWidget.onComplete);
                },

                onComplete: function(who) {

                    if (who) {
                        MyWidget.toWhom = who;
                    }

                    widget.setBody({
                        tag: 'p',
                        text: 'Hello ' + MyWidget.toWhom + '!'
                    });
                }
            }

            /*
                The "onLoad" event is the very first event triggered when the widget is loaded.
                Here, we make it trigger the MyWidget.onLoad() function as listener.
            */
            widget.addEvent('onLoad', MyWidget.onLoad);

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

We chose here to create a MyWidget JSON object to store our functions and variables. This is not mandatory, you can use common JavaScript if you like. Just remember to always prefix your variables with the "var" keyword.

You can explore the other available UWA.Data functions in the "Using Ajax Requests in UWA" section in order to find the one that fits your needs.

Step 6 - Sending data with Ajax

Once you know and understand UWA's Ajax functions, you might want to not only receive content from a server, but also send data to that server, and possibly get new content in exchange.

The body section of the app is preferably used to display content, not forms, although anything is possible.

Therefore, the data your user will send to your server should be entered through the preferences part of the app, any change to the preference will immediately update the app.

Let's say your web service simply takes the data being sent to it using an HTTP GET request, and returns it within the proper "Hello XXX !" string. Again, all UTF-8, all the time...

<?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="http://uwa.netvibes.com/lib/c/UWA/assets/css/standalone.css" />
        <script type="text/javascript"
            src="http://uwa.netvibes.com/lib/c/UWA/js/UWA_Standalone_Alone.js"></script>

        <!-- Application Preferences -->
        <widget:preferences>
            <widget:preference name="hellowho" type="text" label="Hello who ?" defaultValue="World"></widget:preference>
        </widget:preferences>

        <!-- 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 = {

                toWhom: "no one",

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

                    // The URL should return the hellowho in plain text from "who" parameter,
                    // following code will perform a GET request like this:
                    // http://api.example.org/request?who=<widget.getValue('hellowho')>
                    UWA.Data.request('http://api.example.org/request', {
                        onComplete: MyWidget.onComplete,
                        onFailure: MyWidget.onFailure,
                        method: 'GET',
                        data: {
                            who: widget.getValue('hellowho')
                        }
                    });
                },

                onComplete: function(who) {

                    if (who) {
                        MyWidget.toWhom = who;
                    }

                    widget.setBody({
                        tag: 'p',
                        text: 'Hello ' + MyWidget.toWhom + '!'
                    });
                },

                onFailure: function(error) {
                    widget.setBody({
                        tag: 'p',
                        'class': 'error',
                        text: 'Unable to get the API response cause: ' + error
                    });
                }
            }

            /*
                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 "onLoad" event
                listener on the widget.
            */
            widget.addEvent('onLoad', MyWidget.onLoad);

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

If you use POST rather than GET, you can, of course, do it easily with UWA. Check the available options for UWA.Data.request into 'Using Ajax Requests in UWA'.