JavaScript Modules
Table of Contents
Introduction
Quotation bundle uses JavaScript modules to enhance the user interface in various steps of the quotation process. These include widgets that are autoloaded for every page or widgets that loaded only when needed (such as form elements). The widget loading system is based on Require.js and uses a data attribute to check the name of a widget.
By default, widgets are loaded from the quotation bundle but it is also possible to define your widgets. For this you need to define the package in the require.js config.
Packages and naming
Widgets are require.js modules that return a Javascript constructor. The widget system is designed to be used with a Marionette so the return value is usually a Marionette / Backbone view definition. If the module is found, an instance is then created and given the the element and other options as parameters. The widgets are loaded from different packages where packages refer to require.js packages:
requirejs.config({
...
packages: [
{ name: 'klaro_quotation', location: './bundles/klaroquotation/js', main: 'app' },
{ name: 'somepackage', location: './bundles/package/js' }
]
});
The default package is klaro_quotation
which means scripts are searched in the quotation bundle javascript package. If the package is omitted, then klaro_quotation
is assumed as the package. The actual name of the javascript file is [widget_name].module.js
.
For example, to load a widget named confirm
, the directory defined in the default package klaro_quotation
is searched for the script name confirm.module.js
. To load a widget name somepackage/confirm
, the directory of the package somepackage
is searched for the script name confirm.module.js
.
Creating a widget
To put it simply, widgets are require.js modules that return a Backbone view. For example, the confirm module in the previous example could be:
// confirm.module.js
define(['backbone', 'marionette'], function(Backbone, Marionette) {
'use strict';
return Backbone.Marionette.ItemView.extend({
events : {
'click' : 'handleClick'
},
handleClick: function(e) {
e.preventDefault();
if(confirm("Are you sure?")) {
window.location.replace(this.$el.attr('href'));
}
}
});
});
Starting the widget
The ways to load a module are described below.
Loading a widget on a specific element
Javascript modules can be attached to any HTML element by using the data attribute "app" (data-app="..."
) and they will be automatically loaded. For example the confirm widget can added to a link:
<a href="..." data-app="confirm">Do something dangerous</a>
This will load the script and instantiate the returned definition. The widget will receive as parameter the element any other data attributes attached to it:
<a href="..." data-app="confirm" data-confirm-text="Are you sure?">Do something dangerous</a>
This will make the extra data attribute available in the view options:
define(['backbone', 'marionette'], function(Backbone, Marionette) {
'use strict';
return Backbone.Marionette.ItemView.extend({
confirmText : null,
initialize: function(options) {
this.confirmText = options.confirmText || 'Are you sure?';
},
// ...
});
});
Autoloading widgets
To load modules to the page scope, use the following Twig command to do so:
{{ klaro_quotation_load_modules([
{ module : 'bootstrap', 'el' : 'body' },
{ module : 'notification' },
{ module : 'somepackage/toolbarupdate' },
]) }}
The module
key tells the name of the widget (possibly preceded by the package). The whole array is then passed to the widget itself, so you can define other parameters such as an element to which the widget will attach itself.
Form widgets
Form widgets are like the other widgets but they are speficically meant to be attached to phase form inputs. They are loaded by the master form widget which looks for a data attribute data-form-input="[widget]"
. This allows the form to unload and load form widgets as fields are hidden and shown.
The naming of the form widgets follows the convention of phase.[widget_name]
(loaded from quotation bundle). To load a custom widget, use data-form-input="somepackage/phase.[widget_name]"
. This will look for a script named phase.[widget_name].module.js
under the somepackage
directory and load it. As with other widgets, the form widget receives the element to which the data attribute is attached to as a parameter.