Skip to content

02. Writing modules

Moerphy edited this page Nov 24, 2011 · 4 revisions

Writing modules

Dizzy is split up in various, loosely coupled modules. It’s using requireJS to load the modules from /dev/js/modules, so you should get comfortable using it (o:

A module can contain anything: a new tool for the toolbar (like text editing), a loader for certain file types, etc.. almost every feature should be put in as a module.
A module should never know what other modules there are. They only communicate through a publish/subscribe system (similiar to Javascript events, but not necessarily async) provided by the application.

Writing a module

Alright, let’s write the simplest module possible:

  • Add a new file to /dev/js/modules. Let’s call it simple.js
  • Add the following code:
define([], function(){ // AMD standard for modules without dependencies
  // do anything that does not require
  // other modules to be ready here
  console.log('Module loaded'); 
  return {
    init: function(){
      // all modules loaded, 
      // you can do almost anything here
      console.log('Application ready, module started');
    }
  };
});
  • Open dev/js/modules.js. In there is a similiar construct with an array with a lot of strings like this:
define([
    'modules/canvas', 'modules/modes',
    'modules/io/mouse', 
    ... // more strings
    ], function ... // some more stuff here..

To make requireJS load your module with the others you need to put its file path (without, the .js suffix!) in this array. In our example, just append , ‘modules/simple’ to the array and you’re done.

Module communication

If you write a feature other modules should be able to use too, you should make it available through the publish/subscribe system I mentioned above.
To use this system, you’ll need the sandbox. The sandbox is an object that offers both the publish() and subscribe()methods to the modules (the odd naming comes from a talk by Nicholas Zakas, where he outlined a similiar application design).

To import the sandbox object and use it, do the following:

define(['sandbox'], function( box ){ // makes the sandbox available through the box variable
  // subscribe to this event. Subscribing should be done as early as possible in the module
  // (publishing dizzy.presentation.load means 
  // that some module should load a presentation file onto the canvas)
  // data contains whatever data the publisher passed along with the event
  box.subscribe('dizzy.presentation.load', function(data){
    // for this event, data contains the filename that should be loaded
    console.log( "This file will be loaded: " + data.file );
  });
  // you can subscribe to anything, even your own events (will be published below)
  box.subscribe('foo.bar', function(data){
    console.log(data.fnord);
  });
  // return the module
  return {
    init: function(){
      // all modules are loaded and all subscribtions should be in place
      // publishing should be done here
      box.publish('foo.bar', { fnord: 'o snap!' });
    }
  };
});

Namespacing

In the above example we could also subscribe to ‘foo’ instead of ‘foo.bar’ and would get the event anyway, because the dot is used to namespace events.
Also, if we subscribe to ‘foo.bar’ and publish ‘foo.bar.baz’, we still would recieve the event.
Protip: subscribe to ‘dizzy’ to recieve almost every event in the appliction so far (o:

Modules that provide features through pub/sub should document the subscription name and the data format here .

Clone this wiki locally