Creating a (Google Maps) ToscaWidget

[Updated 28 Mar 2007 after tweaking twMaps according to Alberto’s comments.]

I’ve been watching ToscaWidgets (TW) for a while now and keep thinking that widgets could be very useful. I’ve been perusing the TW site and the new TW mailing list, and there doesn’t seem to be much documentation on how to create new widgets.

Today, I got the idea to create a Google Maps widget. It started with someone asking in the #pylons IRC channel about getting access to a domain-specific Google Maps API key from the configuration settings during a request.

In the byCycle trip planner, our API keys are buried in a JavaScript file, but the config file would be a much better place for them. But then there’s the question of how to stuff the right API key into the JavaScript at the right point. Widgets seemed like they might be the answer, and since a map widget is something that could be useful in the trip planner, I decided to dive in.

By looking through the examples in the TW documentation, the TW source, the twForms source, and this PDF of a presentation by Kevin Dangoor, I was able to get something reasonable working within a few hours. It’s even easy_install-able (easy_install twMaps).

I also created a simple Pylons project to test the widget. This entry on the new Python Web Documentation Project site was very helpful for showing how to integrate ToscaWidgets into a Pylons application (I assume there’ll soon be a magic incantation you can use instead of copying a bunch of stuff into your middleware settings).

What I’m going to focus on in this post is creating a new widget and packaging it up for use by others, using a recipe-style approach with commentary at each step. In a future post, I’ll show how to use the twMaps Google Maps widget in a Pylons project. For now, you can browse a sample Pylons app here.

Install ToscaWidgets

easy_install -U ToscaWidgets

Create a Package Layout

ToscaWidgets includes a paster template for creating a package layout:

paster create --template=toscawidgets

This will prompt for a bunch of info, then create a directory structure similar to this:

- twMaps
    - twMaps.egg-info
    - tests
    - toscawidgets
        - widgets
            - maps
    - setup.cfg

Under the maps directory, I added this:

                - static
                    - gmap
                        - gmap.css
                        - gmap.js
                    - templates
                        (Empty for now)
                    -  (GMap widget class will go here)

This layout allows for multiple related widgets in a package. You could put multiple widgets in and import them all into ‘’, but I prefer to put each widget into a separate module, then import each one into ‘’.

There are only a few files you need to create for each widget. It’s possible to write your HTML template, CSS, and Javascript inline in the widget module, but usually that’s a bad idea. In my case, the HTML template was so simple, that I wrote it inline anyway (which is why the templates directory is empty).

Create Your Widget

Conceptually, creating a widget is quite simple. You create your static resources (stylesheets and javascripts) and template and tie everything together in a widget class. In your Web app, you just import your widget, pass it some parameters, and tell it to display itself. (You have to add a few lines to your templates also—see below.)

The javascript

/* gmap.js */

