qti3-item-player-vue3 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +752 -0
- package/dist/assets/css/bootstrap.css +11266 -0
- package/dist/assets/css/bootstrap.css.map +1 -0
- package/dist/assets/css/styles.css +0 -0
- package/dist/assets/js/bootstrap.bundle.min.js +7 -0
- package/dist/assets/js/bootstrap.bundle.min.js.map +1 -0
- package/dist/assets/pci/css/styles.css +1152 -0
- package/dist/assets/pci/pci.html +528 -0
- package/dist/favicon.svg +20 -0
- package/dist/qti3-item-player-vue3.js +43472 -0
- package/dist/qti3-item-player-vue3.umd.cjs +215 -0
- package/dist/qti3Player.css +1 -0
- package/package.json +57 -0
package/README.md
ADDED
@@ -0,0 +1,752 @@
|
|
1
|
+
# Amp-up.io QTI 3 Player Component for Vue 3
|
2
|
+
|
3
|
+
<div id="top"></div>
|
4
|
+
|
5
|
+
[![MIT License][license-shield]][license-url]
|
6
|
+
|
7
|
+
<a href="https://site.imsglobal.org/certifications/amp-upio/amp-upio-qti-3-test-player" target="_blank">
|
8
|
+
<img align="right" src="https://site.imsglobal.org/sites/default/files/media/images/logo_ims/1edtech_trusted-apps-certified.svg" width="187" height="200" border="1" alt="1EdTech Certified">
|
9
|
+
</a>
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
This is the **Vue 3 version** of the original Amp-up.io QTI 3 Player Component ("QTI 3 Player") which was originally built with Vue 2.6.
|
14
|
+
|
15
|
+
The QTI 3 Player is a 100% JavaScript component that aims to encapsulate the best practices and behaviors of the 1EdTech QTI 3 Assessment **Item** specification.
|
16
|
+
|
17
|
+
A conforming QTI 3 authoring or exporting system can construct a QTI 3 Item XML solution that will "play" authentically and reliably in the QTI 3 Player - according to the Best Practices Implementation Guide which can be found here:
|
18
|
+
|
19
|
+
[1EdTech QTI v3 Best Practices and Implementation Guide](https://www.imsglobal.org/spec/qti/v3p0/impl)
|
20
|
+
|
21
|
+
QTI 3 Player has achieved both <a href="https://site.imsglobal.org/certifications/amp-upio/amp-upio-qti-3-test-player" target="_blank">QTI 3 Basic and QTI 3 Advanced "Delivery" Conformance</a> Certification from 1EdTech. Furthermore, QTI 3 Player supports many so-called "Elective" capabilities that go beyond Advanced delivery conformance.
|
22
|
+
|
23
|
+
For a complete list of the QTI3 XML elements supported by the QTI 3 Player component, please refer to the [QTI 3 Player Item Reference](https://docs.google.com/document/d/1KCImUAk-2uBqSOHRO1lJa1orrzF4b8cl/#heading=h.gjdgxs).
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
## About The Project
|
28
|
+
|
29
|
+
The QTI 3 Player has API's, interfaces, and capabilities which are optimized for formative or classroom assessment settings. Such settings typically require sophisticated QTI features such as adaptive items, item templating (sometimes called item "cloning"), template processing, and full response processing; i.e., scoring. The QTI 3 Player implements the full expressive QTI 3 Item XML vocabulary according to best practices. Consequently, you don't have to know anything about QTI. Just install the component in your project, inject XML, and go! In the following demo, a "TestRunner" application embeds the QTI 3 Player component for Item Rendering.
|
30
|
+
|
31
|
+
<a href="https://qti.amp-up.io/testrunner/" target="_blank">View TestRunner Demo</a>
|
32
|
+
|
33
|
+
<div align="center">
|
34
|
+
<p><b>Thumbnails of Items/Rendering</b></p>
|
35
|
+
|
36
|
+
<img src="https://user-images.githubusercontent.com/898605/158195206-4f82d851-f3f0-47f6-9756-fbee098c7dcf.png" width="320" height="270">
|
37
|
+
<img src="https://user-images.githubusercontent.com/898605/158033033-dbb00c44-6d95-4ec0-9591-9d3459fcc1b8.png" width="320" height="270">
|
38
|
+
<img src="https://user-images.githubusercontent.com/898605/158033144-d19063f0-43c4-48e4-a2d1-6e4de6439fc9.png" width="320" height="270">
|
39
|
+
<img src="https://user-images.githubusercontent.com/898605/158032910-d739e359-c248-4bad-be30-935bb23aa6ff.png" width="320" height="270">
|
40
|
+
</div>
|
41
|
+
|
42
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
## Getting Started
|
47
|
+
|
48
|
+
### 1. Clone the repo
|
49
|
+
```sh
|
50
|
+
git clone https://github.com/amp-up-io/qti3-item-player-vue3.git
|
51
|
+
```
|
52
|
+
|
53
|
+
### 2. Install Node.js >= 20
|
54
|
+
QTI 3 Player for Vue 3 has been built and tested with Node v20.14.0.
|
55
|
+
|
56
|
+
### 3. Installation
|
57
|
+
QTI 3 Player for Vue 3 includes a dependency on Vue 3, and a dependency on Vite for bundling.
|
58
|
+
|
59
|
+
```sh
|
60
|
+
npm install
|
61
|
+
```
|
62
|
+
|
63
|
+
### 4. Compiles and hot-reloads for development
|
64
|
+
```sh
|
65
|
+
npm run dev
|
66
|
+
```
|
67
|
+
|
68
|
+
### 5. Compiles, minifies, creates package
|
69
|
+
```sh
|
70
|
+
npm run build
|
71
|
+
```
|
72
|
+
|
73
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
## Usage
|
78
|
+
|
79
|
+
The [Demo TestRunner](https://github.com/amp-up-io/qti3-item-player-controller) is a good way to get familiar with QTI 3 Player usage. Specifically, please see the [TestRunner.vue](https://github.com/amp-up-io/qti3-item-player-controller/blob/main/src/views/TestRunner.vue) sub-component.
|
80
|
+
|
81
|
+
|
82
|
+
### 1. Import QTI 3 Player and QTI 3 Player CSS
|
83
|
+
|
84
|
+
```js
|
85
|
+
// The Qti3Player component and built-in CSS
|
86
|
+
import Qti3Player from 'qti3-item-player-vue3'
|
87
|
+
import 'qti3-item-player-vue3/dist/qti3Player.css'
|
88
|
+
```
|
89
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
90
|
+
|
91
|
+
|
92
|
+
### 2. Load the QTI 3 Player component in your Page or Template
|
93
|
+
|
94
|
+
```html
|
95
|
+
<Qti3Player
|
96
|
+
ref="qti3player"
|
97
|
+
:container-class="containerClass"
|
98
|
+
:container-padding-class="containerPaddingClass"
|
99
|
+
:color-class="colorClass"
|
100
|
+
suppress-alert-messages
|
101
|
+
suppress-invalid-response-messages
|
102
|
+
@notifyQti3PlayerReady="handlePlayerReady"
|
103
|
+
@notifyQti3ItemReady="handleItemReady"
|
104
|
+
@notifyQti3SuspendAttemptCompleted="handleSuspendAttemptCompleted"
|
105
|
+
@notifyQti3EndAttemptCompleted="handleEndAttemptCompleted"
|
106
|
+
@notifyQti3ScoreAttemptCompleted="handleScoreAttemptCompleted"
|
107
|
+
@notifyQti3ItemAlertEvent="displayItemAlertEvent"
|
108
|
+
@notifyQti3ItemCatalogEvent="handleItemCatalogEvent"
|
109
|
+
/>
|
110
|
+
```
|
111
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
112
|
+
|
113
|
+
|
114
|
+
### 3. Listen for the QTI 3 Player 'notifyQti3PlayerReady' event
|
115
|
+
|
116
|
+
This event signifies that the QTI 3 Player component is loaded and ready for action. The following snippet is a sample handler for the `notifyQti3PlayerReady` event. QTI 3 Player hands itself as an argument to the `notifyQti3PlayerReady` event, thus simplifying further QTI 3 Player API calls.
|
117
|
+
|
118
|
+
```js
|
119
|
+
/**
|
120
|
+
* @description Event handler for the QTI 3 Player component's 'notifyQti3PlayerReady'
|
121
|
+
* event. This event is fired upon mounting of QTI 3 Player.
|
122
|
+
*
|
123
|
+
* The Qti3Player is now ready for loading XML.
|
124
|
+
* @param {Component} qti3Player - the QTI 3 Player component itself
|
125
|
+
*/
|
126
|
+
handlePlayerReady (qti3Player) {
|
127
|
+
this.qti3Player = qti3Player
|
128
|
+
}
|
129
|
+
```
|
130
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
131
|
+
|
132
|
+
|
133
|
+
### 4. Load a QTI 3 Item into QTI 3 Player
|
134
|
+
|
135
|
+
Once QTI 3 Player is loaded and ready (see #3 above), QTI 3 Item XML can be loaded directly into QTI 3 Player via the Player's `loadItemFromXML` method which takes two arguments `xml {String}` and `configuration {Object}`.
|
136
|
+
|
137
|
+
```js
|
138
|
+
// Load item XML with a configuration. Use the 'this.qti3Player' reference
|
139
|
+
// saved in the notifyQti3PlayerReady event handler.
|
140
|
+
this.qti3Player.loadItemFromXml(xml, configuration)
|
141
|
+
```
|
142
|
+
|
143
|
+
#### 4a) About a Configuration
|
144
|
+
|
145
|
+
The `configuration` object is used to specify runtime context to QTI 3 Player during the item session loaded in `loadItemFromXml`. A configuration object has the following structure:
|
146
|
+
|
147
|
+
```js
|
148
|
+
configuration: {
|
149
|
+
guid: <{String} identifier used to track item state>,
|
150
|
+
pnp: <{Object} used to define Personal Needs and Preferences>,
|
151
|
+
status: <{String} use to define Item Lifecycle Status>,
|
152
|
+
sessionControl: <{Object} used to define Item Session Control>,
|
153
|
+
state: <{Object} used to RESTORE prior state saved from a prior Item Session>
|
154
|
+
}
|
155
|
+
```
|
156
|
+
|
157
|
+
#### 4b) Constructing a Configuration
|
158
|
+
|
159
|
+
The following snippet is an example of how an application can construct a `configuration`.
|
160
|
+
|
161
|
+
```js
|
162
|
+
// Intialize
|
163
|
+
const configuration = {}
|
164
|
+
|
165
|
+
// Stamp an item's tracking guid (if any) onto the configuration
|
166
|
+
configuration.guid = myItemTrackingGuid
|
167
|
+
|
168
|
+
// QTI 3 Player includes a helper class called 'PnpFactory' which can be used
|
169
|
+
// to build a Personal Needs and Preferences definition.
|
170
|
+
// The Default pnp object in the PnpFactory is:
|
171
|
+
const pnp = {
|
172
|
+
textAppearance: {
|
173
|
+
colorStyle: 'qti3-player-color-default'
|
174
|
+
},
|
175
|
+
// Glossary is universal support turned on (true) by default
|
176
|
+
glossaryOnScreen: true,
|
177
|
+
// Keyword translation is off ('') by default
|
178
|
+
keywordTranslationLanguage: '',
|
179
|
+
// Custom SBAC Illustrated Glossary is off (false) by default
|
180
|
+
extSbacGlossaryIllustration: false,
|
181
|
+
layoutSingleColumn: false // unsupported - see Roadmap (Simplified Layout)
|
182
|
+
}
|
183
|
+
|
184
|
+
// Set the configuration's 'pnp' property
|
185
|
+
configuration.pnp = pnp
|
186
|
+
|
187
|
+
// OPTIONAL
|
188
|
+
// Use 'status' to reflect the current QTI Item Lifecycle Status, which is an
|
189
|
+
// enumerated vocabulary from the set of:
|
190
|
+
// { 'initial' | 'interacting' | 'closed' | 'review' | 'solution'}
|
191
|
+
configuration.status = 'interacting'
|
192
|
+
|
193
|
+
// Set 'status' to 'review' in order to disable interactions; i.e., interactions
|
194
|
+
// can no longer be altered.
|
195
|
+
// configuration.status = 'review'
|
196
|
+
|
197
|
+
// QTI 3 Player includes a helper class called 'SessionControlFactory' which can be
|
198
|
+
// used to build an Item Session Control definition.
|
199
|
+
// The Default sessionControl object in the SessionControlFactory is:
|
200
|
+
const defaultItemSessionControl = {
|
201
|
+
max_attempts: 0, // no limit
|
202
|
+
show_feedback: false,
|
203
|
+
validate_responses: false
|
204
|
+
}
|
205
|
+
|
206
|
+
// Set the configuration's 'sessionControl' property
|
207
|
+
configuration.sessionControl = defaultItemSessionControl
|
208
|
+
|
209
|
+
// OPTIONAL
|
210
|
+
// If a 'state' property is in a configuration then QTI 3 Player will
|
211
|
+
// use this to restore a prior item state - including all
|
212
|
+
// template, context, outcome, and response variables.
|
213
|
+
const state = testController.getTestStateItemState(myItemTrackingGuid)
|
214
|
+
if (typeof state !== 'undefined') configuration.state = state
|
215
|
+
```
|
216
|
+
|
217
|
+
In the absence of a `pnp` property, QTI 3 Player will use defaults, or previous settings, for presentation and accessibility supports. In the absence of a `sessionControl` property, QTI 3 Player will use defaults, or previous settings, for the Item Session Control definition.
|
218
|
+
|
219
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
220
|
+
|
221
|
+
|
222
|
+
### 5. Listen for the QTI 3 Player 'notifyQti3ItemReady' Event
|
223
|
+
|
224
|
+
QTI 3 Player triggers a `notifyQti3ItemReady` event upon completion of the Player's `loadItemFromXML` method. The following snippet is a sample handler for the `notifyQti3ItemReady` event.
|
225
|
+
|
226
|
+
```js
|
227
|
+
/**
|
228
|
+
* @description Event handler for the QTI3Player component's 'notifyQti3ItemReady'
|
229
|
+
* event. This event is fired upon completion of the qti-assessment-item
|
230
|
+
* component's loading of XML.
|
231
|
+
*/
|
232
|
+
handleItemReady () {
|
233
|
+
console.log('QTI 3 Item XML is loaded and rendered! The latest "attempt" has officially begun.')
|
234
|
+
}
|
235
|
+
```
|
236
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
237
|
+
|
238
|
+
|
239
|
+
### 6. Retrieving Item State
|
240
|
+
|
241
|
+
After item XML is loaded and an attempt has begun, a test controller may retrieve the item's current state via two methods:
|
242
|
+
|
243
|
+
* **endAttempt**
|
244
|
+
|
245
|
+
This performs response validation (if validateResponses=true), ends the attempt, _executes response processing_, and produces the state of all item variables. Typical use is when `submissionMode: "individual"`, or when you want to generate a raw score from the responses and the response processing. Note that Feedback (inline, block, modal) is also displayed if `showFeedback: true`.
|
246
|
+
|
247
|
+
QTI 3 Player supports the _full QTI 3 response processing_ expression vocabulary.
|
248
|
+
|
249
|
+
* **suspendAttempt**
|
250
|
+
|
251
|
+
This performs response validation (if `validateResponses: true`) and produces the state of all item variables. _No response processing is executed._ Typical use is when `submissionMode: "simultaneous"`.
|
252
|
+
|
253
|
+
The `endAttempt` and `suspendAttempt` methods may take a considerable amount of time to complete. QTI 3 Player triggers the `notifyQti3EndAttemptCompleted` and `notifyQti3SuspendAttemptCompleted` events, respectively, upon completion of an `endAttempt` or a `suspendAttempt` method call.
|
254
|
+
|
255
|
+
#### 6a) Calling endAttempt and handling the notifyQti3EndAttemptCompleted event
|
256
|
+
|
257
|
+
```js
|
258
|
+
// Call the endAttempt method, passing a string/target action that will be
|
259
|
+
// echoed back in the notifyQti3EndAttemptCompleted event payload.
|
260
|
+
this.qti3Player.endAttempt('navigateNextItem')
|
261
|
+
```
|
262
|
+
|
263
|
+
```js
|
264
|
+
/**
|
265
|
+
* @description Example event handler for the QTI3Player component's 'notifyQti3EndAttemptCompleted'
|
266
|
+
* event. This event is fired upon completion of the endAttempt method.
|
267
|
+
* @param {Object} data - the item's state, including outcomes from response processing
|
268
|
+
*/
|
269
|
+
handleEndAttemptCompleted (data) {
|
270
|
+
// 'data' contains the item state, including any validation messages,
|
271
|
+
// response variable values, outcome variable values, template variable values,
|
272
|
+
// and context variable values.
|
273
|
+
// ... do something ...
|
274
|
+
}
|
275
|
+
```
|
276
|
+
|
277
|
+
#### 6b) Calling suspendAttempt and handling the notifyQti3SuspendAttemptCompleted event
|
278
|
+
|
279
|
+
```js
|
280
|
+
// Call the suspendAttempt method, passing a string/target action that will be
|
281
|
+
// echoed back in the notifyQti3SuspendAttemptCompleted event payload.
|
282
|
+
this.qti3Player.suspendAttempt('navigateNextItem')
|
283
|
+
```
|
284
|
+
|
285
|
+
```js
|
286
|
+
/**
|
287
|
+
* @description Example event handler for the QTI3Player component's 'notifyQti3SuspendAttemptCompleted'
|
288
|
+
* event. This event is fired upon completion of the suspendAttempt method.
|
289
|
+
* @param {Object} data - the item's state
|
290
|
+
*/
|
291
|
+
handleSuspendAttemptCompleted (data) {
|
292
|
+
// 'data' contains the item state, including any validation messages,
|
293
|
+
// response variable values, outcome variable values, template variable values,
|
294
|
+
// and context variable values.
|
295
|
+
// ... do something ...
|
296
|
+
}
|
297
|
+
```
|
298
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
299
|
+
|
300
|
+
|
301
|
+
### 7. About Item State
|
302
|
+
|
303
|
+
#### Item State Object Structure
|
304
|
+
|
305
|
+
The `endAttempt`, `suspendAttempt`, and `scoreAttempt` methods produce a `state` object
|
306
|
+
with the following properties/structure:
|
307
|
+
|
308
|
+
```js
|
309
|
+
"state": {
|
310
|
+
"identifier": "<qti-assessment-item identifier>",
|
311
|
+
"guid": "<tracking guid passed in the configuration>",
|
312
|
+
"contextVariables": [ <built-in and declared context variables> ],
|
313
|
+
"responseVariables": [ <built-in and declared response variables> ],
|
314
|
+
"outcomeVariables": [ <built-in and declared outcome variables> ],
|
315
|
+
"templateVariables": [ <declared template variables> ],
|
316
|
+
"validationMessages": [ <validation messages (if validateResponses: true, and response constraints not met)> ]
|
317
|
+
}
|
318
|
+
```
|
319
|
+
|
320
|
+
#### Full Item State Example Payload
|
321
|
+
|
322
|
+
In this item, there are two qti-choice-interaction's, each with single cardinality. This item is not adaptive; i.e., `adaptive="false"`, and the item's XML contains no response processing that changes the original value of `completionStatus`.
|
323
|
+
|
324
|
+
```js
|
325
|
+
{
|
326
|
+
"state": {
|
327
|
+
"identifier": "q2-choice-interaction-single-sv-4a",
|
328
|
+
"guid": "0000-0002-0001",
|
329
|
+
"contextVariables": [
|
330
|
+
{
|
331
|
+
"identifier": "QTI_CONTEXT",
|
332
|
+
"cardinality": "record",
|
333
|
+
"value": {}
|
334
|
+
}
|
335
|
+
],
|
336
|
+
"responseVariables": [
|
337
|
+
{
|
338
|
+
"identifier": "numAttempts",
|
339
|
+
"cardinality": "single",
|
340
|
+
"value": 1,
|
341
|
+
"state": null
|
342
|
+
},
|
343
|
+
{
|
344
|
+
"identifier": "duration",
|
345
|
+
"cardinality": "single",
|
346
|
+
"value": 0,
|
347
|
+
"state": null
|
348
|
+
},
|
349
|
+
{
|
350
|
+
"identifier": "RESPONSE1",
|
351
|
+
"cardinality": "single",
|
352
|
+
"value": "ChoiceA",
|
353
|
+
"state": {
|
354
|
+
"order": [
|
355
|
+
"ChoiceA",
|
356
|
+
"ChoiceB",
|
357
|
+
"ChoiceC"
|
358
|
+
]
|
359
|
+
},
|
360
|
+
"correctResponse": null
|
361
|
+
},
|
362
|
+
{
|
363
|
+
"identifier": "RESPONSE2",
|
364
|
+
"cardinality": "single",
|
365
|
+
"value": "ChoiceB",
|
366
|
+
"state": {
|
367
|
+
"order": [
|
368
|
+
"ChoiceA",
|
369
|
+
"ChoiceB",
|
370
|
+
"ChoiceC"
|
371
|
+
]
|
372
|
+
},
|
373
|
+
"correctResponse": null
|
374
|
+
}
|
375
|
+
],
|
376
|
+
"outcomeVariables": [
|
377
|
+
{
|
378
|
+
"identifier": "SCORE",
|
379
|
+
"cardinality": "single",
|
380
|
+
"value": 0
|
381
|
+
},
|
382
|
+
{
|
383
|
+
"identifier": "completionStatus",
|
384
|
+
"cardinality": "single",
|
385
|
+
"value": "not_attempted"
|
386
|
+
}
|
387
|
+
],
|
388
|
+
"templateVariables": [],
|
389
|
+
"validationMessages": []
|
390
|
+
},
|
391
|
+
"target": "navigateNextItem"
|
392
|
+
}
|
393
|
+
```
|
394
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
395
|
+
|
396
|
+
|
397
|
+
### 8. Scoring API
|
398
|
+
|
399
|
+
There are scenarios where an encapsulating application may load item XML - along with a provided Item State - into QTI 3 Player and then score the Item State by executing response processing. Such a scenario exists when a Test Part's `submission-mode` is set to `simultaneous`. Another use-case is when a scoring system is batch-scoring a collection of items and a candidate's Item States from a submitted Test. For these scenarios, use the `scoreAttempt` method:
|
400
|
+
|
401
|
+
* **scoreAttempt**
|
402
|
+
|
403
|
+
Given an Item State, _executes response processing_ with the item's XML, and produces the state of all item variables upon completion of response processing. No response validation is performed. Typical use is when `submissionMode: "simultaneous"`, or when you want to generate a raw score from the responses and the response processing _without_ invoking the endAttempt method (which has some side-effects - such as incrementing the numAttempts variable - that may be undesirable when simply trying to get a machine score from the given Item State).
|
404
|
+
|
405
|
+
QTI 3 Player supports the _full QTI 3 response processing_ expression vocabulary.
|
406
|
+
|
407
|
+
The `scoreAttempt` method may take a considerable amount of time to complete. QTI 3 Player triggers the `notifyQti3ScoreAttemptCompleted` event upon completion of a `scoreAttempt` method invocation.
|
408
|
+
|
409
|
+
```html
|
410
|
+
<Qti3Player
|
411
|
+
ref="qti3player"
|
412
|
+
@notifyQti3ScoreAttemptCompleted="handleScoreAttemptCompleted"
|
413
|
+
/>
|
414
|
+
```
|
415
|
+
|
416
|
+
#### 8a) Calling scoreAttempt and handling the notifyQti3ScoreAttemptCompleted event
|
417
|
+
|
418
|
+
```js
|
419
|
+
// Call the scoreAttempt method, passing a string/target action that will be
|
420
|
+
// echoed back in the notifyQti3ScoreAttemptCompleted event payload.
|
421
|
+
this.qti3Player.scoreAttempt('itemScoreReady')
|
422
|
+
```
|
423
|
+
|
424
|
+
```js
|
425
|
+
/**
|
426
|
+
* @description Example event handler for the QTI3Player component's 'notifyQti3ScoreAttemptCompleted'
|
427
|
+
* event. This event is fired upon completion of the scoreAttempt method.
|
428
|
+
* @param {Object} data - the item's state, including outcomes from response processing
|
429
|
+
*/
|
430
|
+
handleScoreAttemptCompleted (data) {
|
431
|
+
// 'data' contains the item state in a 'state' property, including response variable values,
|
432
|
+
// outcome variable values, template variable values, and context variable values.
|
433
|
+
// 'data' also has a 'target' property that echos the value (if any) of the target string
|
434
|
+
// parameter passed into the originaging scoreAttempt call.
|
435
|
+
// ... do something ...
|
436
|
+
console.log('SCORE ATTEMPT OUTCOMES', data.state)
|
437
|
+
const itemState = data.state
|
438
|
+
const target = data.target
|
439
|
+
// Echo all Outcome variables in the Item State
|
440
|
+
itemState.outcomeVariables.forEach((outcomeVariable) => {
|
441
|
+
console.log(`[Outcome][${outcomeVariable.identifier}][Value=${outcomeVariable.value}]`)
|
442
|
+
})
|
443
|
+
}
|
444
|
+
```
|
445
|
+
|
446
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
447
|
+
|
448
|
+
|
449
|
+
### 9. Item Session 'Alert' Messages and the notifyQti3ItemAlertEvent
|
450
|
+
|
451
|
+
An item session 'alert' message is triggered by QTI 3 Player when a person exceeds an interaction's max-choices or max-associations threshold. QTI 3 Player uses a built-in messaging/toast component to display such alerts to the candidate.
|
452
|
+
|
453
|
+
An encapsulating application may instrument the QTI 3 Player to _not display alert messages_ by specifying the boolean attribute `suppress-alert-messages`. Example:
|
454
|
+
|
455
|
+
```html
|
456
|
+
<Qti3Player
|
457
|
+
ref="qti3player"
|
458
|
+
suppress-alert-messages
|
459
|
+
@notifyQti3ItemAlertEvent="displayItemAlertEvent"
|
460
|
+
/>
|
461
|
+
```
|
462
|
+
|
463
|
+
An encapsulating application should implement a handler for the `notifyQti3ItemAlertEvent` when instrumenting QTI 3 Player to suppress its internal alert message display. Example:
|
464
|
+
|
465
|
+
```js
|
466
|
+
/**
|
467
|
+
* @description Handler for QTI item alert messages such as max selections messages.
|
468
|
+
* @param {Object} event - object containing an icon property and a message property
|
469
|
+
*/
|
470
|
+
displayItemAlertEvent (event) {
|
471
|
+
// This example uses the sweetalert component to display messages as toasts
|
472
|
+
Swal.fire({
|
473
|
+
toast: true,
|
474
|
+
position: 'top-end',
|
475
|
+
icon: event.icon,
|
476
|
+
html: event.message,
|
477
|
+
showConfirmButton: false,
|
478
|
+
showCloseButton: true,
|
479
|
+
timer: 3000,
|
480
|
+
timerProgressBar: true
|
481
|
+
})
|
482
|
+
}
|
483
|
+
```
|
484
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
485
|
+
|
486
|
+
|
487
|
+
### 10. Item Session 'Invalid Response' Messages
|
488
|
+
|
489
|
+
An item session 'invalid response' message is triggered by QTI 3 Player when,
|
490
|
+
|
491
|
+
* `SessionControl.validateResponses=true`, and
|
492
|
+
* A response validity requirement is not met on an interaction in the loaded item
|
493
|
+
|
494
|
+
As with item session 'alert' messages, QTI 3 Player uses a built-in messaging/toast component to display such 'invalid response' messages to the candidate.
|
495
|
+
|
496
|
+
An encapsulating application may instrument the QTI 3 Player to _not display invalid response messages_ by specifying the boolean attribute `suppress-invalid-response-messages`. Example:
|
497
|
+
|
498
|
+
```html
|
499
|
+
<Qti3Player
|
500
|
+
ref="qti3player"
|
501
|
+
suppress-invalid-response-messages
|
502
|
+
/>
|
503
|
+
```
|
504
|
+
|
505
|
+
All violations of response validity are reported in the `validationMessages` property of the state object returned to the notifyQti3EndAttemptCompleted and notifyQti3SuspendAttemptCompleted event handlers.
|
506
|
+
|
507
|
+
```js
|
508
|
+
"state": {
|
509
|
+
"identifier": "<qti-assessment-item identifier>",
|
510
|
+
"guid": "<tracking guid passed in the configuration>",
|
511
|
+
"contextVariables": [ <built-in and declared context variables> ],
|
512
|
+
"responseVariables": [ <built-in and declared response variables> ],
|
513
|
+
"outcomeVariables": [ <built-in and declared outcome variables> ],
|
514
|
+
"templateVariables": [ <declared template variables> ],
|
515
|
+
"validationMessages": [
|
516
|
+
{
|
517
|
+
"identifier": "RESPONSE3",
|
518
|
+
"message": "Not enough selected! Please select at least two."
|
519
|
+
}
|
520
|
+
]
|
521
|
+
}
|
522
|
+
```
|
523
|
+
|
524
|
+
This permits an encapsulating application to handle and display validation messages using its own UX.
|
525
|
+
|
526
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
527
|
+
|
528
|
+
|
529
|
+
### 11. Item 'Catalog' Events
|
530
|
+
|
531
|
+
An item 'catalog' event is triggered by QTI 3 Player when a user selects a control (such as a highlighted term) within the item's presentation that is bound to an item's catalog. As of QTI 3 Player version 0.3.1, the only supported catalog event () is a 'glossary' event. QTI 3 Player will display its own Catalog Glossary Dialog component when a user selects a control within the item's presentation that is bound to a 'glossary' event.
|
532
|
+
|
533
|
+
|
534
|
+
<div align="center">
|
535
|
+
<p><b>Example of QTI 3 Player Glossary Dialog</b></p>
|
536
|
+
<img src="https://user-images.githubusercontent.com/898605/161848852-6cec8b3d-f843-403c-a651-99b284946f65.png" width="260" height="240">
|
537
|
+
</div>
|
538
|
+
|
539
|
+
|
540
|
+
An encapsulating application may instrument the QTI 3 Player to _not display its internal Catalog Dialog component_ by specifying the boolean attribute `suppress-catalog-messages`. When instrumenting QTI 3 Player to suppress its internal catalog message display, an application should implement a handler for the `notifyQti3ItemCatalogEvent`. This permits an application to handle and display catalog event messages using its own UX. Example:
|
541
|
+
|
542
|
+
```html
|
543
|
+
<Qti3Player
|
544
|
+
ref="qti3player"
|
545
|
+
suppress-catalog-messages
|
546
|
+
@notifyQti3ItemCatalogEvent="handleItemCatalogEvent"
|
547
|
+
/>
|
548
|
+
```
|
549
|
+
|
550
|
+
```js
|
551
|
+
/**
|
552
|
+
* @description Handler for QTI item catalog events such as 'glossary' events.
|
553
|
+
* @param {Object} event - object containing a catalog event payload
|
554
|
+
* Sample event schema:
|
555
|
+
* {
|
556
|
+
* type: "glossary",
|
557
|
+
* term: "acronym",
|
558
|
+
* catalogIdRef: "glosscat",
|
559
|
+
* data: [
|
560
|
+
* {
|
561
|
+
* support: "glossary-on-screen",
|
562
|
+
* card: {
|
563
|
+
* content: ""<p>An abbreviation.</p>"",
|
564
|
+
* properties: {
|
565
|
+
* name: "qti-html-content"
|
566
|
+
* }
|
567
|
+
* }
|
568
|
+
* }
|
569
|
+
* ... additional Card supports in Catalog based on PNP ...
|
570
|
+
* ]
|
571
|
+
* }
|
572
|
+
*/
|
573
|
+
handleItemCatalogEvent (event) {
|
574
|
+
console.log('[ItemCatalogEvent][Type: ' + event.type + ']', event)
|
575
|
+
switch (event.type) {
|
576
|
+
case 'glossary':
|
577
|
+
// Do something!
|
578
|
+
break
|
579
|
+
default:
|
580
|
+
}
|
581
|
+
},
|
582
|
+
```
|
583
|
+
|
584
|
+
#### Supported Keyword Translation Language Codes ####
|
585
|
+
|
586
|
+
QTI 3 Player groups PNP 'glossary-on-screen', 'keyword-translation', and 'ext:sbac-glossary-illustration' supports into 'glossary' events that will trigger a Catalog event of type 'glossary'.
|
587
|
+
|
588
|
+
As of the 0.3.4 release, QTI 3 Player supports the following IS0 639 language codes for keyword translations:
|
589
|
+
|
590
|
+
`{ ar | cmn | de | en | es | fr | hmn | it | ja | ko | my | nl | pa | ru | so | tl | uk | vi | yue | zh }`
|
591
|
+
|
592
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
593
|
+
|
594
|
+
|
595
|
+
### 12. About Dynamic Catalog Rebinding
|
596
|
+
|
597
|
+
Under most use-cases, a PNP is passed into QTI 3 Player as part of the configuration (see 4b Constructing a Configuration) as an item's XML is loaded. However, _after an item is loaded_, an encapsulating application may update PNP settings and then force a catalog rebinding with the updated PNP settings. QTI 3 Player implements a `bindCatalog` API method for this use-case.
|
598
|
+
|
599
|
+
```js
|
600
|
+
// 1) Use the PnpFactory helper class to build an updated PNP.
|
601
|
+
let pnpFactory = new PnpFactory()
|
602
|
+
// Example: turn off glossary
|
603
|
+
pnpFactory.setGlossaryOnScreen(false)
|
604
|
+
// Example: turn on Spanish keyword translations
|
605
|
+
pnpFactory.setKeywordTranslationLanguage('es')
|
606
|
+
// Example: turn on ext:sbac-glossary-illustration
|
607
|
+
pnpFactory.setExtSbacGlossaryIllustration(true)
|
608
|
+
|
609
|
+
// 2) Set QTI 3 Player's current PNP to our new PNP constructed in 1) above.
|
610
|
+
this.qti3Player.setItemContextPnp(pnpFactory.getPnp())
|
611
|
+
|
612
|
+
// 3) Even with a new Item Context PNP (step 2) above, QTI 3 Player will not
|
613
|
+
// automatically rebind the PNP + Catalog.
|
614
|
+
// Force QTI3 Player to bind (rebind) the Catalog.
|
615
|
+
this.qti3Player.bindCatalog()
|
616
|
+
```
|
617
|
+
|
618
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
619
|
+
|
620
|
+
|
621
|
+
## QTI 3 Player Presentation Attributes
|
622
|
+
|
623
|
+
QTI 3 Player has several attributes to instrument presentation within an encapsulating application/web page. These attributes are `container-class`, `container-padding-class`, and `color-class`
|
624
|
+
|
625
|
+
### container-class
|
626
|
+
|
627
|
+
Container classes are used to contain and pad content within them. QTI 3 Player comes with built-in support for two container classes: `qti3-player-container-fluid` and `qti3-player-container`.
|
628
|
+
|
629
|
+
* qti3-player-container-fluid **DEFAULT**
|
630
|
+
|
631
|
+
This container is a width=100%, padding=0 container at all widths.
|
632
|
+
|
633
|
+
* qti3-player-container
|
634
|
+
|
635
|
+
This container has responsive breakpoints at screen widths of 1200px, 980px, and 768px.
|
636
|
+
|
637
|
+
<a href="https://qti.amp-up.io/testrunner/test/1" target="testrunner">Experiment with the Container Class</a> Note: Click the "Settings" menu in the top-right corner of the TestRunner application.
|
638
|
+
|
639
|
+
|
640
|
+
### container-padding-class
|
641
|
+
|
642
|
+
Container padding classes are for setting the padding between the QTI 3 Player container and the qti-assessment-item rendered content. QTI 3 Player comes with built-in support for six container padding classes.
|
643
|
+
|
644
|
+
* qti3-player-container-padding-0 { padding: 0; } **DEFAULT**
|
645
|
+
* qti3-player-container-padding-1 { padding: 0.25rem; }
|
646
|
+
* qti3-player-container-padding-2 { padding: 0.5rem; }
|
647
|
+
* qti3-player-container-padding-3 { padding: 1rem; }
|
648
|
+
* qti3-player-container-padding-4 { padding: 1.5rem; }
|
649
|
+
* qti3-player-container-padding-5 { padding: 3rem; }
|
650
|
+
|
651
|
+
<a href="https://qti.amp-up.io/testrunner/test/1" target="testrunner">Experiment with the Container Padding Class</a> Note: Click the "Settings" menu in the top-right corner of the TestRunner application.
|
652
|
+
|
653
|
+
|
654
|
+
### color-class
|
655
|
+
|
656
|
+
QTI 3 Player has built-in support for 14 foreground / background color combinations (a.k.a. color "themes") in accordance with best practices for many forms of color blindness or other visual impairments. In addition to setting a colorClass in a PNP, color settings may also be applied dynamically.
|
657
|
+
|
658
|
+
* qti3-player-color-default **DEFAULT**
|
659
|
+
* qti3-player-color-defaultreverse (Default - Reverse Polarity)
|
660
|
+
* qti3-player-color-blackwhite (High Contrast - foreground color: black, background color: white)
|
661
|
+
* qti3-player-color-whiteblack (High Contrast - foreground color: white, background color: black)
|
662
|
+
* qti3-player-color-blackrose (foreground color: black, background color: rose)
|
663
|
+
* qti3-player-color-roseblack (foreground color: rose, background color: black)
|
664
|
+
* qti3-player-color-dgraymgray (foreground color: dark gray, background color: medium gray)
|
665
|
+
* qti3-player-color-mgraydgray (foreground color: medium gray, background color: dark gray)
|
666
|
+
* qti3-player-color-yellowblue (foreground color: yellow, background color: blue)
|
667
|
+
* qti3-player-color-blueyellow (foreground color: blue, background color: yellow)
|
668
|
+
* qti3-player-color-blackcyan (foreground color: black, background color: lblue)
|
669
|
+
* qti3-player-color-cyanblack (foreground color: lblue, background color: black)
|
670
|
+
* qti3-player-color-blackcream (foreground color: black, background color: lemonchiffon)
|
671
|
+
* qti3-player-color-creamblack (foreground color: lemonchiffon, background color: black)
|
672
|
+
|
673
|
+
<a href="https://qti.amp-up.io/testrunner/test/1" target="testrunner">Experiment with the Color Class</a> Note: Click the "Settings" menu in the top-right corner of the TestRunner application.
|
674
|
+
|
675
|
+
|
676
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
677
|
+
|
678
|
+
|
679
|
+
|
680
|
+
## Roadmap
|
681
|
+
|
682
|
+
The QTI3 Item Player 2022-2024 development roadmap includes all features and capabilities included in QTI 3 Delivery System "Basic" and "Advanced" conformance + PCI support.
|
683
|
+
|
684
|
+
- [x] Support for the 14 Standard Color Combinations/Themes
|
685
|
+
- [x] Support for Template Processing and all Template Rules
|
686
|
+
- [x] Support for Template Math Variables
|
687
|
+
- [x] Support for Response Processing and all Response Processing Rules
|
688
|
+
- [x] Support for Smarter Balanced-style Choice Interaction
|
689
|
+
- [x] Support for Smarter Balanced-style Audio player
|
690
|
+
- [x] Support for Adaptive Items and QtiEndAttemptInteraction
|
691
|
+
- [x] Catalog Support for Glossary and Keyword Translation
|
692
|
+
- [x] Catalog Support for Smarter Balanced Illustrated Glossary
|
693
|
+
- [x] Rubric Block Support
|
694
|
+
- [x] QtiStylesheet Support
|
695
|
+
- [x] Shared Stimulus Support
|
696
|
+
- [x] QtiMatch Interaction Support
|
697
|
+
- [x] QtiGapMatch Interaction Support
|
698
|
+
- [x] QtiGraphicGapMatch Interaction Support
|
699
|
+
- [x] QtiHottext Interaction Support
|
700
|
+
- [x] QtiHotspot Interaction Support
|
701
|
+
- [x] QtiOrder Interaction Support
|
702
|
+
- [x] QtiPortableCustom Interaction Support
|
703
|
+
- [x] QtiMedia Interaction Support
|
704
|
+
- [x] Scoring API Examples
|
705
|
+
- [x] Support for Interaction "Review" Status
|
706
|
+
- [x] Improved Audio Player
|
707
|
+
- [x] Improved Video Player
|
708
|
+
|
709
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
710
|
+
|
711
|
+
|
712
|
+
|
713
|
+
<!-- LICENSE -->
|
714
|
+
## License
|
715
|
+
|
716
|
+
Distributed under the MIT License. See `LICENSE` for more information.
|
717
|
+
|
718
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
719
|
+
|
720
|
+
|
721
|
+
|
722
|
+
## Built With
|
723
|
+
|
724
|
+
The QTI3 Item Player is built with the Vue.js (v2.6) framework.
|
725
|
+
|
726
|
+
* [Vue.js](https://vuejs.org/)
|
727
|
+
|
728
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
729
|
+
|
730
|
+
|
731
|
+
|
732
|
+
<!-- CONTACT -->
|
733
|
+
## Contact
|
734
|
+
|
735
|
+
Paul Grudnitski - paul.grudnitski@amp-up.io
|
736
|
+
|
737
|
+
Project Link: [https://github.com/amp-up-io/qti3-item-player](https://github.com/amp-up-io/qti3-item-player)
|
738
|
+
|
739
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
740
|
+
|
741
|
+
|
742
|
+
|
743
|
+
<!-- ACKNOWLEDGMENTS -->
|
744
|
+
## Acknowledgments
|
745
|
+
|
746
|
+
This component would not be possible were it not for a fortuitous decision by the aQTI Task Force (the original name of the QTI 3 Working Group) - meeting at CITO headquarters in Arnhem, NE, January 2015 - to make the aQTI / QTI 3 specification "web component friendly".
|
747
|
+
|
748
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
749
|
+
|
750
|
+
|
751
|
+
[license-shield]: https://img.shields.io/github/license/amp-up-io/qti3-item-player?label=License&style=for-the-badge
|
752
|
+
[license-url]: https://github.com/amp-up-io/qti3-item-player/blob/main/LICENSE
|