Developers › Dev.Opera

Converting widgets to Opera extensions: Things to keep in mind

April 25, 2012 · by Shwetank Dixit

Introduction

This article will shed light on some things to keep in mind for Widgets developers when converting widgets into Opera Extensions. We recently announced that the sun is setting on our support for Widgets (and Unite) in upcoming versions of Opera, so this article will help developers who have existing Widgets to convert them into the highly-popular Opera Extensions format, if they so choose.

If you haven’t already, we'd recommended that you take a look at developing Opera extensions and gain some familiarity with how it is made before reading this article.

One very important and useful thing to note is that Opera Extensions are based on the same packaging format as Widgets, i.e, the Widget Packaging and XML Configuration Specification. There are a few differences between the two, but essentially both are based on the same config.xml file, index.html build file, and other files necessary for the look and behavior, which are then packaged together into a zip file (then given a custom file extension — .wgt for widgets and .oex for extensions).

To start with, let’s take a deeper look into the packaging format. We will take the Geolocator widget and convert it to an extension during the course of the article.

Packaging

Widgets are .wgt files and Opera Extensions are .oex files, however, both are essentially .zip files renamed into their respective formats. One thing to keep in mind is that if you want to convert your widget to an extension (especially if it requires some interactivity from the user’s side), the best way is to make it run inside the popup page of the extension. Figure 1 shows how the files differ between a Widget and an Opera Extension

Files inside the geolocator widget file

Files inside the converted geolocator extension file

Figure 1: Files inside the Geolocator widget file (top), and the converted Geolocator extension file (bottom).

In Widgets, generally the build file (called index.html) was the main page where the UI of the whole app manifested itself. All the JS, CSS and image files were ultimately linked to that. In the equivalent Opera Extension, you want to display the functionality in the popup, so start off by renaming your widget’s index.html to popup.html.

Then what about the index.html file? Is isn’t it needed even in extensions? Yes, it is. Next you should create a new index.html build file linking to the background.js script, which should look like so:

<html>
  <head>
    <title>Index Page</title>
    <script type="text/javascript" src="background.js"></script>
  </head>
</html>

The linked background.js file is needed to define the UI properties of the extension (like the icon, the popup file, the size of the popup, etc). So let's create that next; you define the popup like so:

...
popup: {
        href: "popup.html",
        width: 500,
        height: 420
      },
...

Read our article how to use the background.js script to add buttons, badges and popups to extensions to find out more about how background script works.

Keep in mind that this popup.html is just the renamed 'index.html' that we had in the widget.

Correcting the configuration file

Now let's move on to the configuration file: usually referred to as config.xml, this is a simple XML file needed for both widgets and extensions. You already have a widget config.xml, which just needs a few changes to make it work properly in extensions. These changes actually make writing config.xml easier for extensions, which is welcome news!

You need to make the following changes:

  • The <widget> tag for widget config.xml had an attribute called "dockable". That was specific to widgets, so delete it.
  • You need to add an xmnls attribute to the <widget> tag, so that it looks like <widget xmlns = "http://www.w3.org/ns/widgets">
  • In widgets, you have the tag <widgetname>. This should be renamed to <name> in the config.xml for extensions.
  • <width> and <height> are defined in the config.xml for widgets, but they are not needed for extensions, so delete those elements (in extensions, the width and height of the popup is defined in the background.js file).
  • In widgets, the author information was stated in the <id> tag of the config.xml, but this is not needed in extensions. Instead, you can include similar information in the <author> tag, with attributes like "email" and "href".
  • In widgets, icon files used to be defined in the config.xml like so: <icon>icon.png</icon>. In the config.xml for extensions, it is simply defined like <icon src="icon.png" />. You need to make this change as well.
  • The <host> tag is not required in the config.xml for extensions, so delete it.

Storage

The mechanism for storage in widgets and extensions differ slightly. In extensions, you store items using widget.preferences.setItem() and retrieve it using widget.preferences.getItem().

Storage
Actionwidgetextension
Storewidget.setPreferenceForKey()widget.preferences.setItem()
Retrievewidget.preferenceForKey()widget.preferences.getItem()

So you need to replace widget.setPreferenceForKey() with widget.preferences.setItem(), and widget.preferenceForKey() with widget.preferences.getItem() in all of your scripts when you are converting your widgets to extensions. The functions work exactly the same way; its just the naming that has changed.

The finished product

And that's it! Figure 2 shows our existing Widget running as an Opera Extension.

Geolocator extension

Figure 2: The converted Geolocator extension

You can download the Geolocator Widget file and the converted Opera Extension file and peruse the code to see the differences. As an additional example, take a look at the Analog Clock Widget and the converted Analog Clock extension.

Communication with a server using XMLHttpRequest

Some widgets require communication with a server using Ajax. This was pretty straightforward in Widgets, where you could do an XHR request directly from the index page. However, in extensions, you need to communicate with the background script, which will do the Ajax request and then communicate the result back to the popup page. We have an excellent article showing how to do this — Accessing an Opera Extension's background process.

Some widgets required the widget.openURL() method to open links in the browser. To do this in extensions however, the popup file would need to communicate with the background.js file, which will open a new tab and the load the URL within it. You can take a look at the Windows and Tabs API documentation as well as our article on messaging in extensions, which deals with communicating between different parts of an extension (including between popup and background script) and how to go ahead with it.

Polishing things up

Keep in mind that the Opera Extensions you have converting from Widgets may work, but still may or may not conform to the Opera extension publishing guidelines. We'd recommend that you take a look at it, and adjust and polish the extension to conform to the guidelines before submitting it to the Opera addons catalog.

Article cover image: cogs by Kevin Walsh

About this article

Published inDev.Opera
DateApril 25, 2012
AuthorShwetank Dixit
Tagsextensions, widgets
OriginalInternet Archive