We use RequireJS as an AMD loader for our scripts. This means we can separate JS functionality into separate files. This page contains the definition for new modules, with some tips as to how to structure the module.

Firstly, define which other modules this module needs

define(['jquery', 'app/color'], function ($, COLOR) {

Next, declare any of the "private" variables. These will only be accessible inside the module. It's useful to keep these at the top in case you want to change them. These should be non-user-defined variables: remember, this module may be used in several places. Anything you want to be changeable you must pass through in the options object.

var topSpeed = 1000,
    thankyouText = 'Thanks for your help',
    canFlip = true;

The same is true for "private" functions: they will only exist within the module

var colorSwap = function(a, b) {
  // Remember to return something
}

These variables will be reused every time the module is used, so don't use them to store instance-relevant information.

Now you can define the module. Use UPPERCASE for complex objects like this. This is how you will instantiate the module in another file (var s = new SAMPLE(options);).

var SAMPLE = function(options) {
  // Check required options
  if (!options.width) return false;

  // Get the options or their defaults
  this.width = options.width || this.DEFAULT.width;
  this.easing = options.easing || this.DEFAULT.easing;
  this.isCompatible = options.isCompatible || this.DEFAULT.isCompatible;
  // Do some setup stuff
  // Return true or false (or something else)
};

Then you can define any "public" variables that need to be accessed outside of the module. You should also set default values for these user-defined values in case they aren't passed through.

SAMPLE.prototype.color = colorSwap('#fff', '#000');

SAMPLE.prototype.DEFAULT = {
  width: 250,
  easing: 'ease-in',
  isCompatible: true
}

… and "public" functions…

SAMPLE.prototype.setColor = function(val) {
  // Always return true or false from setters
}

SAMPLE.prototype.getColor = function() {
  // Return the value
}

Lastly, return the module so that it's available to other modules that need to define it.

return SAMPLE;

You can use src/js/app/sample.js as a basis for new modules. This has the code and comments from this page which you can amend to your hearts' desire.

TODO: We intend to make all our JS unit-testable, so it must be written with a unit test in mind. In fact, write the test first - it'll help you define what the JS really need to do.