@qti-components/portable-custom-interaction 1.1.4 → 1.2.0
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/dist/elements.d.ts +10 -0
- package/dist/elements.js +8 -0
- package/dist/elements.js.map +1 -0
- package/dist/interface.d.ts +30 -0
- package/dist/interface.js.map +1 -1
- package/dist/qti-portable-custom-interaction.d.ts +18 -8
- package/dist/qti-portable-custom-interaction.js +114 -125
- package/dist/qti-portable-custom-interaction.js.map +1 -1
- package/dist/qti-portable-custom-interaction.styles.d.ts +1 -1
- package/dist/qti-portable-custom-interaction.styles.js +14 -10
- package/dist/qti-portable-custom-interaction.styles.js.map +1 -1
- package/dist/qti-portable-custom-test-interaction.d.ts +2 -0
- package/dist/qti-portable-custom-test-interaction.js +17 -13
- package/dist/qti-portable-custom-test-interaction.js.map +1 -1
- package/dist/register.js +6 -4
- package/dist/register.js.map +1 -1
- package/package.json +10 -4
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { QtiPortableCustomInteraction } from './qti-portable-custom-interaction';
|
|
2
|
+
import { QtiPortableCustomInteractionTest } from './qti-portable-custom-test-interaction';
|
|
3
|
+
export declare const elements: readonly [{
|
|
4
|
+
readonly tag: "qti-portable-custom-interaction";
|
|
5
|
+
readonly ctor: typeof QtiPortableCustomInteraction;
|
|
6
|
+
}, {
|
|
7
|
+
readonly tag: "qti-portable-custom-interaction-test";
|
|
8
|
+
readonly ctor: typeof QtiPortableCustomInteractionTest;
|
|
9
|
+
}];
|
|
10
|
+
export { QtiPortableCustomInteraction, QtiPortableCustomInteractionTest };
|
package/dist/elements.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { QtiPortableCustomInteraction } from './qti-portable-custom-interaction';
|
|
2
|
+
import { QtiPortableCustomInteractionTest } from './qti-portable-custom-test-interaction';
|
|
3
|
+
export const elements = [
|
|
4
|
+
{ tag: 'qti-portable-custom-interaction', ctor: QtiPortableCustomInteraction },
|
|
5
|
+
{ tag: 'qti-portable-custom-interaction-test', ctor: QtiPortableCustomInteractionTest }
|
|
6
|
+
];
|
|
7
|
+
export { QtiPortableCustomInteraction, QtiPortableCustomInteractionTest };
|
|
8
|
+
//# sourceMappingURL=elements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elements.js","sourceRoot":"","sources":["../src/elements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAE,gCAAgC,EAAE,MAAM,wCAAwC,CAAC;AAE1F,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,EAAE,GAAG,EAAE,iCAAiC,EAAE,IAAI,EAAE,4BAA4B,EAAE;IAC9E,EAAE,GAAG,EAAE,sCAAsC,EAAE,IAAI,EAAE,gCAAgC,EAAE;CAC/E,CAAC;AAEX,OAAO,EAAE,4BAA4B,EAAE,gCAAgC,EAAE,CAAC","sourcesContent":["import { QtiPortableCustomInteraction } from './qti-portable-custom-interaction';\nimport { QtiPortableCustomInteractionTest } from './qti-portable-custom-test-interaction';\n\nexport const elements = [\n { tag: 'qti-portable-custom-interaction', ctor: QtiPortableCustomInteraction },\n { tag: 'qti-portable-custom-interaction-test', ctor: QtiPortableCustomInteractionTest }\n] as const;\n\nexport { QtiPortableCustomInteraction, QtiPortableCustomInteractionTest };\n"]}
|
package/dist/interface.d.ts
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
|
+
import type { BaseType, Cardinality } from '@qti-components/base';
|
|
1
2
|
/**
|
|
2
3
|
* Shared status values for PCI lifecycle callbacks.
|
|
3
4
|
*
|
|
4
5
|
* Matches the status vocabulary used in IMS QTI 3 PCI documentation.
|
|
5
6
|
*/
|
|
6
7
|
export type PciInteractionStatus = 'interacting' | 'suspended' | 'closed' | 'solution' | 'review';
|
|
8
|
+
/**
|
|
9
|
+
* Correct response of a response declaration, mirroring `qti-correct-response`.
|
|
10
|
+
*
|
|
11
|
+
* `value` holds the authored `qti-value` content: a single value for `single`
|
|
12
|
+
* cardinality, an array of values for every other cardinality.
|
|
13
|
+
*/
|
|
14
|
+
export interface PciCorrectResponse {
|
|
15
|
+
value: string | string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Response declaration passed into the `getInstance` configuration so a PCI can
|
|
19
|
+
* render a correct response itself when the item is in `solution` status.
|
|
20
|
+
*
|
|
21
|
+
* Mirrors `qti-response-declaration` with camelCased names. Every field is
|
|
22
|
+
* optional, a delivery engine passes as much or as little as it has, and
|
|
23
|
+
* `correctResponse` is absent when the response variable has none.
|
|
24
|
+
*
|
|
25
|
+
* `correctResponse` is also withheld while the candidate is still working: it is
|
|
26
|
+
* only sent when `status` is `solution` or `review`, so a PCI never holds the
|
|
27
|
+
* answer key during `interacting`.
|
|
28
|
+
*
|
|
29
|
+
* See https://github.com/1EdTech/qti-project-management/issues/210
|
|
30
|
+
*/
|
|
31
|
+
export interface PciResponseDeclaration {
|
|
32
|
+
baseType?: BaseType;
|
|
33
|
+
cardinality?: Cardinality;
|
|
34
|
+
correctResponse?: PciCorrectResponse;
|
|
35
|
+
}
|
|
7
36
|
/**
|
|
8
37
|
* Payload passed to `onready` once a PCI reports it is ready.
|
|
9
38
|
*/
|
|
@@ -34,6 +63,7 @@ export interface ConfigProperties<T> {
|
|
|
34
63
|
contextVariables: Record<string, unknown>;
|
|
35
64
|
boundTo: unknown;
|
|
36
65
|
responseIdentifier: string;
|
|
66
|
+
responseDeclaration?: PciResponseDeclaration;
|
|
37
67
|
onready: (payload: PciReadyPayload) => void;
|
|
38
68
|
ondone?: (payload: PciDonePayload) => void;
|
|
39
69
|
status?: PciInteractionStatus;
|
package/dist/interface.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../src/interface.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Shared status values for PCI lifecycle callbacks.\n *\n * Matches the status vocabulary used in IMS QTI 3 PCI documentation.\n */\nexport type PciInteractionStatus = 'interacting' | 'suspended' | 'closed' | 'solution' | 'review';\n\n/**\n * Payload passed to `onready` once a PCI reports it is ready.\n */\nexport interface PciReadyPayload {\n responseIdentifier: string; // The response identifier of the PCI\n status: PciInteractionStatus; // Current status\n}\n\n/**\n * Payload that may be passed to `ondone` when PCI finishes candidate interaction.\n */\nexport interface PciDonePayload {\n responseIdentifier: string; // The response identifier of the PCI\n status: PciInteractionStatus; // The final status after completion\n outcome?: unknown; // Optional outcome data (e.g., score, correctness)\n}\n\n/**\n * Configuration object shape exposed to a PCI instance.\n *\n * Notes for authors:\n * - `properties` contains `data-*` attributes from the host element using dataset rules.\n * - `templateVariables`, `contextVariables`, and `boundTo` follow QTI Appendix-C style JSON values.\n * - `onready` must be called by the PCI once it is interactive.\n * - `ondone` is optional and may be used for explicit completion workflows.\n */\nexport interface ConfigProperties<T> {\n properties: T; // Follows dataset conversion rules (camelCased keys)\n templateVariables: Record<string, unknown>; // Follows structure in Appendix C\n contextVariables: Record<string, unknown>; // Follows structure in Appendix C\n boundTo: unknown; // Follows structure in Appendix C\n responseIdentifier: string; // Unique within interaction scope\n\n onready: (payload: PciReadyPayload) => void; // Callback for when PCI is fully constructed and ready\n ondone?: (payload: PciDonePayload) => void; // Optional callback when candidate finishes interaction\n\n status?: PciInteractionStatus; // Optional, defaults to \"interacting\"\n}\n\n/**\n * IMS-style PCI factory and instance contract.\n *\n * A PCI module registers an object with a `typeIdentifier` and a `getInstance(...)` factory method.\n * The returned PCI instance should implement response/state read/write methods.\n */\nexport interface IMSpci<T> {\n /**\n * Stable PCI type key, expected to match `custom-interaction-type-identifier`.\n */\n typeIdentifier: string;\n\n /** @access public\n * @method getInstance Create a new instance of this portable custom interaction\n * Will be called by the qtiCustomInteractionContext\n * @param {DOM Element} dom - the DOM Element this PCI is being added to\n * @param {Object} configuration - the configuration to apply to this PCI\n * @param {String} state - a previous saved state to apply to this instance.\n * This must have been obtained from a prior call to getState on an\n * instance of this type (same typeIdentifier)\n */\n getInstance: (dom: HTMLElement, configuration: Configuration<T>, state: string) => void;\n\n /** @access public\n * @method getResponse\n * @return {Object} - the value to assign to the bound QTI response variable\n */\n getResponse: () => QtiVariableJSON | undefined;\n\n /** @access public\n * @method setResponse\n * @param {Object} value - the value to assign to the bound QTI response variable\n * NOTE: This is not an official QTI method, so no guarantee it is implemented\n * in all PCIs.\n */\n setResponse: (value: QtiVariableJSON) => void;\n\n /** @access public\n * @method getState\n * @return {String} The current state of this PCI. May be passed to\n * getInstance to later restore this PCI instance.\n * FIXME: host runtime can round-trip object states via prefixed JSON strings;\n * this type remains `string` for IMS compatibility.\n */\n getState: () => string;\n\n /** @access public\n * @method setState\n * @param {String} value - a state previously obtained from getState\n * to restore this PCI instance to a prior state.\n * FIXME: runtime may deserialize prefixed JSON state before applying it.\n */\n setState(value: string): unknown;\n\n /**\n * Optional teardown callback. If present, host may call before unload/cleanup.\n */\n oncompleted?: () => void;\n\n /**\n * Non-standard optional destroy hook; included for compatibility with legacy engines.\n */\n destroy?: () => void; // Not used in IMS and not in TAO implementation, so not used here (optional)\n}\n\n/**\n * Bridge callback signature used by this codebase for PCI registration.\n *\n * IMPORTANT:\n * - This type is intentionally minimal for existing call sites.\n * - Runtime initialization payload in `qti-portable-custom-interaction.ts` contains\n * additional fields (`boundTo`, `templateVariables`, `contextVariables`, etc.).\n * FIXME: align this type with runtime payload to remove ambiguity in generated docs.\n */\nexport declare type Configuration<T> = {\n onready: (pci: IMSpci<ConfigProperties<T>>, state?: string) => void;\n properties: T;\n // PK: following this: https://www.imsglobal.org/spec/qti/v3p0/impl#h.1mc9puik2ft6\n // All below are not used in the IMS Reference implementation, keeping for ref\n /* \n ondone: (pci: IMSPci<T>,response:any,state:string, status?: \"interacting\" | \"closed\" | \"solution\" | \"review\" ) => void;\n status: string;\n templateVariables: any; \n boundTo: any;\n contextVariables\n responseIdentifier\n */\n};\n\n/**\n * QTI base-type `file` representation.\n */\nexport type QtiFileData = {\n data: string;\n mime: string;\n name?: string;\n};\n\nexport type QtiBaseBoolean = boolean;\nexport type QtiBaseInteger = number;\nexport type QtiBaseFloat = number;\nexport type QtiBaseString = string;\nexport type QtiBasePoint = [number, number];\nexport type QtiBasePair = [string, string];\nexport type QtiBaseDirectedPair = [string, string];\nexport type QtiBaseDuration = string; // ISO 8601 duration format\nexport type QtiBaseFile = QtiFileData;\nexport type QtiBaseUri = string;\nexport type QtiBaseIntOrIdentifier = number | string;\nexport type QtiBaseIdentifier = string;\n\n/**\n * Convenience union for primitive response values used by this implementation.\n */\nexport type ResponseType =\n | boolean\n | number\n | string\n | QtiBasePair\n | QtiBasePoint\n | QtiFileData\n | Array<boolean | number | string | QtiBasePair | QtiBasePoint | QtiFileData>;\n\n/**\n * A QTI record entry for `record` cardinality values.\n */\nexport type QtiRecordItem = {\n name: string;\n base?: QtiBaseTypeJSON | null;\n list?: QtiListTypeJSON | null;\n};\nexport type ResponseVariableType = QtiVariableJSON;\n\n/**\n * QTI Appendix-C style JSON representation for base cardinality.\n */\nexport type QtiBaseTypeJSON = {\n boolean?: QtiBaseBoolean;\n integer?: QtiBaseInteger;\n float?: QtiBaseFloat;\n string?: QtiBaseString;\n point?: QtiBasePoint;\n pair?: QtiBasePair;\n directedPair?: QtiBaseDirectedPair;\n duration?: QtiBaseDuration;\n file?: QtiBaseFile;\n uri?: QtiBaseUri;\n intOrIdentifier?: QtiBaseIntOrIdentifier;\n identifier?: QtiBaseIdentifier;\n} | null;\n\n/**\n * QTI Appendix-C style JSON representation for list cardinality.\n */\nexport type QtiListTypeJSON = {\n boolean?: QtiBaseBoolean[];\n integer?: QtiBaseInteger[];\n float?: QtiBaseFloat[];\n string?: QtiBaseString[];\n point?: QtiBasePoint[];\n pair?: QtiBasePair[];\n directedPair?: QtiBaseDirectedPair[];\n duration?: QtiBaseDuration[];\n file?: QtiBaseFile[];\n uri?: QtiBaseUri[];\n intOrIdentifier?: QtiBaseIntOrIdentifier[];\n identifier?: QtiBaseIdentifier[];\n} | null;\n\n/**\n * Complete QTI variable JSON envelope used by PCI bridge messaging.\n */\nexport declare type QtiVariableJSON = {\n base?: QtiBaseTypeJSON;\n list?: QtiListTypeJSON;\n record?: QtiRecordItem[] | null;\n};\n\n/**\n * RequireJS module resolution config accepted by helper utilities and stories.\n */\nexport interface ModuleResolutionConfig {\n waitSeconds?: number;\n context?: string;\n catchError?: boolean;\n paths: {\n [key: string]: string | string[];\n };\n shim?: {\n [key: string]: {\n deps?: string[]; // Array of dependencies\n exports?: string; // The global variable to use as the module's value\n };\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../src/interface.ts"],"names":[],"mappings":"","sourcesContent":["import type { BaseType, Cardinality } from '@qti-components/base';\n\n/**\n * Shared status values for PCI lifecycle callbacks.\n *\n * Matches the status vocabulary used in IMS QTI 3 PCI documentation.\n */\nexport type PciInteractionStatus = 'interacting' | 'suspended' | 'closed' | 'solution' | 'review';\n\n/**\n * Correct response of a response declaration, mirroring `qti-correct-response`.\n *\n * `value` holds the authored `qti-value` content: a single value for `single`\n * cardinality, an array of values for every other cardinality.\n */\nexport interface PciCorrectResponse {\n value: string | string[];\n}\n\n/**\n * Response declaration passed into the `getInstance` configuration so a PCI can\n * render a correct response itself when the item is in `solution` status.\n *\n * Mirrors `qti-response-declaration` with camelCased names. Every field is\n * optional, a delivery engine passes as much or as little as it has, and\n * `correctResponse` is absent when the response variable has none.\n *\n * `correctResponse` is also withheld while the candidate is still working: it is\n * only sent when `status` is `solution` or `review`, so a PCI never holds the\n * answer key during `interacting`.\n *\n * See https://github.com/1EdTech/qti-project-management/issues/210\n */\nexport interface PciResponseDeclaration {\n baseType?: BaseType;\n cardinality?: Cardinality;\n correctResponse?: PciCorrectResponse;\n}\n\n/**\n * Payload passed to `onready` once a PCI reports it is ready.\n */\nexport interface PciReadyPayload {\n responseIdentifier: string; // The response identifier of the PCI\n status: PciInteractionStatus; // Current status\n}\n\n/**\n * Payload that may be passed to `ondone` when PCI finishes candidate interaction.\n */\nexport interface PciDonePayload {\n responseIdentifier: string; // The response identifier of the PCI\n status: PciInteractionStatus; // The final status after completion\n outcome?: unknown; // Optional outcome data (e.g., score, correctness)\n}\n\n/**\n * Configuration object shape exposed to a PCI instance.\n *\n * Notes for authors:\n * - `properties` contains `data-*` attributes from the host element using dataset rules.\n * - `templateVariables`, `contextVariables`, and `boundTo` follow QTI Appendix-C style JSON values.\n * - `onready` must be called by the PCI once it is interactive.\n * - `ondone` is optional and may be used for explicit completion workflows.\n */\nexport interface ConfigProperties<T> {\n properties: T; // Follows dataset conversion rules (camelCased keys)\n templateVariables: Record<string, unknown>; // Follows structure in Appendix C\n contextVariables: Record<string, unknown>; // Follows structure in Appendix C\n boundTo: unknown; // Follows structure in Appendix C\n responseIdentifier: string; // Unique within interaction scope\n responseDeclaration?: PciResponseDeclaration; // Optional; carries correctResponse only when status is solution/review\n\n onready: (payload: PciReadyPayload) => void; // Callback for when PCI is fully constructed and ready\n ondone?: (payload: PciDonePayload) => void; // Optional callback when candidate finishes interaction\n\n status?: PciInteractionStatus; // Optional, defaults to \"interacting\"\n}\n\n/**\n * IMS-style PCI factory and instance contract.\n *\n * A PCI module registers an object with a `typeIdentifier` and a `getInstance(...)` factory method.\n * The returned PCI instance should implement response/state read/write methods.\n */\nexport interface IMSpci<T> {\n /**\n * Stable PCI type key, expected to match `custom-interaction-type-identifier`.\n */\n typeIdentifier: string;\n\n /** @access public\n * @method getInstance Create a new instance of this portable custom interaction\n * Will be called by the qtiCustomInteractionContext\n * @param {DOM Element} dom - the DOM Element this PCI is being added to\n * @param {Object} configuration - the configuration to apply to this PCI\n * @param {String} state - a previous saved state to apply to this instance.\n * This must have been obtained from a prior call to getState on an\n * instance of this type (same typeIdentifier)\n */\n getInstance: (dom: HTMLElement, configuration: Configuration<T>, state: string) => void;\n\n /** @access public\n * @method getResponse\n * @return {Object} - the value to assign to the bound QTI response variable\n */\n getResponse: () => QtiVariableJSON | undefined;\n\n /** @access public\n * @method setResponse\n * @param {Object} value - the value to assign to the bound QTI response variable\n * NOTE: This is not an official QTI method, so no guarantee it is implemented\n * in all PCIs.\n */\n setResponse: (value: QtiVariableJSON) => void;\n\n /** @access public\n * @method getState\n * @return {String} The current state of this PCI. May be passed to\n * getInstance to later restore this PCI instance.\n * FIXME: host runtime can round-trip object states via prefixed JSON strings;\n * this type remains `string` for IMS compatibility.\n */\n getState: () => string;\n\n /** @access public\n * @method setState\n * @param {String} value - a state previously obtained from getState\n * to restore this PCI instance to a prior state.\n * FIXME: runtime may deserialize prefixed JSON state before applying it.\n */\n setState(value: string): unknown;\n\n /**\n * Optional teardown callback. If present, host may call before unload/cleanup.\n */\n oncompleted?: () => void;\n\n /**\n * Non-standard optional destroy hook; included for compatibility with legacy engines.\n */\n destroy?: () => void; // Not used in IMS and not in TAO implementation, so not used here (optional)\n}\n\n/**\n * Bridge callback signature used by this codebase for PCI registration.\n *\n * IMPORTANT:\n * - This type is intentionally minimal for existing call sites.\n * - Runtime initialization payload in `qti-portable-custom-interaction.ts` contains\n * additional fields (`boundTo`, `templateVariables`, `contextVariables`, etc.).\n * FIXME: align this type with runtime payload to remove ambiguity in generated docs.\n */\nexport declare type Configuration<T> = {\n onready: (pci: IMSpci<ConfigProperties<T>>, state?: string) => void;\n properties: T;\n // PK: following this: https://www.imsglobal.org/spec/qti/v3p0/impl#h.1mc9puik2ft6\n // All below are not used in the IMS Reference implementation, keeping for ref\n /* \n ondone: (pci: IMSPci<T>,response:any,state:string, status?: \"interacting\" | \"closed\" | \"solution\" | \"review\" ) => void;\n status: string;\n templateVariables: any; \n boundTo: any;\n contextVariables\n responseIdentifier\n */\n};\n\n/**\n * QTI base-type `file` representation.\n */\nexport type QtiFileData = {\n data: string;\n mime: string;\n name?: string;\n};\n\nexport type QtiBaseBoolean = boolean;\nexport type QtiBaseInteger = number;\nexport type QtiBaseFloat = number;\nexport type QtiBaseString = string;\nexport type QtiBasePoint = [number, number];\nexport type QtiBasePair = [string, string];\nexport type QtiBaseDirectedPair = [string, string];\nexport type QtiBaseDuration = string; // ISO 8601 duration format\nexport type QtiBaseFile = QtiFileData;\nexport type QtiBaseUri = string;\nexport type QtiBaseIntOrIdentifier = number | string;\nexport type QtiBaseIdentifier = string;\n\n/**\n * Convenience union for primitive response values used by this implementation.\n */\nexport type ResponseType =\n | boolean\n | number\n | string\n | QtiBasePair\n | QtiBasePoint\n | QtiFileData\n | Array<boolean | number | string | QtiBasePair | QtiBasePoint | QtiFileData>;\n\n/**\n * A QTI record entry for `record` cardinality values.\n */\nexport type QtiRecordItem = {\n name: string;\n base?: QtiBaseTypeJSON | null;\n list?: QtiListTypeJSON | null;\n};\nexport type ResponseVariableType = QtiVariableJSON;\n\n/**\n * QTI Appendix-C style JSON representation for base cardinality.\n */\nexport type QtiBaseTypeJSON = {\n boolean?: QtiBaseBoolean;\n integer?: QtiBaseInteger;\n float?: QtiBaseFloat;\n string?: QtiBaseString;\n point?: QtiBasePoint;\n pair?: QtiBasePair;\n directedPair?: QtiBaseDirectedPair;\n duration?: QtiBaseDuration;\n file?: QtiBaseFile;\n uri?: QtiBaseUri;\n intOrIdentifier?: QtiBaseIntOrIdentifier;\n identifier?: QtiBaseIdentifier;\n} | null;\n\n/**\n * QTI Appendix-C style JSON representation for list cardinality.\n */\nexport type QtiListTypeJSON = {\n boolean?: QtiBaseBoolean[];\n integer?: QtiBaseInteger[];\n float?: QtiBaseFloat[];\n string?: QtiBaseString[];\n point?: QtiBasePoint[];\n pair?: QtiBasePair[];\n directedPair?: QtiBaseDirectedPair[];\n duration?: QtiBaseDuration[];\n file?: QtiBaseFile[];\n uri?: QtiBaseUri[];\n intOrIdentifier?: QtiBaseIntOrIdentifier[];\n identifier?: QtiBaseIdentifier[];\n} | null;\n\n/**\n * Complete QTI variable JSON envelope used by PCI bridge messaging.\n */\nexport declare type QtiVariableJSON = {\n base?: QtiBaseTypeJSON;\n list?: QtiListTypeJSON;\n record?: QtiRecordItem[] | null;\n};\n\n/**\n * RequireJS module resolution config accepted by helper utilities and stories.\n */\nexport interface ModuleResolutionConfig {\n waitSeconds?: number;\n context?: string;\n catchError?: boolean;\n paths: {\n [key: string]: string | string[];\n };\n shim?: {\n [key: string]: {\n deps?: string[]; // Array of dependencies\n exports?: string; // The global variable to use as the module's value\n };\n };\n}\n"]}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Interaction } from '@qti-components/base';
|
|
2
2
|
import type { CSSResultGroup } from 'lit';
|
|
3
3
|
import type { BaseType, Cardinality, ItemContext, QtiContext } from '@qti-components/base';
|
|
4
|
-
import type { QtiVariableJSON, ResponseVariableType } from './interface';
|
|
4
|
+
import type { PciInteractionStatus, PciResponseDeclaration, QtiVariableJSON, ResponseVariableType } from './interface';
|
|
5
5
|
export declare class QtiPortableCustomInteraction extends Interaction {
|
|
6
6
|
#private;
|
|
7
7
|
protected _iframeLoaded: boolean;
|
|
8
|
+
protected _interactionReady: boolean;
|
|
8
9
|
protected _pendingMessages: Array<{
|
|
9
10
|
method: string;
|
|
10
11
|
params: any;
|
|
11
12
|
}>;
|
|
12
13
|
protected iframe: HTMLIFrameElement;
|
|
13
14
|
protected _iframeMessageOrigin: string | null;
|
|
14
|
-
private _iframeObjectUrl;
|
|
15
15
|
static styles: CSSResultGroup;
|
|
16
16
|
module: string;
|
|
17
17
|
customInteractionTypeIdentifier: string;
|
|
@@ -20,6 +20,22 @@ export declare class QtiPortableCustomInteraction extends Interaction {
|
|
|
20
20
|
requireJsUrl: string;
|
|
21
21
|
baseUrl: string;
|
|
22
22
|
useDefaultPaths: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Item lifecycle status handed to the PCI in its `getInstance` configuration.
|
|
25
|
+
* A delivery engine sets `solution` to let a PCI render the correct response.
|
|
26
|
+
*/
|
|
27
|
+
status: PciInteractionStatus;
|
|
28
|
+
/**
|
|
29
|
+
* Response declaration passed into the PCI configuration, so a PCI can render
|
|
30
|
+
* the correct response itself instead of having it pushed in as a response.
|
|
31
|
+
*
|
|
32
|
+
* Derived from the item context, unless a host sets it explicitly - the
|
|
33
|
+
* correct response viewer does, since it has no response declaration of its own.
|
|
34
|
+
*
|
|
35
|
+
* See https://github.com/1EdTech/qti-project-management/issues/210
|
|
36
|
+
*/
|
|
37
|
+
set responseDeclaration(declaration: PciResponseDeclaration | null);
|
|
38
|
+
get responseDeclaration(): PciResponseDeclaration | null;
|
|
23
39
|
private _errorMessage;
|
|
24
40
|
protected context?: ItemContext;
|
|
25
41
|
protected qtiContext?: QtiContext;
|
|
@@ -91,12 +107,6 @@ export declare class QtiPortableCustomInteraction extends Interaction {
|
|
|
91
107
|
* IFRAME MODE: Generate iframe HTML content
|
|
92
108
|
*/
|
|
93
109
|
protected generateIframeContent(): string;
|
|
94
|
-
/**
|
|
95
|
-
* Toggle the display of the correct response
|
|
96
|
-
* @param responseVariable The response variable containing the correct response
|
|
97
|
-
* @param show Whether to show or hide the correct response
|
|
98
|
-
*/
|
|
99
|
-
toggleInternalCorrectResponse(show: boolean): void;
|
|
100
110
|
/**
|
|
101
111
|
* Method to disable the PCI for review mode
|
|
102
112
|
* This can be used when showing the correct response
|
|
@@ -7,20 +7,39 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { css, html } from 'lit';
|
|
8
8
|
import { property, state } from 'lit/decorators.js';
|
|
9
9
|
import { consume } from '@lit/context';
|
|
10
|
-
import { Interaction, itemContext, qtiContext, removeDoubleSlashes } from '@qti-components/base';
|
|
10
|
+
import { Interaction, itemContext, qtiContext, removeDoubleSlashes, responseAttributeConverter } from '@qti-components/base';
|
|
11
11
|
import styles from './qti-portable-custom-interaction.styles';
|
|
12
|
+
/** Statuses in which the item is showing the correct response, so a PCI may legitimately see it. */
|
|
13
|
+
const STATUSES_SHOWING_CORRECT_RESPONSE = ['solution', 'review'];
|
|
14
|
+
/**
|
|
15
|
+
* Whether a response variable actually declares a correct response.
|
|
16
|
+
*
|
|
17
|
+
* Non-single cardinality yields `[]` for an empty `<qti-correct-response>`, which is "no correct
|
|
18
|
+
* response" and must not be reported as one.
|
|
19
|
+
*/
|
|
20
|
+
function hasCorrectResponseValue(value) {
|
|
21
|
+
if (value === null || value === undefined)
|
|
22
|
+
return false;
|
|
23
|
+
return Array.isArray(value) ? value.length > 0 : value !== '';
|
|
24
|
+
}
|
|
12
25
|
export class QtiPortableCustomInteraction extends Interaction {
|
|
13
26
|
constructor() {
|
|
14
27
|
super(...arguments);
|
|
15
28
|
this._iframeLoaded = false;
|
|
29
|
+
this._interactionReady = false;
|
|
16
30
|
this._pendingMessages = [];
|
|
17
31
|
this._iframeMessageOrigin = null;
|
|
18
|
-
this._iframeObjectUrl = null;
|
|
19
32
|
this.requirePathsJson = '';
|
|
20
33
|
this.requireShimJson = '';
|
|
21
34
|
this.requireJsUrl = 'https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js';
|
|
22
35
|
this.baseUrl = '';
|
|
23
36
|
this.useDefaultPaths = false;
|
|
37
|
+
/**
|
|
38
|
+
* Item lifecycle status handed to the PCI in its `getInstance` configuration.
|
|
39
|
+
* A delivery engine sets `solution` to let a PCI render the correct response.
|
|
40
|
+
*/
|
|
41
|
+
this.status = 'interacting';
|
|
42
|
+
this.#responseDeclaration = null;
|
|
24
43
|
this._errorMessage = null;
|
|
25
44
|
this.response = null;
|
|
26
45
|
this.#parsedRequirePaths = null;
|
|
@@ -50,6 +69,7 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
50
69
|
}
|
|
51
70
|
switch (data.method) {
|
|
52
71
|
case 'iframeReady':
|
|
72
|
+
this._interactionReady = true;
|
|
53
73
|
this.#initializeInteraction();
|
|
54
74
|
this.#processPendingMessages();
|
|
55
75
|
this.dispatchEvent(new CustomEvent('qti-portable-custom-interaction-loaded', {
|
|
@@ -144,6 +164,59 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
144
164
|
}
|
|
145
165
|
`
|
|
146
166
|
]; }
|
|
167
|
+
#responseDeclaration;
|
|
168
|
+
/**
|
|
169
|
+
* Response declaration passed into the PCI configuration, so a PCI can render
|
|
170
|
+
* the correct response itself instead of having it pushed in as a response.
|
|
171
|
+
*
|
|
172
|
+
* Derived from the item context, unless a host sets it explicitly - the
|
|
173
|
+
* correct response viewer does, since it has no response declaration of its own.
|
|
174
|
+
*
|
|
175
|
+
* See https://github.com/1EdTech/qti-project-management/issues/210
|
|
176
|
+
*/
|
|
177
|
+
set responseDeclaration(declaration) {
|
|
178
|
+
this.#responseDeclaration = declaration;
|
|
179
|
+
}
|
|
180
|
+
get responseDeclaration() {
|
|
181
|
+
if (this.#responseDeclaration) {
|
|
182
|
+
return this.#responseDeclaration;
|
|
183
|
+
}
|
|
184
|
+
const variable = this.responseVariable;
|
|
185
|
+
if (!variable) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const declaration = {
|
|
189
|
+
baseType: variable.baseType,
|
|
190
|
+
cardinality: variable.cardinality
|
|
191
|
+
};
|
|
192
|
+
const correctResponse = variable.correctResponse;
|
|
193
|
+
if (hasCorrectResponseValue(correctResponse)) {
|
|
194
|
+
declaration.correctResponse = { value: correctResponse };
|
|
195
|
+
}
|
|
196
|
+
return declaration;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The declaration as it goes into the PCI configuration.
|
|
200
|
+
*
|
|
201
|
+
* `correctResponse` is withheld unless the item is actually showing a solution. A PCI is
|
|
202
|
+
* third-party code running in an iframe, and there is no reason for it to hold the answer key
|
|
203
|
+
* while the candidate is still working - the use case this field exists for only applies once
|
|
204
|
+
* the status says the correct response is being shown.
|
|
205
|
+
*
|
|
206
|
+
* The filter sits here rather than in the `responseDeclaration` getter so it also covers a
|
|
207
|
+
* declaration a host set explicitly, not just the one derived from the item context.
|
|
208
|
+
*/
|
|
209
|
+
#responseDeclarationForStatus() {
|
|
210
|
+
const declaration = this.responseDeclaration;
|
|
211
|
+
if (!declaration?.correctResponse) {
|
|
212
|
+
return declaration;
|
|
213
|
+
}
|
|
214
|
+
if (STATUSES_SHOWING_CORRECT_RESPONSE.includes(this.status)) {
|
|
215
|
+
return declaration;
|
|
216
|
+
}
|
|
217
|
+
const { correctResponse: _withheld, ...rest } = declaration;
|
|
218
|
+
return rest;
|
|
219
|
+
}
|
|
147
220
|
#parsedRequirePaths;
|
|
148
221
|
#parsedRequireShim;
|
|
149
222
|
#pciValidity;
|
|
@@ -575,10 +648,6 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
575
648
|
disconnectedCallback() {
|
|
576
649
|
super.disconnectedCallback();
|
|
577
650
|
window.removeEventListener('message', this.handleIframeMessage);
|
|
578
|
-
if (this._iframeObjectUrl) {
|
|
579
|
-
URL.revokeObjectURL(this._iframeObjectUrl);
|
|
580
|
-
this._iframeObjectUrl = null;
|
|
581
|
-
}
|
|
582
651
|
}
|
|
583
652
|
/**
|
|
584
653
|
* IFRAME MODE: Send message to iframe
|
|
@@ -611,10 +680,7 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
611
680
|
* IFRAME MODE: Create iframe element
|
|
612
681
|
*/
|
|
613
682
|
createIframe() {
|
|
614
|
-
|
|
615
|
-
URL.revokeObjectURL(this._iframeObjectUrl);
|
|
616
|
-
this._iframeObjectUrl = null;
|
|
617
|
-
}
|
|
683
|
+
this._interactionReady = false;
|
|
618
684
|
this.iframe = document.createElement('iframe');
|
|
619
685
|
this.iframe.id = `pci-iframe-${this.responseIdentifier}`;
|
|
620
686
|
this.iframe.setAttribute('title', 'QTI PCI Iframe');
|
|
@@ -627,10 +693,6 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
627
693
|
// Handle iframe load event
|
|
628
694
|
this.iframe.onload = () => {
|
|
629
695
|
this._iframeLoaded = true;
|
|
630
|
-
if (this._iframeObjectUrl) {
|
|
631
|
-
URL.revokeObjectURL(this._iframeObjectUrl);
|
|
632
|
-
this._iframeObjectUrl = null;
|
|
633
|
-
}
|
|
634
696
|
this.#addMarkupToIframe();
|
|
635
697
|
// Send initialization data to iframe
|
|
636
698
|
this.#sendIframeInitData();
|
|
@@ -640,16 +702,14 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
640
702
|
this.iframe.name = iframeName;
|
|
641
703
|
// Generate iframe HTML content with all required scripts
|
|
642
704
|
const iframeContent = this.generateIframeContent();
|
|
643
|
-
//
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
this.iframe.src = `data:text/html;charset=utf-8,${encodedContent}`;
|
|
652
|
-
}
|
|
705
|
+
// Use `srcdoc` rather than a `blob:` (or `data:`) URL. Both of those give the iframe document
|
|
706
|
+
// a URL that is out of scope for any http(s) Service Worker registration, so a player that
|
|
707
|
+
// serves package resources through a Service Worker (CacheStorage, virtual paths) would see
|
|
708
|
+
// every request made from inside the PCI - module scripts, images, media, stylesheets, fetches -
|
|
709
|
+
// bypass it and hit the network instead. An `srcdoc` frame inherits this document's URL and
|
|
710
|
+
// stays controlled by the same Service Worker. It is same-origin either way, and messages are
|
|
711
|
+
// posted with a `'*'` target origin, so nothing about postMessage changes.
|
|
712
|
+
this.iframe.srcdoc = iframeContent;
|
|
653
713
|
// Append iframe to component
|
|
654
714
|
this.appendChild(this.iframe);
|
|
655
715
|
}
|
|
@@ -676,6 +736,8 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
676
736
|
dataAttributes: { ...this.dataset },
|
|
677
737
|
interactionModules: this.#getInteractionModules(),
|
|
678
738
|
boundTo: storedState ? null : this.boundTo,
|
|
739
|
+
responseDeclaration: this.#responseDeclarationForStatus(),
|
|
740
|
+
status: this.status,
|
|
679
741
|
state: storedState
|
|
680
742
|
};
|
|
681
743
|
this.sendMessageToIframe('initialize', initData);
|
|
@@ -730,7 +792,12 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
730
792
|
this.#pciValidity = null;
|
|
731
793
|
this.#pciCustomValidityMessage = '';
|
|
732
794
|
// Reflect any pre-existing response (e.g. restored session) for validation/completionStatus.
|
|
733
|
-
|
|
795
|
+
// Don't clobber a value already set via the `response="..."` attribute.
|
|
796
|
+
const currentResponse = this.response;
|
|
797
|
+
const hasResponse = Array.isArray(currentResponse) ? currentResponse.length > 0 : !!currentResponse;
|
|
798
|
+
if (!hasResponse) {
|
|
799
|
+
this.response = this.responseVariable?.value ?? null;
|
|
800
|
+
}
|
|
734
801
|
window.addEventListener('message', this.handleIframeMessage);
|
|
735
802
|
this.createIframe();
|
|
736
803
|
}
|
|
@@ -747,6 +814,16 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
747
814
|
? `${window.location.origin}${this.dataset.baseUrl}`
|
|
748
815
|
: this.dataset.baseUrl
|
|
749
816
|
: '';
|
|
817
|
+
// `data-base-url` names the directory the item was loaded from, so it is also the base every
|
|
818
|
+
// relative URL inside the interaction should resolve against - the markup's `src`/`href`, the
|
|
819
|
+
// stylesheets, and whatever the PCI module resolves itself. Anchoring `<base>` at the site
|
|
820
|
+
// origin instead would send `../assets/x.png` to `/assets/x.png`. Normalise to a trailing
|
|
821
|
+
// slash: without one the last segment counts as a filename and gets dropped.
|
|
822
|
+
const iframeBaseHref = iframeBaseUrl
|
|
823
|
+
? iframeBaseUrl.endsWith('/')
|
|
824
|
+
? iframeBaseUrl
|
|
825
|
+
: `${iframeBaseUrl}/`
|
|
826
|
+
: `${window.location.origin}/`;
|
|
750
827
|
const forwardConsole = this.dataset.forwardConsole === 'true';
|
|
751
828
|
const isLocalhost = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
|
|
752
829
|
const defaultComponentsCdnUrl = isLocalhost
|
|
@@ -770,7 +847,7 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
770
847
|
<head>
|
|
771
848
|
<meta charset="utf-8" />
|
|
772
849
|
<title>QTI PCI Container</title>
|
|
773
|
-
<base href="${
|
|
850
|
+
<base href="${iframeBaseHref}" />
|
|
774
851
|
<script type="module">
|
|
775
852
|
import '${componentsCdnUrl}';
|
|
776
853
|
</script>
|
|
@@ -892,6 +969,7 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
892
969
|
// PCI Manager for iframe implementation
|
|
893
970
|
window.PCIManager = {
|
|
894
971
|
pciInstance: null,
|
|
972
|
+
pciConfig: null,
|
|
895
973
|
container: null,
|
|
896
974
|
markupEl: null,
|
|
897
975
|
propertiesEl: null,
|
|
@@ -1117,7 +1195,9 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
1117
1195
|
);
|
|
1118
1196
|
},
|
|
1119
1197
|
responseIdentifier: config.responseIdentifier,
|
|
1120
|
-
boundTo: config.boundTo
|
|
1198
|
+
boundTo: config.boundTo,
|
|
1199
|
+
responseDeclaration: config.responseDeclaration || undefined,
|
|
1200
|
+
status: config.status || 'interacting'
|
|
1121
1201
|
};
|
|
1122
1202
|
|
|
1123
1203
|
if (pciInstance.getInstance) {
|
|
@@ -1133,6 +1213,9 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
1133
1213
|
restoredState = config.state;
|
|
1134
1214
|
}
|
|
1135
1215
|
}
|
|
1216
|
+
// Keep the configuration around next to the instance, it carries the
|
|
1217
|
+
// status and response declaration this PCI was constructed with.
|
|
1218
|
+
this.pciConfig = pciConfig;
|
|
1136
1219
|
pciInstance.getInstance(dom, pciConfig, restoredState || undefined);
|
|
1137
1220
|
} else {
|
|
1138
1221
|
this.notifyError('Loaded PCI module has no getInstance().');
|
|
@@ -1646,103 +1729,6 @@ export class QtiPortableCustomInteraction extends Interaction {
|
|
|
1646
1729
|
</body>
|
|
1647
1730
|
</html>`;
|
|
1648
1731
|
}
|
|
1649
|
-
/**
|
|
1650
|
-
* Toggle the display of the correct response
|
|
1651
|
-
* @param responseVariable The response variable containing the correct response
|
|
1652
|
-
* @param show Whether to show or hide the correct response
|
|
1653
|
-
*/
|
|
1654
|
-
toggleInternalCorrectResponse(show) {
|
|
1655
|
-
const responseVariable = this.responseVariable;
|
|
1656
|
-
// Store the correct response or clear it based on the show parameter
|
|
1657
|
-
this.correctResponse = show
|
|
1658
|
-
? responseVariable?.correctResponse
|
|
1659
|
-
: responseVariable.cardinality === 'single'
|
|
1660
|
-
? ''
|
|
1661
|
-
: [];
|
|
1662
|
-
// Get unique identifiers for this PCI's correct response elements
|
|
1663
|
-
const containerId = `correct-response-container-${this.responseIdentifier}`;
|
|
1664
|
-
// Check the parent element for any existing containers with this ID
|
|
1665
|
-
const existingContainers = this.parentElement?.querySelectorAll(`#${containerId}`);
|
|
1666
|
-
if (existingContainers) {
|
|
1667
|
-
existingContainers.forEach(existingContainer => {
|
|
1668
|
-
existingContainer.remove();
|
|
1669
|
-
});
|
|
1670
|
-
}
|
|
1671
|
-
// Handle the current interaction's state
|
|
1672
|
-
if (show) {
|
|
1673
|
-
// Disable the current interaction when showing correct response
|
|
1674
|
-
this.disable();
|
|
1675
|
-
}
|
|
1676
|
-
else {
|
|
1677
|
-
// Enable the current interaction when hiding correct response
|
|
1678
|
-
this.enable();
|
|
1679
|
-
return; // Exit early, nothing else to do
|
|
1680
|
-
}
|
|
1681
|
-
// If there's no correct response to show, exit
|
|
1682
|
-
if (!show || !responseVariable?.correctResponse) {
|
|
1683
|
-
return;
|
|
1684
|
-
}
|
|
1685
|
-
// Create a container for the correct response viewer
|
|
1686
|
-
const correctResponseContainer = document.createElement('div');
|
|
1687
|
-
correctResponseContainer.id = containerId;
|
|
1688
|
-
correctResponseContainer.className = 'pci-correct-response-container';
|
|
1689
|
-
correctResponseContainer.style.position = 'relative';
|
|
1690
|
-
correctResponseContainer.style.marginTop = '20px';
|
|
1691
|
-
correctResponseContainer.style.border = '2px solid green';
|
|
1692
|
-
correctResponseContainer.style.padding = '16px';
|
|
1693
|
-
correctResponseContainer.style.borderRadius = '4px';
|
|
1694
|
-
correctResponseContainer.style.backgroundColor = 'rgba(0, 128, 0, 0.05)';
|
|
1695
|
-
// Add a label for the correct response
|
|
1696
|
-
const label = document.createElement('div');
|
|
1697
|
-
label.textContent = 'Correct Response:';
|
|
1698
|
-
label.style.fontWeight = 'bold';
|
|
1699
|
-
label.style.marginBottom = '10px';
|
|
1700
|
-
label.style.color = 'green';
|
|
1701
|
-
correctResponseContainer.appendChild(label);
|
|
1702
|
-
// Instead of cloning, we'll create a new instance and copy necessary attributes
|
|
1703
|
-
const correctResponseViewer = document.createElement('qti-portable-custom-interaction');
|
|
1704
|
-
// Copy all attributes from the original PCI
|
|
1705
|
-
Array.from(this.attributes).forEach(attr => {
|
|
1706
|
-
if (attr.name !== 'id' && attr.name !== 'response-identifier') {
|
|
1707
|
-
correctResponseViewer.setAttribute(attr.name, attr.value);
|
|
1708
|
-
}
|
|
1709
|
-
});
|
|
1710
|
-
// Set a unique response identifier to avoid conflicts
|
|
1711
|
-
const originalResponseId = this.responseIdentifier;
|
|
1712
|
-
correctResponseViewer.responseIdentifier = `${originalResponseId}-correct`;
|
|
1713
|
-
// Copy any light DOM content from the original PCI
|
|
1714
|
-
// This includes markup and properties
|
|
1715
|
-
Array.from(this.children).forEach(child => {
|
|
1716
|
-
const clonedChild = child.cloneNode(true);
|
|
1717
|
-
correctResponseViewer.appendChild(clonedChild);
|
|
1718
|
-
});
|
|
1719
|
-
// Store the correct response value
|
|
1720
|
-
const correctResponseValue = responseVariable.correctResponse;
|
|
1721
|
-
// Ensure the correct-response viewer is initialized and then configured in the iframe
|
|
1722
|
-
const originalConnectedCallback = correctResponseViewer.connectedCallback;
|
|
1723
|
-
correctResponseViewer.connectedCallback = function () {
|
|
1724
|
-
originalConnectedCallback.call(this);
|
|
1725
|
-
const applyCorrectResponse = () => {
|
|
1726
|
-
const qtiVariableJSON = this.responseVariablesToQtiVariableJSON(correctResponseValue, responseVariable.cardinality, responseVariable.baseType);
|
|
1727
|
-
this.sendMessageToIframe('setBoundTo', {
|
|
1728
|
-
[originalResponseId]: qtiVariableJSON
|
|
1729
|
-
});
|
|
1730
|
-
this.sendMessageToIframe('setState', { state: 'review' });
|
|
1731
|
-
};
|
|
1732
|
-
if (this._iframeLoaded) {
|
|
1733
|
-
applyCorrectResponse();
|
|
1734
|
-
}
|
|
1735
|
-
else {
|
|
1736
|
-
this.addEventListener('qti-portable-custom-interaction-loaded', applyCorrectResponse, { once: true });
|
|
1737
|
-
}
|
|
1738
|
-
};
|
|
1739
|
-
// Make sure the viewer is not interactive
|
|
1740
|
-
correctResponseViewer.style.pointerEvents = 'none';
|
|
1741
|
-
// Add the correct response viewer to the container
|
|
1742
|
-
correctResponseContainer.appendChild(correctResponseViewer);
|
|
1743
|
-
// Append the container after this PCI
|
|
1744
|
-
this.after(correctResponseContainer);
|
|
1745
|
-
}
|
|
1746
1732
|
/**
|
|
1747
1733
|
* Method to disable the PCI for review mode
|
|
1748
1734
|
* This can be used when showing the correct response
|
|
@@ -1831,6 +1817,9 @@ __decorate([
|
|
|
1831
1817
|
__decorate([
|
|
1832
1818
|
property({ type: Boolean, attribute: 'data-use-default-paths' })
|
|
1833
1819
|
], QtiPortableCustomInteraction.prototype, "useDefaultPaths", void 0);
|
|
1820
|
+
__decorate([
|
|
1821
|
+
property({ type: String, attribute: 'data-status' })
|
|
1822
|
+
], QtiPortableCustomInteraction.prototype, "status", void 0);
|
|
1834
1823
|
__decorate([
|
|
1835
1824
|
state()
|
|
1836
1825
|
], QtiPortableCustomInteraction.prototype, "_errorMessage", void 0);
|
|
@@ -1843,6 +1832,6 @@ __decorate([
|
|
|
1843
1832
|
state()
|
|
1844
1833
|
], QtiPortableCustomInteraction.prototype, "qtiContext", void 0);
|
|
1845
1834
|
__decorate([
|
|
1846
|
-
|
|
1835
|
+
property({ attribute: 'response', reflect: false, converter: responseAttributeConverter({ emptyAs: null }) })
|
|
1847
1836
|
], QtiPortableCustomInteraction.prototype, "response", void 0);
|
|
1848
1837
|
//# sourceMappingURL=qti-portable-custom-interaction.js.map
|