-
Notifications
You must be signed in to change notification settings - Fork 0
Creating Modules
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.
createModule()- This registers a new Module with Betterlink. The function takes two parameters:
moduleNameandinitFunction.-
moduleNameis an arbitrary string. It should be unique. -
initFunctionencloses 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.
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.
-
apiprovides access to the globalbetterlinkobject. It's only real use would be to attach a new function to the public API. -
apiInternalis 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
- These functions are detailed and provided in
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.
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.
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).
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.
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.