Ubuntu HTML5 API documentation

Hi developers of HTML5 apps!

I added an API reference documentation of Ubuntu HTML5 Theme on my homepage: API documentation

This reference documentation might land on the Ubuntu developer center, too (thanks Michael Hall!). There, it would be navigable and searchable.

Happy hacking!

Share Button

Ubuntu HTML5 platform: Storage

Several options to persist structured data with HTML5 client devices exist:

  • Web Storage (i.e. localstorage)
  • WebSQL
  • IndexedDB

Ubuntu Touch supports all three options. However, the implemented IndexedDB version uses an old API. We will see how to remidy this by using a polyfill.

Web Storage

The Web Storage W3C specification defines an API to save named key/value pairs. The web storage attribute can be accessed with window.localstorage for persistent data, and with window.sessionstorage for data that ist discarded after the session quits.

Local storage and session storage both have the same API to save key/value pairs. Key and value must both be Strings. Using them is in fact very simple, its API is very small. Here an example that saves an item in the localstorage, retrieves it, and deletes it afterwards:

// saves data in the local storage
localStorage.setItem("username", "max");

// retrieves the data  
var retrievedUsername = localStorage.getItem("username");

// removes the data
localStorage.removeItem("username");

Since keys and values are Strings, to retrieve integers or floats, functions like parseInt() or parseFloat() must be used. Objects can be stored in the localstorage by storing them as JSON Strings:

var someObject = {username="foo", password="1234"};

// saves the data as JSON
localStorage.setItem("userdata", JSON.stringify(someObject));

// retrieves the data as JSON
var retrievedUserData = JSON.parse(localStorage.getItem("userdata"));

Localstorage has the huge advantage that it is supported by all the major web browsers (even IE8!). It however has several disadvantages, too, including:

  • Only Strings can be saved. There is no query language to retrieve objects.
  • Since localstorage only saves Strings, it scales badly for bigger amount of data. As a matter of fact, most implementations of localstorage throw an exception when more than 5MB are used!
  • It has strange locking behavior, which makes it difficult to use when more than one browser window is open.

Most of these shortcomings are solved by WebSQL and indexedDB.

WebSQL

The Web SQL Database specification isn’t maintained anymore and is not part of the HTML5 specification. It is however very important for us, since it is supported by the Ubuntu Touch WebKit implementation! It is also supported by Google Chrome, Safari and Android Browser; IE and Firefox do not implement it.

Web SQL introduces a set of APIs to manipulate client-side databases using SQL. The specification is based on SQLite and defines API methods to open databases, create transactions and execute SQL statements:

  • Database window.openDatabase(database_name, version, database_description, estimated__size, creationCallback) : opens a database, or creates it if it does not exist.
  • database.transaction(callbackFunc, errorCallback, successCallback): opens a transaction. The callback methods are executed in a transaction.
  • transaction.executeSql(sqlStatement, parameters, callbackFunc, errorCallback): executes a SQL statement .

We jump in and show the API in action:

var db = window.openDatabase("myDatabase", "1.0", 
  "TestDatabase", 5*1024*1024);
 
if(!db) {
  alert("The DB could not be created");
  return false
}

// Creates a table and inserts some data into it
db.transaction(createAndInitSQLTable);

