GM_config - a configuration GUI for your scripts

Written by IzzySoft — Last update Aug 9, 2009

18 points

Description

GM_config is a script providing you with an easy to use GUI to help the user configuring your scripts. The GM_config Extender script, as the name suggests, extends it with more useful functionality. These scripts are developed and maintained by sizzlemctwizzle, JoeSimmons, and IzzySoft. The following guide provides an API reference to both, as well as some examples of usage to get you started with these scripts.

API reference

The API reference needs to be split into two sections here. The first documents the API of the core script (GM_config). The second describes the extensions made by this script.

GM_config reference

void init(string title, object settings[, string CSS][, object hooks])
initializing the class:

  • string title: what to display on top of the configuration screen
  • object settings: settings to handle (see example)
    • optional array section [string title, optional string subtitle]
    • string label: text next to the form field
    • string title: tooltip text
    • string type: type of the form element. Chose one of: text, textarea, int, float, checkbox, radio, select
    • array options:
      • for type=select: either ['value_1','value_2',...,'value_n'] or {'value_1':'display_1','value_2':'display_2',...}
      • for type=radio: ['value_1','value_2',...,'value_n']
      • for the other types there are no options
    • mixed default: default value for the form elemt. Type depends on the type of the element.
  • string CSS: additional CSS to apply
  • object hooks: open: function(), save: function(), close: function() - things to execute on these events

void open()
opens the configuration screen.

void close(boolean save)
closes the configuration screen, optionally saving the settings.

void set(string name, mixed val)
Change the specified setting to the specified value. Just changes in the current scope - this function does not actually save the settings.

mixed get(string name)
Get the value for the specified setting from the current scope.

void save()
Save current settings.

object read()
Reads the settings from their storage and returns them as object. To get a value before calling init(), use e.g. lang=(GM_config.read().lang||'english').

void reset()
Reset settings to their defaults, as specified with the init() function.

GM_config_extender reference

The GM_config Extender script adds the following:

void addTooltip(int num, string nam)
This is pretty obsolete now that the core script provides tooltips itself (since v1.0.5) - but I left in inside for the rare cases one needs to alter them at runtime: Add a tooltip to the specified setting on the settings screen:

  • num: position of the setting (starts counting at 0)
  • nam: tooltip text

Must be used when the config screen is opened (e.g. inside the open() hook).

mixed gets()
Retrieve a setting before init() was called. This should only rarely be used. A good case is to retrieve the preferred language - which may be necessary to set up the configuration screen accordingly.

void copySettings()
Copy the stored settings to the clipboard. For Mozilla based browsers, this requires signed.applet.codebase_principal_support to be set to true (e.g. in about:config). Remark: With this setting, each access to the clipboard requires the user to approve. Without it, just an error will pop up.

void pasteSettingsFromClipboard()
Same requirements as the function before. Will take the current clipboard content and overwrite the current settings with it - after the user approved it again. THIS IS DANGEROUS AND PROBABLY SHOULD NOT BE USED AT ALL! Having something else than valid settings in the current clipboard, this will destroy your settings. Better use the next function, though that requires an extra step.

void pasteSettings()
Prompts the user to paste settings into a JavaScript Prompt box, asks for confirmation, and then saves the input as current settings. Should also only be used if you know what you are doing.

void setTranslations(string lang, object translations)
Add your own translations to the translation system. lang should be a two-character language code, the translations are an object with the syntax {'handle':'translation','handle2':'translation2',...}

void initLocalization(string lang, boolean fallback)
Tell the script what settings to use for localization. lang again is a two-character language code. If fallback is set to true, the lang() function will return the passed handle if no translation was found. Set to false, an empty string will be returned in that case.

string lang(string handle)
Returns the translation for handle in the language setup with initLocalization(). If no translation was found for the set language, if will fallback to English. If it can neither find an English translation, it either returns the handle or an empty string - depending of how you initialized the localization.

void localizeButtons()
Adjusts the buttons to the setup language. Must be used when the config screen is opened (e.g. inside the open() hook).

void resizeFrame(string width, string height)
Resizes the configuration window. Specify values like '600px' or '80%'. Must be used when the config screen is opened (e.g. inside the open() hook).

void addBorder(optional object property)
Applies a customized border to the configuration screen. Use the property parameter for your own customized settings. By default, this is: {'width':'5px','style':'ridge','color':'#eae9e8'}. Must be used when the config screen is opened (e.g. inside the open() hook).

string eCSS
Call it either exampleCSS or extendedCSS, just as you like: Gives you a more stylish look and feel for the config screen without having to create your own CSS. Nothing really fancy, but IMHO a bit smarter than the original style. But as you know, there's no accounting for taste :-) Use it in init() if you like.

string fadeCSS
CSS code to be used to fade out the main page content when opening the config menu. This will be appended to the page by GM_config.fadeOut() and removed again by GM_config.fadeIn(), see below.

