How to build mobile widgets

If you’re a web developer or designer, there’s a really exciting development happening right now called ‘mobile widgets’. Carsonified is working with Betavine to spread the word about mobile widgets, so we recently spent four days building one in order to see how hard or easy they are to build. The result was Twiggy, a Twitter search widget, and today we’re going to talk about how we built it.

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 (we used jQuery). 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. The device installs the widget locally, and then it can talk to the web. Widgets can currently run on Nokia S60 phones (currently 1M+ and growing).

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.

Why are they a good idea?

We think mobile widgets are a really good idea because they allow you to reach a huge non-iPhone audience. Don’t get me wrong, everyone at Carsonified has iPhones and we love The Steve, but we’re not ‘normal’ and as web designers and developers, we have to consider there are a heck of a lot of people out there who would really benefit from useful widgets that ran on their phones. (They also run on Opera.)

Also, you can easily port mobile widgets to iPhone with a few simple tweaks. Here’s the version of Twiggy that works on an iPhone.

Here’s a quick video to show widgets in action, on a Nokia N96:

Cold hard cash

To encourage people to try building mobile widgets, Betavine are running a competition with a prize of £20,000. There’s no obligation to Betavine, you keep the IP to the code and they promote the widget to Vodafone customers, so it’s a pretty nifty deal.

What’s in a widget?

As I mentioned above, 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:

  1. A widget configuration file. This is an XML file in the root of the widget structure that holds information about your widget including its size, name, author, and security information.
  2. An index document. Like on a web page, this document contains the basic skeleton/content of the widget. Widgets content can be created using any markup that browsers handle natively, for example HTML, SVG, or XML files. This file also lives in the root of the widget structure.
  3. Images. These are contained in a single images folder.
  4. JavaScript files. These are contained in a single script folder.
  5. Stylesheets. These are contained in a single style folder.

I’m going to hand it over to Elliott Kember, who built Twiggy, to go into detail about how Twiggy was built, and what hurdles we had to overcome. Over to you bud …

Mobile widget tutorial

Thanks, Ryan!

Hey everyone, I’m Elliott and I built Twiggy. I’m going to take you through a brief walk-through of how to build a widget.

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 our widget, we’re using this:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <title>Twiggy</title>
    <!-- This is for the Opera Widget Emulator. -->
    <script type="text/javascript">if(window.parent&&
    parent.emulator)parent.emulator.begin(window)</script>
    <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>

If you want to use any other jQuery plugins, drop them in the /scripts folder and include them as normal:


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

Now, add these lines to your <head>, just in case you ever want to look at the page on your iPhone:


<meta name="viewport" content="initial-scale=1,
maximum-scale=1,minimum-scale=1 user-scalable=no,width = 320" />
<meta name="viewport" content="width=device-width;
initial-scale=1.2; maximum-scale=1.2; user-scalable=0;" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta names="apple-mobile-web-app-status-bar-style"
content="black-translucent" />

They tell the iPhone how to render the page, what level of zoom to use, and basically tell it to treat the page like a web-app.

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:


*{outline: none !important;}
input::-moz-focus-inner { border: 0 !important; }

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:


<label for="search">What are you looking for?</label>

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. When you run it, it’ll run as a widget.

Testing with an emulator

Go get the widget emulator and try it. It should look like this:


The good, the bad and the ugly

This is a cool experiment, because you now have a site that will work in just about anything. The iPhone will handle it, it’ll work as a dashboard slice, browsers like it, and it can be run as a widget. We’ve tried to port it to a PhoneGap app for the iPhone, but no success yet.

There’s really not too much to watch out for. You do, however, have to be careful with your 100% width layouts so that the application doesn’t scroll horizontally.

Here are some other gotchas:

  • Auto-focus input fields wherever logical. Nobody likes using that !$?*! joystick mouse.
  • Hover effects are important. Make buttons obvious, because getting to them is a nightmare.
  • Make sure the phone has your typeface, and renders it nicely. I got caught out with italics.
  • Don’t resize images with HTML – although this is pretty good advice anyway. The phone does it wrong, and it looks horrible.
  • Even if you think you’re only bundling this on the phones, use CSS sprites – because once you’re done, you have a web app waiting to happen, and waiting for your button images to load on hover is lame.
  • There’s no keypress-type event handling, which is a damn shame if you’re making a game. Poll instead.
  • Remember, the phone is fast, but not as fast as your computer is. Neither is the network connection, so be thrifty.

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) != &#039;undefined&#039;){ // A phone!
    return widget.preferenceForKey(key);
  }else{ // It&#039;s a browser!
    return $.cookie(key);
  }
}

