Services are Box.Application extensions that provide new capabilities to the entire system. The most important aspect of a service is its interface. Other modules and services may depend on it and so the interface must remain stable so as not to unexpectedly break code.
Unlike modules, services can interact directly with the Box.Application layer and may access lower level libraries such as jQuery and 3rd party plug-ins. In general, modules should only use services to get work done. Therefore, plugins, such as jQuery UI, should be wrapped or abstracted by a T3 service.
Services can be classified into two major categories: Widgets (UI-specific) and Utilities (non-UI).
Utility services add functionality to the Application layer. T3 does not define any specific implementation details around utilities but does have a few guidelines.
Example Utilities: cookies, ajax, date, strings
Box.Application.addService('router', function(application) {
return {
route: function(url, state) {
history.pushState(state, '', url);
}
};
});
var router = Box.Application.getService('router');
router.route('/home', {});
Widgets are reusable UI-specific pieces of code. They do not contain application logic and should not contain initialization functions. Widgets are still services though and these guidelines are here for creating better interfaces. None not restrictions imposed by the framework.
Examples: popups, tooltips, menus
Box.Application.addService('popups', function(application) {
return {
alert: function(message) { ... },
confirm: function(message, callback) { ... }
};
});
var popupsService = Box.Application.getService('popups');
popupsService.alert('Hello World!');
There are two major patterns that services should follow. The following guidelines are for convention purposes and not hard requirements.
Most utility services follow the singleton pattern.
Examples: dom, cookies, ajax
Box.Application.addService('dom', function(application) {
return {
query: function(selector) { ... },
addClass: function(element, className) { ... }
removeClassClass: function(element, className) { ... }
};
});
var dom = Box.Application.getService('dom');
var element = dom.query('#test');
dom.addClass(element, 'style1');
dom.removeClass(element, 'style2');
As a convention, factories should have a create()
method that returns a new instance of an object.
You can decide what the parameters of create()
are and unlike singletons, you can have initialization
and constructor logic within these objects.
Example Widgets: tooltips, menus, tabs
Box.Application.addService('tooltips', function(application) {
function Tooltip(params) {
this.message = params.message;
}
Tooltip.prototype.show = function() {};
Tooltip.prototype.hide = function() {};
// Return a factory object with some additional functionality
return {
create: function(params) {
return new Tooltip(params);
},
hideAll: function() {
...
}
};
});
var tooltip = Box.Application.getService('tooltips').create({
message: 'Click Me!'
});
tooltip.show();