- The official name for a component should be singular. This is most important for filenames.
- Examples:
_panel.scss
,panel.js
- Exceptions: "Forms", "Tabs", "Breadcrumbs"
- Examples:
- Write out components in lowercase, unless it's a title of a page.
- Named plugins are an exception, like Reveal and Interchange.
The plugin definition is wrapped in an immediately-invoked function expression, to keep variables out of the global scope. The global Foundation
and jQuery
objects are passed into the function.
Putting a negation operator (!
) before a function forces it to execute, making it slightly more efficient, character-wise, than the other method of wrapping the function in parentheses.
The IIFE also allows us to use the $
variable for jQuery, even if jQuery is being used in no conflict mode.
!function($) {}(jQuery)
A plugin is a single class.
function Plugin() {}
Or in ES6:
class Plugin {}
All plugins follow the same constructor format. It accepts an element
parameter, which is the primary element the plugin is attached to. It also accepts an options
object, which extends the default options object.
function Plugin(element, options) {
this.$element = element;
this.options = $.extend({
// Defaults
}, options);
}
Or in ES6:
class Plugin() {
constructor(element, options) {
this.$element = element;
this.options = $.extend({}, Plugin.defaults, element.data(), options);
}
}
The constructor should also call an _init()
method, and if needed an _events()
method, followed by a DOM event indicating that the plugin is done being initialized.
function Plugin(element, options) {
// ...
this._init();
this._events();
this.$element.trigger('init.zf.plugin');
}
All plugin methods should be defined in the plugin object's prototype. Private methods are prefixed with an underscore. Of course, this doesn't actually make them private.
Plugin.prototype = {
_init: function() {},
doSomething: function() {}
}
A plugin should have an _init
method that performs setup operations.
Plugin.prototype = {
_init: function() {}
}
If a plugin responds to DOM events, it should have a separate _events()
method just for defining event listeners.
Plugin.prototype = {
_events: function() {
this.$element.on('click', function() {});
}
}
Custom events should be namespaced and follow the format [eventName].zf.[pluginName]
.
More complex events should fire two events: one when the method starts, and one when the method finishes. Use an infinitive (e.g. open
) for the start event, and past tense (e.g. opened
) for the final event. Always trigger the event from the plugin's primary element.
Reveal.prototype = {
open: function() {
this.$element.trigger('open.zf.reveal');
// Code to open a modal
this.$element.trigger('opened.zf.reveal');
}
}
The plugin constructor is added to the global Foundation
object, allowing it to be used programmatically.
function Plugin(element, options) {}
Foundation.Plugin = Plugin;
Plugins are documented using the JSDoc format. The documentation is consumed by our docs generator Supercollider, which generates HTML generation from the comments.
When documenting your code, these are the hot ones to keep in mind.
Document the plugin's class using @class
.
/**
* Creates a new instance of Plugin.
* @class
*/
var Plugin = function() {}
Document each of the plugin's methods. Use @param
to explain each parameter in the function.
/**
* Does a thing.
* @param {Object} thing - Thing to do.
*/
Plugin.prototype.doThing = function(thing) {}
Document every event that a plugin fires, above the line where the call to $.fn.trigger()
is made. If an event is fired in more than one place in the code, just document it once, the first place it appears.
Use the @event
tag to name the event. Use the format [pluginName]#[eventName]
, where [eventName]
is the same name as the DOM event itself.
/**
* Fires when something happens.
* @event Plugin#thing
*/
this.$element.trigger('thing.zf.plugin');
Add the @fires
tag to any method that triggers an event.
/**
* Does a thing.
* @fires Plugin#thing
*/
Plugin.prototype.doThing = function() {
this.$element.trigger('thing.zf.plugin');
}