@pie-element/multiple-choice 9.9.2-next.4 → 9.9.2-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/controller/lib/index.js +2 -1
- package/controller/lib/index.js.map +1 -1
- package/docs/pie-schema.json +5 -0
- package/docs/pie-schema.json.md +4 -0
- package/lib/index.js +10 -6
- package/lib/index.js.map +1 -1
- package/module/controller.js +1 -0
- package/module/element.js +2 -1
- package/package.json +2 -2
package/controller/lib/index.js
CHANGED
|
@@ -151,7 +151,8 @@ function _model() {
|
|
|
151
151
|
selectedAnswerBackgroundColor: normalizedQuestion.selectedAnswerBackgroundColor || 'initial',
|
|
152
152
|
minSelections: normalizedQuestion.minSelections,
|
|
153
153
|
maxSelections: normalizedQuestion.maxSelections,
|
|
154
|
-
autoplayAudioEnabled: normalizedQuestion.autoplayAudioEnabled
|
|
154
|
+
autoplayAudioEnabled: normalizedQuestion.autoplayAudioEnabled,
|
|
155
|
+
completeAudioEnabled: normalizedQuestion.completeAudioEnabled
|
|
155
156
|
};
|
|
156
157
|
_ref4 = env || {}, role = _ref4.role, mode = _ref4.mode;
|
|
157
158
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["prepareChoice","model","env","defaultFeedback","choice","role","mode","out","label","value","rationale","rationaleEnabled","correct","feedbackEnabled","feedbackType","feedback","type","createDefaultModel","Promise","resolve","defaults","normalize","question","verticalMode","choicesLayout","questionProps","session","updateSession","normalizedQuestion","Object","assign","incorrect","choices","map","lockChoiceOrder","disabled","prompt","promptEnabled","gridColumns","choiceMode","keyMode","choicePrefix","responseCorrect","undefined","language","extraCSSRules","fontSizeFactor","isSelectionButtonBelow","selectedAnswerBackgroundColor","minSelections","maxSelections","autoplayAudioEnabled","teacherInstructions","teacherInstructionsEnabled","getScore","config","selectedChoices","correctChoices","filter","ch","score","reduce","acc","selectedChoice","find","length","str","parseFloat","toFixed","outcome","empty","partialScoringEnabled","partialScoring","enabled","createCorrectResponseSession","id","c","getInnerText","html","replaceAll","getContent","replace","validate","minAnswerChoices","maxAnswerChoices","reversedChoices","reverse","choicesErrors","rationaleErrors","errors","forEach","field","required","hasCorrectResponse","index","identicalAnswer","slice","some","nbOfChoices","answerChoices","correctResponse"],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport isEmpty from 'lodash/isEmpty';\nimport { isResponseCorrect } from './utils';\nimport defaults from './defaults';\nimport { lockChoices, partialScoring, getShuffledChoices } from '@pie-lib/pie-toolbox/controller-utils';\n\nconst prepareChoice = (model, env, defaultFeedback) => (choice) => {\n const { role, mode } = env || {};\n const out = {\n label: choice.label,\n value: choice.value,\n };\n\n if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {\n out.rationale = model.rationaleEnabled ? choice.rationale : null;\n } else {\n out.rationale = null;\n }\n\n if (mode === 'evaluate') {\n out.correct = !!choice.correct;\n\n if (model.feedbackEnabled) {\n const feedbackType = (choice.feedback && choice.feedback.type) || 'none';\n\n if (feedbackType === 'default') {\n out.feedback = defaultFeedback[choice.correct ? 'correct' : 'incorrect'];\n } else if (feedbackType === 'custom') {\n out.feedback = choice.feedback.value;\n }\n }\n }\n\n return out;\n};\n\nexport function createDefaultModel(model = {}) {\n return new Promise((resolve) => resolve({ ...defaults, ...model }));\n}\n\nexport const normalize = (question) => {\n const { verticalMode, choicesLayout, ...questionProps } = question || {};\n\n return {\n ...defaults,\n ...questionProps,\n // This is used for offering support for old models which have the property verticalMode\n // Same thing is set in authoring : packages/multiple-choice/configure/src/index.jsx - createDefaultModel\n choicesLayout: choicesLayout || (verticalMode === false && 'horizontal') || defaults.choicesLayout,\n };\n};\n\n/**\n *\n * @param {*} question\n * @param {*} session\n * @param {*} env\n * @param {*} updateSession - optional - a function that will set the properties passed into it on the session.\n */\nexport async function model(question, session, env, updateSession) {\n const normalizedQuestion = normalize(question);\n\n const defaultFeedback = Object.assign(\n { correct: 'Correct', incorrect: 'Incorrect' },\n normalizedQuestion.defaultFeedback,\n );\n\n let choices = (normalizedQuestion.choices || []).map(prepareChoice(normalizedQuestion, env, defaultFeedback));\n\n const lockChoiceOrder = lockChoices(normalizedQuestion, session, env);\n\n if (!lockChoiceOrder) {\n choices = await getShuffledChoices(choices, session, updateSession, 'value');\n }\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,\n choicesLayout: normalizedQuestion.choicesLayout,\n gridColumns: normalizedQuestion.gridColumns,\n choiceMode: normalizedQuestion.choiceMode,\n keyMode: normalizedQuestion.choicePrefix,\n choices,\n responseCorrect: env.mode === 'evaluate' ? isResponseCorrect(normalizedQuestion, session) : undefined,\n language: normalizedQuestion.language,\n extraCSSRules: normalizedQuestion.extraCSSRules,\n fontSizeFactor: normalizedQuestion.fontSizeFactor,\n isSelectionButtonBelow: normalizedQuestion.isSelectionButtonBelow,\n selectedAnswerBackgroundColor: normalizedQuestion.selectedAnswerBackgroundColor || 'initial',\n minSelections: normalizedQuestion.minSelections,\n maxSelections: normalizedQuestion.maxSelections,\n autoplayAudioEnabled: normalizedQuestion.autoplayAudioEnabled,\n };\n\n const { role, mode } = env || {};\n\n if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {\n out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled\n ? normalizedQuestion.teacherInstructions\n : null;\n } else {\n out.teacherInstructions = null;\n }\n\n return out;\n}\n\nexport const getScore = (config, session) => {\n if (!session || isEmpty(session)) {\n return 0;\n }\n\n const selectedChoices = session.value || [];\n const correctChoices = (config.choices || []).filter((ch) => ch.correct);\n\n let score = selectedChoices.reduce(\n (acc, selectedChoice) => acc + (correctChoices.find((ch) => ch.value === selectedChoice) ? 1 : 0),\n 0,\n );\n\n if (correctChoices.length < selectedChoices.length) {\n score -= selectedChoices.length - correctChoices.length;\n\n if (score < 0) {\n score = 0;\n }\n }\n\n const str = correctChoices.length ? score / correctChoices.length : 0;\n\n return parseFloat(str.toFixed(2));\n};\n\n/**\n *\n * The score is partial by default for checkbox mode, allOrNothing for radio mode.\n * To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring = false. the value in `env` will\n * override the value in `model`.\n * @param {Object} model - the main model\n * @param {*} session\n * @param {Object} env\n */\nexport function outcome(model, session, env) {\n return new Promise((resolve) => {\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n } else {\n const partialScoringEnabled = partialScoring.enabled(model, env) && model.choiceMode !== 'radio';\n const score = getScore(model, session);\n\n resolve({ score: partialScoringEnabled ? score : score === 1 ? 1 : 0, empty: false });\n }\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { choices } = question || { choices: [] };\n\n resolve({\n id: '1',\n value: choices.filter((c) => c.correct).map((c) => c.value),\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags\nconst getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');\n\n// remove all html tags except img and iframe\nconst getContent = (html) => (html || '').replace(/(<(?!img|iframe)([^>]+)>)/gi, '');\n\nexport const validate = (model = {}, config = {}) => {\n const { choices } = model;\n const { minAnswerChoices = 2, maxAnswerChoices } = config;\n const reversedChoices = [...(choices || [])].reverse();\n const choicesErrors = {};\n const rationaleErrors = {};\n const errors = {};\n\n ['teacherInstructions', 'prompt'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n let hasCorrectResponse = false;\n\n reversedChoices.forEach((choice, index) => {\n const { correct, value, label, rationale } = choice;\n\n if (correct) {\n hasCorrectResponse = true;\n }\n\n if (!getContent(label)) {\n choicesErrors[value] = 'Content should not be empty.';\n } else {\n const identicalAnswer = reversedChoices.slice(index + 1).some((c) => c.label === label);\n\n if (identicalAnswer) {\n choicesErrors[value] = 'Content should be unique.';\n }\n }\n\n if (config.rationale?.required && !getContent(rationale)) {\n rationaleErrors[value] = 'This field is required.';\n }\n });\n\n const nbOfChoices = (choices || []).length;\n\n if (nbOfChoices < minAnswerChoices) {\n errors.answerChoices = `There should be at least ${minAnswerChoices} choices defined.`;\n } else if (nbOfChoices > maxAnswerChoices) {\n errors.answerChoices = `No more than ${maxAnswerChoices} choices should be defined.`;\n }\n\n if (!hasCorrectResponse) {\n errors.correctResponse = 'No correct response defined.';\n }\n\n if (!isEmpty(choicesErrors)) {\n errors.choices = choicesErrors;\n }\n\n if (!isEmpty(rationaleErrors)) {\n errors.rationale = rationaleErrors;\n }\n\n return errors;\n};\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["prepareChoice","model","env","defaultFeedback","choice","role","mode","out","label","value","rationale","rationaleEnabled","correct","feedbackEnabled","feedbackType","feedback","type","createDefaultModel","Promise","resolve","defaults","normalize","question","verticalMode","choicesLayout","questionProps","session","updateSession","normalizedQuestion","Object","assign","incorrect","choices","map","lockChoiceOrder","disabled","prompt","promptEnabled","gridColumns","choiceMode","keyMode","choicePrefix","responseCorrect","undefined","language","extraCSSRules","fontSizeFactor","isSelectionButtonBelow","selectedAnswerBackgroundColor","minSelections","maxSelections","autoplayAudioEnabled","completeAudioEnabled","teacherInstructions","teacherInstructionsEnabled","getScore","config","selectedChoices","correctChoices","filter","ch","score","reduce","acc","selectedChoice","find","length","str","parseFloat","toFixed","outcome","empty","partialScoringEnabled","partialScoring","enabled","createCorrectResponseSession","id","c","getInnerText","html","replaceAll","getContent","replace","validate","minAnswerChoices","maxAnswerChoices","reversedChoices","reverse","choicesErrors","rationaleErrors","errors","forEach","field","required","hasCorrectResponse","index","identicalAnswer","slice","some","nbOfChoices","answerChoices","correctResponse"],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport isEmpty from 'lodash/isEmpty';\nimport { isResponseCorrect } from './utils';\nimport defaults from './defaults';\nimport { lockChoices, partialScoring, getShuffledChoices } from '@pie-lib/pie-toolbox/controller-utils';\n\nconst prepareChoice = (model, env, defaultFeedback) => (choice) => {\n const { role, mode } = env || {};\n const out = {\n label: choice.label,\n value: choice.value,\n };\n\n if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {\n out.rationale = model.rationaleEnabled ? choice.rationale : null;\n } else {\n out.rationale = null;\n }\n\n if (mode === 'evaluate') {\n out.correct = !!choice.correct;\n\n if (model.feedbackEnabled) {\n const feedbackType = (choice.feedback && choice.feedback.type) || 'none';\n\n if (feedbackType === 'default') {\n out.feedback = defaultFeedback[choice.correct ? 'correct' : 'incorrect'];\n } else if (feedbackType === 'custom') {\n out.feedback = choice.feedback.value;\n }\n }\n }\n\n return out;\n};\n\nexport function createDefaultModel(model = {}) {\n return new Promise((resolve) => resolve({ ...defaults, ...model }));\n}\n\nexport const normalize = (question) => {\n const { verticalMode, choicesLayout, ...questionProps } = question || {};\n\n return {\n ...defaults,\n ...questionProps,\n // This is used for offering support for old models which have the property verticalMode\n // Same thing is set in authoring : packages/multiple-choice/configure/src/index.jsx - createDefaultModel\n choicesLayout: choicesLayout || (verticalMode === false && 'horizontal') || defaults.choicesLayout,\n };\n};\n\n/**\n *\n * @param {*} question\n * @param {*} session\n * @param {*} env\n * @param {*} updateSession - optional - a function that will set the properties passed into it on the session.\n */\nexport async function model(question, session, env, updateSession) {\n const normalizedQuestion = normalize(question);\n\n const defaultFeedback = Object.assign(\n { correct: 'Correct', incorrect: 'Incorrect' },\n normalizedQuestion.defaultFeedback,\n );\n\n let choices = (normalizedQuestion.choices || []).map(prepareChoice(normalizedQuestion, env, defaultFeedback));\n\n const lockChoiceOrder = lockChoices(normalizedQuestion, session, env);\n\n if (!lockChoiceOrder) {\n choices = await getShuffledChoices(choices, session, updateSession, 'value');\n }\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,\n choicesLayout: normalizedQuestion.choicesLayout,\n gridColumns: normalizedQuestion.gridColumns,\n choiceMode: normalizedQuestion.choiceMode,\n keyMode: normalizedQuestion.choicePrefix,\n choices,\n responseCorrect: env.mode === 'evaluate' ? isResponseCorrect(normalizedQuestion, session) : undefined,\n language: normalizedQuestion.language,\n extraCSSRules: normalizedQuestion.extraCSSRules,\n fontSizeFactor: normalizedQuestion.fontSizeFactor,\n isSelectionButtonBelow: normalizedQuestion.isSelectionButtonBelow,\n selectedAnswerBackgroundColor: normalizedQuestion.selectedAnswerBackgroundColor || 'initial',\n minSelections: normalizedQuestion.minSelections,\n maxSelections: normalizedQuestion.maxSelections,\n autoplayAudioEnabled: normalizedQuestion.autoplayAudioEnabled,\n completeAudioEnabled: normalizedQuestion.completeAudioEnabled,\n };\n\n const { role, mode } = env || {};\n\n if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {\n out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled\n ? normalizedQuestion.teacherInstructions\n : null;\n } else {\n out.teacherInstructions = null;\n }\n\n return out;\n}\n\nexport const getScore = (config, session) => {\n if (!session || isEmpty(session)) {\n return 0;\n }\n\n const selectedChoices = session.value || [];\n const correctChoices = (config.choices || []).filter((ch) => ch.correct);\n\n let score = selectedChoices.reduce(\n (acc, selectedChoice) => acc + (correctChoices.find((ch) => ch.value === selectedChoice) ? 1 : 0),\n 0,\n );\n\n if (correctChoices.length < selectedChoices.length) {\n score -= selectedChoices.length - correctChoices.length;\n\n if (score < 0) {\n score = 0;\n }\n }\n\n const str = correctChoices.length ? score / correctChoices.length : 0;\n\n return parseFloat(str.toFixed(2));\n};\n\n/**\n *\n * The score is partial by default for checkbox mode, allOrNothing for radio mode.\n * To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring = false. the value in `env` will\n * override the value in `model`.\n * @param {Object} model - the main model\n * @param {*} session\n * @param {Object} env\n */\nexport function outcome(model, session, env) {\n return new Promise((resolve) => {\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n } else {\n const partialScoringEnabled = partialScoring.enabled(model, env) && model.choiceMode !== 'radio';\n const score = getScore(model, session);\n\n resolve({ score: partialScoringEnabled ? score : score === 1 ? 1 : 0, empty: false });\n }\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { choices } = question || { choices: [] };\n\n resolve({\n id: '1',\n value: choices.filter((c) => c.correct).map((c) => c.value),\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags\nconst getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');\n\n// remove all html tags except img and iframe\nconst getContent = (html) => (html || '').replace(/(<(?!img|iframe)([^>]+)>)/gi, '');\n\nexport const validate = (model = {}, config = {}) => {\n const { choices } = model;\n const { minAnswerChoices = 2, maxAnswerChoices } = config;\n const reversedChoices = [...(choices || [])].reverse();\n const choicesErrors = {};\n const rationaleErrors = {};\n const errors = {};\n\n ['teacherInstructions', 'prompt'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n let hasCorrectResponse = false;\n\n reversedChoices.forEach((choice, index) => {\n const { correct, value, label, rationale } = choice;\n\n if (correct) {\n hasCorrectResponse = true;\n }\n\n if (!getContent(label)) {\n choicesErrors[value] = 'Content should not be empty.';\n } else {\n const identicalAnswer = reversedChoices.slice(index + 1).some((c) => c.label === label);\n\n if (identicalAnswer) {\n choicesErrors[value] = 'Content should be unique.';\n }\n }\n\n if (config.rationale?.required && !getContent(rationale)) {\n rationaleErrors[value] = 'This field is required.';\n }\n });\n\n const nbOfChoices = (choices || []).length;\n\n if (nbOfChoices < minAnswerChoices) {\n errors.answerChoices = `There should be at least ${minAnswerChoices} choices defined.`;\n } else if (nbOfChoices > maxAnswerChoices) {\n errors.answerChoices = `No more than ${maxAnswerChoices} choices should be defined.`;\n }\n\n if (!hasCorrectResponse) {\n errors.correctResponse = 'No correct response defined.';\n }\n\n if (!isEmpty(choicesErrors)) {\n errors.choices = choicesErrors;\n }\n\n if (!isEmpty(rationaleErrors)) {\n errors.rationale = rationaleErrors;\n }\n\n return errors;\n};\n"],"file":"index.js"}
|
package/docs/pie-schema.json
CHANGED
|
@@ -224,6 +224,11 @@
|
|
|
224
224
|
"type": "boolean",
|
|
225
225
|
"title": "autoplayAudioEnabled"
|
|
226
226
|
},
|
|
227
|
+
"completeAudioEnabled": {
|
|
228
|
+
"description": "Indicates if the audio should reach the end before the item can be marked as 'complete'",
|
|
229
|
+
"type": "boolean",
|
|
230
|
+
"title": "completeAudioEnabled"
|
|
231
|
+
},
|
|
227
232
|
"id": {
|
|
228
233
|
"description": "Identifier to identify the Pie Element in html markup, Must be unique within a pie item config.",
|
|
229
234
|
"type": "string",
|
package/docs/pie-schema.json.md
CHANGED
|
@@ -195,6 +195,10 @@ Indicates font size adjustment factor
|
|
|
195
195
|
|
|
196
196
|
Indicates if the audio for the prompt should autoplay
|
|
197
197
|
|
|
198
|
+
# `completeAudioEnabled` (boolean)
|
|
199
|
+
|
|
200
|
+
Indicates if the audio should reach the end before the item can be marked as 'complete'
|
|
201
|
+
|
|
198
202
|
# `id` (string, required)
|
|
199
203
|
|
|
200
204
|
Identifier to identify the Pie Element in html markup, Must be unique within a pie item config.
|
package/lib/index.js
CHANGED
|
@@ -46,7 +46,11 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
|
|
|
46
46
|
var log = (0, _debug["default"])('pie-ui:multiple-choice');
|
|
47
47
|
|
|
48
48
|
var isComplete = function isComplete(session, model, audioComplete) {
|
|
49
|
-
|
|
49
|
+
var _ref = model || {},
|
|
50
|
+
autoplayAudioEnabled = _ref.autoplayAudioEnabled,
|
|
51
|
+
completeAudioEnabled = _ref.completeAudioEnabled;
|
|
52
|
+
|
|
53
|
+
if (autoplayAudioEnabled && completeAudioEnabled && !audioComplete) {
|
|
50
54
|
return false;
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -54,11 +58,11 @@ var isComplete = function isComplete(session, model, audioComplete) {
|
|
|
54
58
|
return false;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
var
|
|
58
|
-
choiceMode =
|
|
59
|
-
|
|
60
|
-
minSelections =
|
|
61
|
-
maxSelections =
|
|
61
|
+
var _ref2 = model || {},
|
|
62
|
+
choiceMode = _ref2.choiceMode,
|
|
63
|
+
_ref2$minSelections = _ref2.minSelections,
|
|
64
|
+
minSelections = _ref2$minSelections === void 0 ? 1 : _ref2$minSelections,
|
|
65
|
+
maxSelections = _ref2.maxSelections;
|
|
62
66
|
|
|
63
67
|
var selections = session.value.length || 0;
|
|
64
68
|
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["log","isComplete","session","model","audioComplete","autoplayAudioEnabled","value","choiceMode","minSelections","maxSelections","selections","length","MultipleChoice","_model","_session","_rerender","element","React","createElement","Main","onChoiceChanged","_onChange","bind","onShowCorrectToggle","setAttribute","setLangAttribute","ReactDOM","render","leading","trailing","_dispatchResponseChanged","dispatchEvent","SessionChangedEvent","tagName","toLowerCase","_dispatchModelSet","ModelSetEvent","undefined","language","lang","slice","s","data","info","document","id","innerHTML","Object","assign","style","position","bottom","left","transform","backgroundColor","color","padding","borderRadius","boxShadow","zIndex","observer","MutationObserver","mutationsList","forEach","mutation","type","audio","querySelector","_createAudioInfoToast","enableAudio","play","removeChild","removeEventListener","setTimeout","paused","appendChild","addEventListener","handlePlaying","handleEnded","disconnect","observe","childList","subtree","HTMLElement"],"mappings":"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","sourcesContent":["import Main from './main';\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport debounce from 'lodash/debounce';\nimport debug from 'debug';\nimport { ModelSetEvent, SessionChangedEvent } from '@pie-framework/pie-player-events';\nimport { renderMath } from '@pie-lib/pie-toolbox/math-rendering';\nimport { updateSessionValue } from './session-updater';\n\nconst log = debug('pie-ui:multiple-choice');\n\nexport const isComplete = (session, model, audioComplete) => {\n if (model.autoplayAudioEnabled && !audioComplete) {\n return false;\n }\n\n if (!session || !session.value) {\n return false;\n }\n\n const { choiceMode, minSelections = 1, maxSelections } = model || {};\n const selections = session.value.length || 0;\n\n if (choiceMode === 'radio') {\n return !!selections;\n }\n\n if (selections < minSelections || selections > maxSelections) {\n return false;\n }\n\n return true;\n};\n\nexport default class MultipleChoice extends HTMLElement {\n constructor() {\n super();\n this._model = null;\n this._session = null;\n this.audioComplete = false;\n\n this._rerender = debounce(\n () => {\n if (this._model && this._session) {\n var element = React.createElement(Main, {\n model: this._model,\n session: this._session,\n onChoiceChanged: this._onChange.bind(this),\n onShowCorrectToggle: this.onShowCorrectToggle.bind(this),\n });\n\n //TODO: aria-label is set in the _rerender because we need to change it when the model.choiceMode is updated. Consider revisiting the placement of the aria-label setting in the _rerender\n this.setAttribute(\n 'aria-label',\n this._model.choiceMode === 'radio' ? 'Multiple Choice Question' : 'Multiple Correct Answer Question',\n );\n this.setAttribute('role', 'region');\n this.setLangAttribute();\n\n ReactDOM.render(element, this, () => {\n log('render complete - render math');\n renderMath(this);\n });\n } else {\n log('skip');\n }\n },\n 50,\n { leading: false, trailing: true },\n );\n\n this._dispatchResponseChanged = debounce(() => {\n this.dispatchEvent(\n new SessionChangedEvent(this.tagName.toLowerCase(), isComplete(this._session, this._model, this.audioComplete)),\n );\n });\n\n this._dispatchModelSet = debounce(\n () => {\n this.dispatchEvent(\n new ModelSetEvent(\n this.tagName.toLowerCase(),\n isComplete(this._session, this._model),\n this._model !== undefined,\n ),\n );\n },\n 50,\n { leading: false, trailing: true },\n );\n }\n\n onShowCorrectToggle() {\n renderMath(this);\n }\n\n setLangAttribute() {\n const language = this._model && typeof this._model.language ? this._model.language : '';\n const lang = language ? language.slice(0, 2) : 'en';\n this.setAttribute('lang', lang);\n }\n\n set model(s) {\n this._model = s;\n this._rerender();\n this._dispatchModelSet();\n }\n\n get session() {\n return this._session;\n }\n\n set session(s) {\n this._session = s;\n this._rerender();\n //TODO: remove this session-changed should only be emit on user change\n this._dispatchResponseChanged();\n }\n\n _onChange(data) {\n updateSessionValue(this._session, this._model.choiceMode, data);\n this._dispatchResponseChanged();\n this._rerender();\n }\n\n _createAudioInfoToast() {\n const info = document.createElement('div');\n info.id = 'play-audio-info';\n info.innerHTML =\n 'Click anywhere to enable audio autoplay. Browser restrictions require user interaction to play audio.';\n Object.assign(info.style, {\n position: 'fixed',\n bottom: '20px',\n left: '50%',\n transform: 'translateX(-50%)',\n backgroundColor: '#333',\n color: '#fff',\n padding: '10px 20px',\n borderRadius: '5px',\n boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',\n zIndex: '1000',\n });\n\n return info;\n }\n\n connectedCallback() {\n this._rerender();\n\n if (this._model && !this._model.autoplayAudioEnabled) {\n return;\n }\n\n const observer = new MutationObserver((mutationsList, observer) => {\n mutationsList.forEach((mutation) => {\n if (mutation.type === 'childList') {\n const audio = this.querySelector('audio[autoplay]');\n\n if (!audio) return;\n\n const info = this._createAudioInfoToast();\n const enableAudio = () => {\n if (this.querySelector('#play-audio-info')) {\n audio.play();\n this.removeChild(info);\n }\n\n document.removeEventListener('click', enableAudio);\n };\n\n // if the audio is paused, it means the user has not interacted with the page yet and the audio will not play\n // FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked\n setTimeout(() => {\n if (audio.paused && !this.querySelector('#play-audio-info')) {\n // add info message as a toast to enable audio playback\n this.appendChild(info);\n document.addEventListener('click', enableAudio);\n }\n }, 500);\n\n // we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering\n const handlePlaying = () => {\n const info = this.querySelector('#play-audio-info');\n\n if (info) {\n this.removeChild(info);\n }\n\n audio.removeEventListener('playing', handlePlaying);\n };\n\n audio.addEventListener('playing', handlePlaying);\n\n // we need to listen for the ended event to update the isComplete state\n const handleEnded = () => {\n this.audioComplete = true;\n this._dispatchResponseChanged();\n audio.removeEventListener('ended', handleEnded);\n };\n\n audio.addEventListener('ended', handleEnded);\n\n observer.disconnect();\n }\n });\n });\n\n observer.observe(this, { childList: true, subtree: true });\n }\n}\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["log","isComplete","session","model","audioComplete","autoplayAudioEnabled","completeAudioEnabled","value","choiceMode","minSelections","maxSelections","selections","length","MultipleChoice","_model","_session","_rerender","element","React","createElement","Main","onChoiceChanged","_onChange","bind","onShowCorrectToggle","setAttribute","setLangAttribute","ReactDOM","render","leading","trailing","_dispatchResponseChanged","dispatchEvent","SessionChangedEvent","tagName","toLowerCase","_dispatchModelSet","ModelSetEvent","undefined","language","lang","slice","s","data","info","document","id","innerHTML","Object","assign","style","position","bottom","left","transform","backgroundColor","color","padding","borderRadius","boxShadow","zIndex","observer","MutationObserver","mutationsList","forEach","mutation","type","audio","querySelector","_createAudioInfoToast","enableAudio","play","removeChild","removeEventListener","setTimeout","paused","appendChild","addEventListener","handlePlaying","handleEnded","disconnect","observe","childList","subtree","HTMLElement"],"mappings":"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","sourcesContent":["import Main from './main';\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport debounce from 'lodash/debounce';\nimport debug from 'debug';\nimport { ModelSetEvent, SessionChangedEvent } from '@pie-framework/pie-player-events';\nimport { renderMath } from '@pie-lib/pie-toolbox/math-rendering';\nimport { updateSessionValue } from './session-updater';\n\nconst log = debug('pie-ui:multiple-choice');\n\nexport const isComplete = (session, model, audioComplete) => {\n const { autoplayAudioEnabled, completeAudioEnabled } = model || {};\n\n if (autoplayAudioEnabled && completeAudioEnabled && !audioComplete) {\n return false;\n }\n\n if (!session || !session.value) {\n return false;\n }\n\n const { choiceMode, minSelections = 1, maxSelections } = model || {};\n const selections = session.value.length || 0;\n\n if (choiceMode === 'radio') {\n return !!selections;\n }\n\n if (selections < minSelections || selections > maxSelections) {\n return false;\n }\n\n return true;\n};\n\nexport default class MultipleChoice extends HTMLElement {\n constructor() {\n super();\n this._model = null;\n this._session = null;\n this.audioComplete = false;\n\n this._rerender = debounce(\n () => {\n if (this._model && this._session) {\n var element = React.createElement(Main, {\n model: this._model,\n session: this._session,\n onChoiceChanged: this._onChange.bind(this),\n onShowCorrectToggle: this.onShowCorrectToggle.bind(this),\n });\n\n //TODO: aria-label is set in the _rerender because we need to change it when the model.choiceMode is updated. Consider revisiting the placement of the aria-label setting in the _rerender\n this.setAttribute(\n 'aria-label',\n this._model.choiceMode === 'radio' ? 'Multiple Choice Question' : 'Multiple Correct Answer Question',\n );\n this.setAttribute('role', 'region');\n this.setLangAttribute();\n\n ReactDOM.render(element, this, () => {\n log('render complete - render math');\n renderMath(this);\n });\n } else {\n log('skip');\n }\n },\n 50,\n { leading: false, trailing: true },\n );\n\n this._dispatchResponseChanged = debounce(() => {\n this.dispatchEvent(\n new SessionChangedEvent(this.tagName.toLowerCase(), isComplete(this._session, this._model, this.audioComplete)),\n );\n });\n\n this._dispatchModelSet = debounce(\n () => {\n this.dispatchEvent(\n new ModelSetEvent(\n this.tagName.toLowerCase(),\n isComplete(this._session, this._model),\n this._model !== undefined,\n ),\n );\n },\n 50,\n { leading: false, trailing: true },\n );\n }\n\n onShowCorrectToggle() {\n renderMath(this);\n }\n\n setLangAttribute() {\n const language = this._model && typeof this._model.language ? this._model.language : '';\n const lang = language ? language.slice(0, 2) : 'en';\n this.setAttribute('lang', lang);\n }\n\n set model(s) {\n this._model = s;\n this._rerender();\n this._dispatchModelSet();\n }\n\n get session() {\n return this._session;\n }\n\n set session(s) {\n this._session = s;\n this._rerender();\n //TODO: remove this session-changed should only be emit on user change\n this._dispatchResponseChanged();\n }\n\n _onChange(data) {\n updateSessionValue(this._session, this._model.choiceMode, data);\n this._dispatchResponseChanged();\n this._rerender();\n }\n\n _createAudioInfoToast() {\n const info = document.createElement('div');\n info.id = 'play-audio-info';\n info.innerHTML =\n 'Click anywhere to enable audio autoplay. Browser restrictions require user interaction to play audio.';\n Object.assign(info.style, {\n position: 'fixed',\n bottom: '20px',\n left: '50%',\n transform: 'translateX(-50%)',\n backgroundColor: '#333',\n color: '#fff',\n padding: '10px 20px',\n borderRadius: '5px',\n boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',\n zIndex: '1000',\n });\n\n return info;\n }\n\n connectedCallback() {\n this._rerender();\n\n if (this._model && !this._model.autoplayAudioEnabled) {\n return;\n }\n\n const observer = new MutationObserver((mutationsList, observer) => {\n mutationsList.forEach((mutation) => {\n if (mutation.type === 'childList') {\n const audio = this.querySelector('audio[autoplay]');\n\n if (!audio) return;\n\n const info = this._createAudioInfoToast();\n const enableAudio = () => {\n if (this.querySelector('#play-audio-info')) {\n audio.play();\n this.removeChild(info);\n }\n\n document.removeEventListener('click', enableAudio);\n };\n\n // if the audio is paused, it means the user has not interacted with the page yet and the audio will not play\n // FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked\n setTimeout(() => {\n if (audio.paused && !this.querySelector('#play-audio-info')) {\n // add info message as a toast to enable audio playback\n this.appendChild(info);\n document.addEventListener('click', enableAudio);\n }\n }, 500);\n\n // we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering\n const handlePlaying = () => {\n const info = this.querySelector('#play-audio-info');\n\n if (info) {\n this.removeChild(info);\n }\n\n audio.removeEventListener('playing', handlePlaying);\n };\n\n audio.addEventListener('playing', handlePlaying);\n\n // we need to listen for the ended event to update the isComplete state\n const handleEnded = () => {\n this.audioComplete = true;\n this._dispatchResponseChanged();\n audio.removeEventListener('ended', handleEnded);\n };\n\n audio.addEventListener('ended', handleEnded);\n\n observer.disconnect();\n }\n });\n });\n\n observer.observe(this, { childList: true, subtree: true });\n }\n}\n"],"file":"index.js"}
|
package/module/controller.js
CHANGED
|
@@ -20705,6 +20705,7 @@ async function model(question, session, env, updateSession) {
|
|
|
20705
20705
|
minSelections: normalizedQuestion.minSelections,
|
|
20706
20706
|
maxSelections: normalizedQuestion.maxSelections,
|
|
20707
20707
|
autoplayAudioEnabled: normalizedQuestion.autoplayAudioEnabled,
|
|
20708
|
+
completeAudioEnabled: normalizedQuestion.completeAudioEnabled,
|
|
20708
20709
|
};
|
|
20709
20710
|
|
|
20710
20711
|
const { role, mode } = env || {};
|
package/module/element.js
CHANGED
|
@@ -13069,7 +13069,8 @@ const debug = _dll_debug;
|
|
|
13069
13069
|
const {renderMath: renderMath} = _dll_pie_lib__pie_toolbox_math_rendering;
|
|
13070
13070
|
const log = debug('pie-ui:multiple-choice');
|
|
13071
13071
|
const isComplete = (session, model, audioComplete) => {
|
|
13072
|
-
|
|
13072
|
+
const {autoplayAudioEnabled, completeAudioEnabled} = model || ({});
|
|
13073
|
+
if (autoplayAudioEnabled && completeAudioEnabled && !audioComplete) {
|
|
13073
13074
|
return false;
|
|
13074
13075
|
}
|
|
13075
13076
|
if (!session || !session.value) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-element/multiple-choice",
|
|
3
3
|
"repository": "pie-framework/pie-elements",
|
|
4
|
-
"version": "9.9.2-next.
|
|
4
|
+
"version": "9.9.2-next.6+29d0b9d28",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"react-test-renderer": "^16.3.2",
|
|
20
20
|
"react-transition-group": "^2.3.1"
|
|
21
21
|
},
|
|
22
|
-
"gitHead": "
|
|
22
|
+
"gitHead": "29d0b9d2881c794cb6416e8809da4eae63f147d7",
|
|
23
23
|
"scripts": {
|
|
24
24
|
"postpublish": "../../scripts/postpublish"
|
|
25
25
|
},
|