void fadeOut(optional string fadeCSS)
Appends CSS code to the page to fade it out, while excluding the config menu frame. If you don't pass the optional parameter, it will use GM_config.fadeCSS, where you can base your own customized CSS upon. To use it, you have to explicitly pass it to GM_config.init() with the open() hook. Don't forget to place GM_config.fadeIn() into the close() hook as well if you want to see the main page again after closing the menu :-)

void fadeIn()
Simply removes the style added by GM_config.fadeOut(). Is intended to be used as described there.

void sections2tabs()
Convert the sections created using the base class functionality into tabs, to spread the configuration screen to multiple virtual pages. This is technically realized by hiding/showing elements, so "physically" it is still a single page - which means e.g. the save button saves settings from all tabs, and nothing gets lost when switching tabs.

Example usage

To keep things as clear as possible, the following examples will just deal with a minimal "Personal Data" form with the fields "name" (string), "age" (integer), "married" (Radio-Choice), and "public" (boolean). I will try to focus on the topics given, and you can combine things later for yourselves.

The Basic Form

GM_config.init('Configuration for Personal Data',{
  name:    { label: 'Name:', type: 'text', cols:50, default: 'John Doe' },
  age :    { label: 'Age:', type: 'int', default: 21 },
  gender:  { label: 'Gender:', title: 'Are you a guy - or a girl?', type: 'radio', options:['Male','Female'], default: 'Male' },
  public:  { label: 'Public Profile:', type: 'checkbox', default: false }
});
GM_config.open();

This is the very basic method - no fancy stuff, just focussed on the data. With the init() call we tell GM_config what data we are handling, and what the defaults are. With the read() command we check for saved data. Finally, the open() command will invoke the config screen, which then will take care for the rest itself. All you probably need to do additionally is to have a proper handler set up to invoke open() - since this way (as above) it would be called on every page load. So we better put that into the Greasemonkey User Menu:

GM_registerMenuCommand('PersonalData: Configuration',GM_config.open);

Done. If that's all you need, you can stay with GM_config - and don't need the extender.

And this is what it would look like:
gm_config_ext_basic.gif (8 KB)

The Localized Form

To get our localization working, we first need to provide some additional translations. The GM_config Extender already knows how to deal with the buttons in English and German - but it does not know anything specific for your script. So we will teach it first:

lang_en = {
  'ConfigTitle': 'Configuration for Personal Data',
  'Name': 'Name',
  'Age': 'Age',
  'Gender': 'Gender',
  'PublicProfile': 'Public Profile'
};
lang_de = {
  'ConfigTitle': 'Konfiguration für Personal Data',
  'Name': 'Name',
  'Age': 'Alter',
  'Gender': 'Geschlecht',
  'PublicProfile': 'Öffentliches Profil'
};
GM_config.setTranslations('en',lang_en);
GM_config.setTranslations('de',lang_de);
GM_config.initLocalization('de',true);

Should be quite clear: First we set up two objects with the translations for English and German (that's the two objects defined, lang_en and lang_de). Then we tell setTranslations() to add them to the translations already known, and finally we use initLocalization() to tell the GM_config Extender to use the German translations plus, in case no German and no English translation is found, just to return the original string. No we can go for a revised version of our code from the Basic Form above:

GM_config.init(GM_config.lang('ConfigTitle'),{
  name:    { label: GM_config.lang('Name'), type: 'text', cols:50, default: 'John Doe' },
  age :    { label: GM_config.lang('Age'), type: 'int', default: 21 },
  gender:  { label: GM_config.lang('Gender'), type: 'radio', options:['Male','Female'], default: 'Male' },
  public:  { label: GM_config.lang('PublicProfile'), type: 'checkbox', default: false }
});
GM_registerMenuCommand('PersonalData: Configuration',GM_config.open);

Well, you may notice I forgot about translating the genders and the menu item - but you got the idea and can do that yourselves :-)

What this configuration screen would look like, you can see here:
gm_config_ext_localized.gif (9 KB)

The Enhanced Form

To keep this clear, we will skip the localization here and revert to the "Basic Form" to start with. What we are going to do, is

  • add a border to the config frame
  • apply some custom CSS
  • Resize the config frame
  • add tooltips to our settings to explain them
  • obtain a stored setting (our language) prior to init() to use the correct localization (well, without using it here - to keep things clear, as said)
var lang = GM_config.gets('lang','en'); // get the language - or set it to 'en' if it was not yet stored
var configStyle = <><![CDATA[
/* Remove the 40% wasted space to the left */
.indent40 {
  margin-left: auto !important;
}
]]></>.toString();
GM_config.init('Configuration for Personal Data',{
    name:    { label: 'Name:', type: 'text', cols:50, default: 'John Doe' },
    age :    { label: 'Age:', type: 'int', default: 21 },
    gender:  { label: 'Gender:', type: 'radio', options:['Male','Female'], default: 'Male' },
    public:  { label: 'Public Profile:', type: 'checkbox', default: false }
  },
  configStyle, // add your CSS - or replace this with GM_config.eCSS
  {
    open: function() {
      GM_config.addBorder(); // add a fancy border
      GM_config.resizeFrame('480px','360px'); // resize the config window
      GM_config.addTooltip(0,'Put your name here'); // add some tooltips
      GM_config.addTooltip(1,'How old are you today?');
      // GM_config.sections2tabs(); // convert the sections to tabs - but we didn't define any section
    },
    save: function() { location.reload(); } // reload the page when configuration was changed
  }
);

