Modules for iCab Mobile (Updated 2011/03/26)

Update 2011/03/26
Please also read the blog post “iCab Mobile Modules and Apple” for recent events, affecting the modules feature.

The version 2.1 of iCab Mobile introduces a new “modules” feature. Modules make it possible to add new features in iCab Mobile just by downloading them. They can be used for simple things like increasing the font size so a page is more easy to read on the small iPhone screen, but also more complex tasks can be done, like downloading YouTube videos or to post a web page URL at Twitter (including the login and creating a tiny URL). iCab Mobile 2.1 comes with a few built-in modules, and there are also several modules available for download.

This blog post will explain, how you can write your own modules for iCab Mobile and how you (and maybe other users) can install them in iCab Mobile.

Technical background

Technically, modules are somehow similar to bookmarklets, but with more features and more flexibility. This means the modules are written in JavaScript code and they can do everything that can be done with JavaScript. Unlike bookmarklets, where the complete JavaScript code must be squeezed in one single line so that it can be used as a URL with “javascript” scheme, the modules can be nicely formatted, without any line limitation. Modules have a special header section where the module properties are defined. The properties include an icon that is displayed in the Modules panel of iCab Mobile, but also settings which do allow the user to configure the module in the iCab Mobile module settings panel.

The module structure

The module is a normal text file with JavaScript code. There’s a header section and the code section. Here’s an example, how this looks like:

//startconfig
//id=de.icab.crazy
//icon=iVBORw0KGgoAAAANSUhEUgAAACwAAAAkCAYAAADy19hsAAAWrGlDQ1BJQ0...
//title=Crazy Layout
//description=The module sets random colors for the page elements
//description.de=Das Modul setzt alle Farben der Seite auf Zufallswerte
//var=confirmation;type=confirmation;default=false;
//var=language;type=language;
//endconfig

var hex = "0123456789abcdef";

function iCabMobileGoCrazyForElement(element) {
  if (element.nodeType == 1) {
    if (element.style.display != "none" &&
           element.nodeName.toLowerCase() != 'select') {
      element.style.backgroundColor = "#" +
                   hex.charAt(Math.random()*16) +
                   hex.charAt(Math.random()*16) +
                   hex.charAt(Math.random()*16);
      element.style.color = "#" +
                  hex.charAt(Math.random()*16) +
                  hex.charAt(Math.random()*16) +
                  hex.charAt(Math.random()*16);
      for (var i=0; i<element.childNodes.length; i++) {
        iCabMobileGoCrazyForElement(element.childNodes[i]);
      }
    }
  }
}

var doAction = (confirmation == false);

if (confirmation) {
  var text = "Go crazy?";
  doAction = confirm(text);
}

if (doAction) {
  iCabMobileGoCrazyForElement(window.document.body);
}

The header section defines the properties of the module. The header section starts with the line

//startconfig

and ends with the line

//endconfig

Between these two lines all the properties are defined, each individual property definition occupies exactly one line, so currently you can’t split the definition of a property into multiple lines. Also no empty lines are allowed in the header section. Each property definition has the following format:

//property=value;additional paramaters

The additional parameters are optional and not always needed or required.

There are some properties which are required. If they are missing, iCab Mobile will ignore the module. Other properties are optional and do not need to be present. Here are the properties which are currently supported:

id (required)
This property identifies the module. When updating or reinstalling a module, the value of the “id” will be used to find the old module that has to be replaced by the new one. So when updating a module, you must not change the value of the “id”. Everything else can be modified, even the name of the module. The value of the “id” property should be unique among all existing modules. The best way to find a good “id” value is to use a reverse domain name appended with the module name. If your own web page has the domain “www.your-domain.com” you should set the “id” value to “com.your-domain.moduleName”. All of your own modules will have the same reverse domain prefix and the module name as suffix. If you don’t have your own domain, you can use your name and city as a prefix and maybe some random numbers, anything which makes it unlikely that someone else uses the same id value. The “id” is not visible to the user within iCab Mobile. Its only used to identify the module.
Example: 

//id=de.icab.crazy

or if you don’t have your own domain, you may use something like this:

//id=de.darmstadt.clauss.alexander.crazy
title (required)
The title defines the name of the module and is displayed within the modules settings of iCab mobile. The title property is needed so that the user can enable or disable the modules in the in-app settings and also configure the modules settings.
Example: 

//title=Crazy Colors

