Style Guide
API Quick Reference
JavaScript is required to use the quick reference
The following standards represent the goal for all code in the Glow source tree. We've distilled these from what we consider to be the best community practice and what we as a team have found makes working with JavaScript source code easiest. This is an evolving standard and we expect to add clarification and adjustments as they are needed, but it is expected that any time code is pushed to the Glow source tree it will comply with the current standard.
Creating/Saving files
Using standard file settings makes editing and testing for file-encoding related errors easier.
- You MUST use UTF-8 (with no Byte Order Mark) encoding to save your file.
- You MUST save files with Unix line endings.
- You MUST follow the when naming files. For example, folder and file names MUST be all lowercase.
- You SHOULD set your editor's tabstop to a width of 4.
Naming variables
- You SHOULD use self-documenting names, except for enumeration variables, which SHOULD be named i, j, k, and so on.
- You MUST use camelCase, including names that contain acronyms like "getCss" and "htmlLength".
- You MUST name constructor functions with an initial uppercase letter.
- When a symbol is publicly accessible but is not intended for public use, you MUST prepend an underscore to the name.
- When a symbol is intended to be constant you MUST use all-caps and optionally underscores to separate words.
- When a variable is a temporary, shortened alias to a symbol name under the glow namespace, you MUST prepend a dollar-sign to the name.
- In all other cases variables MUST have an initial lowercase letter.
- When a function accepts an options object that parameter MUST be named "opts".
glow.Banner = function(bannerText, opts) {
var $anim = glow.anim;
this.id = glow.Banner._bannerCount++;
this.bannerText = bannerText;
}
glow.Banner.VERTICAL = 1;
glow.Banner.HORIZONTAL = 2;
glow.Banner._bannerCount = 0;
glow.Banner.prototype.scroll = function( scrollSpeed ) {
}
Declaring functions
- The parameter list MUST start and end with a space.
- When using an options object it MUST be the last parameter
- If a function has no parameters but uses the arguments object you MUST use an "arguments" comment to indicate this.
- A function SHOULD be limited in size to no more than one screen (about 60 lines); refactor very large functions into smaller more specific functions to improve readability and maintainability.
- You MUST follow the formatting shown below.
glow.Calculator = function( element, opts ) {
// statements
}
glow.Calculator.prototype.toHex = function( /* arguments */ ) {
function innerFunc() {
}
// statements
}
Scoping variables
Keeping scope small decreases the possibility of namespace collisions.
- You SHOULD limit the scope of a variable to a single function.
- You MAY use an anonymous function which is executed inline if necessary to keep a variable out of the global scope.
- Anonymous functions that are executed inline MUST be wrapped in parentheses.
// this is the global scope
(function() {
function foo() {
var x = 1;
}
})();
Declaring variables
Keeping the variable declarations near the top makes their scope (function-wide) more obvious.
- All variables used in a function SHOULD be declared together at the top of that function, except enumeration variables.
- You SHOULD combine multiple variable declarations into a single statement.
function combine( /* arguments */ ) {
var total,
argsAreValid;
for (var i = 0; i < arguments.length; i++) {
// statements
}
return (argsAreValid)? total : Number.NaN;
}
Handling options
Users expect options to be optional, it can be confusing when they are not.
- If options are accepted by a function it MUST still work if no options are provided.
- If an argument is not truly optional it MUST NOT be an option.
- If an argument is optional it MUST be provided as a property of the options object.
glow.Calculator = function( element, opts ) {
opts = opts || {};
// you MAY be flexible about the format of arguments
if (typeof opts.width == "number") {
opts.width += "px";
}
// you MUST provide reasonable default values for all options
opts = glow.lang.apply({
width: "400px",
height: null, // if there's no sensible default you MUST set to null
theme: "light"
}, opts);
}
Formatting and whitespace
Whitespace will always be removed during minification, so feel free to add more of it if it makes it more obvious how things are related.
- You MUST end each statement with a semi-colon.
- Extra whitespace SHOULD be added when it helps makes the code more readable.
- Indentation MUST be with tabs (we recommend a tabstop of 4).
- You MAY add additional spaces where appropriate to line items up if it improves readability.
var lat = 0,
long = 0;
// when breaking long chains of method calls follow this format
var country = Map.getInstance()
.setCursor(lat, long)
.getCountry();
Writing comments
Knowing why you've done things as you have will make it easier for others to refactor and maintain your code.
- When you can't be obvious (perhaps you're optimising for speed instead) you SHOULD use comments to explain why you are doing things as you are.
- If you can't be readable, you MUST use comments to explain what are trying to accomplish.
- The API MUST be documented with JsDoc comments.
- When documenting browser-specific workarounds you MUST describe the affected browser's [<name> <version> on <platform> <version>].
// [Opera 9.2 on Mac 10.5] doesn't provide a valid dimension value, so
// we have to calculate it ourselves
if ( isNaN(dimension) ) {
dimension = calculateDimension();
}
Writing if statements
Braces should always be used to make it obvious where the conditional block starts and ends. The linebreak before else makes the else condition easier to find and read.
- Braces MUST always be used in conditional blocks.
- The closing brace of the block MUST be followed by a linebreak.
- Very short code blocks MAY be on a single line. You MUST use spaces to wrap the code in such a block.
if (condition) { return true; }
if (condition) {
// longer statements
}
if (condition) {
// statements
}
else {
// statements
}
if (condition) {
// statements
}
else if (condition) {
// statements
}
else {
// statements
}
if (
( pixelOffset == null || pixelOffset.getOffest().is("0px") )
|| utils.env.getLayout().indexOf("initiated") == -1
) {
// statements
}
// more readable
if (pixelOffset.getOffest().is("-1px")) {
pixelOffset.setCss(getOffest().toCssString());
}
else if (pixelOffset.getOffest().is("0px")) {
pixelOffset.setCss(new CssOffest("0px"));
}
// less readable
if (pixelOffset.getOffest().is("-1px")) {
pixelOffset.setCss(getOffest().toCssString());
} else if (pixelOffset.getOffest().is("0px")) {
pixelOffset.setCss(new CssOffest("0px"));
}