-
Notifications
You must be signed in to change notification settings - Fork 1
/
ui-advanced-customisation.Rmd
205 lines (138 loc) · 9.14 KB
/
ui-advanced-customisation.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
---
title: "Advanced customisation of the options UI"
output: html_document
---
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 the `jamovi/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:
- `ttest.a.yaml`
- `ttest.r.yaml`
- `ttest.u.yaml`
- `js/ttest.js`
The events .js files follow the `CommonJS` javascript module spec, assigning each of the event handlers and functions to an object which is assigned to `module.exports`.
*IMPORTANT:* For customisations to function, the `jus` property in the `u.yaml` file needs to be set to `3.0`.
For example:
```yaml
name: ttest
title: T-Test
jus: '3.0'
compilerMode: tame
children:
- type: ComboBox
name: ttestType
```
```javascript
module.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 a `loaded` event when the analysis options UI is created for the first time. Similarly, a `changed` event is fired, and the event handler function `ttestType_changed(...)` is invoked when the user changes the value of the `ttestType` 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 the `F10` keystroke will register.)
### 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 the `changed` event of the `ttestType` option when the analysis is run.
#### 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). |
#### All controls
| Event | Description |
| ------------- | ------------- |
| changing | Invoked before the value of the control is changed. |
| changed | Invoked after the value of the control is changed. |
#### ListBox
| Event | Description |
| ------------- | ------------- |
| listItemAdded | Invoked when a control is added to a list box. |
| listItemRemoved | Invoked when a control is removed from a list box. |
#### 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 all `Supplier` and `VariableSupplier` 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.
#### 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. |
### Event handlers
All event handlers are invoked with two arguments; the `ui`, and the `event`. 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:
```javascript
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 to `welchs`, the `priorWidth` option is changed to `0.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()` and `endEdit()` functions as follows:
```javascript
ui.view.model.options.beginEdit();
ui.figWidth.setValue(400);
ui.figHeight.setValue(300);
ui.view.model.options.endEdit();
```
In this example, changing the `figWidth` and `figHeight` options only triggers the re-running of the analysis once.
### 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 object
It 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
```
## 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 the `creating` event is handled in the javascript.
For example,
The description of the control in the `u.yaml`
```yaml
- type: CustomControl
name: ttestType
```
and the event handler for the the `.js`
```javascript
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
}
```
## 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 as `hidden: true`. This prevents `jmvtools` 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 the `view` control.
```javascript
'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.
}
}
```