You can also define localized versions of the title. Just append the language code (for example “en” for English, “de” for German, “it” for Italian etc.) of any of the languages which are supported by the iPhone OS to the “title” keyword
like this:

//title.de=Verrückte Farben

This way you can easily localize the module in many languages. The key “title” without a language code appended will be used as default language which is used when none of the defined languages does match the current language of the iPhone or iPod Touch. In general the default language should be English. If no default language is defined, then the very first language that is define will be used as default language. But it is highly recommended, that you simply use English as the default language (without language code).

So if the module supports English and German, the title would be defined this way:

//title=Crazy Colors
//title.de=Verrückte Farben
description (optional)
The description is displayed in the settings panel of the module in iCab Mobile. The description should explain what the module is doing. Localizing is done in the same way as described above for the title. Append the language code to the “description” keyword: 

//description=The module sets random colors for the page elements
//description.de=Das Modul setzt alle Farben der Seite auf Zufallswerte
icon (optional, but highly recommended)
The icon is displayed when the user opens the modules panel where the modules can be activated by tapping on their icon. The icon should be an image file in PNG or JPG format. The data of the image file must be encoded with “base64” and this “base64” encoded data can be then used as value for the “icon” property. Usually the base64 data is formatted in lines of at most 64 characters length, but for the modules, all line breaks must be removed, so the icons data can be completely included in one line. The size of the module icons (the visible part) should be approx. 41*32. You can use the following empty icon image as a template for your own icons:
 

//icon=iVBORw0KGgoAAAANSUhEUgAAACwAAAAkCAYAAADy19hsAAAWrGlDQ1BJQ0...
var
The “var” property defines JavaScript variables, which are initialized by iCab Mobile. These variables can be used to allow the user to configure the modules, but also to get certain system properties, like the system language. 

Variables do have the following format:

//var=NameOfVar;type=typeOfVar;default=defaultValue;title=labelForSettings;

iCab Mobile will create a standard JavaScript variable declaration and initialization for all of these variable properties and adds these to the JavaScript code of the module. So your JavaScript code of the module can check and use these variables just like any other variables.

The value of the “var” property is the name of the variable.

The “title” property is required, when the variable should be presented to the user in the module settings, so the user can change the value of the variable. The value of the “title” property is used as the label in the settings panel. You can add additional localized versions of the title, just by appending the language code (as described above).

The “default” property can be used to define a certain default value for the variable.

The value of the “type” property is the type of the variable, which can be one of the following:

bool or boolean
The variable can have the values true or false. In the module settings this variable will be represented by a “switch” control. If the user switches it on, the variable will have the value true otherwise the variable will have the value false. The title attribute is required for this type. The title is shown as label for the switch in the module settings.
int or integer
The variable can have a numerical value. In the module settings, this variable is represented with a text field where you can enter digits. The title attribute is required for this type. The title is shown as label for the edit field in the module settings.
string or text
The variable can have a string value. In the module settings, it is represented as a text field. The title attribute is required for this type. The title is shown as label for the edit field in the module settings.
pass or password
The variable can have a string value. In the module settings, it is represented as a text field where the input is hidden. The title attribute is required for this type. The title is shown as label for the edit field in the module settings.
lang or language
The value of this variable is a string that contains the language code of the currently selected system language. This variable is not presented in the settings panel of the module. Therefore no title property is required here.
confirm or confirmation
The variable has a boolean value. It is represented in the module settings by a switch where the user can enable or disable a confirmation box. If enabled, iCab Mobile will ask each time the module is activated, if it should be really executed. This variable does not need a “title” property because it is automatically localized within the module settings panel.
autorun
The variable has a boolean value. It is represented in the module settings by a switch where the user can configure, if the module should be automatically run when the page has finished loading. This variable does not need a “title” property because it is automatically localized within the module settings panel. If there’s no variable of the type “autorun” set, the module can only be opened manually. You can set the default value for the variable to switch on or off the “autorun” feature for the module. But the user will be always able to disable the “autorun” feature in the module settings. When the modul is executed, the variable that is defined with the type “autorun” will have the value “true” if the module was executed automatically (which means when the page has finished loading) and the value “false” if the module was opened manually by the user. So a module is able to do different thing when called automatically and when called manually (for example it can mark elements when called automatically to notify the user about something, and modify the elements when called manually, to do the real work). [This feature will be available in iCab Mobile 3.3, it’s not yet available in version 3.2]
select
The variable of this type can be used to select one item from an array of items. This variable type uses the title property in the same way as the other types to define the label in the module settings. This variable type requires that two other properties are defined as well. The “values” property must be defined to create the array of values the user can choose from, and the “valuetitles” property must be defined to define the array of titles for these values. The “valuetitles” properties is localizable again, so append the language code as shown above for the “title” property. For the “values” and “valuetitles” property, all items must be separated by the “|” character.
An example: 

