@citolab/tspci 2.0.5 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -674
- package/package.json +2 -2
- package/public/index.html +289 -289
- package/readme.md +338 -338
- package/release-notes.md +17 -13
- package/src/cli.js +143 -143
- package/src/rollup-plugin-live-server.js +32 -32
- package/src/rollup.config.dev.js +28 -28
- package/src/rollup.config.js +82 -82
- package/src/rollup.config.prod.js +10 -10
- package/types/index.d.ts +88 -88
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@citolab/tspci",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
4
|
"description": "an opiniated typescript ims-pci builder with tao integration",
|
|
5
5
|
"author": "patrick <patrick.deklein@cito.nl>",
|
|
6
6
|
"repository": "@citolab/tspci",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"tailwindcss": "^3.1.3"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "559a1a390389ca87f68e62efbe2d98c92cab7165"
|
|
67
67
|
}
|
package/public/index.html
CHANGED
|
@@ -1,289 +1,289 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<title>Hello RequireJS</title>
|
|
5
|
-
<script
|
|
6
|
-
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"
|
|
7
|
-
integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg=="
|
|
8
|
-
crossorigin="anonymous"
|
|
9
|
-
referrerpolicy="no-referrer"
|
|
10
|
-
></script>
|
|
11
|
-
<!-- <link rel="stylesheet" class="bootswatcher" href="//bootswatch.com/5/lumen/bootstrap.min.css" /> -->
|
|
12
|
-
|
|
13
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
|
|
14
|
-
|
|
15
|
-
<style>
|
|
16
|
-
html {
|
|
17
|
-
font-size: 100%;
|
|
18
|
-
}
|
|
19
|
-
#pciContainer {
|
|
20
|
-
width: 100%;
|
|
21
|
-
/* min-width: 800px; */
|
|
22
|
-
max-width: 1024px;
|
|
23
|
-
height: 600px;
|
|
24
|
-
min-height: 600px;
|
|
25
|
-
/* max-height: 600px; */
|
|
26
|
-
border: 1px solid #eeeeee;
|
|
27
|
-
overflow: hidden;
|
|
28
|
-
margin: 0 auto;
|
|
29
|
-
background-color: white;
|
|
30
|
-
border-radius: 10px;
|
|
31
|
-
margin-top: 1rem;
|
|
32
|
-
}
|
|
33
|
-
#devtools {
|
|
34
|
-
max-width: 1024px;
|
|
35
|
-
margin: 0 auto;
|
|
36
|
-
}
|
|
37
|
-
</style>
|
|
38
|
-
</head>
|
|
39
|
-
<body class="bg-light">
|
|
40
|
-
<div class="container">
|
|
41
|
-
<div
|
|
42
|
-
class="alert alert-danger position-fixed mx-auto bottom-0"
|
|
43
|
-
style="display: none"
|
|
44
|
-
role="alert"
|
|
45
|
-
id="noresponse"
|
|
46
|
-
>
|
|
47
|
-
user has not yet interacted yet, getResponse should return undefined.
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<div id="pciContainer" class="shadow-sm">
|
|
52
|
-
<div id="loading" class="text-muted mx-auto p-4">Loading...</div>
|
|
53
|
-
</div>
|
|
54
|
-
<div id="devtools"></div>
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<script type="module">
|
|
58
|
-
import { h, Component, render } from "https://unpkg.com/preact@latest?module";
|
|
59
|
-
import { useState, useEffect } from "https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module";
|
|
60
|
-
import htm from "https://unpkg.com/htm?module";
|
|
61
|
-
// Initialize htm with Preact
|
|
62
|
-
const html = htm.bind(h);
|
|
63
|
-
|
|
64
|
-
function App({ item }) {
|
|
65
|
-
const [show, setShow] = useState(false);
|
|
66
|
-
|
|
67
|
-
let keyArray = [];
|
|
68
|
-
if (item.config && item.config.properties) {
|
|
69
|
-
keyArray = Object.keys(item.config.properties).map((keyName, keyIndex) => ({
|
|
70
|
-
key: keyName,
|
|
71
|
-
value: item.config.properties[keyName],
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function resetlocalstorage() {
|
|
76
|
-
localStorage.removeItem(item.typeIdentifier + "_state");
|
|
77
|
-
localStorage.removeItem(item.typeIdentifier + "_props");
|
|
78
|
-
localStorage.removeItem(item.typeIdentifier + "_response");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function reset() {
|
|
82
|
-
resetlocalstorage();
|
|
83
|
-
location.reload();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function resetResponse() {
|
|
87
|
-
localStorage.removeItem(item.typeIdentifier + "_response");
|
|
88
|
-
item.resetResponse();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function setResponse() {
|
|
92
|
-
const response = localStorage.getItem(item.typeIdentifier + "_response");
|
|
93
|
-
if (response) {
|
|
94
|
-
item.setResponse({
|
|
95
|
-
base: {
|
|
96
|
-
string: response,
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
} else {
|
|
100
|
-
alert("no response stored");
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function saveResponse() {
|
|
105
|
-
localStorage.setItem(item.typeIdentifier + "_response", item.getResponse().base.string);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function compareResponse() {
|
|
109
|
-
const response = localStorage.getItem(item.typeIdentifier + "_response");
|
|
110
|
-
if (!response) {
|
|
111
|
-
alert("no response stored");
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (response === item.getResponse().base.string) {
|
|
115
|
-
alert("same");
|
|
116
|
-
} else {
|
|
117
|
-
alert("different");
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function reload() {
|
|
122
|
-
const state = item.getState();
|
|
123
|
-
localStorage.setItem(item.typeIdentifier + "_state", JSON.stringify(state));
|
|
124
|
-
location.reload();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function changeConfig(key, value) {
|
|
128
|
-
item.config.properties[key] = value;
|
|
129
|
-
item.trigger(`change${key}`, value);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function reConfig(key, value) {
|
|
133
|
-
localStorage.setItem(item.typeIdentifier + "_props", JSON.stringify(item.config.properties));
|
|
134
|
-
location.reload();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function unload() {
|
|
138
|
-
item.destroy && item.destroy();
|
|
139
|
-
item.oncompleted && item.oncompleted();
|
|
140
|
-
var name = require.undef("index.js");
|
|
141
|
-
loadItem();
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return html`
|
|
145
|
-
<div>
|
|
146
|
-
<div style="width:300px" class="shadow offcanvas offcanvas-end ${show ? "show visible" : ""}">
|
|
147
|
-
<div class="offcanvas-header">
|
|
148
|
-
<h5 class="offcanvas-title" id="offcanvasExampleLabel">properties</h5>
|
|
149
|
-
<button
|
|
150
|
-
type="button"
|
|
151
|
-
onClick="${() => setShow(false)}"
|
|
152
|
-
disabled="${!item.config}"
|
|
153
|
-
class="btn-close text-reset"
|
|
154
|
-
></button>
|
|
155
|
-
</div>
|
|
156
|
-
<div class="offcanvas-body">
|
|
157
|
-
<ul class="card-body">
|
|
158
|
-
${keyArray.map(
|
|
159
|
-
({ key, value }) => html`<div>
|
|
160
|
-
<div>${key}</div>
|
|
161
|
-
<input
|
|
162
|
-
type="text"
|
|
163
|
-
class="form-control"
|
|
164
|
-
value="${value}"
|
|
165
|
-
onkeyup="${(e) => changeConfig(key, e.target.value)}"
|
|
166
|
-
/>
|
|
167
|
-
</div>`
|
|
168
|
-
)}
|
|
169
|
-
</ul>
|
|
170
|
-
<button class="btn btn-primary" onClick="${() => reConfig()}">save and reload</button>
|
|
171
|
-
</div>
|
|
172
|
-
</div>
|
|
173
|
-
|
|
174
|
-
<div class="d-flex justify-content-start mt-3" role="toolbar" aria-label="Toolbar with button groups">
|
|
175
|
-
<div>
|
|
176
|
-
<small class="text-muted">configuration</small>
|
|
177
|
-
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
178
|
-
<button class="btn btn-outline-secondary" onClick="${() => setShow(true)}">props</button>
|
|
179
|
-
<button
|
|
180
|
-
class="btn btn-outline-secondary"
|
|
181
|
-
onClick="${() => alert(JSON.stringify(item.config), null, 4)}"
|
|
182
|
-
>
|
|
183
|
-
config
|
|
184
|
-
</button>
|
|
185
|
-
</div>
|
|
186
|
-
</div>
|
|
187
|
-
|
|
188
|
-
<div>
|
|
189
|
-
<small class="text-muted">data</small>
|
|
190
|
-
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
191
|
-
<button
|
|
192
|
-
class="btn btn-outline-secondary"
|
|
193
|
-
onClick="${() => alert(JSON.stringify(item.getResponse(), null, 4))}"
|
|
194
|
-
>
|
|
195
|
-
getResponse
|
|
196
|
-
</button>
|
|
197
|
-
<button class="btn btn-outline-secondary" onClick="${() => alert(item.getState())}">getStates</button>
|
|
198
|
-
</div>
|
|
199
|
-
</div>
|
|
200
|
-
|
|
201
|
-
<div>
|
|
202
|
-
<small class="text-muted">state</small>
|
|
203
|
-
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
204
|
-
<button class="btn btn-outline-secondary" onClick="${() => reload()}">reload</button>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
<div>
|
|
208
|
-
<small class="text-muted">responses</small>
|
|
209
|
-
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
210
|
-
<button class="btn btn-outline-secondary" onClick="${() => saveResponse()}">store</button>
|
|
211
|
-
<button class="btn btn-outline-secondary" onClick="${() => compareResponse()}">compare</button>
|
|
212
|
-
<button class="btn btn-outline-secondary" onClick="${() => setResponse()}">set</button>
|
|
213
|
-
<button class="btn btn-outline-secondary" disabled="${!item.resetResponse}" onClick="${() => resetResponse()}">reset</button>
|
|
214
|
-
</div>
|
|
215
|
-
</div>
|
|
216
|
-
|
|
217
|
-
<div>
|
|
218
|
-
<small class="text-muted">ㅤ</small>
|
|
219
|
-
<div class="d-flex">
|
|
220
|
-
<button class="btn bg-light shadow-sm btn-outline-danger me-2" disabled="${!(item.destroy || item.oncompleted)}" onClick="${() => unload()}">
|
|
221
|
-
unload
|
|
222
|
-
</button>
|
|
223
|
-
<button class="btn bg-light shadow-sm btn-outline-danger" onClick="${() => reset()}">reset</button>
|
|
224
|
-
</div>
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function register(item) {
|
|
232
|
-
let state = undefined;
|
|
233
|
-
const localStorageState = localStorage.getItem(item.typeIdentifier + "_state");
|
|
234
|
-
if (localStorageState) {
|
|
235
|
-
state = JSON.parse(localStorageState);
|
|
236
|
-
}
|
|
237
|
-
let props = {};
|
|
238
|
-
const localStorageProps = localStorage.getItem(item.typeIdentifier + "_props");
|
|
239
|
-
if (localStorageProps) {
|
|
240
|
-
props = JSON.parse(localStorageProps);
|
|
241
|
-
}
|
|
242
|
-
const dom = document.getElementById("pciContainer");
|
|
243
|
-
const config = {
|
|
244
|
-
onready: () => {
|
|
245
|
-
document.getElementById("loading").innerHTML = "";
|
|
246
|
-
},
|
|
247
|
-
properties: props,
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
item.getInstance(dom, config, state);
|
|
251
|
-
|
|
252
|
-
if (item.getResponse() !== undefined) {
|
|
253
|
-
document.getElementById("noresponse").style.display = "block";
|
|
254
|
-
}
|
|
255
|
-
localStorage.removeItem(item.typeIdentifier + "_state");
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
define("qtiCustomInteractionContext", (qtiCustomInteractionContext) => {
|
|
259
|
-
return { register: (ctxA) => register(ctxA) };
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
function loadItem() {
|
|
263
|
-
requirejs(["index.js"], (itemInstance) => {
|
|
264
|
-
render(html`<${App} item="${itemInstance}" />`, document.getElementById("devtools"));
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
window.onload = () => loadItem();
|
|
268
|
-
</script>
|
|
269
|
-
|
|
270
|
-
<h3 style="margin-top: 12rem;">checklist</h3>
|
|
271
|
-
<ul style="margin-bottom:10rem;">
|
|
272
|
-
<li>Is the css scoped to the item?</li>
|
|
273
|
-
<li>Is the css/item somewhat responsive on smaller screens</li>
|
|
274
|
-
<li>Can you reset the item to its initial state</li>
|
|
275
|
-
<li>Can it restore its state ( reload )</li>
|
|
276
|
-
<li>Can you change the config</li>
|
|
277
|
-
<li>Colorblind</li>
|
|
278
|
-
<li>Touch/Mouse friendly</li>
|
|
279
|
-
<li>Works in older browser like IE11</li>
|
|
280
|
-
<li>Destroys itself correctly, removing event listeners</li>
|
|
281
|
-
<li>No objects or variables on global scope</li>
|
|
282
|
-
<li>Triggers correctly on changed config properties</li>
|
|
283
|
-
<li>Implements on off() methods of tao?</li>
|
|
284
|
-
<li>Response type and response correct</li>
|
|
285
|
-
<li>getResponse() should give undefined when user has not done anything</li>
|
|
286
|
-
<li>For TAO to enter response is the entered comparable by the response given</li>
|
|
287
|
-
</ul>
|
|
288
|
-
</body>
|
|
289
|
-
</html>
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title>Hello RequireJS</title>
|
|
5
|
+
<script
|
|
6
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"
|
|
7
|
+
integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg=="
|
|
8
|
+
crossorigin="anonymous"
|
|
9
|
+
referrerpolicy="no-referrer"
|
|
10
|
+
></script>
|
|
11
|
+
<!-- <link rel="stylesheet" class="bootswatcher" href="//bootswatch.com/5/lumen/bootstrap.min.css" /> -->
|
|
12
|
+
|
|
13
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
|
|
14
|
+
|
|
15
|
+
<style>
|
|
16
|
+
html {
|
|
17
|
+
font-size: 100%;
|
|
18
|
+
}
|
|
19
|
+
#pciContainer {
|
|
20
|
+
width: 100%;
|
|
21
|
+
/* min-width: 800px; */
|
|
22
|
+
max-width: 1024px;
|
|
23
|
+
height: 600px;
|
|
24
|
+
min-height: 600px;
|
|
25
|
+
/* max-height: 600px; */
|
|
26
|
+
border: 1px solid #eeeeee;
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
margin: 0 auto;
|
|
29
|
+
background-color: white;
|
|
30
|
+
border-radius: 10px;
|
|
31
|
+
margin-top: 1rem;
|
|
32
|
+
}
|
|
33
|
+
#devtools {
|
|
34
|
+
max-width: 1024px;
|
|
35
|
+
margin: 0 auto;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
38
|
+
</head>
|
|
39
|
+
<body class="bg-light">
|
|
40
|
+
<div class="container">
|
|
41
|
+
<div
|
|
42
|
+
class="alert alert-danger position-fixed mx-auto bottom-0"
|
|
43
|
+
style="display: none"
|
|
44
|
+
role="alert"
|
|
45
|
+
id="noresponse"
|
|
46
|
+
>
|
|
47
|
+
user has not yet interacted yet, getResponse should return undefined.
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
<div id="pciContainer" class="shadow-sm">
|
|
52
|
+
<div id="loading" class="text-muted mx-auto p-4">Loading...</div>
|
|
53
|
+
</div>
|
|
54
|
+
<div id="devtools"></div>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<script type="module">
|
|
58
|
+
import { h, Component, render } from "https://unpkg.com/preact@latest?module";
|
|
59
|
+
import { useState, useEffect } from "https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module";
|
|
60
|
+
import htm from "https://unpkg.com/htm?module";
|
|
61
|
+
// Initialize htm with Preact
|
|
62
|
+
const html = htm.bind(h);
|
|
63
|
+
|
|
64
|
+
function App({ item }) {
|
|
65
|
+
const [show, setShow] = useState(false);
|
|
66
|
+
|
|
67
|
+
let keyArray = [];
|
|
68
|
+
if (item.config && item.config.properties) {
|
|
69
|
+
keyArray = Object.keys(item.config.properties).map((keyName, keyIndex) => ({
|
|
70
|
+
key: keyName,
|
|
71
|
+
value: item.config.properties[keyName],
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function resetlocalstorage() {
|
|
76
|
+
localStorage.removeItem(item.typeIdentifier + "_state");
|
|
77
|
+
localStorage.removeItem(item.typeIdentifier + "_props");
|
|
78
|
+
localStorage.removeItem(item.typeIdentifier + "_response");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function reset() {
|
|
82
|
+
resetlocalstorage();
|
|
83
|
+
location.reload();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function resetResponse() {
|
|
87
|
+
localStorage.removeItem(item.typeIdentifier + "_response");
|
|
88
|
+
item.resetResponse();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function setResponse() {
|
|
92
|
+
const response = localStorage.getItem(item.typeIdentifier + "_response");
|
|
93
|
+
if (response) {
|
|
94
|
+
item.setResponse({
|
|
95
|
+
base: {
|
|
96
|
+
string: response,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
alert("no response stored");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function saveResponse() {
|
|
105
|
+
localStorage.setItem(item.typeIdentifier + "_response", item.getResponse().base.string);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function compareResponse() {
|
|
109
|
+
const response = localStorage.getItem(item.typeIdentifier + "_response");
|
|
110
|
+
if (!response) {
|
|
111
|
+
alert("no response stored");
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (response === item.getResponse().base.string) {
|
|
115
|
+
alert("same");
|
|
116
|
+
} else {
|
|
117
|
+
alert("different");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function reload() {
|
|
122
|
+
const state = item.getState();
|
|
123
|
+
localStorage.setItem(item.typeIdentifier + "_state", JSON.stringify(state));
|
|
124
|
+
location.reload();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function changeConfig(key, value) {
|
|
128
|
+
item.config.properties[key] = value;
|
|
129
|
+
item.trigger(`change${key}`, value);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function reConfig(key, value) {
|
|
133
|
+
localStorage.setItem(item.typeIdentifier + "_props", JSON.stringify(item.config.properties));
|
|
134
|
+
location.reload();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function unload() {
|
|
138
|
+
item.destroy && item.destroy();
|
|
139
|
+
item.oncompleted && item.oncompleted();
|
|
140
|
+
var name = require.undef("index.js");
|
|
141
|
+
loadItem();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return html`
|
|
145
|
+
<div>
|
|
146
|
+
<div style="width:300px" class="shadow offcanvas offcanvas-end ${show ? "show visible" : ""}">
|
|
147
|
+
<div class="offcanvas-header">
|
|
148
|
+
<h5 class="offcanvas-title" id="offcanvasExampleLabel">properties</h5>
|
|
149
|
+
<button
|
|
150
|
+
type="button"
|
|
151
|
+
onClick="${() => setShow(false)}"
|
|
152
|
+
disabled="${!item.config}"
|
|
153
|
+
class="btn-close text-reset"
|
|
154
|
+
></button>
|
|
155
|
+
</div>
|
|
156
|
+
<div class="offcanvas-body">
|
|
157
|
+
<ul class="card-body">
|
|
158
|
+
${keyArray.map(
|
|
159
|
+
({ key, value }) => html`<div>
|
|
160
|
+
<div>${key}</div>
|
|
161
|
+
<input
|
|
162
|
+
type="text"
|
|
163
|
+
class="form-control"
|
|
164
|
+
value="${value}"
|
|
165
|
+
onkeyup="${(e) => changeConfig(key, e.target.value)}"
|
|
166
|
+
/>
|
|
167
|
+
</div>`
|
|
168
|
+
)}
|
|
169
|
+
</ul>
|
|
170
|
+
<button class="btn btn-primary" onClick="${() => reConfig()}">save and reload</button>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<div class="d-flex justify-content-start mt-3" role="toolbar" aria-label="Toolbar with button groups">
|
|
175
|
+
<div>
|
|
176
|
+
<small class="text-muted">configuration</small>
|
|
177
|
+
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
178
|
+
<button class="btn btn-outline-secondary" onClick="${() => setShow(true)}">props</button>
|
|
179
|
+
<button
|
|
180
|
+
class="btn btn-outline-secondary"
|
|
181
|
+
onClick="${() => alert(JSON.stringify(item.config), null, 4)}"
|
|
182
|
+
>
|
|
183
|
+
config
|
|
184
|
+
</button>
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<div>
|
|
189
|
+
<small class="text-muted">data</small>
|
|
190
|
+
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
191
|
+
<button
|
|
192
|
+
class="btn btn-outline-secondary"
|
|
193
|
+
onClick="${() => alert(JSON.stringify(item.getResponse(), null, 4))}"
|
|
194
|
+
>
|
|
195
|
+
getResponse
|
|
196
|
+
</button>
|
|
197
|
+
<button class="btn btn-outline-secondary" onClick="${() => alert(item.getState())}">getStates</button>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
<div>
|
|
202
|
+
<small class="text-muted">state</small>
|
|
203
|
+
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
204
|
+
<button class="btn btn-outline-secondary" onClick="${() => reload()}">reload</button>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
<div>
|
|
208
|
+
<small class="text-muted">responses</small>
|
|
209
|
+
<div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
|
|
210
|
+
<button class="btn btn-outline-secondary" onClick="${() => saveResponse()}">store</button>
|
|
211
|
+
<button class="btn btn-outline-secondary" onClick="${() => compareResponse()}">compare</button>
|
|
212
|
+
<button class="btn btn-outline-secondary" onClick="${() => setResponse()}">set</button>
|
|
213
|
+
<button class="btn btn-outline-secondary" disabled="${!item.resetResponse}" onClick="${() => resetResponse()}">reset</button>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<div>
|
|
218
|
+
<small class="text-muted">ㅤ</small>
|
|
219
|
+
<div class="d-flex">
|
|
220
|
+
<button class="btn bg-light shadow-sm btn-outline-danger me-2" disabled="${!(item.destroy || item.oncompleted)}" onClick="${() => unload()}">
|
|
221
|
+
unload
|
|
222
|
+
</button>
|
|
223
|
+
<button class="btn bg-light shadow-sm btn-outline-danger" onClick="${() => reset()}">reset</button>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function register(item) {
|
|
232
|
+
let state = undefined;
|
|
233
|
+
const localStorageState = localStorage.getItem(item.typeIdentifier + "_state");
|
|
234
|
+
if (localStorageState) {
|
|
235
|
+
state = JSON.parse(localStorageState);
|
|
236
|
+
}
|
|
237
|
+
let props = {};
|
|
238
|
+
const localStorageProps = localStorage.getItem(item.typeIdentifier + "_props");
|
|
239
|
+
if (localStorageProps) {
|
|
240
|
+
props = JSON.parse(localStorageProps);
|
|
241
|
+
}
|
|
242
|
+
const dom = document.getElementById("pciContainer");
|
|
243
|
+
const config = {
|
|
244
|
+
onready: () => {
|
|
245
|
+
document.getElementById("loading").innerHTML = "";
|
|
246
|
+
},
|
|
247
|
+
properties: props,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
item.getInstance(dom, config, state);
|
|
251
|
+
|
|
252
|
+
if (item.getResponse() !== undefined) {
|
|
253
|
+
document.getElementById("noresponse").style.display = "block";
|
|
254
|
+
}
|
|
255
|
+
localStorage.removeItem(item.typeIdentifier + "_state");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
define("qtiCustomInteractionContext", (qtiCustomInteractionContext) => {
|
|
259
|
+
return { register: (ctxA) => register(ctxA) };
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
function loadItem() {
|
|
263
|
+
requirejs(["index.js"], (itemInstance) => {
|
|
264
|
+
render(html`<${App} item="${itemInstance}" />`, document.getElementById("devtools"));
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
window.onload = () => loadItem();
|
|
268
|
+
</script>
|
|
269
|
+
|
|
270
|
+
<h3 style="margin-top: 12rem;">checklist</h3>
|
|
271
|
+
<ul style="margin-bottom:10rem;">
|
|
272
|
+
<li>Is the css scoped to the item?</li>
|
|
273
|
+
<li>Is the css/item somewhat responsive on smaller screens</li>
|
|
274
|
+
<li>Can you reset the item to its initial state</li>
|
|
275
|
+
<li>Can it restore its state ( reload )</li>
|
|
276
|
+
<li>Can you change the config</li>
|
|
277
|
+
<li>Colorblind</li>
|
|
278
|
+
<li>Touch/Mouse friendly</li>
|
|
279
|
+
<li>Works in older browser like IE11</li>
|
|
280
|
+
<li>Destroys itself correctly, removing event listeners</li>
|
|
281
|
+
<li>No objects or variables on global scope</li>
|
|
282
|
+
<li>Triggers correctly on changed config properties</li>
|
|
283
|
+
<li>Implements on off() methods of tao?</li>
|
|
284
|
+
<li>Response type and response correct</li>
|
|
285
|
+
<li>getResponse() should give undefined when user has not done anything</li>
|
|
286
|
+
<li>For TAO to enter response is the entered comparable by the response given</li>
|
|
287
|
+
</ul>
|
|
288
|
+
</body>
|
|
289
|
+
</html>
|