fcad-core-dragon 2.0.0-beta.1 → 2.0.0-beta.10
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/.editorconfig +6 -31
- package/.prettierrc +11 -0
- package/.vscode/extensions.json +8 -0
- package/.vscode/settings.json +16 -0
- package/CHANGELOG +153 -0
- package/README.md +28 -43
- package/documentation/.vitepress/config.js +114 -0
- package/documentation/api-examples.md +49 -0
- package/documentation/composants/app-base-button.md +58 -0
- package/documentation/composants/app-base-error-display.md +59 -0
- package/documentation/composants/app-base-popover.md +68 -0
- package/documentation/composants/app-comp-audio.md +75 -0
- package/documentation/composants/app-comp-branch-buttons.md +111 -0
- package/documentation/composants/app-comp-button-progress.md +53 -0
- package/documentation/composants/app-comp-carousel.md +53 -0
- package/documentation/composants/app-comp-container.md +53 -0
- package/documentation/composants/app-comp-input-checkbox-next.md +42 -0
- package/documentation/composants/app-comp-input-dropdown-next.md +34 -0
- package/documentation/composants/app-comp-input-radio-next.md +39 -0
- package/documentation/composants/app-comp-input-text-next.md +35 -0
- package/documentation/composants/app-comp-input-text-table-next.md +34 -0
- package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -0
- package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -0
- package/documentation/composants/app-comp-jauge.md +31 -0
- package/documentation/composants/app-comp-menu-item.md +55 -0
- package/documentation/composants/app-comp-menu.md +29 -0
- package/documentation/composants/app-comp-navigation.md +41 -0
- package/documentation/composants/app-comp-note-call.md +53 -0
- package/documentation/composants/app-comp-note-credit.md +53 -0
- package/documentation/composants/app-comp-play-bar-next.md +53 -0
- package/documentation/composants/app-comp-pop-up-next.md +93 -0
- package/documentation/composants/app-comp-quiz-next.md +235 -0
- package/documentation/composants/app-comp-quiz-recall.md +53 -0
- package/documentation/composants/app-comp-svg-next.md +53 -0
- package/documentation/composants/app-comp-table-of-content.md +50 -0
- package/documentation/composants/app-comp-video-player.md +82 -0
- package/documentation/composants.md +46 -0
- package/documentation/composants_critiques/ModelPageComposant.md +53 -0
- package/documentation/composants_critiques/app-base-module.md +43 -0
- package/documentation/composants_critiques/app-base-page.md +48 -0
- package/documentation/composants_critiques/app-base.md +311 -0
- package/documentation/composants_critiques/main.md +15 -0
- package/documentation/demarrage.md +50 -0
- package/documentation/deploiement.md +58 -0
- package/documentation/index.md +33 -0
- package/documentation/markdown-examples.md +85 -0
- package/documentation/public/npm_version.png +0 -0
- package/documentation/public/vite.svg +15 -0
- package/documentation/public/vuejs.svg +2 -0
- package/documentation/public/vuetify.svg +6 -0
- package/eslint.config.js +60 -0
- package/package.json +43 -47
- package/src/$locales/en.json +86 -108
- package/src/$locales/fr.json +66 -127
- package/src/assets/data/onboardingMessages.json +1 -1
- package/src/components/AppBase.vue +960 -405
- package/src/components/AppBaseButton.test.js +21 -0
- package/src/components/AppBaseButton.vue +42 -10
- package/src/components/AppBaseErrorDisplay.vue +207 -189
- package/src/components/AppBaseFlipCard.vue +1 -0
- package/src/components/AppBaseModule.vue +769 -977
- package/src/components/AppBasePage.vue +635 -81
- package/src/components/AppBasePopover.vue +41 -0
- package/src/components/AppBaseSkeleton.vue +66 -0
- package/src/components/AppCompAudio.vue +256 -0
- package/src/components/AppCompBranchButtons.vue +79 -153
- package/src/components/AppCompButtonProgress.vue +21 -36
- package/src/components/AppCompCarousel.vue +231 -87
- package/src/components/{AppCompTranscript.vue → AppCompContainer.vue} +12 -2
- package/src/components/AppCompInputCheckBoxNx.vue +323 -0
- package/src/components/AppCompInputDropdownNx.vue +299 -0
- package/src/components/AppCompInputRadioNx.vue +284 -0
- package/src/components/AppCompInputTextNx.vue +153 -0
- package/src/components/AppCompInputTextTableNx.vue +202 -0
- package/src/components/AppCompInputTextToFillDropdownNx.vue +340 -0
- package/src/components/AppCompInputTextToFillNx.vue +313 -0
- package/src/components/AppCompJauge.vue +36 -10
- package/src/components/AppCompMenu.vue +246 -32
- package/src/components/AppCompMenuItem.vue +87 -21
- package/src/components/AppCompNavigation.vue +470 -447
- package/src/components/AppCompNoteCall.vue +93 -58
- package/src/components/AppCompNoteCredit.vue +423 -96
- package/src/components/AppCompPlayBarNext.vue +2288 -0
- package/src/components/AppCompPopUpNext.vue +504 -0
- package/src/components/AppCompQuizNext.vue +510 -0
- package/src/components/AppCompQuizRecall.vue +199 -99
- package/src/components/AppCompSVGNext.vue +346 -0
- package/src/components/AppCompSettingsMenu.vue +17 -16
- package/src/components/AppCompTableOfContent.vue +262 -99
- package/src/components/AppCompVideoPlayer.vue +183 -142
- package/src/components/BaseModule.vue +8 -20
- package/src/components/tests__/AppBaseButton.spec.js +53 -0
- package/src/components/tests__/useTimer.spec.js +91 -0
- package/src/composables/useIdleDetector.js +56 -0
- package/src/composables/useQuiz.js +89 -0
- package/src/composables/useTimer.js +172 -0
- package/src/directives/nvdaFix.js +53 -0
- package/src/externalComps/ModuleView.vue +22 -0
- package/src/externalComps/SummaryView.vue +91 -0
- package/src/main.js +397 -148
- package/src/module/stores/appStore.js +947 -0
- package/src/module/xapi/ADL.js +241 -60
- package/src/module/xapi/Crypto/Hasher.js +8 -8
- package/src/module/xapi/Crypto/WordArray.js +6 -6
- package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +4 -4
- package/src/module/xapi/Crypto/algorithms/C_algo.js +14 -18
- package/src/module/xapi/Crypto/algorithms/HMAC.js +1 -1
- package/src/module/xapi/Crypto/algorithms/SHA1.js +1 -1
- package/src/module/xapi/Crypto/encoders/Base.js +7 -7
- package/src/module/xapi/Crypto/encoders/Base64.js +3 -3
- package/src/module/xapi/Crypto/encoders/Hex.js +2 -2
- package/src/module/xapi/Crypto/encoders/Latin1.js +3 -3
- package/src/module/xapi/Crypto/encoders/Utf8.js +3 -3
- package/src/module/xapi/Statement/index.js +3 -3
- package/src/module/xapi/launch.js +10 -10
- package/src/module/xapi/utils.js +17 -17
- package/src/module/xapi/wrapper.js +219 -214
- package/src/module/xapi/xapiStatement.js +29 -29
- package/src/plugins/analytics.js +34 -0
- package/src/plugins/bus.js +7 -2
- package/src/plugins/gsap.js +5 -7
- package/src/plugins/helper.js +97 -34
- package/src/plugins/i18n.js +13 -18
- package/src/plugins/idb.js +45 -30
- package/src/plugins/save.js +1 -1
- package/src/plugins/scorm.js +15 -15
- package/src/plugins/xapi.js +2 -2
- package/src/public/index.html +22 -10
- package/src/router/index.js +29 -13
- package/src/router/routes.js +29 -54
- package/src/shared/generalfuncs.js +186 -30
- package/src/shared/validators.js +809 -40
- package/vitest.config.js +19 -0
- package/.eslintignore +0 -29
- package/.eslintrc.js +0 -86
- package/.prettierrc.js +0 -5
- package/babel.config.js +0 -3
- package/src/components/AppBaseDragChoice.vue +0 -91
- package/src/components/AppBaseDropZone.vue +0 -112
- package/src/components/AppCompBif.vue +0 -120
- package/src/components/AppCompDragAndDrop.vue +0 -339
- package/src/components/AppCompInputAssociation.vue +0 -332
- package/src/components/AppCompInputCheckBox.vue +0 -227
- package/src/components/AppCompInputDropdown.vue +0 -184
- package/src/components/AppCompInputRadio.vue +0 -169
- package/src/components/AppCompInputTextBox.vue +0 -91
- package/src/components/AppCompInputTextTable.vue +0 -155
- package/src/components/AppCompInputTextToFillDropdown.vue +0 -255
- package/src/components/AppCompInputTextToFillText.vue +0 -164
- package/src/components/AppCompMediaPlayer.vue +0 -397
- package/src/components/AppCompPlayBar.vue +0 -1319
- package/src/components/AppCompPopUp.vue +0 -522
- package/src/components/AppCompPopover.vue +0 -27
- package/src/components/AppCompQuiz.vue +0 -2989
- package/src/components/AppCompSVG.vue +0 -309
- package/src/mixins/$pageMixins.js +0 -459
- package/src/mixins/$quizMixins.js +0 -456
- package/src/mixins/timerMixin.js +0 -156
- package/src/module/store.js +0 -895
- package/src/plugins/timeManager.js +0 -77
- package/src/routes_bckp.js +0 -313
- package/src/routes_static.js +0 -344
- package/vue.config.js +0 -83
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="input-box">
|
|
3
|
-
<!--choices-->
|
|
4
|
-
<div class="parentQuizChoices" style="display:flex">
|
|
5
|
-
<app-base-drop-zone
|
|
6
|
-
key="default"
|
|
7
|
-
zone-id="default"
|
|
8
|
-
:choices-contenu="listZoneChoices['default']"
|
|
9
|
-
@drop-event-zone="dropEventZone($event)"
|
|
10
|
-
/>
|
|
11
|
-
</div>
|
|
12
|
-
<!--zones-->
|
|
13
|
-
<div style="display:flex">
|
|
14
|
-
<div
|
|
15
|
-
v-for="singleDragDropZone in inputData.zone_depots"
|
|
16
|
-
:key="singleDragDropZone.id"
|
|
17
|
-
:class="
|
|
18
|
-
`dragdroplist-${singleDragDropZone.id} ` +
|
|
19
|
-
classInput(singleDragDropZone.id)
|
|
20
|
-
"
|
|
21
|
-
>
|
|
22
|
-
<label
|
|
23
|
-
:for="`${inputDataId}_${singleDragDropZone.id}`"
|
|
24
|
-
v-html="singleDragDropZone.contenu.alt"
|
|
25
|
-
></label>
|
|
26
|
-
<app-base-drop-zone
|
|
27
|
-
:zone-id="singleDragDropZone.id"
|
|
28
|
-
:zone-contenu="singleDragDropZone.contenu"
|
|
29
|
-
:choices-contenu="listZoneChoices[singleDragDropZone.id]"
|
|
30
|
-
@drop-event-zone="dropEventZone($event)"
|
|
31
|
-
/>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
</template>
|
|
36
|
-
<script>
|
|
37
|
-
import $extendsQuiz from '../mixins/$quizMixins'
|
|
38
|
-
import AppBaseDropZone from './AppBaseDropZone.vue'
|
|
39
|
-
export default {
|
|
40
|
-
components: {
|
|
41
|
-
AppBaseDropZone
|
|
42
|
-
},
|
|
43
|
-
mixins: [$extendsQuiz],
|
|
44
|
-
|
|
45
|
-
props: {
|
|
46
|
-
inputType: {
|
|
47
|
-
type: String,
|
|
48
|
-
default: ''
|
|
49
|
-
},
|
|
50
|
-
inputDataId: {
|
|
51
|
-
type: String,
|
|
52
|
-
default: ''
|
|
53
|
-
},
|
|
54
|
-
inputData: {
|
|
55
|
-
type: Object,
|
|
56
|
-
default: () => {}
|
|
57
|
-
},
|
|
58
|
-
quizCompleted: {
|
|
59
|
-
type: Boolean,
|
|
60
|
-
default: false
|
|
61
|
-
},
|
|
62
|
-
solution: {
|
|
63
|
-
type: Object,
|
|
64
|
-
default: () => []
|
|
65
|
-
},
|
|
66
|
-
showSolution: {
|
|
67
|
-
type: Boolean,
|
|
68
|
-
default: false
|
|
69
|
-
},
|
|
70
|
-
shuffleAnswers: {
|
|
71
|
-
type: Boolean, //@todo add shuffle
|
|
72
|
-
default: false
|
|
73
|
-
},
|
|
74
|
-
quizDragDrop: {
|
|
75
|
-
type: Object,
|
|
76
|
-
default: () => {}
|
|
77
|
-
}, //use to pass the value of the input
|
|
78
|
-
quizSubmit: {
|
|
79
|
-
type: Boolean,
|
|
80
|
-
default: false
|
|
81
|
-
} //use to call a submit
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
data() {
|
|
85
|
-
return {
|
|
86
|
-
quizDragDropValue: {}, //not using quizDragDrop because quizDragDrop is a prop
|
|
87
|
-
listZoneChoices: {} //the choice in the actives zones
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
computed: {},
|
|
92
|
-
|
|
93
|
-
watch: {
|
|
94
|
-
/**
|
|
95
|
-
* @description to pass value to AppCompQuiz
|
|
96
|
-
* @param {Object} newValue
|
|
97
|
-
* @fires input-change
|
|
98
|
-
*/
|
|
99
|
-
quizDragDropValue(newValue) {
|
|
100
|
-
this.$emit('input-change', newValue)
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* @description to receive the value from AppCompQuiz
|
|
105
|
-
* @param {Object} newValue
|
|
106
|
-
*/
|
|
107
|
-
quizDragDrop(newValue) {
|
|
108
|
-
//check if all zone are empty
|
|
109
|
-
if (Object.keys(newValue).length > 0) {
|
|
110
|
-
let isReset = true
|
|
111
|
-
let isAnswered = false
|
|
112
|
-
for (const key in newValue) {
|
|
113
|
-
if (Object.hasOwnProperty.call(newValue, key)) {
|
|
114
|
-
const element = newValue[key]
|
|
115
|
-
if (element.length > 0) {
|
|
116
|
-
isReset = false
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (isReset) {
|
|
121
|
-
for (const key in this.listZoneChoices) {
|
|
122
|
-
if (Object.hasOwnProperty.call(this.listZoneChoices, key)) {
|
|
123
|
-
const element = this.listZoneChoices[key]
|
|
124
|
-
if (element.length > 0 && key !== 'default') {
|
|
125
|
-
isAnswered = true
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
if (isReset && isAnswered) {
|
|
131
|
-
//reset choice to default
|
|
132
|
-
this.listZoneChoices = { default: [] }
|
|
133
|
-
let listChoices = []
|
|
134
|
-
for (
|
|
135
|
-
let index2 = 0;
|
|
136
|
-
index2 < this.inputData.zone_depots.length;
|
|
137
|
-
index2++
|
|
138
|
-
) {
|
|
139
|
-
const element = this.inputData.zone_depots[index2]
|
|
140
|
-
this.$set(this.listZoneChoices, element.id, [])
|
|
141
|
-
}
|
|
142
|
-
//fill listZoneChoices to populate the zone
|
|
143
|
-
for (
|
|
144
|
-
let index = 0;
|
|
145
|
-
index < this.inputData.choix_deplaceable.length;
|
|
146
|
-
index++
|
|
147
|
-
) {
|
|
148
|
-
const choiceType = this.inputData.choix_deplaceable[index]
|
|
149
|
-
for (let repeat = 0; repeat < choiceType.repetition; repeat++) {
|
|
150
|
-
const singleChoice = {
|
|
151
|
-
choiceId: choiceType.id + '_' + repeat,
|
|
152
|
-
choiceValue: choiceType.id,
|
|
153
|
-
choiceContenu: choiceType.contenu
|
|
154
|
-
}
|
|
155
|
-
listChoices.push(singleChoice)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
this.listZoneChoices['default'] = listChoices
|
|
159
|
-
}
|
|
160
|
-
this.quizDragDropValue = newValue
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
/**
|
|
164
|
-
* @description to change the value passed
|
|
165
|
-
* @fires input-change to AppCompQuiz.vue
|
|
166
|
-
*/
|
|
167
|
-
listZoneChoices: {
|
|
168
|
-
handler(newValue) {
|
|
169
|
-
let newDragDropValue = {}
|
|
170
|
-
for (const key in newValue) {
|
|
171
|
-
if (key !== 'default') {
|
|
172
|
-
this.$set(newDragDropValue, key, [])
|
|
173
|
-
if (Object.hasOwnProperty.call(newValue, key)) {
|
|
174
|
-
if (key !== 'default') {
|
|
175
|
-
const zone = newValue[key]
|
|
176
|
-
//each item in the array
|
|
177
|
-
zone.forEach((choice) => {
|
|
178
|
-
newDragDropValue[key].push(choice.choiceValue)
|
|
179
|
-
})
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
this.$emit('input-change', newDragDropValue)
|
|
185
|
-
},
|
|
186
|
-
deep: true,
|
|
187
|
-
immediate: true
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
mounted() {
|
|
192
|
-
this.listZoneChoices = { default: [] }
|
|
193
|
-
let listChoices = []
|
|
194
|
-
for (let index2 = 0; index2 < this.inputData.zone_depots.length; index2++) {
|
|
195
|
-
const element = this.inputData.zone_depots[index2]
|
|
196
|
-
this.$set(this.listZoneChoices, element.id, [])
|
|
197
|
-
}
|
|
198
|
-
//fill listZoneChoices to populate the zone
|
|
199
|
-
for (
|
|
200
|
-
let index = 0;
|
|
201
|
-
index < this.inputData.choix_deplaceable.length;
|
|
202
|
-
index++
|
|
203
|
-
) {
|
|
204
|
-
const choiceType = this.inputData.choix_deplaceable[index]
|
|
205
|
-
for (let repeat = 0; repeat < choiceType.repetition; repeat++) {
|
|
206
|
-
const singleChoice = {
|
|
207
|
-
choiceId: choiceType.id + '_' + repeat,
|
|
208
|
-
choiceValue: choiceType.id,
|
|
209
|
-
choiceContenu: choiceType.contenu
|
|
210
|
-
}
|
|
211
|
-
listChoices.push(singleChoice)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (Object.keys(this.quizDragDrop).length > 0) {
|
|
216
|
-
for (const key in this.quizDragDrop) {
|
|
217
|
-
if (Object.hasOwnProperty.call(this.quizDragDrop, key)) {
|
|
218
|
-
const theZoneChoices = this.quizDragDrop[key]
|
|
219
|
-
for (let index3 = 0; index3 < theZoneChoices.length; index3++) {
|
|
220
|
-
const element = theZoneChoices[index3]
|
|
221
|
-
//find singleChoice
|
|
222
|
-
const theChoice = listChoices.filter(
|
|
223
|
-
(choice) => choice.choiceValue == element
|
|
224
|
-
)[0]
|
|
225
|
-
//add to zone
|
|
226
|
-
this.listZoneChoices[key].push(theChoice)
|
|
227
|
-
//remove from listChoices
|
|
228
|
-
listChoices = listChoices.filter(
|
|
229
|
-
(choice) => choice.choiceId !== theChoice.choiceId
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
//put the choices left in the default zone
|
|
236
|
-
this.listZoneChoices['default'] = listChoices
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
methods: {
|
|
240
|
-
/**
|
|
241
|
-
* @description check if a values exists in a array
|
|
242
|
-
* @param {Array} array
|
|
243
|
-
* @param value
|
|
244
|
-
* @returns {Boolean}
|
|
245
|
-
*/
|
|
246
|
-
containsValue(array, value) {
|
|
247
|
-
return array.includes(value)
|
|
248
|
-
},
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* @description shuffles an array used to randomized the option order if shuffleAnswers is true
|
|
252
|
-
* @param {Array} array
|
|
253
|
-
* @returns {Array}
|
|
254
|
-
* @todo redo shuffle
|
|
255
|
-
*/
|
|
256
|
-
shuffleArray(array) {
|
|
257
|
-
let newArray = []
|
|
258
|
-
let newArray2 = []
|
|
259
|
-
|
|
260
|
-
for (let i = 0; i < array.length; i++) {
|
|
261
|
-
const element = array[i]
|
|
262
|
-
//todo remove null values
|
|
263
|
-
newArray.push(element)
|
|
264
|
-
}
|
|
265
|
-
while (newArray.length > 0) {
|
|
266
|
-
let pos = Math.floor(newArray.length * Math.random())
|
|
267
|
-
newArray2.push(newArray[pos])
|
|
268
|
-
newArray.splice(pos, 1)
|
|
269
|
-
}
|
|
270
|
-
return newArray2
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* @description move 1 choice from zoneStart to zoneEnd
|
|
275
|
-
* @param {Object} value object with 3 attributes
|
|
276
|
-
* @param {String} value.zoneStart the original zone of the choice
|
|
277
|
-
* @param {String} value.zoneEnd the final zone of the choice
|
|
278
|
-
* @param {String} value.choiceId the choice
|
|
279
|
-
*/
|
|
280
|
-
dropEventZone(value) {
|
|
281
|
-
const zoneStart = value.zoneStart
|
|
282
|
-
const zoneEnd = value.zoneEnd
|
|
283
|
-
const choiceId = value.choiceId
|
|
284
|
-
if (zoneStart == zoneEnd) {
|
|
285
|
-
//do nothing or move
|
|
286
|
-
//@todo code here
|
|
287
|
-
console.log('same zone')
|
|
288
|
-
} else {
|
|
289
|
-
//find choice in zoneStart
|
|
290
|
-
const choicesList = this.listZoneChoices[zoneStart]
|
|
291
|
-
const theChoice = choicesList.filter(
|
|
292
|
-
(choice) => choice.choiceId == choiceId
|
|
293
|
-
)[0]
|
|
294
|
-
//move choice from zoneStart to zoneEnd
|
|
295
|
-
this.listZoneChoices[zoneEnd].push(theChoice)
|
|
296
|
-
const newChoicesList = choicesList.filter(
|
|
297
|
-
(choice) => choice.choiceId !== choiceId
|
|
298
|
-
)
|
|
299
|
-
this.listZoneChoices[zoneStart] = newChoicesList
|
|
300
|
-
}
|
|
301
|
-
},
|
|
302
|
-
/**
|
|
303
|
-
* @description compares 2 array
|
|
304
|
-
* @param {Array} array1
|
|
305
|
-
* @param {Array} array2
|
|
306
|
-
* @returns {Boolean}
|
|
307
|
-
*/
|
|
308
|
-
isEqual(array1, array2) {
|
|
309
|
-
// if length is not equal
|
|
310
|
-
if (array1.length != array2.length) {
|
|
311
|
-
return false
|
|
312
|
-
} else {
|
|
313
|
-
// comapring each element of array
|
|
314
|
-
for (let i = 0; i < array1.length; i++) {
|
|
315
|
-
if (array1[i] != array2[i]) {
|
|
316
|
-
return false
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return true
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
</script>
|
|
325
|
-
<style scoped>
|
|
326
|
-
.quizZone,
|
|
327
|
-
.quizZoneActive {
|
|
328
|
-
height: 300px;
|
|
329
|
-
width: 300px;
|
|
330
|
-
border: solid 1px;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
.quizZone {
|
|
334
|
-
border-color: black;
|
|
335
|
-
}
|
|
336
|
-
.quizZoneActive {
|
|
337
|
-
border-color: red;
|
|
338
|
-
}
|
|
339
|
-
</style>
|
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="input-box">
|
|
3
|
-
<div style="display:flex">
|
|
4
|
-
<div
|
|
5
|
-
v-for="singleAssociationZone in inputData.zone_depots"
|
|
6
|
-
:key="singleAssociationZone.id"
|
|
7
|
-
:class="
|
|
8
|
-
`associationlist-${singleAssociationZone.id} ` +
|
|
9
|
-
classInput(singleAssociationZone.id)
|
|
10
|
-
"
|
|
11
|
-
>
|
|
12
|
-
<label
|
|
13
|
-
:for="`${inputDataId}_${singleAssociationZone.id}`"
|
|
14
|
-
v-html="singleAssociationZone.contenu.alt"
|
|
15
|
-
></label>
|
|
16
|
-
<div
|
|
17
|
-
:class="
|
|
18
|
-
quizClickedZone == singleAssociationZone.id
|
|
19
|
-
? 'quizZoneActive'
|
|
20
|
-
: 'quizZone'
|
|
21
|
-
"
|
|
22
|
-
@click="activateChoice(singleAssociationZone.id)"
|
|
23
|
-
>
|
|
24
|
-
<!--zone is img-->
|
|
25
|
-
<div
|
|
26
|
-
v-if="singleAssociationZone.contenu.type == 'img'"
|
|
27
|
-
class="quizZoneIsImg"
|
|
28
|
-
>
|
|
29
|
-
<img
|
|
30
|
-
:src="singleAssociationZone.contenu.affichage"
|
|
31
|
-
:alt="singleAssociationZone.contenu.alt"
|
|
32
|
-
/>
|
|
33
|
-
</div>
|
|
34
|
-
<!--zone is text-->
|
|
35
|
-
<div
|
|
36
|
-
v-if="singleAssociationZone.contenu.type == 'str'"
|
|
37
|
-
class="quizZoneIsText"
|
|
38
|
-
>
|
|
39
|
-
<p v-html="singleAssociationZone.contenu.affichage"></p>
|
|
40
|
-
</div>
|
|
41
|
-
<!--selected item-->
|
|
42
|
-
<!---selected is img--->
|
|
43
|
-
<div
|
|
44
|
-
v-if="
|
|
45
|
-
quizAssociation[singleAssociationZone.id] &&
|
|
46
|
-
quizAssociation[singleAssociationZone.id] !== '' &&
|
|
47
|
-
inputData.choix_deplaceable[
|
|
48
|
-
quizAssociation[singleAssociationZone.id]
|
|
49
|
-
].contenu.type == 'img'
|
|
50
|
-
"
|
|
51
|
-
class="quizZoneWithImg"
|
|
52
|
-
>
|
|
53
|
-
<img
|
|
54
|
-
:src="
|
|
55
|
-
inputData.choix_deplaceable[
|
|
56
|
-
quizAssociation[singleAssociationZone.id]
|
|
57
|
-
].contenu.affichage
|
|
58
|
-
"
|
|
59
|
-
:alt="
|
|
60
|
-
inputData.choix_deplaceable[
|
|
61
|
-
quizAssociation[singleAssociationZone.id]
|
|
62
|
-
].contenu.alt
|
|
63
|
-
"
|
|
64
|
-
/>
|
|
65
|
-
</div>
|
|
66
|
-
<!---selected is text--->
|
|
67
|
-
<div
|
|
68
|
-
v-if="
|
|
69
|
-
quizAssociation[singleAssociationZone.id] &&
|
|
70
|
-
quizAssociation[singleAssociationZone.id] !== '' &&
|
|
71
|
-
inputData.choix_deplaceable[
|
|
72
|
-
quizAssociation[singleAssociationZone.id]
|
|
73
|
-
].contenu.type == 'str'
|
|
74
|
-
"
|
|
75
|
-
class="quizZoneWithText"
|
|
76
|
-
>
|
|
77
|
-
<p
|
|
78
|
-
v-html="
|
|
79
|
-
inputData.choix_deplaceable[
|
|
80
|
-
quizAssociation[singleAssociationZone.id]
|
|
81
|
-
].contenu.affichage
|
|
82
|
-
"
|
|
83
|
-
></p>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
<!--choices-->
|
|
89
|
-
<div
|
|
90
|
-
style="display:flex"
|
|
91
|
-
:class="quizClickedZone ? 'parentQuizChoicesActive' : 'parentQuizChoices'"
|
|
92
|
-
>
|
|
93
|
-
<div
|
|
94
|
-
v-for="singleAssociationChoice in inputData.choix_deplaceable"
|
|
95
|
-
:key="singleAssociationChoice.id"
|
|
96
|
-
:class="`associationlist-${singleAssociationChoice.id}`"
|
|
97
|
-
>
|
|
98
|
-
<label
|
|
99
|
-
:for="`${inputDataId}_${singleAssociationChoice.id}`"
|
|
100
|
-
v-html="singleAssociationChoice.contenu.alt"
|
|
101
|
-
></label>
|
|
102
|
-
<div
|
|
103
|
-
class="quizAssociationChoice"
|
|
104
|
-
@click="assignValueToZone(singleAssociationChoice.id)"
|
|
105
|
-
>
|
|
106
|
-
<!---is img--->
|
|
107
|
-
<div
|
|
108
|
-
v-if="singleAssociationChoice.contenu.type == 'img'"
|
|
109
|
-
class="quizChoiceWithImg"
|
|
110
|
-
>
|
|
111
|
-
<img
|
|
112
|
-
:src="singleAssociationChoice.contenu.affichage"
|
|
113
|
-
:alt="singleAssociationChoice.contenu.alt"
|
|
114
|
-
/>
|
|
115
|
-
</div>
|
|
116
|
-
<!---is text--->
|
|
117
|
-
<div
|
|
118
|
-
v-if="singleAssociationChoice.contenu.type == 'str'"
|
|
119
|
-
class="quizChoiceWithText"
|
|
120
|
-
>
|
|
121
|
-
<p v-html="singleAssociationChoice.contenu.affichage"></p>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
</template>
|
|
128
|
-
<script>
|
|
129
|
-
import $extendsQuiz from '../mixins/$quizMixins'
|
|
130
|
-
export default {
|
|
131
|
-
mixins: [$extendsQuiz],
|
|
132
|
-
|
|
133
|
-
props: {
|
|
134
|
-
inputType: {
|
|
135
|
-
type: String,
|
|
136
|
-
default: ''
|
|
137
|
-
},
|
|
138
|
-
inputDataId: {
|
|
139
|
-
type: String,
|
|
140
|
-
default: ''
|
|
141
|
-
},
|
|
142
|
-
inputData: {
|
|
143
|
-
type: Object,
|
|
144
|
-
default: () => {}
|
|
145
|
-
},
|
|
146
|
-
quizCompleted: {
|
|
147
|
-
type: Boolean,
|
|
148
|
-
default: false
|
|
149
|
-
},
|
|
150
|
-
solution: {
|
|
151
|
-
type: Object,
|
|
152
|
-
default: () => []
|
|
153
|
-
},
|
|
154
|
-
showSolution: {
|
|
155
|
-
type: Boolean,
|
|
156
|
-
default: false
|
|
157
|
-
},
|
|
158
|
-
shuffleAnswers: {
|
|
159
|
-
type: Boolean,
|
|
160
|
-
default: false
|
|
161
|
-
},
|
|
162
|
-
quizAssociation: {
|
|
163
|
-
type: Object,
|
|
164
|
-
default: () => {}
|
|
165
|
-
}, //use to pass the value of the input
|
|
166
|
-
quizSubmit: {
|
|
167
|
-
type: Boolean,
|
|
168
|
-
default: false
|
|
169
|
-
} //use to call a submit
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
data() {
|
|
173
|
-
return {
|
|
174
|
-
quizClickedZone: '', //for the id of the last clicked zone to assign the choice
|
|
175
|
-
quizAssociationValue: [] //not using quizAssociation because quizAssociation is a prop
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
computed: {
|
|
180
|
-
/**
|
|
181
|
-
* @description
|
|
182
|
-
*
|
|
183
|
-
quizZoneContent(zoneId) {
|
|
184
|
-
//check if zone is filled
|
|
185
|
-
if (zoneId == false) {
|
|
186
|
-
// check if zone has image
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
return zoneId
|
|
190
|
-
}*/
|
|
191
|
-
},
|
|
192
|
-
|
|
193
|
-
watch: {
|
|
194
|
-
/**
|
|
195
|
-
* @description to pass value to AppCompQuiz
|
|
196
|
-
* @fires input-change to AppCompQuiz.vue
|
|
197
|
-
*/
|
|
198
|
-
quizAssociationValue(newValue) {
|
|
199
|
-
this.$emit('input-change', newValue)
|
|
200
|
-
},
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* @description to pass the value from AppCompQuiz
|
|
204
|
-
*/
|
|
205
|
-
quizAssociation(newValue) {
|
|
206
|
-
this.quizAssociationValue = newValue
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
mounted() {
|
|
211
|
-
let associatedChoices = []
|
|
212
|
-
for (let i = 0; i < this.inputData.length; i++) {
|
|
213
|
-
let singleAssociation
|
|
214
|
-
if (this.shuffleAnswers) {
|
|
215
|
-
singleAssociation = this.inputData[i]
|
|
216
|
-
//@todo shuffle
|
|
217
|
-
singleAssociation.option = this.shuffleArray(singleAssociation.option)
|
|
218
|
-
} else {
|
|
219
|
-
singleAssociation = this.inputData[i]
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if (this.quizAssociation.length == 0) {
|
|
223
|
-
this.quizAssociationValue = associatedChoices
|
|
224
|
-
} else {
|
|
225
|
-
this.quizAssociationValue = this.quizAssociation
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
methods: {
|
|
230
|
-
/**
|
|
231
|
-
* @description check if a values exists in a array
|
|
232
|
-
* @param {Array} array
|
|
233
|
-
* @param value
|
|
234
|
-
* @returns {Boolean}
|
|
235
|
-
*/
|
|
236
|
-
containsValue(array, value) {
|
|
237
|
-
return array.includes(value)
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* @description shuffles an array used to randomized the option order if shuffleAnswers is true
|
|
242
|
-
* @param {Array} array
|
|
243
|
-
* @returns {Array}
|
|
244
|
-
* @todo redo shuffle
|
|
245
|
-
*/
|
|
246
|
-
shuffleArray(array) {
|
|
247
|
-
let newArray = []
|
|
248
|
-
let newArray2 = []
|
|
249
|
-
|
|
250
|
-
for (let i = 0; i < array.length; i++) {
|
|
251
|
-
const element = array[i]
|
|
252
|
-
//todo remove null values
|
|
253
|
-
newArray.push(element)
|
|
254
|
-
}
|
|
255
|
-
while (newArray.length > 0) {
|
|
256
|
-
let pos = Math.floor(newArray.length * Math.random())
|
|
257
|
-
newArray2.push(newArray[pos])
|
|
258
|
-
newArray.splice(pos, 1)
|
|
259
|
-
}
|
|
260
|
-
return newArray2
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* @description activates choices to assign to that zone
|
|
265
|
-
* @param {String} zoneId
|
|
266
|
-
*/
|
|
267
|
-
activateChoice(zoneId) {
|
|
268
|
-
if (this.quizClickedZone == zoneId) {
|
|
269
|
-
this.quizClickedZone = ''
|
|
270
|
-
} else {
|
|
271
|
-
this.quizClickedZone = zoneId
|
|
272
|
-
}
|
|
273
|
-
},
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* @description remove current uses of value and assign value to quiz
|
|
277
|
-
* @param {String} choiceId
|
|
278
|
-
*/
|
|
279
|
-
assignValueToZone(choiceId) {
|
|
280
|
-
if (this.quizClickedZone !== '' && choiceId !== '') {
|
|
281
|
-
//remove current uses of value
|
|
282
|
-
for (const singleKey in this.quizAssociationValue) {
|
|
283
|
-
if (
|
|
284
|
-
Object.hasOwnProperty.call(this.quizAssociationValue, singleKey)
|
|
285
|
-
) {
|
|
286
|
-
const element = this.quizAssociationValue[singleKey]
|
|
287
|
-
if (element == choiceId) {
|
|
288
|
-
this.$set(this.quizAssociationValue, singleKey, '')
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
/*
|
|
293
|
-
let listKeys = Object.keys(this.quizAssociationValue)
|
|
294
|
-
for (let index = 0; index < listKeys.length; index++) {
|
|
295
|
-
if (this.quizAssociationValue[listKeys[index]] == choiceId) {
|
|
296
|
-
this.$set(this.quizAssociationValue, listKeys[index], '')
|
|
297
|
-
}
|
|
298
|
-
}*/
|
|
299
|
-
//assing value
|
|
300
|
-
this.$set(this.quizAssociationValue, this.quizClickedZone, choiceId)
|
|
301
|
-
//deactivate choices
|
|
302
|
-
this.quizClickedZone = ''
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
</script>
|
|
308
|
-
<style scoped>
|
|
309
|
-
.quizZone,
|
|
310
|
-
.quizZoneActive {
|
|
311
|
-
height: 300px;
|
|
312
|
-
width: 300px;
|
|
313
|
-
border: solid 1px;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.quizZone {
|
|
317
|
-
border-color: black;
|
|
318
|
-
}
|
|
319
|
-
.quizZoneActive {
|
|
320
|
-
border-color: red;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
.parentQuizChoicesActive {
|
|
324
|
-
background: yellow;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
.quizAssociationChoice {
|
|
328
|
-
height: 300px;
|
|
329
|
-
width: 300px;
|
|
330
|
-
border: solid black 1px;
|
|
331
|
-
}
|
|
332
|
-
</style>
|