Admitted, the CSS used in the example is not doing that much - but the example shall just show how to use the stuff (besides, as the comment suggests, you can use GM_config.eCSS here, which is available in GM_config Extender since v1.0.1). Extend it as you like, or see the links below for projects using GM_config where you may "borrow" nice style definitions.

Let's see what this may look like - much better already:
gm_config_ext_enhanced.gif (8 KB)

Using sections

Sections can be used to group settings. You may not need this if you've got only a few settings - but the more they get, the more useful sections can be. To define a section, you just embed the section setting within the first element it should hold, e.g. like this:

name: { section: ['Personal'], label: 'Name:', type: 'text', default: 'John' }

As you may notice, we've got an array here - so there may be more than one element. You're right, it can have two: The first is the section title, while you can consider the optional second to be a kind of subtitle, which we don't use in our example. So our complete code for this example is almost identical to the one for the Enhanced Form, just with two sections introduced as just described. For completeness and your convenience, here comes the full example code:

  var lang = GM_config.gets('lang','en'); // get the language - or set it to 'en' if it was not yet stored
  var configStyle = <><![CDATA[
/* Remove the 40% wasted space to the left */
.indent40 {
  margin-left: auto !important;
}
]]></>.toString();
GM_config.init('Configuration for Personal Data',{
    name:    { section: ['Personal'], label: 'Name:', type: 'text', cols:50, default: 'John Doe' },
    age :    { label: 'Age:', type: 'int', default: 21 },
    gender:  { label: 'Gender:', type: 'radio', options:['Male','Female'], default: 'Male' },
    public:  { section: ['Profile'], label: 'Public Profile:', type: 'checkbox', default: false }
  },
  GM_config.eCSS, // to add your CSS - replace this with configStyle
  {
    open: function() {
      GM_config.addBorder(); // add a fancy border
      GM_config.resizeFrame('480px','360px'); // resize the config window - oh, far too large ;)
      GM_config.addTooltip(0,'Put your name here'); // add some tooltips
      GM_config.addTooltip(1,'How old are you today?');
      // GM_config.sections2tabs(); // convert the sections to tabs - but we didn't define any section
    },
    save: function() { location.reload(); } // reload the page when configuration was changed
  }
);

For sure you are curious what this may look like, so I have a screenshot for this example as well:
gm_config_ext_enhanced_sec.gif (8 KB)

Turning sections into tabs

Even more configuration options, and they no longer fit on screen? We've got a solution for this as well: Let's turn the sections into tabs! For this, we just need to extend the open() function with a simple call to a method of the extender: GM_config.sections2tabs() will do the job for us. No other changes to above code for using sections is required. Though, the full code here again:

  var lang = GM_config.gets('lang','en'); // get the language - or set it to 'en' if it was not yet stored
  var configStyle = <><![CDATA[
/* Remove the 40% wasted space to the left */
.indent40 {
  margin-left: auto !important;
}
]]></>.toString();
GM_config.init('Configuration for Personal Data',{
    name:    { section: ['Personal'], label: 'Name:', type: 'text', cols:50, default: 'John Doe' },
    age :    { label: 'Age:', type: 'int', default: 21 },
    gender:  { label: 'Gender:', type: 'radio', options:['Male','Female'], default: 'Male' },
    public:  { section: ['Profile'], label: 'Public Profile:', type: 'checkbox', default: false }
  },
  GM_config.eCSS, // to add your CSS - replace this with configStyle
  {
    open: function() {
      GM_config.addBorder(); // add a fancy border
      GM_config.resizeFrame('480px','360px'); // resize the config window
      GM_config.sections2tabs();
      GM_config.addTooltip(0,'Put your name here'); // add some tooltips
      GM_config.addTooltip(1,'How old are you today?');
      // GM_config.sections2tabs(); // convert the sections to tabs - but we didn't define any section
    },
    save: function() { location.reload(); } // reload the page when configuration was changed
  }
);

Not to forget the screenshot of this one:
gm_config_ext_enhanced_sectab.gif (8 KB)
This screenshot has been made with Firefox 3.0 on Windows, where the tabs do not look that nice (it looks much better on Linux). So if you are a "stylist", I'm open to your CSS recommendations!

Using drop-down boxes

Drop-down boxes can be defined in two different ways:

 choice: { label:'Drop-Down', type:'select', options: ['One','Two','Three'], default: 'One' }

This would create a simple <option>One</option> style SELECT. If you need it like <option value="1">One</option>, you can use this:

 choice: { label:'Drop-Down', type:'select', options: {'1':'One','2':'Two','3':'Three'}, default: '1' }

Links

The following links provide further information:

Scripts mentioned in guide

Users mentioned in guide