@longsightgroup/qti3-player 0.4.0 → 0.5.4
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/README.md +146 -13
- package/dist/content/content-dom.d.ts +11 -0
- package/dist/content/content-dom.d.ts.map +1 -0
- package/dist/content/content-dom.js +262 -0
- package/dist/content/content-dom.js.map +1 -0
- package/dist/content/content-renderer.d.ts +17 -0
- package/dist/content/content-renderer.d.ts.map +1 -0
- package/dist/content/content-renderer.js +82 -0
- package/dist/content/content-renderer.js.map +1 -0
- package/dist/controls/remove-button.d.ts +3 -0
- package/dist/controls/remove-button.d.ts.map +1 -0
- package/dist/controls/remove-button.js +12 -0
- package/dist/controls/remove-button.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interactions/choice-interaction.d.ts +4 -0
- package/dist/interactions/choice-interaction.d.ts.map +1 -0
- package/dist/interactions/choice-interaction.js +81 -0
- package/dist/interactions/choice-interaction.js.map +1 -0
- package/dist/interactions/drawing-interaction.d.ts +6 -0
- package/dist/interactions/drawing-interaction.d.ts.map +1 -0
- package/dist/interactions/drawing-interaction.js +401 -0
- package/dist/interactions/drawing-interaction.js.map +1 -0
- package/dist/interactions/end-attempt-interaction.d.ts +4 -0
- package/dist/interactions/end-attempt-interaction.d.ts.map +1 -0
- package/dist/interactions/end-attempt-interaction.js +13 -0
- package/dist/interactions/end-attempt-interaction.js.map +1 -0
- package/dist/interactions/gap-match-interaction.d.ts +4 -0
- package/dist/interactions/gap-match-interaction.d.ts.map +1 -0
- package/dist/interactions/gap-match-interaction.js +277 -0
- package/dist/interactions/gap-match-interaction.js.map +1 -0
- package/dist/interactions/graphic-associate-interaction.d.ts +4 -0
- package/dist/interactions/graphic-associate-interaction.d.ts.map +1 -0
- package/dist/interactions/graphic-associate-interaction.js +297 -0
- package/dist/interactions/graphic-associate-interaction.js.map +1 -0
- package/dist/interactions/graphic-context.d.ts +3 -0
- package/dist/interactions/graphic-context.d.ts.map +1 -0
- package/dist/interactions/graphic-context.js +35 -0
- package/dist/interactions/graphic-context.js.map +1 -0
- package/dist/interactions/hotspot-interaction.d.ts +4 -0
- package/dist/interactions/hotspot-interaction.d.ts.map +1 -0
- package/dist/interactions/hotspot-interaction.js +68 -0
- package/dist/interactions/hotspot-interaction.js.map +1 -0
- package/dist/interactions/hottext-interaction.d.ts +3 -0
- package/dist/interactions/hottext-interaction.d.ts.map +1 -0
- package/dist/interactions/hottext-interaction.js +66 -0
- package/dist/interactions/hottext-interaction.js.map +1 -0
- package/dist/interactions/inline-choice-interaction.d.ts +4 -0
- package/dist/interactions/inline-choice-interaction.d.ts.map +1 -0
- package/dist/interactions/inline-choice-interaction.js +31 -0
- package/dist/interactions/inline-choice-interaction.js.map +1 -0
- package/dist/interactions/inline-controls.d.ts +6 -0
- package/dist/interactions/inline-controls.d.ts.map +1 -0
- package/dist/interactions/inline-controls.js +15 -0
- package/dist/interactions/inline-controls.js.map +1 -0
- package/dist/interactions/interaction-diagnostics.d.ts +7 -0
- package/dist/interactions/interaction-diagnostics.d.ts.map +1 -0
- package/dist/interactions/interaction-diagnostics.js +137 -0
- package/dist/interactions/interaction-diagnostics.js.map +1 -0
- package/dist/interactions/interaction-dispatch.d.ts +2 -0
- package/dist/interactions/interaction-dispatch.d.ts.map +1 -0
- package/dist/interactions/interaction-dispatch.js +2 -0
- package/dist/interactions/interaction-dispatch.js.map +1 -0
- package/dist/interactions/interaction-label.d.ts +4 -0
- package/dist/interactions/interaction-label.d.ts.map +1 -0
- package/dist/interactions/interaction-label.js +8 -0
- package/dist/interactions/interaction-label.js.map +1 -0
- package/dist/interactions/interaction-registry.d.ts +24 -0
- package/dist/interactions/interaction-registry.d.ts.map +1 -0
- package/dist/interactions/interaction-registry.js +138 -0
- package/dist/interactions/interaction-registry.js.map +1 -0
- package/dist/interactions/match-interaction.d.ts +4 -0
- package/dist/interactions/match-interaction.d.ts.map +1 -0
- package/dist/interactions/match-interaction.js +188 -0
- package/dist/interactions/match-interaction.js.map +1 -0
- package/dist/interactions/object-asset.d.ts +8 -0
- package/dist/interactions/object-asset.d.ts.map +1 -0
- package/dist/interactions/object-asset.js +182 -0
- package/dist/interactions/object-asset.js.map +1 -0
- package/dist/interactions/pair-interaction.d.ts +4 -0
- package/dist/interactions/pair-interaction.d.ts.map +1 -0
- package/dist/interactions/pair-interaction.js +125 -0
- package/dist/interactions/pair-interaction.js.map +1 -0
- package/dist/interactions/point-value.d.ts +16 -0
- package/dist/interactions/point-value.d.ts.map +1 -0
- package/dist/interactions/point-value.js +37 -0
- package/dist/interactions/point-value.js.map +1 -0
- package/dist/interactions/portable-custom-interaction.d.ts +16 -0
- package/dist/interactions/portable-custom-interaction.d.ts.map +1 -0
- package/dist/interactions/portable-custom-interaction.js +97 -0
- package/dist/interactions/portable-custom-interaction.js.map +1 -0
- package/dist/interactions/position-object-interaction.d.ts +4 -0
- package/dist/interactions/position-object-interaction.d.ts.map +1 -0
- package/dist/interactions/position-object-interaction.js +177 -0
- package/dist/interactions/position-object-interaction.js.map +1 -0
- package/dist/interactions/routing.d.ts +5 -0
- package/dist/interactions/routing.d.ts.map +1 -0
- package/dist/interactions/routing.js +24 -0
- package/dist/interactions/routing.js.map +1 -0
- package/dist/interactions/select-point-interaction.d.ts +4 -0
- package/dist/interactions/select-point-interaction.d.ts.map +1 -0
- package/dist/interactions/select-point-interaction.js +166 -0
- package/dist/interactions/select-point-interaction.js.map +1 -0
- package/dist/interactions/shared.d.ts +12 -0
- package/dist/interactions/shared.d.ts.map +1 -0
- package/dist/interactions/shared.js +65 -0
- package/dist/interactions/shared.js.map +1 -0
- package/dist/interactions/text-interaction.d.ts +6 -0
- package/dist/interactions/text-interaction.d.ts.map +1 -0
- package/dist/interactions/text-interaction.js +110 -0
- package/dist/interactions/text-interaction.js.map +1 -0
- package/dist/interactions/unsupported-interaction.d.ts +4 -0
- package/dist/interactions/unsupported-interaction.d.ts.map +1 -0
- package/dist/interactions/unsupported-interaction.js +23 -0
- package/dist/interactions/unsupported-interaction.js.map +1 -0
- package/dist/interactions/upload-interaction.d.ts +4 -0
- package/dist/interactions/upload-interaction.d.ts.map +1 -0
- package/dist/interactions/upload-interaction.js +10 -0
- package/dist/interactions/upload-interaction.js.map +1 -0
- package/dist/player/attempt-availability.d.ts +6 -0
- package/dist/player/attempt-availability.d.ts.map +1 -0
- package/dist/player/attempt-availability.js +27 -0
- package/dist/player/attempt-availability.js.map +1 -0
- package/dist/player/content-state.d.ts +19 -0
- package/dist/player/content-state.d.ts.map +1 -0
- package/dist/player/content-state.js +39 -0
- package/dist/player/content-state.js.map +1 -0
- package/dist/player/dynamic-body.d.ts +7 -0
- package/dist/player/dynamic-body.d.ts.map +1 -0
- package/dist/player/dynamic-body.js +28 -0
- package/dist/player/dynamic-body.js.map +1 -0
- package/dist/player/feedback-panel.d.ts +3 -0
- package/dist/player/feedback-panel.d.ts.map +1 -0
- package/dist/player/feedback-panel.js +14 -0
- package/dist/player/feedback-panel.js.map +1 -0
- package/dist/player/fetch-xml.d.ts +2 -0
- package/dist/player/fetch-xml.d.ts.map +1 -0
- package/dist/player/fetch-xml.js +10 -0
- package/dist/player/fetch-xml.js.map +1 -0
- package/dist/player/interaction-render.d.ts +14 -0
- package/dist/player/interaction-render.d.ts.map +1 -0
- package/dist/player/interaction-render.js +51 -0
- package/dist/player/interaction-render.js.map +1 -0
- package/dist/player/render-shell.d.ts +8 -0
- package/dist/player/render-shell.d.ts.map +1 -0
- package/dist/player/render-shell.js +37 -0
- package/dist/player/render-shell.js.map +1 -0
- package/dist/player/resolve-assets.d.ts +3 -0
- package/dist/player/resolve-assets.d.ts.map +1 -0
- package/dist/player/resolve-assets.js +12 -0
- package/dist/player/resolve-assets.js.map +1 -0
- package/dist/player/validation-messages.d.ts +17 -0
- package/dist/player/validation-messages.d.ts.map +1 -0
- package/dist/player/validation-messages.js +33 -0
- package/dist/player/validation-messages.js.map +1 -0
- package/dist/player-adapter.d.ts +62 -0
- package/dist/player-adapter.d.ts.map +1 -0
- package/dist/player-adapter.js +119 -0
- package/dist/player-adapter.js.map +1 -0
- package/dist/player-dev.d.ts +4 -0
- package/dist/player-dev.d.ts.map +1 -0
- package/dist/player-dev.js +14 -0
- package/dist/player-dev.js.map +1 -0
- package/dist/player-element.d.ts +14 -1
- package/dist/player-element.d.ts.map +1 -1
- package/dist/player-element.js +57 -5
- package/dist/player-element.js.map +1 -1
- package/dist/player-locale.d.ts +8 -3
- package/dist/player-locale.d.ts.map +1 -1
- package/dist/player-locale.js +16 -175
- package/dist/player-locale.js.map +1 -1
- package/dist/player-message-catalog-default.d.ts +4 -0
- package/dist/player-message-catalog-default.d.ts.map +1 -0
- package/dist/player-message-catalog-default.js +118 -0
- package/dist/player-message-catalog-default.js.map +1 -0
- package/dist/player-message-catalog-validate.d.ts +31 -0
- package/dist/player-message-catalog-validate.d.ts.map +1 -0
- package/dist/player-message-catalog-validate.js +327 -0
- package/dist/player-message-catalog-validate.js.map +1 -0
- package/dist/player-message-catalog.d.ts +18 -0
- package/dist/player-message-catalog.d.ts.map +1 -0
- package/dist/player-message-catalog.js +40 -0
- package/dist/player-message-catalog.js.map +1 -0
- package/dist/player-message-keys.d.ts +6 -0
- package/dist/player-message-keys.d.ts.map +1 -0
- package/dist/player-message-keys.js +7 -0
- package/dist/player-message-keys.js.map +1 -0
- package/dist/player-message-manifest.d.ts +272 -0
- package/dist/player-message-manifest.d.ts.map +1 -0
- package/dist/player-message-manifest.js +83 -0
- package/dist/player-message-manifest.js.map +1 -0
- package/dist/player-message-overrides.d.ts +3 -0
- package/dist/player-message-overrides.d.ts.map +1 -0
- package/dist/player-message-overrides.js +28 -0
- package/dist/player-message-overrides.js.map +1 -0
- package/dist/player-message-resolver.d.ts +31 -0
- package/dist/player-message-resolver.d.ts.map +1 -0
- package/dist/player-message-resolver.js +110 -0
- package/dist/player-message-resolver.js.map +1 -0
- package/dist/player-messages.d.ts +0 -38
- package/dist/player-messages.d.ts.map +1 -1
- package/dist/player-types.d.ts +12 -2
- package/dist/player-types.d.ts.map +1 -1
- package/dist/reorder/a11y.d.ts +7 -0
- package/dist/reorder/a11y.d.ts.map +1 -0
- package/dist/reorder/a11y.js +34 -0
- package/dist/reorder/a11y.js.map +1 -0
- package/dist/reorder/graphic-order-interaction.d.ts +4 -0
- package/dist/reorder/graphic-order-interaction.d.ts.map +1 -0
- package/dist/reorder/graphic-order-interaction.js +205 -0
- package/dist/reorder/graphic-order-interaction.js.map +1 -0
- package/dist/reorder/list-controls.d.ts +22 -0
- package/dist/reorder/list-controls.d.ts.map +1 -0
- package/dist/reorder/list-controls.js +75 -0
- package/dist/reorder/list-controls.js.map +1 -0
- package/dist/reorder/order-interaction.d.ts +4 -0
- package/dist/reorder/order-interaction.d.ts.map +1 -0
- package/dist/reorder/order-interaction.js +54 -0
- package/dist/reorder/order-interaction.js.map +1 -0
- package/dist/styles/base-styles.d.ts +2 -0
- package/dist/styles/base-styles.d.ts.map +1 -0
- package/dist/styles/base-styles.js +133 -0
- package/dist/styles/base-styles.js.map +1 -0
- package/dist/styles/choice-hottext-styles.d.ts +2 -0
- package/dist/styles/choice-hottext-styles.d.ts.map +1 -0
- package/dist/styles/choice-hottext-styles.js +76 -0
- package/dist/styles/choice-hottext-styles.js.map +1 -0
- package/dist/styles/control-styles.d.ts +2 -0
- package/dist/styles/control-styles.d.ts.map +1 -0
- package/dist/styles/control-styles.js +114 -0
- package/dist/styles/control-styles.js.map +1 -0
- package/dist/styles/drawing-styles.d.ts +2 -0
- package/dist/styles/drawing-styles.d.ts.map +1 -0
- package/dist/styles/drawing-styles.js +30 -0
- package/dist/styles/drawing-styles.js.map +1 -0
- package/dist/styles/gap-match-styles.d.ts +2 -0
- package/dist/styles/gap-match-styles.d.ts.map +1 -0
- package/dist/styles/gap-match-styles.js +33 -0
- package/dist/styles/gap-match-styles.js.map +1 -0
- package/dist/styles/graphic-styles.d.ts +2 -0
- package/dist/styles/graphic-styles.d.ts.map +1 -0
- package/dist/styles/graphic-styles.js +289 -0
- package/dist/styles/graphic-styles.js.map +1 -0
- package/dist/styles/match-pair-styles.d.ts +2 -0
- package/dist/styles/match-pair-styles.d.ts.map +1 -0
- package/dist/styles/match-pair-styles.js +62 -0
- package/dist/styles/match-pair-styles.js.map +1 -0
- package/dist/styles/text-slider-styles.d.ts +2 -0
- package/dist/styles/text-slider-styles.d.ts.map +1 -0
- package/dist/styles/text-slider-styles.js +35 -0
- package/dist/styles/text-slider-styles.js.map +1 -0
- package/package.json +8 -8
- package/src/controls/remove-button.ts +8 -5
- package/src/index.ts +61 -5
- package/src/interactions/choice-interaction.ts +6 -2
- package/src/interactions/drawing-interaction.ts +14 -9
- package/src/interactions/end-attempt-interaction.ts +3 -3
- package/src/interactions/gap-match-interaction.ts +32 -13
- package/src/interactions/graphic-associate-interaction.ts +15 -10
- package/src/interactions/hotspot-interaction.ts +10 -6
- package/src/interactions/inline-choice-interaction.ts +4 -4
- package/src/interactions/interaction-registry.ts +12 -12
- package/src/interactions/match-interaction.ts +9 -6
- package/src/interactions/pair-interaction.ts +22 -14
- package/src/interactions/position-object-interaction.ts +22 -13
- package/src/interactions/select-point-interaction.ts +25 -13
- package/src/interactions/shared.ts +21 -4
- package/src/interactions/text-interaction.ts +14 -4
- package/src/interactions/upload-interaction.ts +6 -3
- package/src/player/interaction-render.ts +4 -4
- package/src/player-adapter.ts +253 -0
- package/src/player-dev.ts +14 -0
- package/src/player-element.ts +78 -8
- package/src/player-locale.ts +28 -199
- package/src/player-message-catalog-default.ts +119 -0
- package/src/player-message-catalog-validate.ts +425 -0
- package/src/player-message-catalog.ts +72 -0
- package/src/player-message-keys.ts +12 -0
- package/src/player-message-manifest.ts +103 -0
- package/src/player-message-overrides.ts +38 -0
- package/src/player-message-resolver.ts +205 -0
- package/src/player-messages.ts +0 -30
- package/src/player-types.ts +15 -4
- package/src/reorder/a11y.ts +22 -7
- package/src/reorder/graphic-order-interaction.ts +23 -16
- package/src/reorder/list-controls.ts +8 -6
- package/src/reorder/order-interaction.ts +7 -5
- package/src/styles/base-styles.ts +20 -5
- package/src/styles/graphic-styles.ts +0 -6
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
objectHeight,
|
|
7
7
|
objectWidth,
|
|
8
8
|
placeHotspotButton,
|
|
9
|
-
readableType,
|
|
10
9
|
responseGroup,
|
|
11
10
|
valueToStrings,
|
|
12
11
|
} from "../interaction-support.js";
|
|
12
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
13
13
|
import { parseUnlimitedMaximum } from "../response-limits.js";
|
|
14
14
|
import { appendGraphicContext } from "./graphic-context.js";
|
|
15
15
|
import { appendInlineControl, normalizeInlineSegmentText } from "./inline-controls.js";
|
|
@@ -33,13 +33,14 @@ export function renderGapMatchResponse(
|
|
|
33
33
|
interaction: QtiInteraction,
|
|
34
34
|
update: (value: QtiValue) => void,
|
|
35
35
|
currentValue: QtiValue,
|
|
36
|
+
messages: PlayerMessageResolver,
|
|
36
37
|
): HTMLElement {
|
|
37
38
|
if (
|
|
38
39
|
interaction.type === "graphicGapMatch" &&
|
|
39
40
|
interaction.object &&
|
|
40
41
|
interaction.choices.some((choice) => choice.role === "hotspot")
|
|
41
42
|
) {
|
|
42
|
-
return renderGraphicGapMatchResponse(interaction, update, currentValue);
|
|
43
|
+
return renderGraphicGapMatchResponse(interaction, update, currentValue, messages);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
const group = responseGroup();
|
|
@@ -54,11 +55,16 @@ export function renderGapMatchResponse(
|
|
|
54
55
|
let selectedSource: QtiChoice | undefined;
|
|
55
56
|
let draggedSource: string | undefined;
|
|
56
57
|
|
|
57
|
-
const sourceRegion = tokenRegion(
|
|
58
|
+
const sourceRegion = tokenRegion(
|
|
59
|
+
messages.message("interactionChoicesBank", { type: interaction.type }),
|
|
60
|
+
);
|
|
58
61
|
const gapRegion = document.createElement("div");
|
|
59
62
|
gapRegion.className = "qti3-gap-region qti3-gap-passage";
|
|
60
63
|
gapRegion.role = "group";
|
|
61
|
-
gapRegion.setAttribute(
|
|
64
|
+
gapRegion.setAttribute(
|
|
65
|
+
"aria-label",
|
|
66
|
+
messages.message("interactionGapTargets", { type: interaction.type }),
|
|
67
|
+
);
|
|
62
68
|
for (const pair of valueToStrings(currentValue)) {
|
|
63
69
|
const [sourceIdentifier, gapIdentifier] = pair.split(/\s+/);
|
|
64
70
|
const source = sources.find((choice) => choice.identifier === sourceIdentifier);
|
|
@@ -91,7 +97,7 @@ export function renderGapMatchResponse(
|
|
|
91
97
|
};
|
|
92
98
|
const gapControl = (gap: QtiChoice, index: number) => {
|
|
93
99
|
const assigned = assignments.get(gap.identifier);
|
|
94
|
-
const gapLabel =
|
|
100
|
+
const gapLabel = messages.message("gapLabel", { index: index + 1 });
|
|
95
101
|
const target = document.createElement("span");
|
|
96
102
|
target.className = "qti3-gap-target";
|
|
97
103
|
target.dataset.gapIdentifier = gap.identifier;
|
|
@@ -112,7 +118,9 @@ export function renderGapMatchResponse(
|
|
|
112
118
|
button.textContent = assigned ? assigned.text : "";
|
|
113
119
|
button.setAttribute(
|
|
114
120
|
"aria-label",
|
|
115
|
-
assigned
|
|
121
|
+
assigned
|
|
122
|
+
? messages.message("gapAssignedState", { label: gapLabel, assigned: assigned.text })
|
|
123
|
+
: messages.message("gapEmptyState", { label: gapLabel }),
|
|
116
124
|
);
|
|
117
125
|
button.addEventListener("click", () => assign(gap, selectedSource?.identifier));
|
|
118
126
|
button.addEventListener("keydown", (event) => {
|
|
@@ -173,6 +181,7 @@ function renderGraphicGapMatchResponse(
|
|
|
173
181
|
interaction: QtiInteraction,
|
|
174
182
|
update: (value: QtiValue) => void,
|
|
175
183
|
currentValue: QtiValue,
|
|
184
|
+
messages: PlayerMessageResolver,
|
|
176
185
|
): HTMLElement {
|
|
177
186
|
const group = responseGroup();
|
|
178
187
|
const width = objectWidth(interaction);
|
|
@@ -202,7 +211,10 @@ function renderGraphicGapMatchResponse(
|
|
|
202
211
|
"qti3-graphic-gap-match-surface",
|
|
203
212
|
);
|
|
204
213
|
surface.role = "group";
|
|
205
|
-
surface.setAttribute(
|
|
214
|
+
surface.setAttribute(
|
|
215
|
+
"aria-label",
|
|
216
|
+
messages.message("interactionTargetImage", { type: interaction.type }),
|
|
217
|
+
);
|
|
206
218
|
surface.style.overflow = "visible";
|
|
207
219
|
surface.style.setProperty(
|
|
208
220
|
"--qti3-graphic-gap-label-block-size",
|
|
@@ -213,11 +225,14 @@ function renderGraphicGapMatchResponse(
|
|
|
213
225
|
appendGraphicObjectImage(
|
|
214
226
|
surface,
|
|
215
227
|
interaction.object,
|
|
216
|
-
interaction.object.text ||
|
|
228
|
+
interaction.object.text ||
|
|
229
|
+
messages.message("interactionImageAlt", { type: interaction.type }),
|
|
217
230
|
);
|
|
218
231
|
}
|
|
219
232
|
|
|
220
|
-
const sourceRegion = tokenRegion(
|
|
233
|
+
const sourceRegion = tokenRegion(
|
|
234
|
+
messages.message("interactionChoicesBank", { type: interaction.type }),
|
|
235
|
+
);
|
|
221
236
|
sourceRegion.classList.add("qti3-graphic-gap-source-region");
|
|
222
237
|
const choicesWidth = positivePixelValue(interaction.attributes["data-choices-container-width"]);
|
|
223
238
|
if (choicesWidth !== undefined) sourceRegion.style.maxInlineSize = `${choicesWidth}px`;
|
|
@@ -260,7 +275,9 @@ function renderGraphicGapMatchResponse(
|
|
|
260
275
|
commit();
|
|
261
276
|
};
|
|
262
277
|
const targetLabel = (gap: QtiChoice, index: number) =>
|
|
263
|
-
gap.attributes["aria-label"] ||
|
|
278
|
+
gap.attributes["aria-label"] ||
|
|
279
|
+
gap.attributes["hotspot-label"] ||
|
|
280
|
+
messages.message("graphicGapTargetLabel", { index: index + 1 });
|
|
264
281
|
const renderTargetButton = (gap: QtiChoice, index: number): HTMLButtonElement => {
|
|
265
282
|
const assigned = assignments.get(gap.identifier);
|
|
266
283
|
const label = targetLabel(gap, index);
|
|
@@ -271,7 +288,9 @@ function renderGraphicGapMatchResponse(
|
|
|
271
288
|
button.dataset.selected = assigned ? "true" : "false";
|
|
272
289
|
button.setAttribute(
|
|
273
290
|
"aria-label",
|
|
274
|
-
assigned
|
|
291
|
+
assigned
|
|
292
|
+
? messages.message("gapAssignedState", { label, assigned: assigned.text })
|
|
293
|
+
: messages.message("gapEmptyState", { label }),
|
|
275
294
|
);
|
|
276
295
|
button.addEventListener("dragover", (event) => {
|
|
277
296
|
event.preventDefault();
|
|
@@ -308,8 +327,8 @@ function renderGraphicGapMatchResponse(
|
|
|
308
327
|
}
|
|
309
328
|
summary.textContent =
|
|
310
329
|
assignments.size > 0
|
|
311
|
-
?
|
|
312
|
-
:
|
|
330
|
+
? messages.message("gapLabelsPlacedCount", { count: assignments.size })
|
|
331
|
+
: messages.message("gapNoLabelsPlaced");
|
|
313
332
|
};
|
|
314
333
|
|
|
315
334
|
for (const source of sources) {
|
|
@@ -11,18 +11,17 @@ import {
|
|
|
11
11
|
objectHeight,
|
|
12
12
|
objectWidth,
|
|
13
13
|
placeHotspotButton,
|
|
14
|
-
readableType,
|
|
15
14
|
responseGroup,
|
|
16
15
|
valueToStrings,
|
|
17
16
|
} from "../interaction-support.js";
|
|
18
|
-
import type {
|
|
17
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
19
18
|
import { exceedsHotspotMatchMax, maximumAllowedResponses } from "../response-limits.js";
|
|
20
19
|
|
|
21
20
|
export function renderGraphicAssociateResponse(
|
|
22
21
|
interaction: QtiInteraction,
|
|
23
22
|
update: (value: QtiValue) => void,
|
|
24
23
|
currentValue: QtiValue,
|
|
25
|
-
messages:
|
|
24
|
+
messages: PlayerMessageResolver,
|
|
26
25
|
): HTMLElement {
|
|
27
26
|
const group = responseGroup();
|
|
28
27
|
|
|
@@ -47,14 +46,17 @@ export function renderGraphicAssociateResponse(
|
|
|
47
46
|
const surface = document.createElement("div");
|
|
48
47
|
applyGraphicSurfaceLayout(surface, width, height, "qti3-graphic-associate-surface");
|
|
49
48
|
surface.role = "group";
|
|
50
|
-
surface.setAttribute(
|
|
49
|
+
surface.setAttribute(
|
|
50
|
+
"aria-label",
|
|
51
|
+
messages.message("interactionHotspots", { type: interaction.type }),
|
|
52
|
+
);
|
|
51
53
|
|
|
52
54
|
const object = interaction.object;
|
|
53
55
|
if (object) {
|
|
54
56
|
appendGraphicObjectImage(
|
|
55
57
|
surface,
|
|
56
58
|
object,
|
|
57
|
-
object.text ||
|
|
59
|
+
object.text || messages.message("interactionImageAlt", { type: interaction.type }),
|
|
58
60
|
);
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -69,7 +71,10 @@ export function renderGraphicAssociateResponse(
|
|
|
69
71
|
summary.setAttribute("aria-live", "polite");
|
|
70
72
|
const pairList = document.createElement("ul");
|
|
71
73
|
pairList.className = "qti3-pair-list";
|
|
72
|
-
pairList.setAttribute(
|
|
74
|
+
pairList.setAttribute(
|
|
75
|
+
"aria-label",
|
|
76
|
+
messages.message("interactionSelectedPairsList", { type: interaction.type }),
|
|
77
|
+
);
|
|
73
78
|
|
|
74
79
|
const commit = () => {
|
|
75
80
|
if (interaction.responseCardinality === "single") update(selectedPairs[0] ?? null);
|
|
@@ -214,18 +219,18 @@ export function renderGraphicAssociateResponse(
|
|
|
214
219
|
button.dataset.selected = isActive || isPaired ? "true" : "false";
|
|
215
220
|
}
|
|
216
221
|
summary.textContent = selectedHotspot
|
|
217
|
-
? messages.hotspotSelectedChooseAnother
|
|
222
|
+
? messages.message("hotspotSelectedChooseAnother", {
|
|
218
223
|
label: hotspotDisplayLabel(selectedHotspot, choices),
|
|
219
224
|
})
|
|
220
225
|
: selectedPairs.length > 0
|
|
221
|
-
? messages.associationsMade
|
|
222
|
-
: messages.noAssociationsMade
|
|
226
|
+
? messages.message("associationsMade", { count: selectedPairs.length })
|
|
227
|
+
: messages.message("noAssociationsMade");
|
|
223
228
|
pairList.replaceChildren(
|
|
224
229
|
...selectedPairs.map((pair) => {
|
|
225
230
|
const [source = "", target = ""] = pair.split(" ");
|
|
226
231
|
const sourceChoice = choices.find((choice) => choice.identifier === source);
|
|
227
232
|
const targetChoice = choices.find((choice) => choice.identifier === target);
|
|
228
|
-
const pairLabel = messages.associationPairLabel
|
|
233
|
+
const pairLabel = messages.message("associationPairLabel", {
|
|
229
234
|
source: sourceChoice ? hotspotDisplayLabel(sourceChoice, choices) : source,
|
|
230
235
|
target: targetChoice ? hotspotDisplayLabel(targetChoice, choices) : target,
|
|
231
236
|
});
|
|
@@ -7,17 +7,16 @@ import {
|
|
|
7
7
|
objectHeight,
|
|
8
8
|
objectWidth,
|
|
9
9
|
placeHotspotButton,
|
|
10
|
-
readableType,
|
|
11
10
|
responseGroup,
|
|
12
11
|
valueToStrings,
|
|
13
12
|
} from "../interaction-support.js";
|
|
14
|
-
import type {
|
|
13
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
15
14
|
|
|
16
15
|
export function renderHotspotResponse(
|
|
17
16
|
interaction: QtiInteraction,
|
|
18
17
|
update: (value: QtiValue) => void,
|
|
19
18
|
currentValue: QtiValue,
|
|
20
|
-
messages:
|
|
19
|
+
messages: PlayerMessageResolver,
|
|
21
20
|
): HTMLElement {
|
|
22
21
|
const group = responseGroup();
|
|
23
22
|
|
|
@@ -37,7 +36,7 @@ export function renderHotspotResponse(
|
|
|
37
36
|
appendGraphicObjectImage(
|
|
38
37
|
surface,
|
|
39
38
|
object,
|
|
40
|
-
object.text ||
|
|
39
|
+
object.text || messages.message("interactionImageAlt", { type: interaction.type }),
|
|
41
40
|
);
|
|
42
41
|
}
|
|
43
42
|
|
|
@@ -46,7 +45,7 @@ export function renderHotspotResponse(
|
|
|
46
45
|
const selectedSummary = document.createElement("p");
|
|
47
46
|
selectedSummary.className = "qti3-selection-summary";
|
|
48
47
|
selectedSummary.setAttribute("aria-live", "polite");
|
|
49
|
-
selectedSummary.textContent = messages.noRegionSelected
|
|
48
|
+
selectedSummary.textContent = messages.message("noRegionSelected");
|
|
50
49
|
const syncSelected = () => {
|
|
51
50
|
for (const button of surface.querySelectorAll<HTMLButtonElement>("button")) {
|
|
52
51
|
const isSelected = selected.has(button.dataset.choiceIdentifier ?? "");
|
|
@@ -54,7 +53,12 @@ export function renderHotspotResponse(
|
|
|
54
53
|
button.dataset.selected = isSelected ? "true" : "false";
|
|
55
54
|
}
|
|
56
55
|
selectedSummary.textContent =
|
|
57
|
-
selected.size > 0
|
|
56
|
+
selected.size > 0
|
|
57
|
+
? messages.message("hotspotSelectionSummary", {
|
|
58
|
+
selection: [...selected].join(", "),
|
|
59
|
+
count: selected.size,
|
|
60
|
+
})
|
|
61
|
+
: messages.message("noRegionSelected");
|
|
58
62
|
};
|
|
59
63
|
for (const choice of choices) {
|
|
60
64
|
const button = document.createElement("button");
|
|
@@ -4,17 +4,17 @@ import {
|
|
|
4
4
|
missingChoicesMessage,
|
|
5
5
|
valueToStrings,
|
|
6
6
|
} from "../interaction-support.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
8
8
|
import { interactionLabel } from "./interaction-label.js";
|
|
9
9
|
|
|
10
10
|
function appendOptions(
|
|
11
11
|
select: HTMLSelectElement,
|
|
12
12
|
choices: QtiChoice[],
|
|
13
|
-
messages:
|
|
13
|
+
messages: PlayerMessageResolver,
|
|
14
14
|
): void {
|
|
15
15
|
const empty = document.createElement("option");
|
|
16
16
|
empty.value = "";
|
|
17
|
-
empty.textContent = messages.inlineChoicePrompt
|
|
17
|
+
empty.textContent = messages.message("inlineChoicePrompt");
|
|
18
18
|
select.append(empty);
|
|
19
19
|
for (const choice of choices) {
|
|
20
20
|
const option = document.createElement("option");
|
|
@@ -28,7 +28,7 @@ export function renderSelect(
|
|
|
28
28
|
interaction: QtiInteraction,
|
|
29
29
|
update: (value: QtiValue) => void,
|
|
30
30
|
currentValue: QtiValue,
|
|
31
|
-
messages:
|
|
31
|
+
messages: PlayerMessageResolver,
|
|
32
32
|
): HTMLElement {
|
|
33
33
|
const choices = interactionChoices(interaction);
|
|
34
34
|
if (choices.length === 0) return missingChoicesMessage(interaction);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { QtiInteraction, QtiValue } from "@longsightgroup/qti3-core";
|
|
2
|
-
import type {
|
|
2
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
3
3
|
import { renderGraphicOrderResponse } from "../reorder/graphic-order-interaction.js";
|
|
4
4
|
import { renderOrderedResponse } from "../reorder/order-interaction.js";
|
|
5
5
|
import { renderChoice } from "./choice-interaction.js";
|
|
@@ -24,7 +24,7 @@ export interface InteractionResponseContext {
|
|
|
24
24
|
interaction: QtiInteraction;
|
|
25
25
|
update: (value: QtiValue) => void;
|
|
26
26
|
currentValue: QtiValue;
|
|
27
|
-
messages:
|
|
27
|
+
messages: PlayerMessageResolver;
|
|
28
28
|
isCompleted: () => boolean;
|
|
29
29
|
endAttempt: () => void;
|
|
30
30
|
renderPortableCustom: (
|
|
@@ -81,8 +81,8 @@ export const interactionRegistry: InteractionRegistryEntry[] = [
|
|
|
81
81
|
id: "gapMatch",
|
|
82
82
|
matches: (interaction) =>
|
|
83
83
|
interaction.type === "gapMatch" || interaction.type === "graphicGapMatch",
|
|
84
|
-
render: ({ interaction, update, currentValue }) =>
|
|
85
|
-
renderGapMatchResponse(interaction, update, currentValue),
|
|
84
|
+
render: ({ interaction, update, currentValue, messages }) =>
|
|
85
|
+
renderGapMatchResponse(interaction, update, currentValue, messages),
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
id: "graphicAssociate",
|
|
@@ -117,8 +117,8 @@ export const interactionRegistry: InteractionRegistryEntry[] = [
|
|
|
117
117
|
{
|
|
118
118
|
id: "choice",
|
|
119
119
|
matches: usesChoiceSet,
|
|
120
|
-
render: ({ interaction, update, currentValue }) =>
|
|
121
|
-
renderChoice(interaction, update, currentValue),
|
|
120
|
+
render: ({ interaction, update, currentValue, messages }) =>
|
|
121
|
+
renderChoice(interaction, update, currentValue, messages),
|
|
122
122
|
},
|
|
123
123
|
{
|
|
124
124
|
id: "inlineChoice",
|
|
@@ -129,8 +129,8 @@ export const interactionRegistry: InteractionRegistryEntry[] = [
|
|
|
129
129
|
{
|
|
130
130
|
id: "extendedText",
|
|
131
131
|
matches: (interaction) => interaction.type === "extendedText",
|
|
132
|
-
render: ({ interaction, update, currentValue }) =>
|
|
133
|
-
renderTextResponse(interaction, update, "extended", currentValue),
|
|
132
|
+
render: ({ interaction, update, currentValue, messages }) =>
|
|
133
|
+
renderTextResponse(interaction, update, "extended", currentValue, messages),
|
|
134
134
|
},
|
|
135
135
|
{
|
|
136
136
|
id: "selectPoint",
|
|
@@ -159,14 +159,14 @@ export const interactionRegistry: InteractionRegistryEntry[] = [
|
|
|
159
159
|
{
|
|
160
160
|
id: "textEntry",
|
|
161
161
|
matches: (interaction) => interaction.type === "textEntry",
|
|
162
|
-
render: ({ interaction, update, currentValue }) =>
|
|
163
|
-
renderTextResponse(interaction, update, "entry", currentValue),
|
|
162
|
+
render: ({ interaction, update, currentValue, messages }) =>
|
|
163
|
+
renderTextResponse(interaction, update, "entry", currentValue, messages),
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
166
|
id: "slider",
|
|
167
167
|
matches: (interaction) => interaction.type === "slider",
|
|
168
|
-
render: ({ interaction, update, currentValue }) =>
|
|
169
|
-
renderSliderResponse(interaction, update, currentValue),
|
|
168
|
+
render: ({ interaction, update, currentValue, messages }) =>
|
|
169
|
+
renderSliderResponse(interaction, update, currentValue, messages),
|
|
170
170
|
},
|
|
171
171
|
{
|
|
172
172
|
id: "upload",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { QtiChoice, QtiInteraction, QtiValue } from "@longsightgroup/qti3-core";
|
|
2
2
|
import { removeButton } from "../controls/remove-button.js";
|
|
3
3
|
import { missingChoicesMessage, responseGroup, valueToStrings } from "../interaction-support.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
5
5
|
import { parseUnlimitedMaximum } from "../response-limits.js";
|
|
6
6
|
import { choiceText, sourceChoices, targetChoices, tokenButton, tokenRegion } from "./shared.js";
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ export function renderMatchResponse(
|
|
|
9
9
|
interaction: QtiInteraction,
|
|
10
10
|
update: (value: QtiValue) => void,
|
|
11
11
|
currentValue: QtiValue,
|
|
12
|
-
messages:
|
|
12
|
+
messages: PlayerMessageResolver,
|
|
13
13
|
): HTMLElement {
|
|
14
14
|
const group = responseGroup();
|
|
15
15
|
|
|
@@ -26,13 +26,13 @@ export function renderMatchResponse(
|
|
|
26
26
|
|
|
27
27
|
const selector = document.createElement("div");
|
|
28
28
|
selector.className = "qti3-match-selector";
|
|
29
|
-
const sourceRegion = tokenRegion("
|
|
29
|
+
const sourceRegion = tokenRegion(messages.message("matchSourcesBank"));
|
|
30
30
|
sourceRegion.classList.add("qti3-match-source-bank");
|
|
31
|
-
const targetRegion = tokenRegion("
|
|
31
|
+
const targetRegion = tokenRegion(messages.message("matchTargetsBank"));
|
|
32
32
|
targetRegion.classList.add("qti3-match-target-bank");
|
|
33
33
|
const pairList = document.createElement("ul");
|
|
34
34
|
pairList.className = "qti3-pair-list";
|
|
35
|
-
pairList.setAttribute("aria-label", "
|
|
35
|
+
pairList.setAttribute("aria-label", messages.message("matchSelectedPairsList"));
|
|
36
36
|
|
|
37
37
|
const commit = () => {
|
|
38
38
|
if (interaction.responseCardinality === "single") update(selectedPairs[0] ?? null);
|
|
@@ -68,7 +68,10 @@ export function renderMatchResponse(
|
|
|
68
68
|
pairList.replaceChildren(
|
|
69
69
|
...selectedPairs.map((pair) => {
|
|
70
70
|
const [source, target] = pair.split(" ");
|
|
71
|
-
const label =
|
|
71
|
+
const label = messages.message("associationPairLabel", {
|
|
72
|
+
source: choiceText(sources, source),
|
|
73
|
+
target: choiceText(targets, target),
|
|
74
|
+
});
|
|
72
75
|
const item = document.createElement("li");
|
|
73
76
|
item.className = "qti3-pair-chip";
|
|
74
77
|
const text = document.createElement("span");
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import type { QtiChoice, QtiInteraction, QtiValue } from "@longsightgroup/qti3-core";
|
|
2
2
|
import { removeButton } from "../controls/remove-button.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
readableType,
|
|
6
|
-
responseGroup,
|
|
7
|
-
valueToStrings,
|
|
8
|
-
} from "../interaction-support.js";
|
|
9
|
-
import type { QtiPlayerMessages } from "../player-messages.js";
|
|
3
|
+
import { missingChoicesMessage, responseGroup, valueToStrings } from "../interaction-support.js";
|
|
4
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
10
5
|
import {
|
|
11
6
|
choiceText,
|
|
12
7
|
pairRegionLabels,
|
|
@@ -20,7 +15,7 @@ export function renderPairResponse(
|
|
|
20
15
|
interaction: QtiInteraction,
|
|
21
16
|
update: (value: QtiValue) => void,
|
|
22
17
|
currentValue: QtiValue,
|
|
23
|
-
messages:
|
|
18
|
+
messages: PlayerMessageResolver,
|
|
24
19
|
): HTMLElement {
|
|
25
20
|
const group = responseGroup();
|
|
26
21
|
|
|
@@ -33,15 +28,24 @@ export function renderPairResponse(
|
|
|
33
28
|
const selectedPairs: string[] = valueToStrings(currentValue);
|
|
34
29
|
let selectedSource: QtiChoice | undefined;
|
|
35
30
|
let selectedTarget: QtiChoice | undefined;
|
|
36
|
-
const labels = pairRegionLabels(interaction);
|
|
31
|
+
const labels = pairRegionLabels(interaction, messages);
|
|
37
32
|
|
|
38
|
-
const sourceRegion = tokenRegion(
|
|
39
|
-
|
|
33
|
+
const sourceRegion = tokenRegion(
|
|
34
|
+
messages.message("interactionSourcesBank", { type: interaction.type }),
|
|
35
|
+
labels.source,
|
|
36
|
+
);
|
|
37
|
+
const targetRegion = tokenRegion(
|
|
38
|
+
messages.message("interactionTargetsBank", { type: interaction.type }),
|
|
39
|
+
labels.target,
|
|
40
|
+
);
|
|
40
41
|
const selector = document.createElement("div");
|
|
41
42
|
selector.className = "qti3-pair-selector";
|
|
42
43
|
const pairList = document.createElement("ul");
|
|
43
44
|
pairList.className = "qti3-pair-list";
|
|
44
|
-
pairList.setAttribute(
|
|
45
|
+
pairList.setAttribute(
|
|
46
|
+
"aria-label",
|
|
47
|
+
messages.message("interactionSelectedPairsList", { type: interaction.type }),
|
|
48
|
+
);
|
|
45
49
|
let draggedSource: string | undefined;
|
|
46
50
|
|
|
47
51
|
const commit = () => {
|
|
@@ -84,11 +88,15 @@ export function renderPairResponse(
|
|
|
84
88
|
pairList.replaceChildren(
|
|
85
89
|
...selectedPairs.map((pair) => {
|
|
86
90
|
const [source, target] = pair.split(" ");
|
|
91
|
+
const label = messages.message("associationPairLabel", {
|
|
92
|
+
source: choiceText(sources, source),
|
|
93
|
+
target: choiceText(targets, target),
|
|
94
|
+
});
|
|
87
95
|
const item = document.createElement("li");
|
|
88
96
|
item.className = "qti3-pair-chip";
|
|
89
97
|
const text = document.createElement("span");
|
|
90
|
-
text.textContent =
|
|
91
|
-
const remove = removeButton(
|
|
98
|
+
text.textContent = label;
|
|
99
|
+
const remove = removeButton(label, messages);
|
|
92
100
|
remove.addEventListener("click", () => {
|
|
93
101
|
const index = selectedPairs.indexOf(pair);
|
|
94
102
|
if (index >= 0) selectedPairs.splice(index, 1);
|
|
@@ -6,11 +6,10 @@ import {
|
|
|
6
6
|
appendGraphicObjectImage,
|
|
7
7
|
objectIsImage,
|
|
8
8
|
percent,
|
|
9
|
-
readableType,
|
|
10
9
|
responseGroup,
|
|
11
10
|
} from "../interaction-support.js";
|
|
12
11
|
import { movementButton } from "../movement.js";
|
|
13
|
-
import type {
|
|
12
|
+
import type { PlayerMessageResolver } from "../player-message-resolver.js";
|
|
14
13
|
import {
|
|
15
14
|
objectAssetHeight,
|
|
16
15
|
objectAssetWidth,
|
|
@@ -22,11 +21,14 @@ export function renderPositionObjectResponse(
|
|
|
22
21
|
interaction: QtiInteraction,
|
|
23
22
|
update: (value: QtiValue) => void,
|
|
24
23
|
currentValue: QtiValue,
|
|
25
|
-
messages:
|
|
24
|
+
messages: PlayerMessageResolver,
|
|
26
25
|
): HTMLElement {
|
|
27
26
|
const group = responseGroup();
|
|
28
27
|
group.role = "group";
|
|
29
|
-
group.setAttribute(
|
|
28
|
+
group.setAttribute(
|
|
29
|
+
"aria-label",
|
|
30
|
+
messages.message("interactionPlacementResponse", { type: interaction.type }),
|
|
31
|
+
);
|
|
30
32
|
|
|
31
33
|
const stageObject = interaction.positionObjectStage ?? interaction.object;
|
|
32
34
|
const movableObject = interaction.positionObjectStage ? interaction.object : undefined;
|
|
@@ -43,7 +45,10 @@ export function renderPositionObjectResponse(
|
|
|
43
45
|
stage.style.setProperty("--qti3-position-object-marker-block-size", `${movableHeight}px`);
|
|
44
46
|
stage.tabIndex = 0;
|
|
45
47
|
stage.role = "group";
|
|
46
|
-
stage.setAttribute(
|
|
48
|
+
stage.setAttribute(
|
|
49
|
+
"aria-label",
|
|
50
|
+
messages.message("interactionPlacementStage", { type: interaction.type }),
|
|
51
|
+
);
|
|
47
52
|
|
|
48
53
|
if (stageObject?.data && objectIsImage(stageObject)) {
|
|
49
54
|
appendGraphicObjectImage(stage, stageObject, stageObject.text || "");
|
|
@@ -52,7 +57,7 @@ export function renderPositionObjectResponse(
|
|
|
52
57
|
const marker = document.createElement("button");
|
|
53
58
|
marker.type = "button";
|
|
54
59
|
marker.className = "qti3-position-object-marker";
|
|
55
|
-
marker.setAttribute("aria-label", messages.movableObject
|
|
60
|
+
marker.setAttribute("aria-label", messages.message("movableObject"));
|
|
56
61
|
applyPositionObjectMarkerSize(marker, movableWidth, movableHeight);
|
|
57
62
|
marker.draggable = false;
|
|
58
63
|
|
|
@@ -62,12 +67,13 @@ export function renderPositionObjectResponse(
|
|
|
62
67
|
image.alt = "";
|
|
63
68
|
marker.append(image);
|
|
64
69
|
} else {
|
|
65
|
-
marker.textContent = messages.placeObject
|
|
70
|
+
marker.textContent = messages.message("placeObject");
|
|
66
71
|
}
|
|
67
72
|
stage.append(marker);
|
|
68
73
|
|
|
69
74
|
const coordinate = document.createElement("output");
|
|
70
|
-
coordinate.className = "qti3-coordinate-output";
|
|
75
|
+
coordinate.className = "qti3-coordinate-output qti-visually-hidden";
|
|
76
|
+
coordinate.setAttribute("aria-live", "polite");
|
|
71
77
|
const clamp = () => {
|
|
72
78
|
point.x = Math.max(0, Math.min(width, point.x));
|
|
73
79
|
point.y = Math.max(0, Math.min(height, point.y));
|
|
@@ -90,10 +96,10 @@ export function renderPositionObjectResponse(
|
|
|
90
96
|
`calc(100% + ${Math.round(movableHeight / 2 + 8)}px)`,
|
|
91
97
|
);
|
|
92
98
|
coordinate.value = "";
|
|
93
|
-
coordinate.textContent = "
|
|
99
|
+
coordinate.textContent = messages.message("objectNotPlaced");
|
|
94
100
|
stage.setAttribute(
|
|
95
101
|
"aria-label",
|
|
96
|
-
|
|
102
|
+
messages.message("interactionPlacementStageEmpty", { type: interaction.type }),
|
|
97
103
|
);
|
|
98
104
|
return;
|
|
99
105
|
}
|
|
@@ -107,10 +113,11 @@ export function renderPositionObjectResponse(
|
|
|
107
113
|
`${percent(point.y, height)}%`,
|
|
108
114
|
);
|
|
109
115
|
coordinate.value = pointToString(point);
|
|
110
|
-
|
|
116
|
+
const coordinates = pointToString(point);
|
|
117
|
+
coordinate.textContent = messages.message("objectPositionedAt", { coordinates });
|
|
111
118
|
stage.setAttribute(
|
|
112
119
|
"aria-label",
|
|
113
|
-
|
|
120
|
+
messages.message("interactionPlacementStageAt", { type: interaction.type, coordinates }),
|
|
114
121
|
);
|
|
115
122
|
};
|
|
116
123
|
const pointFromPointer = (event: MouseEvent | PointerEvent) => {
|
|
@@ -200,7 +207,9 @@ export function renderPositionObjectResponse(
|
|
|
200
207
|
["down", 0, 1],
|
|
201
208
|
] as const) {
|
|
202
209
|
controls.append(
|
|
203
|
-
movementButton(direction, messages.moveObject
|
|
210
|
+
movementButton(direction, messages.message("moveObject", { direction }), () =>
|
|
211
|
+
moveBy(dx, dy),
|
|
212
|
+
),
|
|
204
213
|
);
|
|
205
214
|
}
|
|
206
215
|
|