Section author: Jonathon Love
3. Advanced Customisation¶
3.1. Customizing UI controls¶
Sometimes the
.u.yaml
-file alone doesn’t provide enough flexibility for an analysis options UI. More complex UIs can be achieved through writing additional javascript that provides more complex behaviour. This allows much greater freedom and flexibility, and allows you to design an options UI completely from scratch if necessary.The options UI is customised through attaching javascript ‘event handler’ functions to the user interface. These then respond to events such as a UI ‘loaded’ event, or an option ‘changed’ event in response to a user interaction.
Additional UI functions are defined in a javascript-file with a
.js
-suffix, and are placed in thejamovi/js
folder of the module. The name of the.js
-file should match the names of the other.yaml
-files for that analysis. For example:The events
.js
-files follow theCommonJS
javascript module spec, assigning each of the event handlers and functions to an object which is assigned tomodule.exports
.IMPORTANT: For customisations to function, the
jus
property in the.u.yaml
-file needs to be set to3.0
.For example:
name: ttest title: T-Test jus: '3.0' compilerMode: tame children: - type: ComboBox name: ttestTypemodule.exports = { // event handlers and functions are defined here // this is an example of an event handler view_loaded: function(ui, event) { // do something }, // this is another example of an event handler ttestType_changed: function(ui, event) { let value = this.calculateValue(); // do something }, // this is an example of an auxiliary function calculateValue: function() { // do something } };In the above example, the
view_loaded(...)
event handler is invoked with aloaded
event when the analysis options UI is created for the first time. Similarly, achanged
event is fired, and the event handler functionttestType_changed(...)
is invoked when the user changes the value of thettestType
option.Note that jamovi ships with the Chrome developer tools, so it’s possible to invoke these, and have access to the debugger, DOM viewer, etc. The dev tools are invoked by pressing
F10
. (Note that sometimes jamovi’s internal iframes prevent this key stroke from registering. You sometimes need to click the blue bar along the top to move the focus back to the main window, before theF10
keystroke will register.)
3.1.1. Events¶
Event handlers are added by naming the function with the following pattern. Option name, followed by an underscore, followed by the event name
{optionName}_{eventName}
.For example:
ttestType_changed
jamovi will automatically attach the event handler
ttestType_changed(...)
to thechanged
event of thettestType
option when the analysis is run.
3.1.1.1. View¶
Event Description creating Invoked at the very beginning of the options panel creation, before anything is added to the DOM. loaded Invoked after the options panel has been created and the DOM has been populated. The same analysis options panel persists as long as jamovi is still running, and is shared by all analyses of the same type, so this is only invoked once. This is the most common event to use for customising the UI. updated Invoked when the user selects a different analysis (of the same type) and the options need to change to reflect the new analysis’ option values (This is also called when the user inserts a new analysis, when an option panel for that analysis type already exists).
3.1.1.2. All controls¶
Event Description changing changed Invoked before the value of the control is changed. Invoked after the value of the control is changed.
3.1.1.3. ListBox¶
Event Description listItemAdded listItemRemoved Invoked when a control is added to a list box. Invoked when a control is removed from a list box.
3.1.1.4. Suppliers¶
Event Description updated Invoked when a variable name or level name is changes. IMPORTANT NOTE: The use of the
updated
event is required for allSupplier
andVariableSupplier
controls (under certain conditions). If it is not implemented then jamovi will display the following error:Error: The use of a ‘VariableSupplier’ control, with the property > populate: ‘manual’, requires an ‘updated’ event handler to be assigned.or:
Error: The use of a ‘Supplier’ control requires an ‘updated’ event handler to be assigned.These suppliers require manual population and therefore need to be appropriately updated in response to variable or level name changes.
3.1.1.5. Custom Control¶
Event Description creating Invoked during the creation phase of the options panel. Allows for access to the custom control for customisation before it is made visible. updated Invoked when a variable name or level name is changes.
3.1.2. Event handlers¶
All event handlers are invoked with two arguments; the
ui
, and theevent
. The ui is a convenience object containing all the other controls in the options panel and the DOM. All the option controls are available in the ui argument as properties. For example:ttestType_changed(ui, event) { let ttype = ui.ttestType.value() if (ttype === 'welchs') ui.priorWidth.setValue(0.707) }In this example, when the user changes the
ttestType
option towelchs
, thepriorWidth
option is changed to0.707
. All options have the.value()
and.setValue()
methods.Note that each change to the values of the options triggers the re-running of the analysis. If multiple option values need to change in response to an event, it is better to batch these changes together, to prevent the analysis being restarted again and again. Option changes can be batched together with the
ui.view.model.options
beginEdit()
andendEdit()
functions as follows:ui.view.model.options.beginEdit(); ui.figWidth.setValue(400); ui.figHeight.setValue(300); ui.view.model.options.endEdit();In this example, changing the
figWidth
andfigHeight
options only triggers the re-running of the analysis once.
3.1.3. Accessing the DOM¶
The DOM for the root of options UI can be accessed from the ui through the
view
property:ui.view.el | the root DOM node ui.view.$el | the root DOM node as a jQuery objectIt is also possible to inspect the DOM using the chrome dev tools shipped with jamovi (to access these, click the blue bar at the top of jamovi, and press
F10
).Additionally, the DOM elements for most of the option controls are accessible through the
el
and$el
property. i.e.let figWidth = ui.figWidth.el let $figWidth = ui.figWidth.$el
3.2. Adding a custom control¶
Sometimes the controls built into jamovi do not provide the behaviour your analysis requires. In this scenario, it’s possible to create a ‘custom control’ which is placed within the DOM.
A control of type
CustomControl
allows for this possibility, when added to the.u.yaml
-file, and thecreating
event is handled in the javascript.For example, the description of the control in the
.u.yaml
- type: CustomControl name: ttestTypeand the event handler for the the
.js
ttestType_creating: function(ui, event) { let $element = ui.ttestType.$el; // in this instance, the $element object represents the root DOM node // of the custom control. sub-nodes can be added to this node, and the // control will be laid out by the layout manager in the final options // UI }
3.3. Options UI from scratch¶
Sometimes an analysis requires a very radical UI design that can’t be accommodated by the standard UI controls or a custom control. If this is the case, an entirely custom UI may need to be developed.
To achieve this, the options and their types are defined as usual in the
.a.yaml
-file, however, each option is marked ashidden: true
. This preventsjmvtools
from (re)adding the standard UI controls into the.u.yaml
-file, allowing you to implement them yourself.To construct the UI, all the DOM setup for the custom panel should occur in a
creating
event handler for theview
control.'use strict'; module.exports = { view_creating: function(ui, event) { let $panel = ui.view.$el; // in this instance, the $panel object represents the root DOM node // of the options panel. sub-nodes can be added to this node. } }