So what is a mobile widget?

A mobile widget is a simple web app that's built with open web technology like HTML, CSS and JavaScript. You don't have to write a line of Java or any proprietary code and you don't have to understand anything about "mobile development". The files are packaged up into a zip file and downloaded to the phone.

Widgets have access to a permanent storage facility for settings and downloaded data. This mechanism is similar to cookies, but the storage capacity is larger and does not automatically expire after a given time.

What's in a widget?

A widget is built with HTML, CSS and JavaScript and packaged as a regular zip file, renamed to use the extension .wgt.

Here's what's in the zip:

Mobile widget tutorial

First, you'll need a directory. In that directory, make an "index.html" file, a "style.css" file, a "scripts" directory, and an "images" directory. You can structure your files any way you feel most comfortable with. If you want to split your CSS files up by contents later on, that's fine.

Now, in your HTML file, put some content. For this example we're using:

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">

      <html>

        <head>
          <title>Twiggy</title>
          <link rel="stylesheet" href="style.css">
        </head>

        <body>
        </body>
      </html>
    

You can open it in a browser, and see what it looks like (it should be blank). Now, get a copy of jQuery and put it in your "scripts" directory, and add a line like this to your to include it.

      <script type="text/javascript" src="scripts/jquery-1.3.2.min.js"></script>
    

Write all your application's javascript in an "actions.js" file, which goes in your /scripts folder. Add it like this:

      <script type="text/javascript" src="scripts/actions.js"></script>
    

In your <body>, insert the following divs:

      <div id="home" class="panel">

        <form id="main-search" class="panel" action="#">
          <label for="search">What is your name?</label>
          <input id="search" />

          <input type="submit" id="bigsubmit" value="Go!"/>
        </form>
      </div>

      <div id="results" class="panel">
        <!-- result goes in here -->
      </div>
    

Inside the body, we've put two divs with class "panel". These are different pages of our application, and only one will show at a time. When we submit the form on the "home" panel, we want the home panel to hide, and the "results" panel to show.

The JavaScript

Now for some actions.js Javascript code:

      var search = function(text){
        text = "Hello, "+text+"!";
        $("#home").hide();
        $("#results").text(text);
        $(".panel#results").fadeIn("fast");
        return false;
      };

      $("document").ready(function(){
        $("#search").focus();
        $("#results").hide();
        $("#main-search").submit(function(){
          value = $("#search").val();
          search(value);
        });
      });
    

Rad! We've got ourselves a widget.

Making it look pretty

Now let's add some style:

      html, body {
        padding: 0;
        margin: 0;
      }

      body {
        display: block;
        width: 100%;
        font-family: verdana;
        background: #007FC0;
        text-align: center;
        color: white;
      }

      #home.panel {
        padding: 20px 0;
        display: block;
      }

      #results.panel {
        background: #ff00ff;
      }

      #search {
        margin-top: 10px;
        padding: 4px;
        border: 1px solid #ff00ff;
        font-size: 13px;
      }
    

And we've got the beginnings of a widget.

The configuration

Now, all you have to do is add a config.xml file, which looks like this:

      <?xml version="1.0" encoding="UTF-8"?>

      <widget dockable="yes">
        <widgetname>My Awesome Application</widgetname>
        <description>It asks you your name, and says hi!</description>
        <icon src="icon_64.png" />

        <width>240</width>
        <height>320</height>
        <author>
          <name>John Q. Developer</name>

        </author>
        <id>
          <name>My Awesome Application</name>
          <revised>2009-04-08</revised>
        </id>

      </widget>
    

And you've got it. Feel free to open that in Opera just to test it out.

Searching Twitter

Now, if you want to search Twitter, include the plugin from tweet.seaofclouds.com after your jquery javascript file:

      <script type="text/javascript" src="scripts/jquery.tweet.js"></script>
    

While you're there, change your label to:

      
    

Change your actions.js file to:

      var search = function(text){
        $("#home").hide();
        $("#results").fadeIn("fast");
        $("#results").tweet({
          query: text,
          join_text: "auto",
          avatar_size: 32,
          count: 10,
          loading_text: "loading tweets...",
          auto_join_text_reply: "",
          auto_join_text_default: "",
          auto_join_text_ed: "", 
          auto_join_text_ing: "",
          auto_join_text_reply: "",
          auto_join_text_url: ""
        });
        return false;
      };

      $("document").ready(function(){
        $("#search").focus();
        $("#results").hide();
        $("#main-search").submit(function(){
          value = $("#search").val();
          search(value);
          return false;
        });
      });
    

And add this to your CSS:

      #results { float: left; display: block; width: 100%; }
      ul { margin: 0; padding :0; }

      li {
        list-style-type: none;
        text-align: left;
        background: white;
        color: #333;
        line-height: 1.5;
        border-top: 1px solid #007FC0;
        float: left;
        display: block;
        padding: 5px 0;
        font-size: 12px;
        width: 100%;
      }

      li img {
        float: left;
        display: block;
        margin: 5px 8px 5px 5px;
      }
    

And you're done! Zip everything in that folder up into a file called "search.wgt" (zip -r search.wgt *) and put it on your phone via USB cable or Bluetooth. When you run it, it'll run as a widget.

The good, the bad and the ugly

There are way more mobile browsers and widget runtimes, and it's not simple to deal with them all at the same time. Standards are moving to change that, but it takes time.

Here are some other gotchas:

Data storage for widgets

Storing stuff on the phone is done through some Javascript API calls. You don't have access to anything juicy yet, but you can store and retrieve strings, using the widget.getPreferenceForKey() and widget.setPreference() methods. To be clever, include the jQuery Cookie plugin and do this:

      var get_key = function(key){
        if (typeof(widget) != "undefined"){ // A Widget Engine!
          return widget.preferenceForKey(key);
        }else{ // It's a browser!
          return $.cookie(key);
        }
      }

      var set_key = function(value, key){
        if (typeof(widget) != "undefined"){
          return widget.setPreferenceForKey(value, key)
        }else{
          return($.cookie(key, value));
        }
      }
    

This way, you can set and get keys without worrying about whether you're saving to a cookie on a web-browser, or to the storage of a widget engine.

Additional Resources

In addition to the information on this page are two supporting documents which will help you to create apps for the Vodafone 360 H1 phone by Samsung.

'Different Resolutions on Mobile Phones' gives you advice on how to develop apps in a way which enables you to make it easier to scale across different devices with different screen resolutions and pixel depths.

'Mobile Widget User Experience Guidelines' gives you advice on how to develops apps in a way which meets Vodafone's widget user experience and gives you visual design guidance on how to design your widget.