@citolab/tspci 1.5.7 → 2.0.5

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/public/index.html CHANGED
@@ -1,351 +1,289 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <title>Hello RequireJS</title>
5
-
6
- <link
7
- href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css"
8
- rel="stylesheet"
9
- integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor"
10
- crossorigin="anonymous"
11
- />
12
-
13
- <script
14
- src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js"
15
- integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2"
16
- crossorigin="anonymous"
17
- ></script>
18
-
19
- <script
20
- src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"
21
- integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg=="
22
- crossorigin="anonymous"
23
- referrerpolicy="no-referrer"
24
- ></script>
25
-
26
- <style>
27
- html {
28
- font-size: 100%;
29
- }
30
- #pciContainer {
31
- width: 100%;
32
- /* min-width: 800px; */
33
- max-width: 1024px;
34
- height: 600px;
35
- min-height: 600px;
36
- /* max-height: 600px; */
37
- border: 1px solid #eeeeee;
38
- overflow: hidden;
39
- margin: 0 auto;
40
- background-color: white;
41
- border-radius: 10px;
42
- margin-top: 1rem;
43
- }
44
- #devtools {
45
- max-width: 1024px;
46
- margin: 0 auto;
47
- }
48
- </style>
49
- </head>
50
- <body class="bg-light">
51
- <div class="container">
52
- <div
53
- class="alert alert-danger position-fixed mx-auto bottom-0"
54
- style="display: none"
55
- role="alert"
56
- id="noresponse"
57
- >
58
- user has not yet interacted yet, getResponse should return undefined.
59
- </div>
60
-
61
- <div id="pciContainer" class="shadow-sm">
62
- <div id="loading" class="text-muted mx-auto p-4">Loading...</div>
63
- </div>
64
- <div id="devtools"></div>
65
- </div>
66
-
67
- <script type="module">
68
- import { h, Component, render } from "https://unpkg.com/preact@latest?module";
69
- import { useState, useEffect } from "https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module";
70
- import htm from "https://unpkg.com/htm?module";
71
- // Initialize htm with Preact
72
- const html = htm.bind(h);
73
-
74
- function App({ item }) {
75
- const [show, setShow] = useState(false);
76
- const [response, setResponse] = useState(undefined);
77
-
78
- useEffect(() => {
79
- localStorage.getItem(item.typeIdentifier + "_response");
80
- }, []);
81
-
82
- useEffect(() => {
83
- if (response !== undefined) {
84
- localStorage.setItem(item.typeIdentifier + "_response", item.getResponse().base.string);
85
- } else {
86
- localStorage.removeItem(item.typeIdentifier + "_response");
87
- item.resetResponse && item.resetResponse();
88
- }
89
- }, [response]);
90
-
91
- let keyArray = [];
92
- if (item.config && item.config.properties) {
93
- keyArray = Object.keys(item.config.properties).map((keyName, keyIndex) => ({
94
- key: keyName,
95
- value: item.config.properties[keyName],
96
- }));
97
- }
98
-
99
- function resetlocalstorage() {
100
- localStorage.removeItem(item.typeIdentifier + "_state");
101
- localStorage.removeItem(item.typeIdentifier + "_props");
102
- setResponse(undefined);
103
- }
104
-
105
- function reset() {
106
- resetlocalstorage();
107
- location.reload();
108
- }
109
-
110
- function storeResponse() {
111
- if (item.getResponse() !== undefined) {
112
- setResponse(item.getResponse().base.string);
113
- }
114
- }
115
-
116
- function compareResponse() {
117
- const response = localStorage.getItem(item.typeIdentifier + "_response");
118
- if (!response) {
119
- alert("no response stored");
120
- return;
121
- }
122
- if (response === item.getResponse().base.string) {
123
- alert("same");
124
- } else {
125
- alert("different");
126
- }
127
- }
128
-
129
- function resetResponse() {
130
- setResponse(undefined);
131
- }
132
-
133
- function setStoredResponse() {
134
- item.setResponse &&
135
- item.setResponse({
136
- base: {
137
- string: response,
138
- },
139
- });
140
- }
141
-
142
- function reload() {
143
- const state = item.getState();
144
- localStorage.setItem(item.typeIdentifier + "_state", JSON.stringify(state));
145
- location.reload();
146
- }
147
-
148
- function changeConfig(key, value) {
149
- item.config.properties[key] = value;
150
- item.trigger(`change${key}`, value);
151
- }
152
-
153
- function reConfig(key, value) {
154
- localStorage.setItem(item.typeIdentifier + "_props", JSON.stringify(item.config.properties));
155
- location.reload();
156
- }
157
-
158
- function unload() {
159
- item.destroy && item.destroy();
160
- item.oncompleted && item.oncompleted();
161
- var name = require.undef("index.js");
162
- loadItem();
163
- }
164
-
165
- return html`
166
- <div>
167
- <div style="width:300px" class="shadow offcanvas offcanvas-end ${show ? "show visible" : ""}">
168
- <div class="offcanvas-header">
169
- <h5 class="offcanvas-title" id="offcanvasExampleLabel">properties</h5>
170
- <button
171
- type="button"
172
- onClick="${() => setShow(false)}"
173
- disabled="${!item.config}"
174
- class="btn-close text-reset"
175
- ></button>
176
- </div>
177
- <div class="offcanvas-body">
178
- <ul class="card-body">
179
- ${keyArray.map(
180
- ({ key, value }) => html`<div>
181
- <div>${key}</div>
182
- <input
183
- type="text"
184
- class="form-control"
185
- value="${value}"
186
- onkeyup="${(e) => changeConfig(key, e.target.value)}"
187
- />
188
- </div>`
189
- )}
190
- </ul>
191
- <button class="btn btn-primary" onClick="${() => reConfig()}">save and reload</button>
192
- </div>
193
- </div>
194
-
195
- <div class="d-flex justify-content-start mt-3" role="toolbar" aria-label="Toolbar with button groups">
196
- <div>
197
- <small class="text-muted">configuration</small>
198
- <div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
199
- <button class="btn btn-outline-secondary" onClick="${() => setShow(true)}">props</button>
200
- <button
201
- class="btn btn-outline-secondary"
202
- onClick="${() => alert(JSON.stringify(item.config), null, 4)}"
203
- >
204
- config
205
- </button>
206
- </div>
207
- </div>
208
-
209
- <div>
210
- <small class="text-muted">data</small>
211
- <div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
212
- <button
213
- class="btn btn-outline-secondary"
214
- onClick="${() => alert(JSON.stringify(item.getResponse(), null, 4))}"
215
- >
216
- getResponse
217
- </button>
218
- <button class="btn btn-outline-secondary" onClick="${() => alert(item.getState())}">getState</button>
219
- </div>
220
- </div>
221
-
222
- <div>
223
- <small class="text-muted">state</small>
224
- <div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
225
- <button
226
- class="btn btn-outline-secondary"
227
- data-bs-placement="bottom"
228
- data-bs-toggle="tooltip"
229
- data-bs-html="true"
230
- title="<ol class="m-0"><li class="text-start">state in localstorage</li><li>reload page</li><li>load state</li><li>remove localstorage</li></ol>"
231
- onClick="${() => reload()}"
232
- >
233
- reload
234
- </button>
235
- </div>
236
- </div>
237
-
238
- <div>
239
- <small class="text-muted">response</small>
240
- <div class="btn-group me-2 shadow-sm" role="group" aria-label="Basic checkbox toggle button group">
241
- <button class="btn btn-outline-secondary" data-bs-placement="bottom"
242
- data-bs-toggle="tooltip"
243
- data-bs-html="true"
244
- title="Save response in localstorage" onClick="${() => storeResponse()}">store</button>
245
- <button class="btn btn-outline-secondary" data-bs-placement="bottom"
246
- data-bs-toggle="tooltip"
247
- data-bs-html="true"
248
- title="Compare current response with response in localstorage" onClick="${() =>
249
- compareResponse()}">compare</button>
250
- <button class="btn btn-outline-secondary" data-bs-placement="bottom"
251
- data-bs-toggle="tooltip"
252
- data-bs-html="true"
253
- title="set stored response back into item with setResponse (*TAO PCI only)" disabled="${!item.setResponse}" onClick="${() =>
254
- setStoredResponse()}">set</button>
255
- <button class="btn btn-outline-secondary" data-bs-placement="bottom"
256
- data-bs-toggle="tooltip"
257
- data-bs-html="true"
258
- title="reset reponse in item (*TAO PCI only)" disabled="${!item.resetResponse}" onClick="${() =>
259
- resetResponse()}">reset</button>
260
- </div>
261
- <div>${response}</div>
262
- </div>
263
-
264
-
265
-
266
-
267
- <div>
268
- <small class="text-muted">ㅤ</small>
269
- <div class="d-flex">
270
- <button data-bs-toggle="tooltip"
271
- disabled="${!(item.destroy || item.oncompleted)}"
272
- data-bs-html="true"
273
- title="reset everything in localstorage (config/state/response) and reload" class="btn bg-light shadow-sm btn-outline-danger me-2" onClick="${() => unload()}">
274
- unload
275
- </button>
276
- <button data-bs-toggle="tooltip"
277
- data-bs-html="true"
278
- title="reset everything in localstorage (config/state/response) and reload" class="btn bg-light shadow-sm btn-outline-danger" onClick="${() => reset()}">reset</button>
279
- </div>
280
- </div>
281
- </div>
282
- </div>
283
- `;
284
- }
285
-
286
- function register(item) {
287
- let state = undefined;
288
- const localStorageState = localStorage.getItem(item.typeIdentifier + "_state");
289
- if (localStorageState) {
290
- state = JSON.parse(localStorageState);
291
- }
292
- let props = {};
293
- const localStorageProps = localStorage.getItem(item.typeIdentifier + "_props");
294
- if (localStorageProps) {
295
- props = JSON.parse(localStorageProps);
296
- }
297
- const dom = document.getElementById("pciContainer");
298
- const config = {
299
- onready: () => {
300
- document.getElementById("loading").innerHTML = "";
301
- },
302
- properties: props,
303
- };
304
-
305
- item.getInstance(dom, config, state);
306
-
307
- if (item.getResponse() !== undefined) {
308
- document.getElementById("noresponse").style.display = "block";
309
- }
310
-
311
- localStorage.removeItem(item.typeIdentifier + "_state");
312
- }
313
-
314
- define("qtiCustomInteractionContext", (qtiCustomInteractionContext) => {
315
- return { register: (ctxA) => register(ctxA) };
316
- });
317
-
318
- function loadItem() {
319
- requirejs(["index.js"], (itemInstance) => {
320
- render(html`<${App} item="${itemInstance}" />`, document.getElementById("devtools"));
321
- // enable tooltips
322
- var tooltipList = [].slice
323
- .call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
324
- .map(function (tooltipTriggerEl) {
325
- return new bootstrap.Tooltip(tooltipTriggerEl);
326
- });
327
- });
328
- }
329
- window.onload = () => loadItem();
330
- </script>
331
-
332
- <h3 style="margin-top: 12rem">checklist</h3>
333
- <ul style="margin-bottom: 10rem">
334
- <li>Is the css scoped to the item?</li>
335
- <li>Is the css/item somewhat responsive on smaller screens</li>
336
- <li>Can you reset the item to its initial state</li>
337
- <li>Can it restore its state ( reload )</li>
338
- <li>Can you change the config</li>
339
- <li>Colorblind</li>
340
- <li>Touch/Mouse friendly</li>
341
- <li>Works in older browser like IE11</li>
342
- <li>Destroys itself correctly, removing event listeners</li>
343
- <li>No objects or variables on global scope</li>
344
- <li>Triggers correctly on changed config properties</li>
345
- <li>Implements on off() methods of tao?</li>
346
- <li>Response type and response correct</li>
347
- <li>getResponse() should give undefined when user has not done anything</li>
348
- <li>For TAO to enter response is the entered comparable by the response given</li>
349
- </ul>
350
- </body>
351
- </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>