var set_key = function(value, key){
  if (typeof(widget) != &#039;undefined&#039;){
    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, or to the phone. Happy hunting!

Elliott is a freelance developer who lives in Bath, and used to work for Carsonified. He writes CSS, uses Rails and is generally available. He also likes long walks on the beach and candle-lit dinners. You can find him at @elliottkember or elliottkember.com.

Treehouse

Our mission is to bring affordable Technology education to people everywhere, in order to help them achieve their dreams and change the world.

Comments

30 comments on “How to build mobile widgets

  1. Cool piece. Sharing code is so much more helpful than just talking about it.Ryan was talking about transparency lately as an important value for businesses. It seems like the Crasonified brand values are not limited to business only. Love it!

  2. Cool piece.
    Sharing code is so much more helpful than just talking about it.

    Ryan was talking about transparency lately as an important value for businesses. It seems like the Crasonified brand values are not limited to business only. Love it!

  3. Firstly, this is a comprehensive article, and very informative. The process of building this – and even more so the accompanying web site – has been great.But secondly, *my* disclaimer: I'm the world's most persistent mobile widget naysayer :-)I'm still lost on two points in particular:1) Why is it better to make a widget than just to do this in the browser? In most cases the same browser engine is used for the widget, so the compatibility (or lack of it!) does not change magically because of the choice of container.2) How do you update it? Are you going to ask your users to install another version of a funny little ZIP file every time?As a web designer, and if I was making an impartial decision (sorry, Dan ;-) ), I would have to think very carefully about going down the widget route. I don't want your readers to come away with the thought that this is the only way to get modern interactivity to a mobile device.To me, it makes far more sense to use the same code to create a mobile web site with exactly the same functionality. (After all, this widget requires a connection to work anyway.)Not only would it be just as compatible (in fact, possibly more so, because I can adapt the site in realtime to the requesting device more easily than a packaged widget can), but I would also be able to update it or fix bugs on the server without having to ask any of my users to reinstall it again.Further, by building it as a web app: – it's just as easy for the user to launch (via the magic of, erm, bookmarks) – you'll get to see usage statistics – it's easier to monetize through open-market ads – you'll get the same client-side capabilities as widgets via BONDII notice you ended up doing this anyway: http://www.elliottkember.com/twiggy – and in fact by escaping the widget container, you *did* make it work on the iPhone! Ahem… :-)Finally, I'm no conspiracy theorist, but it's worth realising that widgets are a web app container that certain parts of the mobile ecosystem have greater control over than they do regular off-deck sites.

  4. Firstly, this is a comprehensive article, and very informative. The process of building this – and even more so the accompanying web site – has been great.

    But secondly, *my* disclaimer: I'm the world's most persistent mobile widget naysayer :-)

    I'm still lost on two points in particular:

    1) Why is it better to make a widget than just to do this in the browser? In most cases the same browser engine is used for the widget, so the compatibility (or lack of it!) does not change magically because of the choice of container.

    2) How do you update it? Are you going to ask your users to install another version of a funny little ZIP file every time?

    As a web designer, and if I was making an impartial decision (sorry, Dan ;-) ), I would have to think very carefully about going down the widget route. I don't want your readers to come away with the thought that this is the only way to get modern interactivity to a mobile device.

    To me, it makes far more sense to use the same code to create a mobile web site with exactly the same functionality. (After all, this widget requires a connection to work anyway.)

    Not only would it be just as compatible (in fact, possibly more so, because I can adapt the site in realtime to the requesting device more easily than a packaged widget can), but I would also be able to update it or fix bugs on the server without having to ask any of my users to reinstall it again.

    Further, by building it as a web app:

    – it's just as easy for the user to launch (via the magic of, erm, bookmarks)
    – you'll get to see usage statistics
    – it's easier to monetize through open-market ads
    – you'll get the same client-side capabilities as widgets via BONDI

    I notice you ended up doing this anyway: http://www.elliottkember.com/twiggy – and in fact by escaping the widget container, you *did* make it work on the iPhone! Ahem… :-)

    Finally, I'm no conspiracy theorist, but it's worth realising that widgets are a web app container that certain parts of the mobile ecosystem have greater control over than they do regular off-deck sites.

  5. wow this is very nice of you to share this code. This is the first time for me to be here and I'm amazed to see this much knowledged shared in one post. I agree with Adam that transparency is a really strong value in business. The more real you are the more people will trust you. And of course it's known that people rather do business with others they trust rather than a complete stranger!

  6. wow this is very nice of you to share this code. This is the first time for me to be here and I'm amazed to see this much knowledged shared in one post.

    I agree with Adam that transparency is a really strong value in business. The more real you are the more people will trust you. And of course it's known that people rather do business with others they trust rather than a complete stranger!

  7. What an amazing article.Thanks alot for all of this insightful information. you really made me consider mobile wdgets

  8. What an amazing article.
    Thanks alot for all of this insightful information. you really made me consider mobile wdgets

  9. Hi James,Great points – and I appreciate you making them. To answer your questions:1) Widgets are eventually going to have access to system-level functionality like location, contacts and more. This is because they're more trusted than a web app because the user said it was OK to install them.2) The Widget Manager will check for updates and ask if it's oK to install them – much in the same way that iTunes lets you know about updates to iPhone apps

  10. Hi James,

    Great points – and I appreciate you making them. To answer your questions:

    1) Widgets are eventually going to have access to system-level functionality like location, contacts and more. This is because they're more trusted than a web app because the user said it was OK to install them.

    2) The Widget Manager will check for updates and ask if it's oK to install them – much in the same way that iTunes lets you know about updates to iPhone apps

  11. Great article. I love the way you walked through every step. I had been trying to find a detailed layout of how to do it. Again, solid article. Thanks.

  12. You know at first I thought this was going to be complicated but you really made sense with this. I easily understood your examples and instructions. Thanks!

  13. Love the Twiggy font you've used in the heading – what font is that? Yes you can tell I'm biased towards the design of this, rather than the development side of making widgets.

  14. Love the Twiggy font you've used in the heading – what font is that? Yes you can tell I'm biased towards the design of this, rather than the development side of making widgets.

  15. Great introduction to mobile widget development. Am curious where this fractured market is going to go and whether or not the consumer will care for widgets versus dedicated apps on mobile platforms. Likely to depend upon how good the mobile widget platform is and how good the majority of widgets are. Again, great job on the article.http://jccameron.com

  16. Great introduction to mobile widget development. Am curious where this fractured market is going to go and whether or not the consumer will care for widgets versus dedicated apps on mobile platforms. Likely to depend upon how good the mobile widget platform is and how good the majority of widgets are.

    Again, great job on the article.

    http://jccameron.com

  17. Wow, am also a freelance web designer but I don't have any idea about this using on the phone, I will try this to my phone if it will works. Thanks for this amazing information.

  18. Wow, am also a freelance web designer but I don't have any idea about this using on the phone, I will try this to my phone if it will works. Thanks for this amazing information.

  19. Pingback: Developing a mobile blogclient with Breeze | futtta's blog

  20. nice one,
    Since I saw this tutorial in .net magazine, I have been thinking of designing a widget esp for my iphone, and this tutorial has gone a long way to simplify some things for me.
    you are awesome, thankx

  21. There’s an interesting set of tools from phonegap. It’s open sourced, so a good way to go. I think things are moving more toward a mobile culture, ie. going mobo. So building apps is going to be the way to go (iPhone, Droid, Blackberry, you name it). I should mention thought that having the right mobile etiquette (see http://www.goingmobo.com/category/etiquette for more) and mobile techniques can make all the difference. (BTW I think there’s a big difference between yakkers and mobos.)

    Also: laptops being replaced by mobile devices like the iPad. We may have desktops, but the rest of the technology is truly going mobo. Good dev stuff. -JJ