Creating Opera Speed Dial Extensions

By Daniel Davis

From Opera 15 onward, Opera 11 & 12’s extension format is no longer supported, and instead, we’ve switched to Chromium’s extension model. Check out our new documentation for developing extensions for Opera 15 and higher and start building your own extensions.

Introduction

Back in 2007, we introduced Speed Dial to the world. The concept proved extremely popular and similar implementations can now be found in other browsers as well. But as proud as we are, what kind of parents would we be if we didn't help our baby to grow up and develop new skills? For the Opera 11.10 release, we've improved the visual display and UX of Speed Dial and added hooks for developers to control the way their site looks when rendered in a Speed Dial cell. In Opera 11.50, we're taking this a step further with Speed Dial extensions.

Just as you can extend your browser with one of the many hundreds of Opera extensions, you can also customise and extend Speed Dial to make it even more useful. Instead of being limited to web page or icon screenshots, Speed Dial can now render live extension content, and this article shows you how.

Note: To see an example running, you'll need Opera 11.50 or later plus a Speed Dial extension example: download our Speed Dial clock.

The basics

In order to maintain extensibility with regular Opera extensions, Speed Dial extensions use the same format and structure but with a couple of additions. In other words, the following small additions to the config.xml file can change an existing Opera extension into a Speed Dial extension:

  • A <feature> element with a name attribute of value opera:speeddial, which turns the extension into a Speed Dial extension.
  • A viewmodes attribute on the containing <widget> tag with the value minimized: this shows the background page in a Speed Dial cell.

Please be aware, however, that extensions cannot currently use both the Speed Dial feature and the browser toolbar. In other words, an extension that has a toolbar button cannot also be a Speed Dial extension in the current implementation.

Specifying the Speed Dial extension with config.xml

Let's put the methodology into practice and walk through an example extension. To see the following code snippets in context, download our Speed Dial clock extension and look at the source files inside the package. Figure 1 shows how our extension will look when finished.

Clock extension installed in the Opera browser's Speed Dial.

Figure 1: The clock extension installed in the Opera browser's Speed Dial.

Whereas regular Speed Dial cells show a screenshot of a page out on the Web, Speed Dial extensions show the start (or background) page of the extension—this is index.html by default. To enable this, we first need to add the viewmodes attribute to our config.xml's <widget> tag, with the value minimized:

<widget xmlns="http://www.w3.org/ns/widgets" id="http://example.com/SimpleClockSD" viewmodes="minimized">

This tells the browser to show the extension's background page in minimized form—the size of an individual Speed Dial window at 100% zoom level is 256 pixels wide and 160 pixels tall. In addition, we also need to add a feature element for Opera Speed Dial with its required attribute, and a param element:

<feature name="opera:speeddial" required="false">
  <param name="url" value="http://en.wikipedia.org/wiki/Time"/>
</feature>

The feature element's required attribute indicates whether the Speed Dial is needed for this extension to run. For example, there may be other browsers or user agents that are compatible with Opera extensions but don't have a Speed Dial. If your extension should still work in these cases use the value false; if your extension won't work without the Speed Dial choose true.

The param element is required, and specifies which page should open when the Speed Dial icon is clicked.

Here's the complete config.xml file for this extension:

<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="http://example.com/SimpleClockSD" defaultlocale="en" viewmodes="minimized">
  <name short="Simple Clock">Clock Speed Dial Extension</name>
  <description>This is an example Speed Dial extension showing a simple clock.</description>
  <author href="http://people.opera.com/danield/">Daniel Davis</author>
  <icon src="images/icon_64.png"/> <!-- Icon source: http://www.openclipart.org/detail/17552 -->
  <feature name="opera:speeddial" required="false">
    <param name="url" value="http://en.wikipedia.org/wiki/Time"/>
  </feature>
</widget>

Adding content to the extension

The next step is to create something interesting to show in the Speed Dial window. This is the extension's background page so we need to create a file named index.html in the same directory as config.xml. For this example, we're making a simple JavaScript digital clock that shows the current time to the second. Firstly, we'll create a basic index.html with an empty output element:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="style.css">
    <title>Clock Speed Dial Extension</title>
  </head>
  <body>
    <output></output>
    <script src="scripts/background.js"></script>
  </body>
</html>

Following that, we need to create a scripts directory containing the background.js file that we've linked to. This JS file looks like so:

