Skip to content
betson edited this page Sep 7, 2014 · 1 revision

You'll notice that all /src files (excluding stubs.js) are constructed using a custom Module format. A common file may look like:

// smooth-scroller.js
betterlink_user_interface.createModule("Smooth Scrolling", function(api, apiInternal) {
    api.requireModules( ["Event Messaging"] );
    // Do things here
});

We require that each file be completely enclosed within one of these module definitions. This prevents us from leaking any implementation details into the global namespace.

Module Basics

createModule()
This registers a new Module with Betterlink. The function takes two parameters: moduleName and initFunction.
  • moduleName is an arbitrary string. It should be unique.
  • initFunction encloses all JavaScript that will get executed when the module is initialized.
api.requireModules()
Defines dependencies this module relies upon. By registering dependencies, we ensure Betterlink loads modules in the appropriate order. The function takes an array: dependencies.

Initialization Function

All variable declarations, function definitions, and anything else that happens within the function stays within the function scope. These variables also persist throughout the lifetime of Betterlink. This gives us good flexibility to create self-contained libraries.

Two variables are passed into the init function: api and apiInternal.

  • api provides access to the global betterlink object. It's only real use would be to attach a new function to the public API.
  • apiInternal is the magic glue that binds our modules together. With it, you can access functions and properties that have been defined in the private API.
    • These functions are detailed and provided in stubs.js

Index-Notation for Public Attributes

Betterlink is run through Google Closure Compiler before being deployed. As a side effect of minimizing the footprint, all property names are shortened and mangled. When accessing any publicly-facing property, you must use index-notation.

Good: return api['config']['highlightElementId'];

Bad: return api.config.highlightElementId;

This includes any properties on objects that are passed between the user interface modules and the core library. The reason is simple, but annoying:

  • If the user interface modules were compiled along with the core library (which would happen during a standard deployment), everything would work fine. However, because under local development the UI modules are interfacing with the core library as a third-party API, the mangled property names would not match the local property names.

An example of this situation can be seen with the result parameter for the SumbmissionDisplay event.

Handling Exceptions

Exceptions take two forms in Betterlink. They either occur during module initialization, or during the normal course of interaction.

Exceptions that occur during initialization are immediately caught by the core library and logged to the console. This marks the module as unsupported and prevents any parent modules from loading. All other modules will continue to initialize, and Betterlink will attempt to run.

If Exceptions occur outside of initialization, these behave as normal. They will log an error with a stack trace to the console and halt execution of the current script. Handle these within the module definition as appropriate.

Integrating New Modules

Every new file needs to be listed in two places:

  • betterlink-interface/example_site.html
    • Allows the file to be loaded from the provided demo page
  • betterlink-interface/local-chrome-extension/injector.js
    • Lists the files to be dynamically injected via the custom Chrome Extension

In both lists, files should be topologically sorted (i.e., each file should be listed after any file it depends upon).

Choosing Dependencies

Basic rule of thumb: if you are accessing a property off of apiInternal that is namespaced, then that namespace should be a dependency.

Corollary: If you are adding a new property to the private API, then you should namespace your property based on the current module.

Use the existing modules as a guide.

When Initialization Occurs

For all modules created within betterlink-interface, the module will be initialized after the DOM is ready. For modern browsers, this is triggered after the DOMContentLoaded event. For older browsers, we use the load event.

Clone this wiki locally