//var=s;type=select;valuetitles=One|Two|Three;values=1|2|3;title=Number;default=2

In the settings the user would be able to choose between “One”, “Two” and “Three”. If the user selects “One” the variable s would have the value 1, if the user selects “Two” the variable s would have the value 2 etc. The default value would be 2 and the user would see that “Two” is preselected. The whole setting would have the label “Number”.

When the user activates a module, iCab Mobile will process the header sections and creates JavaScript variable declarations for all the variable definitions from the header section. The values for these variables will be determined by the module settings. Technically, iCab will add these variable declarations before the JavaScript code section of the module, so the module can access these variables. These variables and the JavaScript code section will be embedded in a block, so they have their own scope and do not interfere with the JavaScript code and variables which are already present in the web page.

This means, when the module looks like this:

//startconfig
//id=de.icab.module
//icon=iVBORw0KGgoAAAANSUhEUgAAACwAAAAkCAYAAADy19hsAAAWrGlDQ1BJQ0...
//title=Some Module
//var=confirmation;type=confirmation;default=false;
//var=language;type=language;
//var=text;type=string;title=Text;
//endconfig

function DoSomething() {
  // here's the actual code which is doing all the work of the module
}

if (confirmation) {
  doAction = confirm("Really activate the module?");
} else {
  doAction = true;
}

if (doAction) {
  DoSomething();
}

the resulting code that is actually executed in the context of the web page looks like this:

{
  var confirmation = true;
  var language = "en";
  var text = "User Input";

  function DoSomething() {
    // here's the actual code which is doing all the work
  }

  if (confirmation) {
    doAction = confirm("Really activate the module?");
  } else {
    doAction = true;
  }

  if (doAction) {
    DoSomething();
  }
}

Special JavaScript functions

Modules can also call special JavaScript functions, which are defined by iCab Mobile to do certain tasks.

There are the following functions available:

startDownload(url,file)
This function starts a download. The parameters are the URL and a suggestion
for the filename under which the download should be saved.
postRequest(url,content,”callBackFunction”)
This function gets the data from the URL using the HTTP POST command (posting “content” to the server) and then passes the HTTP status code and the data to a function called “callBackFunction” (see getRequest() below for a description of the callback function).
getRequest(url,”callBackFunction”)
This function gets the data from the URL using the HTTP GET command and then passes the HTTP status code and the data to a function called “callBackFunction” (the second parameter is a string with the name of the callback function that must be implemented by the Module to process the data): 

function callBackFunction(status, data) {
  // "status" is an integer value with the HTTP status code (200, 404, etc)
  // "data" is a string with the URL data
}

Installing the modules

Installing the modules is done by simply downloading them from a web site. So all you need to do is to provide a web page which contains a link to your module. The link URL must use the URL scheme “icabmodule” or “javascriptmodule” instead of the usual “http” scheme. This is how iCab Mobile detects that it should download and install a module.

For example, if your module can be accessed with the URL http://your.webspace.com/modules/TheModule.icabmodule
the HTML link you would have to include in your web page would look like this:

<a href="icabmodule://your.webspace.com/modules/TheModule.icabmodule">Download TheModule</a>

or alternatively look like this:

<a href="javascriptmodule://your.webspace.com/modules/TheModule.icabmodule">Download TheModule</a>

If you include these links on a web page which is accessible to other people as well, other iCab Mobile users would be also able to install your module. So you can easily share your modules with other users.

I’ve created two URL schemes for the modules. In case other iPhone developers are interested in this module feature (candidates would be developers of other iPhone browsers), it would be great if all these modules would be compatible. In this case the general URL scheme “javascriptmodule” could be used by all the Apps supporting the modules feature. And the other URL scheme could be used for application specific-modules (so “icabmodule” would be only accepted by iCab Mobile).
Just a reminder: My AppLink Proposal can be also used by other iPhone Apps.

You can also sent the module to me so I can include it into the modules download page, which is accessible through the “Download” module that is built-in in iCab Mobile. This way the module can be immediately found by all iCab Mobile users.