window.addEventListener('load', function() {
  // Simple function to prefix a zero if the value passed is less than 10
  function formatTime(time) {
    return (time < 10) ? '0' + time : time;
  }
    
  var output = document.querySelector('output');
  var date, hours, mins, secs;
    
  // Get and display the current time every 500 milliseconds
  var timer = window.setInterval(function() {
    date = new Date();
    hours = date.getHours();
    mins = date.getMinutes();
    secs = date.getSeconds();
    output.innerHTML = formatTime(hours) + ':' + formatTime(mins) + ':' + formatTime(secs);
  }, 500); // Twice a second to allow for slight delays in JavaScript execution
}, false);

The accompanying style sheet (style.css) is also simple, but includes a cunning trick:

* {
  margin: 0;
  padding: 0;
}
html {
  height: 100%;
}

/* Use display:table and display:table-cell
so that we can use vertical-align:middle */
body {
  background: #444;
  color: #fff;
  display: table;
  height: 100%;
  width: 100%;
}
output {
  display: table-cell;
  font-family: monospace;
  font-size: 10em;
  text-align: center;
  text-shadow: 0 0.1em 0.1em #000;
  vertical-align: middle;
}

/* Styles here are only applied in a "minimized" state */
@media screen and (view-mode: minimized) {
  output {
    font-size: 1.8em;
  }
}

As you can see, there is a CSS3 media query at the bottom of this file that checks for the view-mode: minimized condition, in keeping with the view-mode Media Feature specification. In other words, the styles in this section will only apply when the page is shown in a minimized state such as a Speed Dial cell. This is a handy way to override styles for a certain situation without having to maintain multiple designs.

Finishing the extension off

As usual, to package our creation as an extension we zip all the files in the directory (but not the directory itself) and rename it with an .oex extension. If you haven't done so already, download the clock_SD_extension.oex and give it a try.

The SpeedDialContext API

Once installed, our extension can dynamically control its Speed Dial cell with the SpeedDialContext API. This is a very simple API with two writable properties: title and url. They are accessed from the background JavaScript through the opera.contexts.speeddial object, like so:

if (opera.contexts.speeddial) {
  var sd = opera.contexts.speeddial; 
  sd.title = "My title";
  sd.url = "mypage.html"; 
}

We can use this feature to enhance our clock extension, for example by making it display a friendly message depending on the time of day. The only file we need to edit is the background.js JavaScript file:

window.addEventListener('load', function() {
  // Simple function to prefix a zero if the value passed is less than 10
  function formatTime(time) {
    return (time < 10) ? '0' + time : time;
  }
    
  var output = document.querySelector('output');
  var date, hours, mins, secs, tmp_hours, timeofday;
  var messages = {
    "morning": "Good morning!",
    "afternoon": "Good afternoon!",
    "evening": "Good evening!",
    "night": "Shouldn't you be in bed?"
  };
    
  // Get and display the current time every 500 milliseconds
  var timer = window.setInterval(function() {
    date = new Date();
    hours = date.getHours();
    mins = date.getMinutes();
    secs = date.getSeconds();
    output.innerHTML = formatTime(hours) + ':' + formatTime(mins) + ':' + formatTime(secs);
        
    // Make the Speed Dial title display time-related message
    if (hours !== tmp_hours) {
      if (hours > 15) {
        timeofday = 'evening';
      } else if (hours > 11) {
        timeofday = 'afternoon';
      } else if (hours > 3) {
        timeofday = 'morning';
      } else {
        timeofday = 'night';
      }
            
      if (opera.contexts.speeddial) {
        opera.contexts.speeddial.title = messages[timeofday];
      }
      tmp_hours = hours;
    }
  }, 500); // Twice a second to allow for slight delays in JavaScript execution
}, false);

This is the same as the first example but with a few things added, namely:

  • A messages object containing messages for various times of day.
  • A repeated check that runs code when the hour has changed.
  • A line that shows the relevant message from the messages object in the Speed Dial title.

This extension can be downloaded here: friendly_clock_SD_extension.oex. When installed, this is how it will look:

Friendly clock extension installed in the Opera browser's Speed Dial.

Figure 2: The friendly clock extension installed in the Opera browser's Speed Dial.

Conclusion

As you can see, extension developers now have an extra window of opportunity to add convenience, ease-of-use or just fun to their extensions. The examples here are basic but show the potential of Speed Dial extensions when combined with clever ideas and web development skills. We're hoping to see Speed Dial extensions become more than just pretty links to a website, so we look forward to seeing the creative ways you use this API over at the Opera extensions repository!

Reference

Opera Extensions API: Speed Dial guide

This article is licensed under a Creative Commons Attribution 3.0 Unported license.

Comments

The forum archive of this article is still available on My Opera.

No new comments accepted.