twGMap = (function () {
  var api_url = '';

  function $(id) {
    return document.getElementById(id);

  return {
    load_api: function (api_key) {
      document.write('<script type="text/javascript" src="api_key=%s"></script>');

     * ``opts`` is an Object that may contain the following keys:
     *     ``center_y``
     *     ``center_x``
     *     ``zoom``
    create_map: function(container_id, opts) {
      // We need ``_create_map`` to close over ``container_id`` and ``opts``
      var _create_map = function () {
        if (typeof(GMap2) == 'undefined') {
          setTimeout(_create_map, 1000);
        var container = $(container_id);
        var map = new GMap2(container);
        center_y = opts.center_y || 0;
        center_x = opts.center_x || 0;
        zoom = opts.zoom || 7;
        map.setCenter(new GLatLng(center_y, center_x), zoom);
        // TODO: add opts for everything below
        map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());
        map.addControl(new GScaleControl());
        map.addControl(new GOverviewMapControl());
        new GKeyboardHandler(map); = map;

There’s nothing particularly special about this; it’s just JavaScript.

(Aside: The only thing that may be interesting is the style, if you haven’t seen it before. The anonymous function that everything is wrapped in creates a private namespace. We can declare functions and vars in there and they’re not accessible from the outside. We return an anonymous literal object that exposes twGMap’s public interface. The private vars are accessible within this object.)

The stylesheet

/* gmap.css */

#twgmap {
    width: 400px;
    height: 400px;

Again, nothing interesting; just default dimensions to make sure the map will show up. A user could include a different stylesheet that overrides this.

We could probably also parameterize the dimension settings, send them to the “create_map“ JavaScript function, and set the map container dimensions using DOM methods (a good idea actually, now that I think of it). It would also be cool if it was possible to create CSS templates that can be filled in similarly to HTML templates. (It’s likely that this already possible and I just don’t know how to do it.)

The HTML template

Normally, you’d probably write your HTML template in a separate file under the templates directory. As you can see in the “GMap“ class below, though, the template for the the Google Maps widget is very simple, so I just wrote it inline.

To point to a template in a separate file, use Buffet syntax, which looks something like this:

template = ''

The widget class

Here’s where things start to get interesting. The HTML template, JS and CSS above are just standard stuff, and we could use them by copying them into our project and using script and link tags to include the JS and CSS in the template.

In other words, we don’t need to create a widget, but there are some compelling reasons for why we might want to.

For one thing, we normally have separate directories for different types of files (css, js, etc). We don’t have to do this—we could create a widgets directory with a layout similar to the one above. This would get us part way there in that it would at least be a little easier to detach a particular widget from a project and use it somewhere else.

Using Widgets, though, allows complete separation; the files don’t need to be copied into your project at all. You just import the widget and it sets things up so your framework knows how to access the widget’s resources. This makes it really easy for you to reuse your widgets and share them. In turn, it makes it easy for you to use other widgets (the twForms package has a bunch, for example).

Another thing that’s nice with Widgets is that we don’t have to manually include widget templates or script and link tags ourselves. The widget system knows how to do that for us, so that all that’s required to display a widget in a page is telling it to display itself in a particular place in the page.

So, there are some reasons to use widgets; now, let’s look at the code.


from toscawidgets.api import Widget, CSSLink, JSLink, js_function

__all__ = ['GMap']

twgmap_css = CSSLink(modname=__name__, filename='static/gmap/gmap.css',
twgmap_js = JSLink(modname=__name__, filename='static/gmap/gmap.js')

class GMap(Widget):
    params = ['css_class', 'map_opts']
    css_class = 'twgmap'
    map_opts = {'api_key': None, 'center_y': 0, 'center_x': 0, 'zoom': 14}
    template = '

    css = [twgmap_css]
    javascript = [twgmap_js]
    include_dynamic_js_calls = True

    def __init__(self, id=None, parent=None, children=[], **kw):
        self.map_opts.update(kw.get('map_opts', {}))
        super(GMap, self).__init__(id, parent, children, **kw)

    def update_params(self, d):
        super(GMap, self).update_params(d)
        self.add_call('twGMap.load_api("%s");' % self.map_opts['api_key'])
        create_map = js_function('twGMap.create_map')
        # Use initial map opts as base...
        map_opts = self.map_opts.copy()
        # ...then update with map opts in ``d``
        map_opts.update(d.get('map_opts', {}))
        for k in map_opts:
            try: v = float(map_opts[k])
            except: pass
            else: map_opts[k] = v
        self.add_call(create_map(, map_opts))

There’s not a whole lot to it in the end.

“CSSLink“, in essence, creates a stylesheet link tag. The link is relative to the “modname“ package so that if “modname“ is twmaps.widgets.maps.gmap and filename is static/my_widget/my_widget.css, the full path to the CSS file will be /twmaps.widgets.maps.gmap/static/my_widget/my_widget.css. “JSLink“ does the same thing.

Basically, CSSLink and JSLink are just fancy ways to create CSS & JS tags that can be associated with a widget in Python. Using “twgmap_css“ from the example above, twgmap_css.display() outputs `<link rel=”stylesheet” type=”text/css” href=”/twmaps.widgets.maps.gmap/static/gmap/gmap.css” media=”screen” />`.

Inside the “GMap“ class:

“params“ are the params that can be set when creating a widget; they get added to the “params“ list of any base classes. We can set a default value for a param, as I did with both “css_class“ and “map_opts“. (I think params can be set to be required too.)

The first argument passed to the constructor becomes the “id“ param. (One issue I had was that I was unable to set a default “id“ and then override it.)

“template“ is the HTML template for the widget. It can either be specified directly as a string or as pointer to an external template file. The names in “params“ are available in the template (e.g., ${css_class}).

“css“ is a list of CSS resources; note that it must be a list, even if it just contains one item

“javascript“ is just like “css“ (at least in basic usage)

“include_dynamic_js_calls“ tells the widget to include JavaScript function calls during page load; you specify these functions using “self.add_call“. The argument to “add_call“ is JavaScript code in the form of a string. Those JS calls are added to the bottom of the HTML body.

In the code above, I used “js_function“ to generate a Python function that when called, creates a string of JS code. The arguments to that function are converted to JSON, which become the args to the JS function call.

So there you have it: set up some CSS and JS links, point to your HTML template, define parameters for the widget that you can pass through to your template and/or JS, add some callbacks to initialize your JS, and that’s about it.

Example usage:

>>> from toscawidgets.widgets import maps
>>> opts = {'api_key': 'XYZ', 'center_y': 45, 'center_x': -123}
>>> map_widget = maps.gmap.GMap('twgmap', map_opts=opts)
>>> map_widget.display()
'<div id="twgmap" class="twgmap"></div>'


Tests would be a good thing to add, yes. Using `paster create` to generate the package layout creates a tests package to use as a starting point.

Package It Up

Packaging is a matter of writing a file that contains various metadata (name, license, and so forth) and then running a build command. Using the `paster create` command generates a—it prompts for the metadata and fills in with that metadata and the necessary commands. It may be necessary to tweak, but then again, it may not.

Once is in order, we can run python bdist_egg. The resulting egg can be found in the dist directory. You could post this somewhere and people could download it and install it using python install. It’s much cooler though to put the package up on PyPI (AKA cheeseshop). Here’s one way to do that:

python register  # follow instructions
python register bdist_egg upload
python register sdist upload
easy_install YourPackage


Install latest version of twMaps

easy_install -U twMaps

Check out the code, including a sample Pylons app

svn co


That concludes creating and packaging a ToscaWidget. In an upcoming post, I’ll go through an example of using the GMap widget in a Pylons project.

Please add any corrections, suggestions, etc in the comments. If you have any questions, I’ll try to answer them, but keep in mind that I am just getting started with TW myself.

2 thoughts on “Creating a (Google Maps) ToscaWidget

  1. Hi Wyatt,

    Very nice article! Just one little problem: You seem to have grokked TW way to well without decent docs, that takes much pressure away from me to write them! :P

    Anyway, some comments/suggestions in random order:

    • Yes, you can pass variables to CSSSource/JSSources (not *Links) with the “source_vars” variables. They behave in a parallel way to “params”. I must admity I rarely use them though and have been tempted to remove them altogether and provide the same behavior with just “params” for consistency’s sake.
    • You don’t need to manually create the directory structure for a widget egg, “paster create -t toscawidgets twGMap” will do it automatically.
    • You can also “add_call”s inside init or post_init (in that case you won’t need the “include_dynamic_js_calls” attribute). The reason you might need to do it in “update_params” is if you want to override initial parameters when displaying the widget.

    I’ll extend on this some more because it’s an important part of TW’s design:

    Widgets are designed to be initialized once in the lifetime of your application (this is legacy behavior from TG widgets) and reused in every controller/template that needs them. To avoid creating dozens of very similar instances, most widgets allow you to override any (or most) params when displaying them. This is the reason you might want to add the calls at update params: so you can override variables sent to js when displaying the widget.

    • You can let TW convert parameters from python to js for you (uses simplejson). To do that you’ll do:
    from toscawidgets.api import js_function
    init_map = js_function(“twGMap.create_map”)

    and then in update_params:


    (To make default “map_options” you declare as a class attribute or when instantiating a widget available at “d” you should list it at “params”)

    • Yes, that boiler-plate at (Pylons’) will soon be incorporated at…

    Well, that’s all I can think of now… very nice article indeed! :) Hope I’m over a contract soon and get some docs out to save the trouble of chasing snippets of wisdom all around the net for others. :)


Comments are closed.