UNPKG

@caspingus/lt

Version:

A utility library of helpers and tools for working with Learnosity APIs.

146 lines (135 loc) 4.55 kB
import * as app from '../../../core/app'; import logger from '../../../../utils/logger'; import * as question from '../../../core/questions'; /** * Extensions add specific functionality to Items API. * They rely on modules within LT being available. * * -- * * Adds a prefix to all multiple-choice labels (correct * answer and distractors). * * Ignores block UI and radio button under option. * * Supports * - multi-select MCQs * - shuffle responses * - columns * * <p><img src="https://raw.githubusercontent.com/michaelsharman/LT/main/src/assets/images/mcqprefix.png" alt="" width="660"></p> * @module Extensions/Assessment/mcqLabelPrefix */ const state = { chosenMask: 'upperAlpha', prefixMask: { lowerAlpha: 97, upperAlpha: 65, numeric: 49, }, explicitPrefixes: [], renderedCss: false, suffix: '.', }; /** * Sets up an item load listener to add a prefix to all * MCQ possible response labels. * @example * import { LT } from '@caspingus/lt/src/assessment/index'; * * LT.init(itemsApp); // Set up LT with the Items API application instance variable * LT.extensions.mcqLabelPrefix.run(); * @param {string} mask Which mask pattern to use. Supports `upperAlpha` (default), `lowerAlpha`, and `numeric`. * @param {string} suffix Any suffix you want added to the label prefix. Defaults to `.`. * @param {array} prefixes Array of custom string prefixes to use. * @since 0.6.0 */ export function run(mask = 'upperAlpha', suffix = '.', prefixes) { if (state.prefixMask.hasOwnProperty(mask)) { state.chosenMask = mask; } if (suffix && typeof suffix === 'string') { state.suffix = suffix; } if (prefixes && Array.isArray(prefixes)) { state.explicitPrefixes = prefixes; } state.renderedCss || injectCSS(); app.appInstance().on('item:load', () => { addPrefix(question.questions()); }); } /** * * @param {array} q Array of questions, if any, on the current item * @since 0.6.0 * @ignore */ function addPrefix(itemQuestions) { const asciiStart = state.prefixMask[state.chosenMask]; const suffix = state.suffix; try { for (const q of itemQuestions) { if (q.type === 'mcq' && q?.ui_style?.type !== 'block' && q?.ui_style?.type !== 'horizontal-input-bottom') { const r = q.response_id; const elOptions = document.getElementById(r).querySelectorAll('.lrn-mcq-option'); let responseIndex = 0; for (const o of elOptions) { const elLabels = o.querySelector('.lrn-possible-answer').children; const elExistingPrefixes = o.querySelector('.lrn-prefix-label'); // If we haven't already printed prefixes if (!elExistingPrefixes) { let prefixValue; // Check whether we're using a prefix mask or an explicit set of prefixes if ( Array.isArray(state.explicitPrefixes) && state.explicitPrefixes.length && typeof state.explicitPrefixes[responseIndex] === 'string' ) { prefixValue = state.explicitPrefixes[responseIndex]; } else { prefixValue = String.fromCharCode(asciiStart + responseIndex); } for (let i = 0; i < elLabels.length; i++) { const p = document.createElement('span'); p.classList.add('lrn-prefix-label'); p.append(`${prefixValue}${suffix}`); elLabels[i].prepend(p); } responseIndex++; } } } } } catch (err) { logger.error(err); } } /** * Injects the necessary CSS to the header * @since 0.6.0 * @ignore */ function injectCSS() { const elStyle = document.createElement('style'); const css = ` /* Learnosity MCQ label prefix styles */ .lrn-prefix-label { padding-right: 15px; font-weight: 500; } @media (max-width: 750px) { .lrn-prefix-label { padding-right: 10px; } } @media (max-width: 650px) { .lrn-prefix-label { padding-right: 5px; } } `; elStyle.textContent = css; document.head.append(elStyle); state.renderedCss = true; }