function createAndInitSQLTable(tx) {
  tx.executeSql('CREATE TABLE 
        IF NOT EXISTS CONFIGURATION(id unique, key TEXT, value TEXT)');
  tx.executeSql('INSERT INTO CONFIGURATION (id, key, value) 
        VALUES (1, "admin", "secret")');
  tx.executeSql('INSERT INTO CONFIGURATION (id, key, value) 
        VALUES (1, "minimize_on_close", "false")');
}

// displays the result in the HTML
db.transaction(function (tx) {  
  tx.executeSql('SELECT * FROM CONFIGURATION ', [], 
      showConfiguration, null);
});


function showConfiguration(tx, results){
  var domElem =  document.getElementById('#configurationEntries');
  var rows = results.rows;
  for (i = 0; i < rows.length; i++){
    var keyValue = rows.item(i).key + ": " + rows.item(i).value;
    domElem.innerHTML +=  keyValue ;
}

One disadvantage of WebSQL is that it is not a W3C standard. Mozilla/Firefox even decided to not endorse it. Instead, IndexedDB is the alternative advocated by Mozilla.

IndexedDB

Like Web Storage, IndexedDB is a key/value storage. It has many advantages over Web Storage:

  • Javascript Objects can be saved.
  • Accessing values (which can be objects) can be made fast by creating "indexes".
  • It offers transactions.
  • It is asynchronous, thus it does not block the program flow.
  • It is supported by many browsers: Google Chrome (only the desktop version), Firefox and IE10+.

The bad news is that only an old version of IndexedDB is implemented in Ubuntu Touch (the Android browser implements the same old verison). This version does, for example, not define the IDBVersionChangeEvent variable.
Instead of using this fossil version of the W3C API, I recommand to use a polyfill to enable IndexedDB using WebSql. I use IndexDBShim for that.

Polyfills

In web development, a polyfill (or polyfiller) is downloadable code which provides facilities that are not built into a web browser. For example, many features of HTML5 are not supported by versions of Internet Explorer older than version 8 or 9, but can be used by web pages if those pages install a polyfill.

To enable IndexDBShim add this to your HTML page:

<script src="IndexedDBShim.js"></script>

Then enable the polyfill it as follows:

// Is there a current implementation of IndexedDB?
var requireShim = typeof window.IDBVersionChangeEvent === 'undefined';

// Is WebSQL available?
var supportsWebSql = typeof window.openDatabase != 'undefined';

if(requireShim && supportsWebSql){
  window.shimIndexedDB.__useShim(); // Use the Polyfills 
}

Using a polyfill to emulate IndexedDB with WebSQL isn't really a bad thing: for example, Firefox already implements indexedDB with SQL Lite.

Here is a small example which shows how to use indexedDB:

var users = [
  { name: "Anne" },
  { name: "Marie" },
  { name: "Thomas" }
];
 
var request = window.indexedDB.open("UserDB", "My user database");
request.onsuccess = function(event) {
  var objectStore = event.result.objectStore("users");
  for (var index = 0; i < kids.length; i++) {
    var user = users[i];
    objectStore.add(user).onsuccess = function(event) {
      document.getElementById("display").textContent +=
            user.name + " with id " + event.result;
    };
  }
};

Conclusion

Ubuntu Touch offers different HTML5 storing options to save structured data. "Webstorage" is the most easy and the most effective for unstructered and small data. "WebSQL" brings the whole world of SQL to the browser. Finally, "IndexedDB" directly allows to persist Javascript objects.

Share Button

Ubuntu HTML5 platform: Header, Progress bars, Text inputs, Ubuntu Shapes

This is one further article about the Ubuntu HTML5 platform and the last article on widgets. We will examine the application header, progress bars, text inputs and ubuntu shapes.

Header

The header is an UI component which sits on top of an application. It

  • shows the user, where he is
  • switches tabs, which are views of equal importance (see the guidelines)

To show a header containing several tabs,

  • create a section container having an attribute data-role="header"
  • add list items to that section-element having the attribute data-role="tab"

Here is explanatory code snippet:

<header data-role="header">
  <nav class="tabs" data-role="navbar">
    <div class="tabs-inner">
      <ul data-role="tabs">
        <li class="active" data-role="tab">
          <a href="#item1" id="firstTab"<First</a>
        </li>
        <li class="inactive" data-role="tab">
          <a href="#item2" id="secondTab">Second</a>
        </li>
      </ul>
    </div>
  </nav>
</header>

And here is a screenshot of such a header UI element:

Header

Header

There is no predefined UI method to bind a callback function to a tab, yet. So, I created a small example to show how to switch pages when the user clicks on a tab: JS Bin – Header and tabs.

Progress bars

Progress bars are new HTML5 elements. Ubuntu HTML5 comes with CSS styling instructions to style them.

Declaring progress bars is made as follows:

<progress></progress>
<progress class="bigger"></progress>

Here is a link to try out progress bars on JS Bin: JS Bin – Progress bars

Progress bars with attributes like "value" or "max" are not styled yet (as of Ubuntu HTML5 Theme version 0.1). Here is an example that will NOT be styled correctly:

<progress max="100" value="80"></progress>

Text inputs

HTML5 brings new input types like “number”, “url”, “email”, etc. These new input types have several advantages:

  • Different on screen-keyboards might be used. For example, “numbers” might be entered with a numeric keyboard.
  • The input can be validated by the browser before submitting a form to a server. E.g. the type “email” will show an error when the user tries to submit an email address without a “@”-character.

Here are some examples to show the individual input types:

<div class="inset">
  <input type="text" placeholder="simple text field">
</div>
<div class="inset">
  <input type="text" disabled="" placeholder="disabled text field">
</div<
<div class="inset">
  <input type="tel" placeholder="telephone field">
</div>
<div class="inset">
  <input type="search" placeholder="search field">
</div>
<div class="inset">
  <input type="number" placeholder="number field">
</div>
<div class="inset">
  <input type="url" placeholder="url field">
</div>
<div class="inset">
  <input type="password" placeholder="password with echo">
</div>
<div class="inset">
  <textarea placeholder="the placeholder text is a text which is displayed when there is no content in the TextArea"></textarea>
</div>

This code can be tried online: JS Bin – Inputs types.

No UI methods are needed to access the values of these input fields, document.getElementById("elementid").value suffices.

Shapes

Shapes are “decorators” to make elements like images look as follows:

Ubuntu Shape

Ubuntu Shape

Using them is simple:

<div data-role="shape">
  <img src="http://cordova.apache.org/images/cordova_bot.png">
</div>

Since Shapes are created by using images, setting height and width might make them look bad.

The example can be tried online here: JS Bin – Shapes

The next article will focus on the storage options “localstorage”, “WebSQL”, and “IndexedDB”.

Share Button

Ubuntu HTML5 platform: popover menus and toolbar

This is the next article from the series about the Ubuntu HTML5 platform. This time, we focus on popover menus and on the toolbar.

Popover menu

Popover menus kind of look like speech bubbles. They are “attached” to an element and open next to it. the way they open is controlled by the attribute data-gravity:

  • gravity=n (north), i.e. the speech bubbles tail points to the top of the browser viewport
  • gravity=s (south), i.e. the speech bubbles tail points to the bottom of the browser viewport
  • gravity=e (east), i.e. the speech bubbles tail points to the right of the browser viewport
  • gravity=w (west), i.e. the speech bubbles tail points to the left of the browser viewport

Here is a picture of the different options:
FourPopoverMenus

The picture above was made with the following HTML markup:

<div class="popover active" data-gravity="n" style="top:10px; left:10px; width:130px">
  <ul class="list">
    <li class="active"><a href="#">Item1</a></li>
    <li><a href="#">Item2</a></li>
  </ul>
</div>
<div class="popover active" data-gravity="s" style="top:10px; left:150px; width:130px">
  <ul class="list">
    <li class="active"><a href="#">Item1</a></li>
    <li><a href="#">Item2</a></li>
  </ul>
</div>
<div class="popover active" data-gravity="e" style="top:10px; left:300px;width:130px">
  <ul class="list">
    <li class="active"><a href="#">Item1</a></li>
    <li><a href="#">Item2</a></li>
  </ul>
</div>
<div class="popover active" data-gravity="w" style="top:10px; left:450px; width:130px">
  <ul class="list">
    <li class="active"><a href="#">Item1</a></li>
    <li><a href="#">Item2</a></li>
  </ul>
</div>

You can try and edit this code on JS Bin: JS Bin – Four popover menus

This code displays four popover menus; each one is made of two list items. They are made visible by setting class="active". Popover menus without class="active" are not shown!

Popover menus are positioned absolutely, thus they need the “left” and “top” style attributes. In practice, the app developer almost never need to compute these attributes, since they are computed automatically with List.prototype.show():

var button = UI.button("myButton");
UI.popover(button, "popover1").show();

The method show() does two things:

  1. It adds “active” to the classlist of the popover menu. This makes the element visible.
  2. It computes the “top” and “left” style parameters, so that the popover menu opens next to the button and according to its data-gravity attribute.

There is also an hide() and a toggle() method, to hide or toggle a popover menu element.

As an example, the following code opens a popover menu above a button and closes it as soon as the user clicks the other button.

<button data-role="button" id="button1">Button 1</button>
<button data-role="button" id="button2">Button 2</button>
<div id="popover1" class="popover" data-gravity="s">
  <ul class="list">
    <li class="active"><a href="#">Item1</a></li>
    <li><a href="#">Item2</a></li>
  </ul>
</div>
<div id="popover2" class="popover" data-gravity="s">
  <ul class="list">
    <li class="active"><a href="#">Item1</a></li>
    <li><a href="#">Item2</a></li>
  </ul>
</div>

<script>
var button1 = UI.button("button1");
button1.click(function() {
  UI.popover(this, "popover1").toggle();
  UI.popover(this, "popover2").hide();
});

var button2 = UI.button("button2");
button2.click(function (){
    UI.popover(this, "popover2").toggle();
    UI.popover(this, "popover1").hide();
});
</script>

You can try and edit this code on JS Bin: JS Bin – Opening and closing popover menus

Toolbar

The toolbar lives at the bottom edge of the screen as a footer. It contains icons that engender actions whenever the user clicks on them.

While it is technically possible to put more than five icons on the toolbar, the Ubuntu Touch guidelines specifies that the maximum number of icons is five.

The toolbar is defined as follows:

<footer id="footer" class="revealed" data-role="footer">
  <nav>
    <ul>
      <li><a href="#"><span>Add Feed</span></li>
      <li><span>Delete Feed</span></li>
      <li><img alt="Tap me!" src="../../ambiance/img/back@18.png"><span>Back</span></li>
    </ul>
  </nav>
</footer>

The classname revealed indicates that the toolbar is shown.
The backbutton is created automatically by the Ubuntu HTML5 theme when the application starts (if a toolbar was defined in the HTML markup).

Ubuntu HTML5 comes with several methods to show and hide the toolbar:

UI.toolbar("footer").show(); 
UI.toolbar("footer").hide();
UI.toolbar("footer").toggles(); 
 // Registers an event handler for touch-release events (or mouse-up event on desktop)
UI.toolbar("footer").touch(handlerFunc);

According to the user interface guidelines, the toolbar should be shown and hidden by touching it. This is realized with the following code:

var toolbar = UI.toolbar("footer");
toolbar.touch( function(){
  toolbar.toggle();
});

This can also be tried out live: JS Bin – Toggline the toolbar on touch events

Unfortunately, there are no predefined javascript methods to add new buttons to the toolbar or remove them from it. For example, this might be useful in an email-application where the buttons “new email” and “refresh” are shown on the main page, and the buttons “send email” and “save as draft” on the “compose” page.

I implemented two methods to add and remove buttons to the toolbar at runtime:

  • addActionToToolbar(id, text, onclick, buttonId, img): Adds a button labeled with “text” to the toolbar, and associates it with the onclick event handler. The actionid and the image are optional.
  • removeActionFromToolbar(buttonId): Removes a button from the toolbar.

The implemented methods can be found here:
JS Bin – Methods to add actions to the toolbar.

Share Button