### 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'); } }); ```