@pie-element/image-cloze-association 6.7.2-next.3 → 6.7.2-next.31
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/docs/pie-schema.json +10 -0
- package/docs/pie-schema.json.md +8 -0
- package/lib/index.js +108 -2
- package/lib/index.js.map +1 -1
- package/lib/root.js +8 -3
- package/lib/root.js.map +1 -1
- package/package.json +2 -2
- package/src/index.js +102 -1
- package/src/root.jsx +6 -1
package/docs/pie-schema.json
CHANGED
|
@@ -241,6 +241,16 @@
|
|
|
241
241
|
"type": "number",
|
|
242
242
|
"title": "fontSizeFactor"
|
|
243
243
|
},
|
|
244
|
+
"autoplayAudioEnabled": {
|
|
245
|
+
"description": "Indicates if the audio for the prompt should autoplay",
|
|
246
|
+
"type": "boolean",
|
|
247
|
+
"title": "autoplayAudioEnabled"
|
|
248
|
+
},
|
|
249
|
+
"completeAudioEnabled": {
|
|
250
|
+
"description": "Indicates if the audio should reach the end before the item can be marked as 'complete'",
|
|
251
|
+
"type": "boolean",
|
|
252
|
+
"title": "completeAudioEnabled"
|
|
253
|
+
},
|
|
244
254
|
"id": {
|
|
245
255
|
"description": "Identifier to identify the Pie Element in html markup, Must be unique within a pie item config.",
|
|
246
256
|
"type": "string",
|
package/docs/pie-schema.json.md
CHANGED
|
@@ -192,6 +192,14 @@ Indicates the padding of the image drop target
|
|
|
192
192
|
|
|
193
193
|
Indicates font size adjustment factor
|
|
194
194
|
|
|
195
|
+
# `autoplayAudioEnabled` (boolean)
|
|
196
|
+
|
|
197
|
+
Indicates if the audio for the prompt should autoplay
|
|
198
|
+
|
|
199
|
+
# `completeAudioEnabled` (boolean)
|
|
200
|
+
|
|
201
|
+
Indicates if the audio should reach the end before the item can be marked as 'complete'
|
|
202
|
+
|
|
195
203
|
# `id` (string, required)
|
|
196
204
|
|
|
197
205
|
Identifier to identify the Pie Element in html markup, Must be unique within a pie item config.
|
package/lib/index.js
CHANGED
|
@@ -54,6 +54,14 @@ var ImageClozeAssociation = /*#__PURE__*/function (_HTMLElement) {
|
|
|
54
54
|
}, {
|
|
55
55
|
key: "isComplete",
|
|
56
56
|
value: function isComplete() {
|
|
57
|
+
var _ref = this._model || {},
|
|
58
|
+
autoplayAudioEnabled = _ref.autoplayAudioEnabled,
|
|
59
|
+
completeAudioEnabled = _ref.completeAudioEnabled;
|
|
60
|
+
|
|
61
|
+
if (autoplayAudioEnabled && completeAudioEnabled && !this.audioComplete) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
57
65
|
if (!this._session || !this._session.answers) {
|
|
58
66
|
return false;
|
|
59
67
|
}
|
|
@@ -82,19 +90,117 @@ var ImageClozeAssociation = /*#__PURE__*/function (_HTMLElement) {
|
|
|
82
90
|
key: "updateAnswer",
|
|
83
91
|
value: function updateAnswer(data) {
|
|
84
92
|
this._session.answers = data;
|
|
93
|
+
this._session.selector = 'Mouse';
|
|
85
94
|
this.dispatchEvent(new _piePlayerEvents.SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));
|
|
86
95
|
|
|
87
96
|
this._render();
|
|
88
97
|
}
|
|
98
|
+
}, {
|
|
99
|
+
key: "_createAudioInfoToast",
|
|
100
|
+
value: function _createAudioInfoToast() {
|
|
101
|
+
var info = document.createElement('div');
|
|
102
|
+
info.id = 'play-audio-info';
|
|
103
|
+
Object.assign(info.style, {
|
|
104
|
+
position: 'absolute',
|
|
105
|
+
top: 0,
|
|
106
|
+
width: '100%',
|
|
107
|
+
height: '100%',
|
|
108
|
+
display: 'flex',
|
|
109
|
+
justifyContent: 'center',
|
|
110
|
+
alignItems: 'center',
|
|
111
|
+
background: 'white',
|
|
112
|
+
zIndex: '1000'
|
|
113
|
+
});
|
|
114
|
+
var img = document.createElement('img');
|
|
115
|
+
img.src = 'https://student.assessment.renaissance.com/ce/quizenginecap/assets/img/playAppsSel.gif';
|
|
116
|
+
img.alt = 'Click anywhere to enable audio autoplay';
|
|
117
|
+
img.width = 500;
|
|
118
|
+
img.height = 300;
|
|
119
|
+
info.appendChild(img);
|
|
120
|
+
return info;
|
|
121
|
+
}
|
|
89
122
|
}, {
|
|
90
123
|
key: "connectedCallback",
|
|
91
124
|
value: function connectedCallback() {
|
|
125
|
+
var _this = this;
|
|
126
|
+
|
|
92
127
|
this._render();
|
|
128
|
+
|
|
129
|
+
if (this._model && !this._model.autoplayAudioEnabled) {
|
|
130
|
+
return;
|
|
131
|
+
} // Observation: audio in Chrome will have the autoplay attribute,
|
|
132
|
+
// while other browsers will not have the autoplay attribute and will need a user interaction to play the audio
|
|
133
|
+
// This workaround fixes the issue of audio being cached and played on any user interaction in Safari and Firefox
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
var observer = new MutationObserver(function (mutationsList, observer) {
|
|
137
|
+
mutationsList.forEach(function (mutation) {
|
|
138
|
+
if (mutation.type === 'childList') {
|
|
139
|
+
var audio = _this.querySelector('audio');
|
|
140
|
+
|
|
141
|
+
var isInsidePrompt = audio && audio.closest('#preview-prompt');
|
|
142
|
+
if (audio && !isInsidePrompt) return;
|
|
143
|
+
if (!audio) return;
|
|
144
|
+
|
|
145
|
+
var info = _this._createAudioInfoToast();
|
|
146
|
+
|
|
147
|
+
var container = _this.querySelector('[class*="main"]');
|
|
148
|
+
|
|
149
|
+
var enableAudio = function enableAudio() {
|
|
150
|
+
if (_this.querySelector('#play-audio-info')) {
|
|
151
|
+
audio.play();
|
|
152
|
+
container.removeChild(info);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
document.removeEventListener('click', enableAudio);
|
|
156
|
+
}; // if the audio is paused, it means the user has not interacted with the page yet and the audio will not play
|
|
157
|
+
// FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
setTimeout(function () {
|
|
161
|
+
if (audio.paused && !_this.querySelector('#play-audio-info')) {
|
|
162
|
+
// add info message as a toast to enable audio playback
|
|
163
|
+
container.appendChild(info);
|
|
164
|
+
document.addEventListener('click', enableAudio);
|
|
165
|
+
} else {
|
|
166
|
+
document.removeEventListener('click', enableAudio);
|
|
167
|
+
}
|
|
168
|
+
}, 500); // we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering
|
|
169
|
+
|
|
170
|
+
var handlePlaying = function handlePlaying() {
|
|
171
|
+
var info = _this.querySelector('#play-audio-info');
|
|
172
|
+
|
|
173
|
+
if (info) {
|
|
174
|
+
_this.removeChild(info);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
audio.removeEventListener('playing', handlePlaying);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
audio.addEventListener('playing', handlePlaying); // we need to listen for the ended event to update the isComplete state
|
|
181
|
+
|
|
182
|
+
var handleEnded = function handleEnded() {
|
|
183
|
+
_this.audioComplete = true;
|
|
184
|
+
|
|
185
|
+
_this.dispatchEvent(new _piePlayerEvents.SessionChangedEvent(_this.tagName.toLowerCase(), _this.isComplete()));
|
|
186
|
+
|
|
187
|
+
audio.removeEventListener('ended', handleEnded);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
audio.addEventListener('ended', handleEnded);
|
|
191
|
+
observer.disconnect();
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
observer.observe(this, {
|
|
196
|
+
childList: true,
|
|
197
|
+
subtree: true
|
|
198
|
+
});
|
|
93
199
|
}
|
|
94
200
|
}, {
|
|
95
201
|
key: "_render",
|
|
96
202
|
value: function _render() {
|
|
97
|
-
var
|
|
203
|
+
var _this2 = this;
|
|
98
204
|
|
|
99
205
|
if (this._model && this._session) {
|
|
100
206
|
var el = /*#__PURE__*/_react["default"].createElement(_root["default"], {
|
|
@@ -104,7 +210,7 @@ var ImageClozeAssociation = /*#__PURE__*/function (_HTMLElement) {
|
|
|
104
210
|
});
|
|
105
211
|
|
|
106
212
|
_reactDom["default"].render(el, this, function () {
|
|
107
|
-
(0, _mathRendering.renderMath)(
|
|
213
|
+
(0, _mathRendering.renderMath)(_this2);
|
|
108
214
|
});
|
|
109
215
|
}
|
|
110
216
|
}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["ImageClozeAssociation","m","_model","dispatchEvent","ModelSetEvent","tagName","toLowerCase","isComplete","_render","_session","answers","Array","isArray","length","s","data","SessionChangedEvent","el","React","createElement","ImageClozeAssociationComponent","model","session","updateAnswer","bind","ReactDOM","render","HTMLElement"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AAEA;;;;;;IAEqBA,qB;;;;;;;;;;;;SACnB,aAAUC,CAAV,EAAa;AACX,WAAKC,MAAL,GAAcD,CAAd;AAEA,WAAKE,aAAL,CAAmB,IAAIC,8BAAJ,CAAkB,KAAKC,OAAL,CAAaC,WAAb,EAAlB,EAA8C,KAAKC,UAAL,EAA9C,EAAiE,CAAC,CAAC,KAAKL,MAAxE,CAAnB;;AACA,WAAKM,OAAL;AACD;;;WAED,sBAAa;AACX,UAAI,CAAC,KAAKC,QAAN,IAAkB,CAAC,KAAKA,QAAL,CAAcC,OAArC,EAA8C;AAC5C,eAAO,KAAP;AACD;;AAED,UAAI,CAACC,KAAK,CAACC,OAAN,CAAc,KAAKH,QAAL,CAAcC,OAA5B,CAAL,EAA2C;AACzC,eAAO,KAAP;AACD;;AAED,aAAOC,KAAK,CAACC,OAAN,CAAc,KAAKH,QAAL,CAAcC,OAA5B,KAAwC,KAAKD,QAAL,CAAcC,OAAd,CAAsBG,MAAtB,GAA+B,CAA9E;AACD;;;SAWD,eAAc;AACZ,aAAO,KAAKJ,QAAZ;AACD,K;SAXD,aAAYK,CAAZ,EAAe;AACb,UAAIA,CAAC,IAAI,CAACA,CAAC,CAACJ,OAAZ,EAAqB;AACnBI,QAAAA,CAAC,CAACJ,OAAF,GAAY,EAAZ;AACD;;AAED,WAAKD,QAAL,GAAgBK,CAAhB;;AACA,WAAKN,OAAL;AACD;;;WAMD,sBAAaO,IAAb,EAAmB;AACjB,WAAKN,QAAL,CAAcC,OAAd,GAAwBK,IAAxB;AAEA,WAAKZ,aAAL,CAAmB,IAAIa,oCAAJ,CAAwB,KAAKX,OAAL,CAAaC,WAAb,EAAxB,EAAoD,KAAKC,UAAL,EAApD,CAAnB;;AAEA,WAAKC,OAAL;AACD;;;WAED,6BAAoB;AAClB,WAAKA,OAAL;AACD;;;WAED,mBAAU;AAAA;;AACR,UAAI,KAAKN,MAAL,IAAe,KAAKO,QAAxB,EAAkC;AAChC,YAAMQ,EAAE,gBAAGC,kBAAMC,aAAN,CAAoBC,gBAApB,EAAoD;AAC7DC,UAAAA,KAAK,EAAE,KAAKnB,MADiD;AAE7DoB,UAAAA,OAAO,EAAE,KAAKb,QAF+C;AAG7Dc,UAAAA,YAAY,EAAE,KAAKA,YAAL,CAAkBC,IAAlB,CAAuB,IAAvB;AAH+C,SAApD,CAAX;;AAMAC,6BAASC,MAAT,CAAgBT,EAAhB,EAAoB,IAApB,EAA0B,YAAM;AAC9B,yCAAW,KAAX;AACD,SAFD;AAGD;AACF;;;kDAzDgDU,W","sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { renderMath } from '@pie-lib/pie-toolbox/math-rendering';\nimport { ModelSetEvent, SessionChangedEvent } from '@pie-framework/pie-player-events';\n\nimport ImageClozeAssociationComponent from './root';\n\nexport default class ImageClozeAssociation extends HTMLElement {\n set model(m) {\n this._model = m;\n\n this.dispatchEvent(new ModelSetEvent(this.tagName.toLowerCase(), this.isComplete(), !!this._model));\n this._render();\n }\n\n isComplete() {\n if (!this._session || !this._session.answers) {\n return false;\n }\n\n if (!Array.isArray(this._session.answers)) {\n return false;\n }\n\n return Array.isArray(this._session.answers) && this._session.answers.length > 0;\n }\n\n set session(s) {\n if (s && !s.answers) {\n s.answers = [];\n }\n\n this._session = s;\n this._render();\n }\n\n get session() {\n return this._session;\n }\n\n updateAnswer(data) {\n this._session.answers = data;\n\n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));\n\n this._render();\n }\n\n connectedCallback() {\n this._render();\n }\n\n _render() {\n if (this._model && this._session) {\n const el = React.createElement(ImageClozeAssociationComponent, {\n model: this._model,\n session: this._session,\n updateAnswer: this.updateAnswer.bind(this),\n });\n\n ReactDOM.render(el, this, () => {\n renderMath(this);\n });\n }\n }\n}\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["ImageClozeAssociation","m","_model","dispatchEvent","ModelSetEvent","tagName","toLowerCase","isComplete","_render","autoplayAudioEnabled","completeAudioEnabled","audioComplete","_session","answers","Array","isArray","length","s","data","selector","SessionChangedEvent","info","document","createElement","id","Object","assign","style","position","top","width","height","display","justifyContent","alignItems","background","zIndex","img","src","alt","appendChild","observer","MutationObserver","mutationsList","forEach","mutation","type","audio","querySelector","isInsidePrompt","closest","_createAudioInfoToast","container","enableAudio","play","removeChild","removeEventListener","setTimeout","paused","addEventListener","handlePlaying","handleEnded","disconnect","observe","childList","subtree","el","React","ImageClozeAssociationComponent","model","session","updateAnswer","bind","ReactDOM","render","HTMLElement"],"mappings":"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","sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { renderMath } from '@pie-lib/pie-toolbox/math-rendering';\nimport { ModelSetEvent, SessionChangedEvent } from '@pie-framework/pie-player-events';\n\nimport ImageClozeAssociationComponent from './root';\n\nexport default class ImageClozeAssociation extends HTMLElement {\n set model(m) {\n this._model = m;\n\n this.dispatchEvent(new ModelSetEvent(this.tagName.toLowerCase(), this.isComplete(), !!this._model));\n this._render();\n }\n\n isComplete() {\n const { autoplayAudioEnabled, completeAudioEnabled } =this._model || {};\n\n if (autoplayAudioEnabled && completeAudioEnabled && !this.audioComplete) {\n return false;\n }\n if (!this._session || !this._session.answers) {\n return false;\n }\n\n if (!Array.isArray(this._session.answers)) {\n return false;\n }\n\n return Array.isArray(this._session.answers) && this._session.answers.length > 0;\n }\n\n set session(s) {\n if (s && !s.answers) {\n s.answers = [];\n }\n\n this._session = s;\n this._render();\n }\n\n get session() {\n return this._session;\n }\n\n updateAnswer(data) {\n this._session.answers = data;\n this._session.selector = 'Mouse';\n \n this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));\n\n this._render();\n }\n\n _createAudioInfoToast() {\n const info = document.createElement('div');\n info.id = 'play-audio-info';\n\n Object.assign(info.style, {\n position: 'absolute',\n top: 0,\n width:'100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n background: 'white',\n zIndex: '1000'\n });\n\n const img = document.createElement('img');\n img.src = 'https://student.assessment.renaissance.com/ce/quizenginecap/assets/img/playAppsSel.gif';\n img.alt = 'Click anywhere to enable audio autoplay';\n img.width = 500;\n img.height = 300;\n\n info.appendChild(img);\n return info;\n }\n\n connectedCallback() {\n this._render();\n\n if (this._model && !this._model.autoplayAudioEnabled) {\n return;\n }\n\n // Observation: audio in Chrome will have the autoplay attribute,\n // while other browsers will not have the autoplay attribute and will need a user interaction to play the audio\n // This workaround fixes the issue of audio being cached and played on any user interaction in Safari and Firefox\n const observer = new MutationObserver((mutationsList, observer) => {\n mutationsList.forEach((mutation) => {\n if (mutation.type === 'childList') {\n const audio = this.querySelector('audio');\n const isInsidePrompt = audio && audio.closest('#preview-prompt');\n\n if (audio && !isInsidePrompt) return;\n if (!audio) return;\n\n const info = this._createAudioInfoToast();\n const container = this.querySelector('[class*=\"main\"]');\n const enableAudio = () => {\n if (this.querySelector('#play-audio-info')) {\n audio.play();\n container.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 container.appendChild(info);\n document.addEventListener('click', enableAudio);\n } else {\n document.removeEventListener('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.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));\n\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 _render() {\n if (this._model && this._session) {\n const el = React.createElement(ImageClozeAssociationComponent, {\n model: this._model,\n session: this._session,\n updateAnswer: this.updateAnswer.bind(this),\n });\n\n ReactDOM.render(el, this, () => {\n renderMath(this);\n });\n }\n }\n}\n"],"file":"index.js"}
|
package/lib/root.js
CHANGED
|
@@ -69,7 +69,8 @@ var styles = function styles(theme) {
|
|
|
69
69
|
return {
|
|
70
70
|
main: {
|
|
71
71
|
color: _renderUi.color.text(),
|
|
72
|
-
backgroundColor: _renderUi.color.background()
|
|
72
|
+
backgroundColor: _renderUi.color.background(),
|
|
73
|
+
position: 'relative'
|
|
73
74
|
},
|
|
74
75
|
teacherInstructions: {
|
|
75
76
|
marginBottom: theme.spacing.unit * 2
|
|
@@ -290,6 +291,7 @@ var ImageClozeAssociationComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
290
291
|
validation = _this$props3$model.validation,
|
|
291
292
|
teacherInstructions = _this$props3$model.teacherInstructions,
|
|
292
293
|
prompt = _this$props3$model.prompt,
|
|
294
|
+
autoplayAudioEnabled = _this$props3$model.autoplayAudioEnabled,
|
|
293
295
|
showDashedBorder = _this$props3$model.showDashedBorder,
|
|
294
296
|
mode = _this$props3$model.mode,
|
|
295
297
|
rationale = _this$props3$model.rationale,
|
|
@@ -342,8 +344,10 @@ var ImageClozeAssociationComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
342
344
|
|
|
343
345
|
if (responseCorrect === false && maxResponsePerZone === 1) {
|
|
344
346
|
answersToShow = [].concat((0, _toConsumableArray2["default"])(answersToShow), (0, _toConsumableArray2["default"])((0, _utilsCorrectness.getUnansweredAnswers)(answersToShow, validation)));
|
|
345
|
-
}
|
|
347
|
+
} // Safari, Firefox, and Edge do not support autoplay audio smoothly in our use case
|
|
348
|
+
|
|
346
349
|
|
|
350
|
+
var addAutoplayAudio = autoplayAudioEnabled && !(/Safari|Firefox|Edg/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent));
|
|
347
351
|
return /*#__PURE__*/_react["default"].createElement(_renderUi.UiLayout, {
|
|
348
352
|
extraCSSRules: extraCSSRules,
|
|
349
353
|
className: classes.main,
|
|
@@ -358,7 +362,8 @@ var ImageClozeAssociationComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
358
362
|
prompt: teacherInstructions
|
|
359
363
|
})), /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
|
|
360
364
|
className: "prompt",
|
|
361
|
-
prompt: prompt
|
|
365
|
+
prompt: prompt,
|
|
366
|
+
autoplayAudioEnabled: addAutoplayAudio
|
|
362
367
|
}), /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
|
|
363
368
|
prompt: stimulus
|
|
364
369
|
}), /*#__PURE__*/_react["default"].createElement(_correctAnswerToggle.CorrectAnswerToggle, {
|
package/lib/root.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/root.jsx"],"names":["translator","Translator","generateId","Math","random","toString","substring","Date","getTime","styles","theme","main","color","text","backgroundColor","background","teacherInstructions","marginBottom","spacing","unit","rationale","marginTop","ImageClozeAssociationComponent","props","draggingElement","setState","id","value","possibleResponses","answer","index","findIndex","response","slice","responseContainerIndex","duplicateResponses","model","updateAnswer","state","answers","maxResponsePerZone","answersToStore","filter","a","containerIndex","length","answersInThisContainer","answersInOtherContainers","b","shiftedItem","shift","maxResponsePerZoneWarning","Array","isArray","push","undefined","filterPossibleAnswers","shouldNotPushInPossibleResponses","showCorrect","responseContainers","session","possibleResponsesWithIds","map","item","groupBy","grp","flatMap","possibleResponsesFiltered","find","classes","disabled","extraCSSRules","image","responseAreaFill","stimulus","responseCorrect","validation","prompt","showDashedBorder","mode","language","uiStyle","answerChoiceTransparency","responseContainerPadding","imageDropTargetPadding","fontSizeFactor","isEvaluateMode","showToggle","possibilityListPosition","isVertical","validResponse","correctAnswers","forEach","container","i","images","v","isCorrect","warningMessage","t","lng","count","answersToShow","hidden","visible","toggleCorrect","handleOnAnswerSelect","beginDrag","handleOnDragEnd","handleOnAnswerRemove","minWidth","width","height","React","Component","WarningInfo","warning","margin","padding","display","alignItems","message","paddingLeft","userSelect","__html","propTypes","PropTypes","string","object","isRequired","func","defaultProps","StyledComponent"],"mappings":"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","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withDragContext } from '@pie-lib/pie-toolbox/drag';\nimport { CSSTransition, TransitionGroup } from 'react-transition-group';\nimport { color, Collapsible, PreviewPrompt, UiLayout, hasText } from '@pie-lib/pie-toolbox/render-ui';\nimport { withStyles } from '@material-ui/core/styles';\nimport NotInterestedIcon from '@material-ui/icons/NotInterested';\nimport { CorrectAnswerToggle } from '@pie-lib/pie-toolbox/correct-answer-toggle';\nimport Translator from '@pie-lib/pie-toolbox/translator';\n\nconst { translator } = Translator;\nimport Image from './image-container';\nimport InteractiveSection from './interactive-section';\nimport PossibleResponses from './possible-responses';\nimport { getUnansweredAnswers, getAnswersCorrectness } from './utils-correctness';\nimport _ from 'lodash';\n\nconst generateId = () => Math.random().toString(36).substring(2) + new Date().getTime().toString(36);\n\nconst styles = (theme) => ({\n main: {\n color: color.text(),\n backgroundColor: color.background(),\n },\n teacherInstructions: {\n marginBottom: theme.spacing.unit * 2,\n },\n rationale: {\n marginTop: theme.spacing.unit * 2,\n },\n});\n\nexport class ImageClozeAssociationComponent extends React.Component {\n constructor(props) {\n super(props);\n const {\n model: { possibleResponses, responseContainers, duplicateResponses, maxResponsePerZone },\n session,\n } = props;\n let { answers } = session || {};\n // set id for each possible response\n const possibleResponsesWithIds = (possibleResponses || []).map((item, index) => ({\n value: item,\n id: `${index}`,\n }));\n\n answers = _(answers || [])\n .groupBy('containerIndex')\n // keep only last maxResponsePerZone answers for each zone\n .map((grp) => grp.slice(-(maxResponsePerZone || 1)))\n .flatMap()\n // set id for each answer\n .map((answer, index) => ({ ...answer, id: `${index}` }))\n // return only answer which have a valid container index\n .filter((answer) => answer.containerIndex < responseContainers.length)\n .value();\n\n const possibleResponsesFiltered = possibleResponsesWithIds.filter(\n (response) => !answers.find((answer) => answer.value === response.value),\n );\n this.state = {\n answers: answers || [],\n draggingElement: { id: '', value: '' },\n possibleResponses: duplicateResponses ? possibleResponsesWithIds : possibleResponsesFiltered,\n // set id for each response containers\n responseContainers: (responseContainers || []).map((item, index) => ({\n index,\n ...item,\n id: `${index}`,\n })),\n maxResponsePerZone: maxResponsePerZone || 1,\n showCorrect: false,\n };\n }\n\n beginDrag = (draggingElement) => {\n this.setState({\n draggingElement,\n });\n };\n\n handleOnDragEnd = () => {\n this.setState({\n draggingElement: { id: '', value: '' },\n });\n };\n\n filterPossibleAnswers = (possibleResponses, answer) => {\n const index = possibleResponses.findIndex((response) => response.value === answer.value);\n\n if (index >= 0) {\n return [\n ...possibleResponses.slice(0, index), // Elements before the found item\n ...possibleResponses.slice(index + 1), // Elements after the found item\n ];\n }\n\n return possibleResponses;\n };\n\n handleOnAnswerSelect = (answer, responseContainerIndex) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, maxResponsePerZone } = this.state;\n let { possibleResponses } = this.state;\n let answersToStore;\n\n if (maxResponsePerZone === answers.filter((a) => a.containerIndex === responseContainerIndex).length) {\n const answersInThisContainer = answers.filter((a) => a.containerIndex === responseContainerIndex);\n const answersInOtherContainers = answers.filter((b) => b.containerIndex !== responseContainerIndex);\n\n const shiftedItem = answersInThisContainer[0];\n if (maxResponsePerZone === 1) {\n answersInThisContainer.shift(); // FIFO\n } else {\n this.setState({ maxResponsePerZoneWarning: true });\n return;\n }\n\n // if duplicates are not allowed, make sure to put the shifted value back in possible responses\n if (!duplicateResponses) {\n possibleResponses = Array.isArray(possibleResponses) ? possibleResponses : [];\n\n possibleResponses.push({\n ...shiftedItem,\n containerIndex: undefined,\n id: shiftedItem.id || generateId(),\n });\n }\n\n // answers will be:\n // + shifted answers for the current container\n // + if duplicatesAllowed, all the other answers from other containers\n // else: all the answers from other containers that are not having the same value\n // + new answer\n answersToStore = [\n ...answersInThisContainer, // shifted\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answersInOtherContainers.filter((a) => (duplicateResponses ? true : a.value !== answer.value)), // un-shifted\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n } else {\n // answers will be:\n // + if duplicatesAllowed, all the other answers, except the one that was dragged\n // else: all the answers that are not having the same value\n // + new answer\n answersToStore = [\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answers.filter((a) => (duplicateResponses ? a.id !== answer.id : a.value !== answer.value)),\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n }\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n possibleResponses:\n // for single response per container remove answer from possible responses\n duplicateResponses ? possibleResponses : this.filterPossibleAnswers(possibleResponses, answer),\n });\n updateAnswer(answersToStore);\n };\n\n handleOnAnswerRemove = (answer) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, possibleResponses } = this.state;\n const answersToStore = answers.filter((a) => a.id !== answer.id);\n const shouldNotPushInPossibleResponses = answer.containerIndex === undefined; // don't duplicate possible responses\n\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n // push back into possible responses the removed answer if responses cannot be duplicated\n possibleResponses:\n duplicateResponses || shouldNotPushInPossibleResponses\n ? possibleResponses\n : [\n ...possibleResponses,\n {\n ...answer,\n containerIndex: undefined,\n },\n ],\n });\n updateAnswer(answersToStore);\n };\n\n toggleCorrect = (showCorrect) => this.setState({ showCorrect });\n\n render() {\n const {\n classes,\n model: {\n disabled,\n duplicateResponses,\n extraCSSRules,\n image,\n responseAreaFill,\n stimulus,\n responseCorrect,\n validation,\n teacherInstructions,\n prompt,\n showDashedBorder,\n mode,\n rationale,\n language,\n uiStyle = {},\n answerChoiceTransparency,\n responseContainerPadding,\n imageDropTargetPadding,\n fontSizeFactor,\n },\n } = this.props;\n const {\n answers,\n draggingElement,\n possibleResponses,\n responseContainers,\n maxResponsePerZone,\n maxResponsePerZoneWarning,\n showCorrect,\n } = this.state;\n const isEvaluateMode = mode === 'evaluate';\n const showToggle = isEvaluateMode && !responseCorrect;\n const { possibilityListPosition = 'bottom' } = uiStyle || {};\n const isVertical = possibilityListPosition === 'left' || possibilityListPosition === 'right';\n\n const { validResponse } = validation || {};\n const correctAnswers = [];\n\n if (validResponse) {\n (validResponse.value || []).forEach((container, i) => {\n (container.images || []).forEach((v) => {\n correctAnswers.push({\n value: v,\n containerIndex: i,\n isCorrect: true\n });\n });\n });\n }\n\n const warningMessage = translator.t('imageClozeAssociation.reachedLimit_other', {\n lng: language,\n count: maxResponsePerZone,\n });\n\n let answersToShow =\n responseCorrect !== undefined ? getAnswersCorrectness(answers, validation, duplicateResponses) : answers;\n\n if (responseCorrect === false && maxResponsePerZone === 1) {\n answersToShow = [...answersToShow, ...getUnansweredAnswers(answersToShow, validation)];\n }\n\n return (\n <UiLayout extraCSSRules={extraCSSRules} className={classes.main} fontSizeFactor={fontSizeFactor}>\n {teacherInstructions && hasText(teacherInstructions) && (\n <Collapsible\n className={classes.teacherInstructions}\n labels={{\n hidden: 'Show Teacher Instructions',\n visible: 'Hide Teacher Instructions',\n }}\n >\n <PreviewPrompt prompt={teacherInstructions} />\n </Collapsible>\n )}\n\n <PreviewPrompt className=\"prompt\" prompt={prompt} />\n\n <PreviewPrompt prompt={stimulus} />\n\n <CorrectAnswerToggle\n show={showToggle}\n toggled={showCorrect}\n onToggle={this.toggleCorrect}\n language={language}\n />\n\n {showCorrect && showToggle ? (\n <InteractiveSection responseCorrect={true} uiStyle={uiStyle}>\n <Image\n canDrag={false}\n answers={correctAnswers}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n responseAreaFill={responseAreaFill}\n responseContainerPadding={responseContainerPadding}\n imageDropTargetPadding={imageDropTargetPadding}\n maxResponsePerZone={maxResponsePerZone}\n />\n </InteractiveSection>\n ) : (\n <InteractiveSection responseCorrect={responseCorrect} uiStyle={uiStyle}>\n <Image\n canDrag={!disabled}\n answers={answersToShow}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n responseAreaFill={responseAreaFill}\n answerChoiceTransparency={answerChoiceTransparency}\n responseContainerPadding={responseContainerPadding}\n imageDropTargetPadding={imageDropTargetPadding}\n maxResponsePerZone={maxResponsePerZone}\n />\n\n {maxResponsePerZoneWarning && <WarningInfo message={warningMessage} />}\n\n <PossibleResponses\n canDrag={!disabled}\n data={possibleResponses}\n onAnswerRemove={this.handleOnAnswerRemove}\n onDragBegin={this.beginDrag}\n onDragEnd={this.handleOnDragEnd}\n answerChoiceTransparency={answerChoiceTransparency}\n customStyle={{\n minWidth: isVertical ? '130px' : image?.width || 'fit-content',\n }}\n isVertical={isVertical}\n minHeight={isVertical ? image?.height : undefined}\n />\n </InteractiveSection>\n )}\n\n {rationale && hasText(rationale) && (\n <Collapsible\n className={classes.rationale}\n labels={{\n hidden: 'Show Rationale',\n visible: 'Hide Rationale',\n }}\n >\n <PreviewPrompt prompt={rationale} />\n </Collapsible>\n )}\n </UiLayout>\n );\n }\n}\n\nconst WarningInfo = withStyles((theme) => ({\n warning: {\n margin: `0 ${theme.spacing.unit * 2}px`,\n backgroundColor: '#dddddd',\n padding: theme.spacing.unit,\n display: 'flex',\n alignItems: 'center',\n '& svg': {\n height: '30px',\n },\n '& h1': {\n padding: '0px',\n margin: '0px',\n },\n },\n message: {\n paddingLeft: theme.spacing.unit / 2,\n userSelect: 'none',\n },\n}))(({ classes, message }) => (\n <TransitionGroup>\n <CSSTransition classNames={'fb'} key=\"fb\" timeout={300}>\n <div key=\"panel\" className={classes.warning}>\n <NotInterestedIcon color={'secondary'} fontSize={'small'}/>\n <span className={classes.message} dangerouslySetInnerHTML={{ __html: message }} />\n </div>\n </CSSTransition>\n </TransitionGroup>\n));\n\nWarningInfo.propTypes = {\n message: PropTypes.string,\n classes: PropTypes.object.isRequired,\n};\n\nImageClozeAssociationComponent.propTypes = {\n classes: PropTypes.object,\n model: PropTypes.object.isRequired,\n session: PropTypes.object,\n updateAnswer: PropTypes.func.isRequired,\n};\n\nImageClozeAssociationComponent.defaultProps = {\n classes: {},\n};\n\nconst StyledComponent = withStyles(styles)(ImageClozeAssociationComponent);\n\nexport default withDragContext(StyledComponent);\n"],"file":"root.js"}
|
|
1
|
+
{"version":3,"sources":["../src/root.jsx"],"names":["translator","Translator","generateId","Math","random","toString","substring","Date","getTime","styles","theme","main","color","text","backgroundColor","background","position","teacherInstructions","marginBottom","spacing","unit","rationale","marginTop","ImageClozeAssociationComponent","props","draggingElement","setState","id","value","possibleResponses","answer","index","findIndex","response","slice","responseContainerIndex","duplicateResponses","model","updateAnswer","state","answers","maxResponsePerZone","answersToStore","filter","a","containerIndex","length","answersInThisContainer","answersInOtherContainers","b","shiftedItem","shift","maxResponsePerZoneWarning","Array","isArray","push","undefined","filterPossibleAnswers","shouldNotPushInPossibleResponses","showCorrect","responseContainers","session","possibleResponsesWithIds","map","item","groupBy","grp","flatMap","possibleResponsesFiltered","find","classes","disabled","extraCSSRules","image","responseAreaFill","stimulus","responseCorrect","validation","prompt","autoplayAudioEnabled","showDashedBorder","mode","language","uiStyle","answerChoiceTransparency","responseContainerPadding","imageDropTargetPadding","fontSizeFactor","isEvaluateMode","showToggle","possibilityListPosition","isVertical","validResponse","correctAnswers","forEach","container","i","images","v","isCorrect","warningMessage","t","lng","count","answersToShow","addAutoplayAudio","test","navigator","userAgent","hidden","visible","toggleCorrect","handleOnAnswerSelect","beginDrag","handleOnDragEnd","handleOnAnswerRemove","minWidth","width","height","React","Component","WarningInfo","warning","margin","padding","display","alignItems","message","paddingLeft","userSelect","__html","propTypes","PropTypes","string","object","isRequired","func","defaultProps","StyledComponent"],"mappings":"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","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withDragContext } from '@pie-lib/pie-toolbox/drag';\nimport { CSSTransition, TransitionGroup } from 'react-transition-group';\nimport { color, Collapsible, PreviewPrompt, UiLayout, hasText } from '@pie-lib/pie-toolbox/render-ui';\nimport { withStyles } from '@material-ui/core/styles';\nimport NotInterestedIcon from '@material-ui/icons/NotInterested';\nimport { CorrectAnswerToggle } from '@pie-lib/pie-toolbox/correct-answer-toggle';\nimport Translator from '@pie-lib/pie-toolbox/translator';\n\nconst { translator } = Translator;\nimport Image from './image-container';\nimport InteractiveSection from './interactive-section';\nimport PossibleResponses from './possible-responses';\nimport { getUnansweredAnswers, getAnswersCorrectness } from './utils-correctness';\nimport _ from 'lodash';\n\nconst generateId = () => Math.random().toString(36).substring(2) + new Date().getTime().toString(36);\n\nconst styles = (theme) => ({\n main: {\n color: color.text(),\n backgroundColor: color.background(),\n position: 'relative'\n },\n teacherInstructions: {\n marginBottom: theme.spacing.unit * 2,\n },\n rationale: {\n marginTop: theme.spacing.unit * 2,\n },\n});\n\nexport class ImageClozeAssociationComponent extends React.Component {\n constructor(props) {\n super(props);\n const {\n model: { possibleResponses, responseContainers, duplicateResponses, maxResponsePerZone },\n session,\n } = props;\n let { answers } = session || {};\n // set id for each possible response\n const possibleResponsesWithIds = (possibleResponses || []).map((item, index) => ({\n value: item,\n id: `${index}`,\n }));\n\n answers = _(answers || [])\n .groupBy('containerIndex')\n // keep only last maxResponsePerZone answers for each zone\n .map((grp) => grp.slice(-(maxResponsePerZone || 1)))\n .flatMap()\n // set id for each answer\n .map((answer, index) => ({ ...answer, id: `${index}` }))\n // return only answer which have a valid container index\n .filter((answer) => answer.containerIndex < responseContainers.length)\n .value();\n\n const possibleResponsesFiltered = possibleResponsesWithIds.filter(\n (response) => !answers.find((answer) => answer.value === response.value),\n );\n this.state = {\n answers: answers || [],\n draggingElement: { id: '', value: '' },\n possibleResponses: duplicateResponses ? possibleResponsesWithIds : possibleResponsesFiltered,\n // set id for each response containers\n responseContainers: (responseContainers || []).map((item, index) => ({\n index,\n ...item,\n id: `${index}`,\n })),\n maxResponsePerZone: maxResponsePerZone || 1,\n showCorrect: false,\n };\n }\n\n beginDrag = (draggingElement) => {\n this.setState({\n draggingElement,\n });\n };\n\n handleOnDragEnd = () => {\n this.setState({\n draggingElement: { id: '', value: '' },\n });\n };\n\n filterPossibleAnswers = (possibleResponses, answer) => {\n const index = possibleResponses.findIndex((response) => response.value === answer.value);\n\n if (index >= 0) {\n return [\n ...possibleResponses.slice(0, index), // Elements before the found item\n ...possibleResponses.slice(index + 1), // Elements after the found item\n ];\n }\n\n return possibleResponses;\n };\n\n handleOnAnswerSelect = (answer, responseContainerIndex) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, maxResponsePerZone } = this.state;\n let { possibleResponses } = this.state;\n let answersToStore;\n\n if (maxResponsePerZone === answers.filter((a) => a.containerIndex === responseContainerIndex).length) {\n const answersInThisContainer = answers.filter((a) => a.containerIndex === responseContainerIndex);\n const answersInOtherContainers = answers.filter((b) => b.containerIndex !== responseContainerIndex);\n\n const shiftedItem = answersInThisContainer[0];\n if (maxResponsePerZone === 1) {\n answersInThisContainer.shift(); // FIFO\n } else {\n this.setState({ maxResponsePerZoneWarning: true });\n return;\n }\n\n // if duplicates are not allowed, make sure to put the shifted value back in possible responses\n if (!duplicateResponses) {\n possibleResponses = Array.isArray(possibleResponses) ? possibleResponses : [];\n\n possibleResponses.push({\n ...shiftedItem,\n containerIndex: undefined,\n id: shiftedItem.id || generateId(),\n });\n }\n\n // answers will be:\n // + shifted answers for the current container\n // + if duplicatesAllowed, all the other answers from other containers\n // else: all the answers from other containers that are not having the same value\n // + new answer\n answersToStore = [\n ...answersInThisContainer, // shifted\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answersInOtherContainers.filter((a) => (duplicateResponses ? true : a.value !== answer.value)), // un-shifted\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n } else {\n // answers will be:\n // + if duplicatesAllowed, all the other answers, except the one that was dragged\n // else: all the answers that are not having the same value\n // + new answer\n answersToStore = [\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answers.filter((a) => (duplicateResponses ? a.id !== answer.id : a.value !== answer.value)),\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n }\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n possibleResponses:\n // for single response per container remove answer from possible responses\n duplicateResponses ? possibleResponses : this.filterPossibleAnswers(possibleResponses, answer),\n });\n updateAnswer(answersToStore);\n };\n\n handleOnAnswerRemove = (answer) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, possibleResponses } = this.state;\n const answersToStore = answers.filter((a) => a.id !== answer.id);\n const shouldNotPushInPossibleResponses = answer.containerIndex === undefined; // don't duplicate possible responses\n\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n // push back into possible responses the removed answer if responses cannot be duplicated\n possibleResponses:\n duplicateResponses || shouldNotPushInPossibleResponses\n ? possibleResponses\n : [\n ...possibleResponses,\n {\n ...answer,\n containerIndex: undefined,\n },\n ],\n });\n updateAnswer(answersToStore);\n };\n\n toggleCorrect = (showCorrect) => this.setState({ showCorrect });\n\n render() {\n const {\n classes,\n model: {\n disabled,\n duplicateResponses,\n extraCSSRules,\n image,\n responseAreaFill,\n stimulus,\n responseCorrect,\n validation,\n teacherInstructions,\n prompt,\n autoplayAudioEnabled,\n showDashedBorder,\n mode,\n rationale,\n language,\n uiStyle = {},\n answerChoiceTransparency,\n responseContainerPadding,\n imageDropTargetPadding,\n fontSizeFactor,\n },\n } = this.props;\n const {\n answers,\n draggingElement,\n possibleResponses,\n responseContainers,\n maxResponsePerZone,\n maxResponsePerZoneWarning,\n showCorrect,\n } = this.state;\n const isEvaluateMode = mode === 'evaluate';\n const showToggle = isEvaluateMode && !responseCorrect;\n const { possibilityListPosition = 'bottom' } = uiStyle || {};\n const isVertical = possibilityListPosition === 'left' || possibilityListPosition === 'right';\n\n const { validResponse } = validation || {};\n const correctAnswers = [];\n\n if (validResponse) {\n (validResponse.value || []).forEach((container, i) => {\n (container.images || []).forEach((v) => {\n correctAnswers.push({\n value: v,\n containerIndex: i,\n isCorrect: true\n });\n });\n });\n }\n\n const warningMessage = translator.t('imageClozeAssociation.reachedLimit_other', {\n lng: language,\n count: maxResponsePerZone,\n });\n\n let answersToShow =\n responseCorrect !== undefined ? getAnswersCorrectness(answers, validation, duplicateResponses) : answers;\n\n if (responseCorrect === false && maxResponsePerZone === 1) {\n answersToShow = [...answersToShow, ...getUnansweredAnswers(answersToShow, validation)];\n }\n\n // Safari, Firefox, and Edge do not support autoplay audio smoothly in our use case\n const addAutoplayAudio = autoplayAudioEnabled && !(/Safari|Firefox|Edg/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent));\n\n return (\n <UiLayout extraCSSRules={extraCSSRules} className={classes.main} fontSizeFactor={fontSizeFactor}>\n {teacherInstructions && hasText(teacherInstructions) && (\n <Collapsible\n className={classes.teacherInstructions}\n labels={{\n hidden: 'Show Teacher Instructions',\n visible: 'Hide Teacher Instructions',\n }}\n >\n <PreviewPrompt prompt={teacherInstructions} />\n </Collapsible>\n )}\n\n <PreviewPrompt className=\"prompt\" prompt={prompt} autoplayAudioEnabled={addAutoplayAudio} />\n\n <PreviewPrompt prompt={stimulus} />\n\n <CorrectAnswerToggle\n show={showToggle}\n toggled={showCorrect}\n onToggle={this.toggleCorrect}\n language={language}\n />\n\n {showCorrect && showToggle ? (\n <InteractiveSection responseCorrect={true} uiStyle={uiStyle}>\n <Image\n canDrag={false}\n answers={correctAnswers}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n responseAreaFill={responseAreaFill}\n responseContainerPadding={responseContainerPadding}\n imageDropTargetPadding={imageDropTargetPadding}\n maxResponsePerZone={maxResponsePerZone}\n />\n </InteractiveSection>\n ) : (\n <InteractiveSection responseCorrect={responseCorrect} uiStyle={uiStyle}>\n <Image\n canDrag={!disabled}\n answers={answersToShow}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n responseAreaFill={responseAreaFill}\n answerChoiceTransparency={answerChoiceTransparency}\n responseContainerPadding={responseContainerPadding}\n imageDropTargetPadding={imageDropTargetPadding}\n maxResponsePerZone={maxResponsePerZone}\n />\n\n {maxResponsePerZoneWarning && <WarningInfo message={warningMessage} />}\n\n <PossibleResponses\n canDrag={!disabled}\n data={possibleResponses}\n onAnswerRemove={this.handleOnAnswerRemove}\n onDragBegin={this.beginDrag}\n onDragEnd={this.handleOnDragEnd}\n answerChoiceTransparency={answerChoiceTransparency}\n customStyle={{\n minWidth: isVertical ? '130px' : image?.width || 'fit-content',\n }}\n isVertical={isVertical}\n minHeight={isVertical ? image?.height : undefined}\n />\n </InteractiveSection>\n )}\n\n {rationale && hasText(rationale) && (\n <Collapsible\n className={classes.rationale}\n labels={{\n hidden: 'Show Rationale',\n visible: 'Hide Rationale',\n }}\n >\n <PreviewPrompt prompt={rationale} />\n </Collapsible>\n )}\n </UiLayout>\n );\n }\n}\n\nconst WarningInfo = withStyles((theme) => ({\n warning: {\n margin: `0 ${theme.spacing.unit * 2}px`,\n backgroundColor: '#dddddd',\n padding: theme.spacing.unit,\n display: 'flex',\n alignItems: 'center',\n '& svg': {\n height: '30px',\n },\n '& h1': {\n padding: '0px',\n margin: '0px',\n },\n },\n message: {\n paddingLeft: theme.spacing.unit / 2,\n userSelect: 'none',\n },\n}))(({ classes, message }) => (\n <TransitionGroup>\n <CSSTransition classNames={'fb'} key=\"fb\" timeout={300}>\n <div key=\"panel\" className={classes.warning}>\n <NotInterestedIcon color={'secondary'} fontSize={'small'}/>\n <span className={classes.message} dangerouslySetInnerHTML={{ __html: message }} />\n </div>\n </CSSTransition>\n </TransitionGroup>\n));\n\nWarningInfo.propTypes = {\n message: PropTypes.string,\n classes: PropTypes.object.isRequired,\n};\n\nImageClozeAssociationComponent.propTypes = {\n classes: PropTypes.object,\n model: PropTypes.object.isRequired,\n session: PropTypes.object,\n updateAnswer: PropTypes.func.isRequired,\n};\n\nImageClozeAssociationComponent.defaultProps = {\n classes: {},\n};\n\nconst StyledComponent = withStyles(styles)(ImageClozeAssociationComponent);\n\nexport default withDragContext(StyledComponent);\n"],"file":"root.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-element/image-cloze-association",
|
|
3
|
-
"version": "6.7.2-next.
|
|
3
|
+
"version": "6.7.2-next.31+96093f50c",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": "pie-framework/pie-elements",
|
|
6
6
|
"publishConfig": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"author": "pie framework developers",
|
|
21
21
|
"license": "ISC",
|
|
22
|
-
"gitHead": "
|
|
22
|
+
"gitHead": "96093f50c5b6a903bd67b0a84c8033fb99304d83",
|
|
23
23
|
"scripts": {
|
|
24
24
|
"postpublish": "../../scripts/postpublish"
|
|
25
25
|
},
|
package/src/index.js
CHANGED
|
@@ -14,6 +14,11 @@ export default class ImageClozeAssociation extends HTMLElement {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
isComplete() {
|
|
17
|
+
const { autoplayAudioEnabled, completeAudioEnabled } =this._model || {};
|
|
18
|
+
|
|
19
|
+
if (autoplayAudioEnabled && completeAudioEnabled && !this.audioComplete) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
17
22
|
if (!this._session || !this._session.answers) {
|
|
18
23
|
return false;
|
|
19
24
|
}
|
|
@@ -40,14 +45,110 @@ export default class ImageClozeAssociation extends HTMLElement {
|
|
|
40
45
|
|
|
41
46
|
updateAnswer(data) {
|
|
42
47
|
this._session.answers = data;
|
|
43
|
-
|
|
48
|
+
this._session.selector = 'Mouse';
|
|
49
|
+
|
|
44
50
|
this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));
|
|
45
51
|
|
|
46
52
|
this._render();
|
|
47
53
|
}
|
|
48
54
|
|
|
55
|
+
_createAudioInfoToast() {
|
|
56
|
+
const info = document.createElement('div');
|
|
57
|
+
info.id = 'play-audio-info';
|
|
58
|
+
|
|
59
|
+
Object.assign(info.style, {
|
|
60
|
+
position: 'absolute',
|
|
61
|
+
top: 0,
|
|
62
|
+
width:'100%',
|
|
63
|
+
height: '100%',
|
|
64
|
+
display: 'flex',
|
|
65
|
+
justifyContent: 'center',
|
|
66
|
+
alignItems: 'center',
|
|
67
|
+
background: 'white',
|
|
68
|
+
zIndex: '1000'
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const img = document.createElement('img');
|
|
72
|
+
img.src = 'https://student.assessment.renaissance.com/ce/quizenginecap/assets/img/playAppsSel.gif';
|
|
73
|
+
img.alt = 'Click anywhere to enable audio autoplay';
|
|
74
|
+
img.width = 500;
|
|
75
|
+
img.height = 300;
|
|
76
|
+
|
|
77
|
+
info.appendChild(img);
|
|
78
|
+
return info;
|
|
79
|
+
}
|
|
80
|
+
|
|
49
81
|
connectedCallback() {
|
|
50
82
|
this._render();
|
|
83
|
+
|
|
84
|
+
if (this._model && !this._model.autoplayAudioEnabled) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Observation: audio in Chrome will have the autoplay attribute,
|
|
89
|
+
// while other browsers will not have the autoplay attribute and will need a user interaction to play the audio
|
|
90
|
+
// This workaround fixes the issue of audio being cached and played on any user interaction in Safari and Firefox
|
|
91
|
+
const observer = new MutationObserver((mutationsList, observer) => {
|
|
92
|
+
mutationsList.forEach((mutation) => {
|
|
93
|
+
if (mutation.type === 'childList') {
|
|
94
|
+
const audio = this.querySelector('audio');
|
|
95
|
+
const isInsidePrompt = audio && audio.closest('#preview-prompt');
|
|
96
|
+
|
|
97
|
+
if (audio && !isInsidePrompt) return;
|
|
98
|
+
if (!audio) return;
|
|
99
|
+
|
|
100
|
+
const info = this._createAudioInfoToast();
|
|
101
|
+
const container = this.querySelector('[class*="main"]');
|
|
102
|
+
const enableAudio = () => {
|
|
103
|
+
if (this.querySelector('#play-audio-info')) {
|
|
104
|
+
audio.play();
|
|
105
|
+
container.removeChild(info);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
document.removeEventListener('click', enableAudio);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// if the audio is paused, it means the user has not interacted with the page yet and the audio will not play
|
|
112
|
+
// FIX FOR SAFARI: play with a slight delay to check if autoplay was blocked
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
if (audio.paused && !this.querySelector('#play-audio-info')) {
|
|
115
|
+
// add info message as a toast to enable audio playback
|
|
116
|
+
container.appendChild(info);
|
|
117
|
+
document.addEventListener('click', enableAudio);
|
|
118
|
+
} else {
|
|
119
|
+
document.removeEventListener('click', enableAudio);
|
|
120
|
+
}
|
|
121
|
+
}, 500);
|
|
122
|
+
|
|
123
|
+
// we need to listen for the playing event to remove the toast in case the audio plays because of re-rendering
|
|
124
|
+
const handlePlaying = () => {
|
|
125
|
+
const info = this.querySelector('#play-audio-info');
|
|
126
|
+
|
|
127
|
+
if (info) {
|
|
128
|
+
this.removeChild(info);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
audio.removeEventListener('playing', handlePlaying);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
audio.addEventListener('playing', handlePlaying);
|
|
135
|
+
|
|
136
|
+
// we need to listen for the ended event to update the isComplete state
|
|
137
|
+
const handleEnded = () => {
|
|
138
|
+
this.audioComplete = true;
|
|
139
|
+
this.dispatchEvent(new SessionChangedEvent(this.tagName.toLowerCase(), this.isComplete()));
|
|
140
|
+
|
|
141
|
+
audio.removeEventListener('ended', handleEnded);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
audio.addEventListener('ended', handleEnded);
|
|
145
|
+
|
|
146
|
+
observer.disconnect();
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
observer.observe(this, { childList: true, subtree: true });
|
|
51
152
|
}
|
|
52
153
|
|
|
53
154
|
_render() {
|
package/src/root.jsx
CHANGED
|
@@ -21,6 +21,7 @@ const styles = (theme) => ({
|
|
|
21
21
|
main: {
|
|
22
22
|
color: color.text(),
|
|
23
23
|
backgroundColor: color.background(),
|
|
24
|
+
position: 'relative'
|
|
24
25
|
},
|
|
25
26
|
teacherInstructions: {
|
|
26
27
|
marginBottom: theme.spacing.unit * 2,
|
|
@@ -215,6 +216,7 @@ export class ImageClozeAssociationComponent extends React.Component {
|
|
|
215
216
|
validation,
|
|
216
217
|
teacherInstructions,
|
|
217
218
|
prompt,
|
|
219
|
+
autoplayAudioEnabled,
|
|
218
220
|
showDashedBorder,
|
|
219
221
|
mode,
|
|
220
222
|
rationale,
|
|
@@ -267,6 +269,9 @@ export class ImageClozeAssociationComponent extends React.Component {
|
|
|
267
269
|
answersToShow = [...answersToShow, ...getUnansweredAnswers(answersToShow, validation)];
|
|
268
270
|
}
|
|
269
271
|
|
|
272
|
+
// Safari, Firefox, and Edge do not support autoplay audio smoothly in our use case
|
|
273
|
+
const addAutoplayAudio = autoplayAudioEnabled && !(/Safari|Firefox|Edg/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent));
|
|
274
|
+
|
|
270
275
|
return (
|
|
271
276
|
<UiLayout extraCSSRules={extraCSSRules} className={classes.main} fontSizeFactor={fontSizeFactor}>
|
|
272
277
|
{teacherInstructions && hasText(teacherInstructions) && (
|
|
@@ -281,7 +286,7 @@ export class ImageClozeAssociationComponent extends React.Component {
|
|
|
281
286
|
</Collapsible>
|
|
282
287
|
)}
|
|
283
288
|
|
|
284
|
-
<PreviewPrompt className="prompt" prompt={prompt} />
|
|
289
|
+
<PreviewPrompt className="prompt" prompt={prompt} autoplayAudioEnabled={addAutoplayAudio} />
|
|
285
290
|
|
|
286
291
|
<PreviewPrompt prompt={stimulus} />
|
|
287
292
|
|