### Install the API Library
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
Install the knowledgeworker-embedded-asset-api library using a package manager like pnpm.
```sh
$ pnpm install knowledgeworker-embedded-asset-api
```
--------------------------------
### Typical Asset Initialization
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/README.md
Demonstrates the basic setup for initializing an asset, including configuration, event handling for initialization, saving state, and marking completion.
```APIDOC
## Typical Asset Initialization
### Description
This example shows how to initialize an asset, configure its behavior, handle the initialization event from the runtime, save the asset's state, and mark the asset as complete.
### Functions Used
- `configure()`: Configures asset behavior, such as disabling auto-completion.
- `onInitialize(callback)`: Registers a callback function to be executed when the asset is initialized by the runtime.
- `setSuspendData(data)`: Saves custom data associated with the asset's state.
- `completed()`: Notifies the runtime that the asset has been completed.
### Code Example
```javascript
import {
configure,
onInitialize,
setSuspendData,
completed,
} from 'knowledgeworker-embedded-asset-api';
// Disable auto-completion for custom completion logic
configure({ autoCompletion: false });
// Initialize when runtime is ready
onInitialize((config) => {
console.log('Asset type:', config.assetType);
// Restore previous state
if (config.suspendData) {
restoreState(JSON.parse(config.suspendData));
}
// Setup UI and event listeners
setupUI();
});
// Save state on changes
document.addEventListener('change', () => {
setSuspendData(JSON.stringify(getCurrentState()));
});
// Mark complete when appropriate
readmeButton.addEventListener('click', () => {
completed();
});
```
```
--------------------------------
### Context Example
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/types.md
Illustrates a typical context hierarchy as it might appear in a course, ordered from the broadest scope (site) to the most specific (asset).
```typescript
// Typical context hierarchy from a course
[
{ uid: 'course-001', type: ContextType.SITE, title: 'Biology 101' },
{ uid: 'ch-2', type: ContextType.CHAPTER, title: 'Chapter 2: Cell Biology' },
{ uid: 'sec-2.1', type: ContextType.SECTION, title: 'Section 2.1: Mitochondria' },
{ uid: 'asset-123', type: ContextType.MEDIUM, title: 'Interactive Mitochondria Model' }
]
```
--------------------------------
### Typical Asset Initialization
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/README.md
Initializes the asset, configures runtime settings, restores state, sets up event listeners, and marks completion. Use this pattern for standard asset setup.
```typescript
import {
configure,
onInitialize,
setSuspendData,
completed,
} from 'knowledgeworker-embedded-asset-api';
// Disable auto-completion for custom completion logic
configure({ autoCompletion: false });
// Initialize when runtime is ready
onInitialize((config) => {
console.log('Asset type:', config.assetType);
// Restore previous state
if (config.suspendData) {
restoreState(JSON.parse(config.suspendData));
}
// Setup event listeners
setupUI();
});
// Save state on changes
document.addEventListener('change', () => {
setSuspendData(JSON.stringify(getCurrentState()));
});
// Mark complete when appropriate
eadmeButton.addEventListener('click', () => {
completed();
});
```
--------------------------------
### Calling Actions After Initialization
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/configuration.md
Provides examples of API actions that can be safely called after the `onInitialize` handler has been invoked and the asset is ready.
```typescript
// After onInitialize fires, these are safe to call:
setHeight(300);
setSuspendData('...');
answered('...', true, 1);
```
--------------------------------
### Complete Initialization Order Example
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/configuration.md
Illustrates the correct sequence for configuring the asset API, registering handlers, and calling actions, ensuring all steps occur at the appropriate time relative to the window load event.
```typescript
// index.html
```
--------------------------------
### ContextType Usage Example
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/types.md
Shows how to access and iterate over the context array provided in the configuration. This allows you to determine the asset's position within the course structure.
```typescript
onInitialize((config) => {
config.context.forEach(ctx => {
console.log(`${ctx.type}: ${ctx.title}`);
});
});
```
--------------------------------
### Test Asset Initialization with Mocked Configuration
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/integration-examples.md
Example test case demonstrating how to use the `mockRuntimeConfig` utility to test the initialization of an asset with specific configurations. It verifies that the `onInitialize` callback receives the correct configuration.
```typescript
// asset.test.ts
import { onInitialize } from 'knowledgeworker-embedded-asset-api';
import { mockRuntimeConfig } from './test-utils';
test('Asset initializes with configuration', () => {
let capturedConfig: Configuration | null = null;
onInitialize((config) => {
capturedConfig = config;
});
mockRuntimeConfig({
assetType: 'question',
isEvaluated: true,
lmsData: { learnerName: 'Jane' },
});
expect(capturedConfig?.lmsData.learnerName).toBe('Jane');
});
```
--------------------------------
### AssetType Usage Example
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/types.md
Demonstrates how to use the AssetType enum to conditionally set up assets based on their type. This is typically done within the onInitialize configuration.
```typescript
onInitialize((config) => {
switch (config.assetType) {
case AssetType.MEDIUM:
// Setup for content
break;
case AssetType.QUESTION:
case AssetType.QUESTION_WITH_CUSTOM_QUESTION_TEXT:
// Setup for question
break;
case AssetType.ADVANCED_QUESTION:
// Setup for advanced question with custom buttons
break;
}
});
```
--------------------------------
### Mock Runtime Configuration for Testing
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/integration-examples.md
Utility function to mock the runtime configuration and simulate the INITIALIZE message from the parent window. This is essential for testing components that rely on initial setup data.
```typescript
// test-utils.ts
export function mockRuntimeConfig(config: Partial) {
const fullConfig: any = {
assetType: 'medium',
isEvaluated: false,
lmsData: { learnerName: 'Test User' },
design: {},
context: [],
suspendData: '',
sharedData: '',
...config,
};
// Set up token for config parsing
window.name = JSON.stringify({
token: 'test-token',
origin: 'http://localhost'
});
// Simulate runtime sending INITIALIZE message
const event = new MessageEvent('message', {
data: {
type: 'KW_PACKAGE_INITIALIZE',
token: 'test-token',
...fullConfig,
css: 'body { color: black; }'
}
});
window.dispatchEvent(event);
}
```
--------------------------------
### Initialize Embedded Asset
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
Use this handler to initialize your asset after the window load event. It provides configuration details necessary for setup.
```TypeScript
import { onInitialize } from 'knowledgeworker-embedded-asset-api';
onInitialize((configuration) => {
// may use `configuration.suspendData` to restore your asset to the last state
});
```
--------------------------------
### TypeScript Configuration Example
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/configuration.md
Shows a basic `tsconfig.json` configuration suitable for projects using the Knowledgeworker Embedded Asset API, specifying target, library, and module settings.
```json
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM"],
"module": "ESNext"
}
}
```
--------------------------------
### onReset
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Registers a callback invoked when a new attempt is started. This is used to reset the state for a new user attempt.
```APIDOC
## onReset
### Description
Registers a callback invoked when a new attempt is started. This is used to reset the state for a new user attempt.
### Method
```ts
onReset(listener: () => void): void
```
### Parameters
#### Path Parameters
N/A
#### Query Parameters
N/A
#### Request Body
N/A
### Request Example
```ts
import { onReset } from 'knowledgeworker-embedded-asset-api';
onReset(() => {
// Reset state for a new attempt
});
```
### Response
#### Success Response (200)
N/A
#### Response Example
N/A
```
--------------------------------
### Advanced Question with Custom Button Visibility
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/integration-examples.md
This example demonstrates how to control the visibility and behavior of 'Check Answer', 'Retry', and 'Solution' buttons based on signals from the runtime environment. It covers answer evaluation, state updates, and UI resets.
```typescript
import {
onInitialize,
answered,
checkAnswerButtonClicked,
retryButtonClicked,
solutionButtonClicked,
onShowCheckAnswerButton,
onShowRetryButton,
onShowSolutionButton,
onShowResult,
onShowSolution,
onReset,
onDeactivate,
} from 'knowledgeworker-embedded-asset-api';
interface ButtonStates {
checkAnswer: boolean;
retry: boolean;
solution: boolean;
}
let buttonStates: ButtonStates = {
checkAnswer: true,
retry: false,
solution: false
};
let userAnswer: string | undefined;
let isCorrect = false;
// Runtime tells us when each button should be visible
onShowCheckAnswerButton((show) => {
buttonStates.checkAnswer = show;
updateButtonVisibility();
});
onShowRetryButton((show) => {
buttonStates.retry = show;
updateButtonVisibility();
});
onShowSolutionButton((show) => {
buttonStates.solution = show;
updateButtonVisibility();
});
// Asset evaluates answer when "Check Answer" is clicked
function handleCheckAnswer() {
// Collect user answer
userAnswer = document.querySelector('input[name="answer"]:checked')?.value;
if (!userAnswer) {
alert('Select an answer first');
return;
}
// Evaluate (in real asset, this could involve complex logic)
isCorrect = userAnswer === 'correct_answer';
const score = isCorrect ? 1 : 0;
// Notify runtime
answered(userAnswer, isCorrect, score);
// Notify that button was clicked
checkAnswerButtonClicked();
}
function handleRetry() {
// Reset UI
document.querySelectorAll('input[name="answer"]').forEach(input => {
(input as HTMLInputElement).checked = false;
});
document.body.classList.remove('answer-correct', 'answer-incorrect');
userAnswer = undefined;
// Notify runtime
retryButtonClicked();
}
function handleSolution() {
// Show solution
document.getElementById('solution')?.style.display = 'block';
// Notify runtime
solutionButtonClicked();
}
// When runtime wants to show result
onShowResult((passed) => {
if (passed) {
document.body.classList.add('answer-correct');
} else {
document.body.classList.add('answer-incorrect');
}
});
// When runtime wants to show solution
onShowSolution(() => {
document.getElementById('solution')?.style.display = 'block';
});
// Reset for retry attempt
onReset(() => {
document.querySelectorAll('input[name="answer"]').forEach(input => {
(input as HTMLInputElement).disabled = false;
(input as HTMLInputElement).checked = false;
});
document.body.classList.remove('answer-correct', 'answer-incorrect');
document.getElementById('solution')?.style.display = 'none';
userAnswer = undefined;
});
// Question cannot be changed further
onDeactivate(() => {
document.querySelectorAll('input[name="answer"]').forEach(input => {
(input as HTMLInputElement).disabled = true;
});
});
function updateButtonVisibility() {
const checkBtn = document.getElementById('check-answer-btn');
const retryBtn = document.getElementById('retry-btn');
const solutionBtn = document.getElementById('solution-btn');
if (checkBtn) {
checkBtn.style.display = buttonStates.checkAnswer ? 'block' : 'none';
checkBtn.disabled = !buttonStates.checkAnswer;
}
if (retryBtn) {
retryBtn.style.display = buttonStates.retry ? 'block' : 'none';
retryBtn.disabled = !buttonStates.retry;
}
if (solutionBtn) {
solutionBtn.style.display = buttonStates.solution ? 'block' : 'none';
solutionBtn.disabled = !buttonStates.solution;
}
}
onInitialize(() => {
// Setup event listeners on buttons
document.getElementById('check-answer-btn')?.addEventListener('click', handleCheckAnswer);
document.getElementById('retry-btn')?.addEventListener('click', handleRetry);
document.getElementById('solution-btn')?.addEventListener('click', handleSolution);
// Initial button state
updateButtonVisibility();
});
```
--------------------------------
### LMSData Usage Example
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/types.md
Demonstrates how to access the learner's name from the LMSData object within the configuration. This can be used for personalized greetings or tracking.
```typescript
onInitialize((config) => {
console.log(`Welcome, ${config.lmsData.learnerName}!`);
});
```
--------------------------------
### Get Runtime Configuration
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/architecture.md
This function retrieves and validates the runtime configuration, which includes the token and origin, by parsing the `window.name` property. It returns `undefined` if the configuration is incomplete or invalid.
```typescript
export const getConfig = (): Config | undefined => {
let config: Partial = {};
try {
config = JSON.parse(window.name);
} catch (e) {}
if (!config?.token || !config?.origin) {
return undefined;
}
return config as Config;
};
```
--------------------------------
### Advanced Question (Custom Buttons)
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/README.md
Provides an example of handling custom buttons within an advanced question asset, including showing/hiding buttons and resetting the question.
```APIDOC
## Advanced Question (Custom Buttons)
### Description
This example illustrates how to implement custom buttons for advanced questions. It covers controlling the visibility of a 'Check Answer' button based on runtime signals and handling the reset action when the user retries.
### Functions Used
- `answered(userAnswer, isCorrect, score)`: Submits the user's answer, correctness, and score.
- `checkAnswerButtonClicked()`: Notifies the runtime that the custom 'Check Answer' button has been clicked.
- `onShowCheckAnswerButton(callback)`: Registers a callback to control the visibility of the 'Check Answer' button.
- `onReset(callback)`: Registers a callback function to be executed when the runtime signals a reset.
### Code Example
```javascript
import {
answered,
checkAnswerButtonClicked,
onShowCheckAnswerButton,
onReset,
} from 'knowledgeworker-embedded-asset-api';
// Runtime controls button visibility
onShowCheckAnswerButton((show) => {
document.getElementById('check-btn').style.display = show ? 'block' : 'none';
});
// Asset notifies when button is clicked
document.getElementById('check-btn').addEventListener('click', () => {
// Evaluate answer and call answered()
const result = evaluateAnswer();
answered(result.answer, result.passed, result.score);
// Notify runtime of button click
checkAnswerButtonClicked();
});
// Reset when user retries
onReset(() => {
resetQuestion();
});
```
```
--------------------------------
### Silent Failure Example: setHeight() in Standalone Window
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/errors.md
Demonstrates a silent failure scenario where 'setHeight' is called in a standalone window. The message is not sent, but no error is thrown.
```typescript
// Running in a standalone window (not an iframe)
import { setHeight } from 'knowledgeworker-embedded-asset-api';
setHeight(500); // Does not throw, but message is not sent
```
--------------------------------
### Interactive Multi-Choice Question Asset
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/integration-examples.md
Implement a multi-choice question with custom styling and immediate feedback. This example handles answer selection, submission, state saving, and displays results based on correctness.
```typescript
import {
configure,
onInitialize,
answered,
onShowResult,
onShowSolution,
onDeactivate,
onReset,
} from 'knowledgeworker-embedded-asset-api';
interface QuestionState {
selectedAnswers: string[];
isSubmitted: boolean;
}
let state: QuestionState = {
selectedAnswers: [],
isSubmitted: false
};
const correctAnswers = ['answer_a', 'answer_c']; // Multi-choice
// Initialize
onInitialize((config) => {
if (config.suspendData) {
const saved = JSON.parse(config.suspendData);
state = saved;
if (state.isSubmitted) {
disableAnswerButtons();
} else {
restoreSelections();
}
}
setupEventListeners();
});
// Handle answer selection
function selectAnswer(answerId: string) {
if (state.isSubmitted) return; // Locked
const index = state.selectedAnswers.indexOf(answerId);
if (index >= 0) {
state.selectedAnswers.splice(index, 1); // Deselect
} else {
state.selectedAnswers.push(answerId); // Select
}
// Update UI
document.getElementById(answerId)?.classList.toggle('selected');
// Save interim state
setSuspendData(JSON.stringify(state));
}
// Submit answer
function submitAnswer() {
if (state.selectedAnswers.length === 0) {
alert('Please select an answer');
return;
}
state.isSubmitted = true;
// Check answer
const correctCount = state.selectedAnswers.filter(a => correctAnswers.includes(a)).length;
const incorrectCount = state.selectedAnswers.length - correctCount;
const passed = incorrectCount === 0;
const score = correctCount / correctAnswers.length; // 1 correct of 2 = 0.5
// Report to runtime
answered(
state.selectedAnswers.join(','),
passed,
score
);
// Save final state
setSuspendData(JSON.stringify(state));
// Disable further changes
disableAnswerButtons();
}
// When runtime requests result display
onShowResult((passed) => {
state.selectedAnswers.forEach(answerId => {
const btn = document.getElementById(answerId);
if (correctAnswers.includes(answerId)) {
btn?.classList.add('correct');
} else {
btn?.classList.add('incorrect');
}
});
correctAnswers.forEach(answerId => {
if (!state.selectedAnswers.includes(answerId)) {
document.getElementById(answerId)?.classList.add('missing');
}
});
});
// When runtime requests solution
onShowSolution(() => {
correctAnswers.forEach(answerId => {
document.getElementById(answerId)?.classList.add('solution');
});
});
// When runtime deactivates question (no more retries)
onDeactivate(() => {
document.body.classList.add('question-deactivated');
document.getElementById('submit-btn').disabled = true;
});
// When user retries
onReset(() => {
state = { selectedAnswers: [], isSubmitted: false };
document.querySelectorAll('button.answer').forEach(btn => {
btn.classList.remove('selected', 'correct', 'incorrect', 'solution', 'missing');
btn.disabled = false;
});
document.body.classList.remove('question-deactivated');
document.getElementById('submit-btn').disabled = false;
setSuspendData(JSON.stringify(state));
});
function disableAnswerButtons() {
document.querySelectorAll('button.answer').forEach(btn => {
btn.disabled = true;
});
}
function setupEventListeners() {
document.querySelectorAll('button.answer').forEach(btn => {
btn.addEventListener('click', () => selectAnswer(btn.id));
});
document.getElementById('submit-btn')?.addEventListener('click', submitAnswer);
}
```
--------------------------------
### Initial Configuration and Handler Registration
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/configuration.md
Shows how to import and use the `configure` function to set initial options and `onInitialize` to register a handler that runs after initialization.
```typescript
import { configure } from 'knowledgeworker-embedded-asset-api';
// Register configuration before page load
configure({
autoCompletion: false
});
// Register handlers
onInitialize((config) => { /* ... */ });
```
--------------------------------
### Handle Reset Event
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
This handler is for question-type assets and signals that a new attempt has started, requiring the question to be activated and all answers reset.
```TypeScript
import { onReset } from 'knowledgeworker-embedded-asset-api';
// Handle if question should be reseted
onReset(() => {
document.body.classList.remove('deactivated');
myAnswers = [];
});
```
--------------------------------
### onInitialize
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
Initializes the asset with configuration data after the window load event. It provides essential information for the asset to set itself up.
```APIDOC
## onInitialize(configuration: Configuration): void
### Description
Is triggered directly after the [window load event](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event) and provides the asset with the necessary information to initialize itself.
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
* **configuration** (Configuration) - Required - The configuration object containing initialization parameters.
* **suspendData** (string) - Data to restore the asset to its last state.
* **sharedData** (string) - Shared data string.
* **assetType** (AssetType) - The type of the asset.
* **isEvaluated** (boolean) - Indicates if the asset is evaluated.
* **lmsData** (LMSData) - Data from the Learning Management System.
* **learnerName** (string) - The name of the learner.
* **design** (Design) - Design parameters for the asset.
* **context** (Context[]) - An array of context objects.
* **uid** (string) - Unique identifier for the context.
* **type** (ContextType) - The type of the context.
* **title** (string) - Optional HTML string for the context title.
### Request Example
```typescript
import { onInitialize } from 'knowledgeworker-embedded-asset-api';
onInitialize((configuration) => {
// may use `configuration.suspendData` to restore your asset to the last state
});
```
### Response
None (void)
```
--------------------------------
### onInitialize
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Registers a callback invoked immediately after window load with runtime configuration. Use this to restore previous state and initialize the asset with runtime settings.
```APIDOC
## onInitialize
### Description
Registers a callback invoked immediately after window load with runtime configuration.
### Method
```ts
onInitialize(listener: (configuration: Configuration) => void): void
```
### Parameters
#### Path Parameters
- **listener** (`(configuration: Configuration) => void`) - Required - Callback receiving asset configuration
### Configuration Object
```ts
interface Configuration {
suspendData: string;
sharedData: string;
assetType: AssetType;
isEvaluated: boolean;
lmsData: LMSData;
design: Design;
context: Context[];
}
```
### Behavior
Invoked once per session after the `window load` event. Use this to restore previous state from `suspendData` and initialize the asset with runtime settings.
### Example
```ts
import { onInitialize } from 'knowledgeworker-embedded-asset-api';
onInitialize((config) => {
console.log('Asset type:', config.assetType);
console.log('Learner:', config.lmsData.learnerName);
// Restore from suspend data
if (config.suspendData) {
const state = JSON.parse(config.suspendData);
restoreAssetState(state);
} else {
initializeAsset();
}
});
```
```
--------------------------------
### onShowSolution
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Registers a callback to display the solution. This callback is invoked when the solution should be presented to the user.
```APIDOC
## onShowSolution
### Description
Registers a callback to display the solution. This callback is invoked when the solution should be presented to the user.
### Method
```ts
onShowSolution(listener: () => void): void
```
### Parameters
#### Path Parameters
N/A
#### Query Parameters
N/A
#### Request Body
N/A
### Request Example
```ts
import { onShowSolution } from 'knowledgeworker-embedded-asset-api';
onShowSolution(() => {
// Display the solution
});
```
### Response
#### Success Response (200)
N/A
#### Response Example
N/A
```
--------------------------------
### configure
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
Configures the API with custom options. The configuration must be set before the window load event is triggered.
```APIDOC
## configure(options: Options): void
### Description
To change the default behavior of the API you can use `configure()` to provide your own configuration. The configuration has to be set before the [window load event](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event) is triggered.
### Parameters
#### Request Body
- **options** (Options) - Required - Configuration options.
- **autoCompletion** (boolean) - Optional - Default: `true`. This param is only necessary for assets of type `medium` and not needed for question assets. By default, Knowledgeworker Create assumes that the package does not contain any interactions or hidden content relevant for completion and marks it as completed after the [window load event](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event). But many types of assets initially hide parts of their content to reduce cognitive load and to adapt to users' individual needs. To measure completion, such hidden contents may have to be taken into account. To do so, you can disable `autoCompletion` and trigger the [`completed()`](#completed-void) action when all relevant content has been seen by the user.
### Request Example
```typescript
import { configure, completed } from 'knowledgeworker-embedded-asset-api';
configure({
autoCompletion: false, // disable automatic completion
});
// Mark the asset as completed
somePopup.addEventListener("click", () => completed());
```
```
--------------------------------
### Register Callback for Reset
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Use `onReset` to register a callback that is invoked when a new attempt is started. This handler is applicable for question-based asset types and is used to reset the state.
```typescript
import { onReset } from 'knowledgeworker-embedded-asset-api';
onReset(() => {
// Callback logic to reset state
});
```
--------------------------------
### Handle Show Solution Event
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
This handler is for question-type assets and is called to display the solution. It is triggered based on runtime question settings.
```TypeScript
import { onShowSolution } from 'knowledgeworker-embedded-asset-api';
// Handle if solution should be shown
onShowSolution(() => {
someAnswer.classList.add('solution');
});
```
--------------------------------
### Reading Runtime Configuration in onInitialize
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/configuration.md
Demonstrates how to access and utilize the configuration object provided by the Knowledgeworker Create runtime within the `onInitialize` handler. This includes reading asset type, learner data, evaluation status, and restoring previous state.
```typescript
import { onInitialize, AssetType } from 'knowledgeworker-embedded-asset-api';
onInitialize((config) => {
// Read one-time initialization data
console.log('Asset type:', config.assetType);
console.log('Learner:', config.lmsData.learnerName);
console.log('Is tracked:', config.isEvaluated);
// Restore previous state
if (config.suspendData) {
const previousState = JSON.parse(config.suspendData);
restoreAsset(previousState);
}
// View course context
config.context.forEach(ctx => {
console.log(`${ctx.type}: ${ctx.title}`);
});
});
```
--------------------------------
### Runtime Setting window.name
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/configuration.md
Demonstrates how the runtime environment sets the `window.name` property to a JSON string containing the authentication token and origin. This is used for initial configuration.
```typescript
// Runtime sets window.name to JSON:
window.name = JSON.stringify({
token: 'secure-token-xyz',
origin: 'https://knowledgeworker.example.com'
});
// Asset library parses this in config.ts
const config = JSON.parse(window.name);
```
--------------------------------
### Validate setSuspendData() string parameter
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/errors.md
Use this example to ensure that the suspendData parameter passed to setSuspendData is always a string. It shows how to handle errors when null, objects, or numbers are provided instead of a string.
```typescript
import { setSuspendData } from 'knowledgeworker-embedded-asset-api';
// Valid
setSuspendData(''); // Empty string OK
setSuspendData('scene1');
setSuspendData(JSON.stringify({ state: 'data' }));
// Invalid: throws
try {
setSuspendData(null); // Throws
} catch (e) {
console.error(e.message); // "SuspendData should be a string!"
}
try {
setSuspendData({ state: 'data' }); // Throws
} catch (e) {
console.error(e.message);
}
try {
setSuspendData(123); // Throws
} catch (e) {
console.error(e.message);
}
```
--------------------------------
### configure
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/actions.md
Configures the default behavior of the embedded asset. This function must be called before the window load event.
```APIDOC
## configure
### Description
Configures the default behavior of the embedded asset. This function must be called before the `window load` event.
### Method
`configure(options: Options): void`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **options** (Options) - Required - Configuration object
- **autoCompletion** (boolean) - Optional - `true` - Whether the asset is automatically marked complete on window load. Only applicable for asset type `medium`.
### Request Example
```typescript
import { configure, completed } from 'knowledgeworker-embedded-asset-api';
// Disable automatic completion
configure({
autoCompletion: false
});
// Later, when content is fully viewed
someUserInteractionElement.addEventListener('click', () => {
completed();
});
```
### Response
#### Success Response (200)
None (void)
#### Response Example
None
### Errors
- Throws if `options` is not an object
```
--------------------------------
### Register Callback to Display Solution
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Use `onShowSolution` to register a callback for displaying the solution. This handler is applicable for question-based asset types and is called when solution display is enabled.
```typescript
import { onShowSolution } from 'knowledgeworker-embedded-asset-api';
onShowSolution(() => {
const solutionElement = document.getElementById('solution');
solutionElement.style.display = 'block';
});
```
--------------------------------
### Validate setHeight() parameter
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/errors.md
This snippet demonstrates the correct usage of the setHeight function, ensuring the height is a positive number or undefined. It includes examples of catching errors for invalid inputs like zero, negative numbers, NaN, or non-numeric types.
```typescript
import { setHeight } from 'knowledgeworker-embedded-asset-api';
// Valid calls
setHeight(100);
setHeight(500);
setHeight(undefined); // Restore default
// Invalid: throws
try {
setHeight(0); // Throws: not positive
} catch (e) {
console.error(e.message);
}
try {
setHeight(-50); // Throws: not positive
} catch (e) {
console.error(e.message);
}
try {
setHeight(NaN); // Throws: not a valid number
} catch (e) {
console.error(e.message);
}
try {
setHeight('300'); // Throws: not a number
} catch (e) {
console.error(e.message);
}
```
--------------------------------
### Register Initialization and Event Handlers
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Register essential handlers like initialization, showing results, and showing solutions. These handlers must be registered before the window load event to ensure proper message handling.
```typescript
import { onInitialize, onShowResult, onShowSolution } from 'knowledgeworker-embedded-asset-api';
// Register handlers in HTML script tag or at module load time
onInitialize((config) => {
console.log('Initialization complete');
});
onShowResult((passed) => {
console.log('Show result:', passed);
});
onShowSolution(() => {
console.log('Show solution');
});
// window.addEventListener('load') is triggered by the browser
// The library's onMessage listener (attached at module load) begins receiving messages
```
--------------------------------
### Initialize Asset with Configuration
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/types.md
The onInitialize handler is called once per session with the Configuration object. Use this to restore state or initialize asset content based on its type.
```typescript
import { onInitialize, AssetType } from 'knowledgeworker-embedded-asset-api';
onInitialize((config: Configuration) => {
// Restore previous state
if (config.suspendData) {
restoreState(JSON.parse(config.suspendData));
}
// Initialize based on asset type
if (config.assetType === AssetType.MEDIUM) {
initializeContentAsset(config);
} else {
initializeQuestion(config);
}
});
```
--------------------------------
### onShowSolutionButton
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Registers a callback to control the visibility of the 'Show Solution' button. This is applicable for 'advanced-question' asset types.
```APIDOC
## onShowSolutionButton
### Description
Registers a callback to show or hide the "Show Solution" button.
### Method
`onShowSolutionButton(listener: (show: boolean) => void): void`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Behavior
Only applicable for asset type `advanced-question`. Determines when the solution button should be shown.
### Example
```ts
import { onShowSolutionButton } from 'knowledgeworker-embedded-asset-api';
onShowSolutionButton((show) => {
const btn = document.getElementById('solution-btn');
btn.style.display = show ? 'block' : 'none';
btn.disabled = !show;
});
```
```
--------------------------------
### Register Show Solution Button Handler
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Register a callback to control the visibility of the 'Show Solution' button. This handler is intended for the 'advanced-question' asset type to determine when the solution should be accessible.
```typescript
import { onShowSolutionButton } from 'knowledgeworker-embedded-asset-api';
onShowSolutionButton((show) => {
const btn = document.getElementById('solution-btn');
btn.style.display = show ? 'block' : 'none';
btn.disabled = !show;
});
```
--------------------------------
### Register Initialization Handler
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/handlers.md
Registers a callback that is invoked immediately after the window loads with the runtime configuration. Use this to restore state and initialize the asset.
```typescript
import { onInitialize } from 'knowledgeworker-embedded-asset-api';
onInitialize((config) => {
console.log('Asset type:', config.assetType);
console.log('Learner:', config.lmsData.learnerName);
// Restore from suspend data
if (config.suspendData) {
const state = JSON.parse(config.suspendData);
restoreAssetState(state);
} else {
initializeAsset();
}
});
```
--------------------------------
### solutionButtonClicked
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/api-reference/actions.md
Notifies the runtime that the "Show Solution" button was clicked. This action is intended for 'advanced-question' asset types, indicating that the solution to the question should be displayed.
```APIDOC
## solutionButtonClicked
Notifies the runtime that the "Show Solution" button was clicked.
```ts
solutionButtonClicked(): void
```
### Behavior
Only applicable for asset type `advanced-question`. Notifies the runtime that the solution should be displayed.
### Example
```ts
import { solutionButtonClicked } from 'knowledgeworker-embedded-asset-api';
solutionBtn.addEventListener('click', () => {
solutionButtonClicked();
});
```
```
--------------------------------
### Error Handling Best Practice: Wrap Action Calls
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/errors.md
Illustrates how to use try-catch blocks to gracefully handle potential errors from 'setHeight' and 'answered' functions.
```typescript
import { setHeight, answered } from 'knowledgeworker-embedded-asset-api';
function handleHeightChange(value: unknown) {
try {
setHeight(Number(value));
} catch (e) {
console.error('Invalid height:', e.message);
}
}
function handleAnswer(userAnswer: unknown, isCorrect: boolean, score: number) {
try {
answered(String(userAnswer), isCorrect, score);
} catch (e) {
console.error('Invalid answer data:', e.message);
}
}
```
--------------------------------
### Importing API Functions and Types
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/index.md
Demonstrates how to import essential functions and types from the main entry point of the Knowledgeworker Embedded Asset API. This is the standard way to begin using the library in your asset.
```typescript
import {
setHeight,
answered,
setSuspendData,
setSharedData,
completed,
configure,
// ... handler functions and types
} from 'knowledgeworker-embedded-asset-api';
```
--------------------------------
### Dynamic Asset Sizing with ResizeObserver
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/README.md
Dynamically adjusts the asset's height based on its content's `offsetHeight` using `ResizeObserver`. Requires `setHeight` from the API and a `padding` variable.
```ts
import { setHeight } from 'knowledgeworker-embedded-asset-api';
// Adjust when content changes
const observer = new ResizeObserver(() => {
const height = document.getElementById('content').offsetHeight;
setHeight(height + padding);
});
observer.observe(document.getElementById('content'));
```
--------------------------------
### Configuration Object Interface
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/configuration.md
Defines the structure of the configuration object automatically provided by the Knowledgeworker Create runtime during asset initialization.
```typescript
interface Configuration {
suspendData: string;
sharedData: string;
assetType: AssetType;
isEvaluated: boolean;
lmsData: LMSData;
design: Design;
context: Context[];
}
```
--------------------------------
### TypeScript Module Pattern for Assets
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/integration-examples.md
Illustrates a recommended project structure using TypeScript modules for organizing assets. This pattern separates types, API wrappers, and asset implementation.
```typescript
// types.ts
export interface AssetConfig {
assetType: string;
isEvaluated: boolean;
learnerName: string;
}
export interface UserState {
currentQuestion: number;
answers: Record;
completed: boolean;
}
// api.ts - Wrapper around library
import * as api from 'knowledgeworker-embedded-asset-api';
export const registerHandlers = (handlers: {
onReady: (config: AssetConfig) => void;
onResult?: (passed: boolean) => void;
}) => {
api.onInitialize((config) => {
handlers.onReady({
assetType: config.assetType,
isEvaluated: config.isEvaluated,
learnerName: config.lmsData.learnerName,
});
});
if (handlers.onResult) {
api.onShowResult(handlers.onResult);
}
};
export const submitAnswer = (answer: string, passed: boolean, score: number) => {
try {
api.answered(answer, passed, score);
} catch (e) {
console.error('Failed to submit answer:', e);
}
};
// main.ts - Asset implementation
import { registerHandlers, submitAnswer } from './api';
import { AssetConfig, UserState } from './types';
class QuestionAsset {
private state: UserState = {
currentQuestion: 0,
answers: {},
completed: false,
};
constructor() {
registerHandlers({
onReady: (config) => this.handleReady(config),
onResult: (passed) => this.handleResult(passed),
});
}
private handleReady(config: AssetConfig) {
console.log(`Ready for ${config.learnerName}`);
// Initialize asset
}
private handleResult(passed: boolean) {
// Update UI to show result
}
public answerQuestion(answer: string) {
const isCorrect = answer === 'correct_answer';
submitAnswer(answer, isCorrect, isCorrect ? 1 : 0);
}
}
new QuestionAsset();
```
--------------------------------
### Answer Submission (Questions)
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/README.md
Illustrates how to submit an answer from a question asset and handle the result feedback provided by the runtime.
```APIDOC
## Answer Submission (Questions)
### Description
This example demonstrates how a question asset can submit a user's answer to the runtime, including whether the answer is correct and a score. It also shows how to react to the result feedback from the runtime.
### Functions Used
- `answered(userAnswer, isCorrect, score)`: Submits the user's answer, correctness, and score to the runtime.
- `onShowResult(callback)`: Registers a callback function to be executed when the runtime provides feedback on the answer.
### Code Example
```javascript
import { answered, onShowResult } from 'knowledgeworker-embedded-asset-api';
// Submit answer
function submitAnswer() {
const userAnswer = document.querySelector('input:checked').value;
const isCorrect = userAnswer === 'correct';
const score = isCorrect ? 1 : 0;
answered(userAnswer, isCorrect, score);
}
// Show feedback
onShowResult((passed) => {
if (passed) {
document.body.classList.add('success');
} else {
document.body.classList.add('error');
}
});
```
```
--------------------------------
### Runtime to Asset Message Listener
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/README.md
Sets up a listener in the runtime to receive messages from the asset. The token is used for security.
```ts
window.addEventListener('message', (event) => {
const { type, token, ...data } = event.data;
// Process message
});
```
--------------------------------
### Simple Content Asset Integration (TypeScript)
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/_autodocs/integration-examples.md
Integrates a rich media asset with progressive disclosure. It disables auto-completion, restores user progress, tracks revealed sections, and adjusts height based on content visibility. Use this for assets where content is initially hidden and revealed through user interaction.
```typescript
import {
configure,
onInitialize,
setHeight,
setSuspendData,
completed,
} from 'knowledgeworker-embedded-asset-api';
// Step 1: Disable auto-completion because content is hidden
configure({
autoCompletion: false
});
// Step 2: Initialize asset
onInitialize((config) => {
console.log('Asset loaded for', config.lmsData.learnerName);
// Restore user progress if any
if (config.suspendData) {
const state = JSON.parse(config.suspendData);
openSection(state.openSection);
}
});
// Step 3: Track interaction
let revealedSections = new Set();
function revealSection(sectionId: string) {
document.getElementById(sectionId).style.display = 'block';
revealedSections.add(sectionId);
// Save progress
setSuspendData(JSON.stringify({
openSection: sectionId,
revealedCount: revealedSections.size
}));
// Check completion
checkCompletion();
}
function checkCompletion() {
const totalSections = 4;
if (revealedSections.size === totalSections) {
// User has seen all sections
completed();
}
}
// Adjust height when content changes
function openSection(sectionId: string) {
revealSection(sectionId);
// Recalculate height based on visible content
const content = document.getElementById('content');
setHeight(content.offsetHeight + 100);
}
```
--------------------------------
### setHeight
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
Tells Knowledgeworker Create to display the embedded asset with the given height. Use `undefined` to restore default behavior.
```APIDOC
## setHeight(height: number | undefined): void
### Description
Tells Knowledgeworker Create to display the embedded asset with the given height. Use `undefined` to restore default behavior.
Embedded assets are integrated via an [iframe tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe). Knowledgeworker Create automatically adjusts the width of this iframe to fit the device screen size as well as surrounding content elements. By default, the height is calculated based on the current width and the initial aspect ratio configured by maximum width and height in the Knowledgeworker Create media asset editor. However, this does not suit all content display situations or dynamic contents and in these circumstances you may want to explicitly set the height of your embedded assets.
### Parameters
#### Request Body
- **height** (number | undefined) - Required - The desired height for the embedded asset in pixels. Use `undefined` to restore default behavior.
### Request Example
```typescript
import { setHeight } from 'knowledgeworker-embedded-asset-api';
// Display this embedded asset with a height of 350 pixels
setHeight(350);
```
```
--------------------------------
### Import and Use setHeight Action
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
Import the setHeight action to dynamically control the display height of an embedded asset. This is useful for content that doesn't conform to the default aspect ratio.
```ts
// Import a library action or handler into your code
import { setHeight } from 'knowledgeworker-embedded-asset-api';
// Tell the Knowledgeworker Create runtime to display this embedded asset with a height of 500 pixels
setHeight(500);
```
--------------------------------
### Handle Show Solution Button Visibility
Source: https://github.com/chemmedia/knowledgeworker-embedded-asset-api/blob/master/README.md
This handler is for assets of type `advanced-question`. It controls the visibility of 'Check answer', 'Retry', or 'Show solution' buttons.
```TypeScript
import { onShowCheckAnswerButton } from 'knowledgeworker-embedded-asset-api';
// Handle if question should be deactivated
onShowCheckAnswerButton((show) => {
if (show) {
checkAnswerButton.removeAttribute('disabled');
} else {
checkAnswerButton.setAttribute('disabled', 'disabled');
}
});
```