fcad-core-dragon 2.0.0-beta.7 → 2.0.0-beta.8
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 +33 -33
- package/.eslintignore +29 -29
- package/.eslintrc.cjs +81 -81
- package/CHANGELOG +6 -1
- package/README.md +71 -71
- package/bk.scss +117 -117
- package/package.json +1 -6
- package/src/assets/data/onboardingMessages.json +47 -47
- package/src/components/AppBase.vue +1 -1
- package/src/components/AppBaseErrorDisplay.vue +438 -438
- package/src/components/AppBaseFlipCard.vue +84 -84
- package/src/components/AppBaseModule.vue +0 -18
- package/src/components/AppBasePopover.vue +41 -41
- package/src/components/AppCompContainer.vue +1 -3
- package/src/components/AppCompInputRadioNext.vue +152 -152
- package/src/components/AppCompInputTextToFillNext.vue +171 -171
- package/src/components/AppCompJauge.vue +74 -74
- package/src/components/AppCompMenuItem.vue +228 -228
- package/src/components/AppCompPlayBarProgress.vue +82 -82
- package/src/components/AppCompSettingsMenu.vue +172 -172
- package/src/components/AppCompViewDisplay.vue +6 -6
- package/src/composables/useQuiz.js +206 -206
- package/src/externalComps/ModuleView.vue +22 -22
- package/src/externalComps/SummaryView.vue +91 -91
- package/src/mixins/$mediaMixins.js +819 -819
- package/src/mixins/timerMixin.js +155 -155
- package/src/module/xapi/Crypto/Hasher.js +241 -241
- package/src/module/xapi/Crypto/WordArray.js +278 -278
- package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
- package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
- package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
- package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
- package/src/module/xapi/Crypto/encoders/Base.js +105 -105
- package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
- package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
- package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
- package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
- package/src/module/xapi/Crypto/index.js +53 -53
- package/src/module/xapi/Statement/activity.js +47 -47
- package/src/module/xapi/Statement/agent.js +55 -55
- package/src/module/xapi/Statement/group.js +26 -26
- package/src/module/xapi/Statement/index.js +259 -259
- package/src/module/xapi/Statement/statement.js +253 -253
- package/src/module/xapi/Statement/statementRef.js +23 -23
- package/src/module/xapi/Statement/substatement.js +22 -22
- package/src/module/xapi/Statement/verb.js +36 -36
- package/src/module/xapi/activitytypes.js +17 -17
- package/src/module/xapi/utils.js +167 -167
- package/src/module/xapi/verbs.js +294 -294
- package/src/module/xapi/xapiStatement.js +444 -444
- package/src/plugins/bus.js +8 -8
- package/src/plugins/gsap.js +14 -14
- package/src/plugins/i18n.js +44 -44
- package/src/plugins/save.js +37 -37
- package/src/plugins/scorm.js +287 -287
- package/src/plugins/xapi.js +11 -11
- package/src/public/index.html +33 -33
- package/src/shared/generalfuncs.js +210 -210
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<!--
|
|
3
|
-
inspire by : https://vuejsexamples.com/generic-flip-card-in-vue-that-allows-completely-arbitrary-content-on-each-side/
|
|
4
|
-
-->
|
|
5
|
-
<div class="flip-card" role="button" aria-pressed="false" @click="fnClick">
|
|
6
|
-
<div class="inside-card" :class="{ flip: isFlipped }">
|
|
7
|
-
<div class="front-card" name="front-card">
|
|
8
|
-
<slot name="front-card" />
|
|
9
|
-
</div>
|
|
10
|
-
<div class="back-card">
|
|
11
|
-
<slot name="back-card" />
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
</template>
|
|
16
|
-
<script>
|
|
17
|
-
export default {
|
|
18
|
-
props: {
|
|
19
|
-
isActive: {
|
|
20
|
-
type: Boolean,
|
|
21
|
-
default: false
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
emits: ['click'],
|
|
25
|
-
data() {
|
|
26
|
-
return {
|
|
27
|
-
isFlipped: false
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
methods: {
|
|
31
|
-
/**
|
|
32
|
-
* @fires click to parent componant or page
|
|
33
|
-
*/
|
|
34
|
-
fnClick() {
|
|
35
|
-
this.$emit('click', this.$el)
|
|
36
|
-
this.isFlipped = !this.isFlipped
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
</script>
|
|
41
|
-
<style lang="scss">
|
|
42
|
-
.flip-card {
|
|
43
|
-
height: auto;
|
|
44
|
-
cursor: pointer;
|
|
45
|
-
|
|
46
|
-
/***** Parameretre modifiable *****/
|
|
47
|
-
perspective: 100%;
|
|
48
|
-
width: 90%;
|
|
49
|
-
|
|
50
|
-
.inside-card {
|
|
51
|
-
position: relative;
|
|
52
|
-
width: 100%;
|
|
53
|
-
height: 100%;
|
|
54
|
-
|
|
55
|
-
/***** Parameretre modifiable *****/
|
|
56
|
-
transform-style: preserve-3d;
|
|
57
|
-
transition: transform 0.5s;
|
|
58
|
-
|
|
59
|
-
&.flip {
|
|
60
|
-
/***** Parameretre modifiable *****/
|
|
61
|
-
transform: rotateY(180deg);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.front-card,
|
|
65
|
-
.back-card {
|
|
66
|
-
position: absolute;
|
|
67
|
-
width: 100%;
|
|
68
|
-
height: 100%;
|
|
69
|
-
-webkit-backface-visibility: hidden;
|
|
70
|
-
backface-visibility: hidden;
|
|
71
|
-
|
|
72
|
-
.img-flip-card {
|
|
73
|
-
width: 90%;
|
|
74
|
-
height: auto;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.back-card {
|
|
79
|
-
/***** Parameretre modifiable *****/
|
|
80
|
-
transform: rotateY(180deg);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<!--
|
|
3
|
+
inspire by : https://vuejsexamples.com/generic-flip-card-in-vue-that-allows-completely-arbitrary-content-on-each-side/
|
|
4
|
+
-->
|
|
5
|
+
<div class="flip-card" role="button" aria-pressed="false" @click="fnClick">
|
|
6
|
+
<div class="inside-card" :class="{ flip: isFlipped }">
|
|
7
|
+
<div class="front-card" name="front-card">
|
|
8
|
+
<slot name="front-card" />
|
|
9
|
+
</div>
|
|
10
|
+
<div class="back-card">
|
|
11
|
+
<slot name="back-card" />
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
<script>
|
|
17
|
+
export default {
|
|
18
|
+
props: {
|
|
19
|
+
isActive: {
|
|
20
|
+
type: Boolean,
|
|
21
|
+
default: false
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
emits: ['click'],
|
|
25
|
+
data() {
|
|
26
|
+
return {
|
|
27
|
+
isFlipped: false
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
methods: {
|
|
31
|
+
/**
|
|
32
|
+
* @fires click to parent componant or page
|
|
33
|
+
*/
|
|
34
|
+
fnClick() {
|
|
35
|
+
this.$emit('click', this.$el)
|
|
36
|
+
this.isFlipped = !this.isFlipped
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
<style lang="scss">
|
|
42
|
+
.flip-card {
|
|
43
|
+
height: auto;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
|
|
46
|
+
/***** Parameretre modifiable *****/
|
|
47
|
+
perspective: 100%;
|
|
48
|
+
width: 90%;
|
|
49
|
+
|
|
50
|
+
.inside-card {
|
|
51
|
+
position: relative;
|
|
52
|
+
width: 100%;
|
|
53
|
+
height: 100%;
|
|
54
|
+
|
|
55
|
+
/***** Parameretre modifiable *****/
|
|
56
|
+
transform-style: preserve-3d;
|
|
57
|
+
transition: transform 0.5s;
|
|
58
|
+
|
|
59
|
+
&.flip {
|
|
60
|
+
/***** Parameretre modifiable *****/
|
|
61
|
+
transform: rotateY(180deg);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.front-card,
|
|
65
|
+
.back-card {
|
|
66
|
+
position: absolute;
|
|
67
|
+
width: 100%;
|
|
68
|
+
height: 100%;
|
|
69
|
+
-webkit-backface-visibility: hidden;
|
|
70
|
+
backface-visibility: hidden;
|
|
71
|
+
|
|
72
|
+
.img-flip-card {
|
|
73
|
+
width: 90%;
|
|
74
|
+
height: auto;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.back-card {
|
|
79
|
+
/***** Parameretre modifiable *****/
|
|
80
|
+
transform: rotateY(180deg);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
@@ -23,10 +23,6 @@
|
|
|
23
23
|
class="app-nav"
|
|
24
24
|
:class="{ show: closeDelay }"
|
|
25
25
|
>
|
|
26
|
-
<!------------------------ Nav for drMode ------------------>
|
|
27
|
-
<!-- <app-comp-table-of-content /> -->
|
|
28
|
-
<!------------------------ Nav for FullMode ---------------->
|
|
29
|
-
|
|
30
26
|
<app-comp-navigation
|
|
31
27
|
:app-status="appReady ? true : null"
|
|
32
28
|
:auto-navigate="theNavigationBetweenActivity"
|
|
@@ -64,7 +60,6 @@
|
|
|
64
60
|
:aria-label="$t('label.side_panel')"
|
|
65
61
|
:class="{
|
|
66
62
|
'v-media': dynamicSidebarContent._context === 'ctxTranscript'
|
|
67
|
-
// 'right-sidebar-show': rightSidebarVisible
|
|
68
63
|
}"
|
|
69
64
|
>
|
|
70
65
|
<div id="right-sidebar-header">
|
|
@@ -618,12 +613,6 @@ export default {
|
|
|
618
613
|
|
|
619
614
|
if (code === 'Escape' && this.rightSidebarVisible)
|
|
620
615
|
return (this.rightSidebarVisible = false)
|
|
621
|
-
|
|
622
|
-
//==========================================
|
|
623
|
-
/*const videoRange = await this.getFocusables()
|
|
624
|
-
if (videoRange && videoRange.indexOf(document.activeElement) === -1)
|
|
625
|
-
return
|
|
626
|
-
this.$bus.$emit('play-media', code)*/
|
|
627
616
|
},
|
|
628
617
|
|
|
629
618
|
/**
|
|
@@ -753,11 +742,6 @@ export default {
|
|
|
753
742
|
//Change transcript content
|
|
754
743
|
if (this.transcriptContent !== c) this.transcriptContent = c
|
|
755
744
|
|
|
756
|
-
if (this.transcriptContainer && this.transcriptContainer !== container) {
|
|
757
|
-
/*console.log('transcriptContainer est différent de container')
|
|
758
|
-
console.log({ ancien: this.transcriptContainer, nouveau: container })
|
|
759
|
-
console.log('agrandir ancien container et réduire nouveau container')*/
|
|
760
|
-
}
|
|
761
745
|
this.transcriptContainer = container
|
|
762
746
|
this.transcriptVisible = true
|
|
763
747
|
},
|
|
@@ -1172,13 +1156,11 @@ export default {
|
|
|
1172
1156
|
let err = false
|
|
1173
1157
|
let errorList = [] //array for errors dectected
|
|
1174
1158
|
if (onboardingMessages && typeof onboardingMessages == 'object') {
|
|
1175
|
-
//continue
|
|
1176
1159
|
//check the list of attributes is message_X
|
|
1177
1160
|
let listMessage = Object.keys(onboardingMessages)
|
|
1178
1161
|
for (let index = 1; index <= listMessage.length; index++) {
|
|
1179
1162
|
const element = listMessage[index - 1]
|
|
1180
1163
|
if (element == 'message_' + index) {
|
|
1181
|
-
//continu
|
|
1182
1164
|
if (
|
|
1183
1165
|
onboardingMessages[element] &&
|
|
1184
1166
|
typeof onboardingMessages[element] == 'object'
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
@ Description: This component is used to create a popover that is accessible via keyboard navigation (tab + space/enter)
|
|
3
|
-
-->
|
|
4
|
-
<template>
|
|
5
|
-
<v-tooltip
|
|
6
|
-
ref="tooltip"
|
|
7
|
-
v-bind="$attrs"
|
|
8
|
-
v-model="show"
|
|
9
|
-
transition="false"
|
|
10
|
-
:open-on-click="true"
|
|
11
|
-
:persistent="false"
|
|
12
|
-
>
|
|
13
|
-
<slot></slot>
|
|
14
|
-
</v-tooltip>
|
|
15
|
-
</template>
|
|
16
|
-
|
|
17
|
-
<script>
|
|
18
|
-
export default {
|
|
19
|
-
name: 'AppBasePopover',
|
|
20
|
-
data() {
|
|
21
|
-
return {
|
|
22
|
-
show: false,
|
|
23
|
-
alertContainer: null
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
watch: {
|
|
27
|
-
show: {
|
|
28
|
-
handler(newValue) {
|
|
29
|
-
if (newValue) {
|
|
30
|
-
const content = this.$refs.tooltip.contentEl.textContent
|
|
31
|
-
this.alertContainer.textContent = ''
|
|
32
|
-
this.alertContainer.textContent = content
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
mounted() {
|
|
38
|
-
this.alertContainer = document.getElementById('hiddenAlertContainer')
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
</script>
|
|
1
|
+
<!--
|
|
2
|
+
@ Description: This component is used to create a popover that is accessible via keyboard navigation (tab + space/enter)
|
|
3
|
+
-->
|
|
4
|
+
<template>
|
|
5
|
+
<v-tooltip
|
|
6
|
+
ref="tooltip"
|
|
7
|
+
v-bind="$attrs"
|
|
8
|
+
v-model="show"
|
|
9
|
+
transition="false"
|
|
10
|
+
:open-on-click="true"
|
|
11
|
+
:persistent="false"
|
|
12
|
+
>
|
|
13
|
+
<slot></slot>
|
|
14
|
+
</v-tooltip>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script>
|
|
18
|
+
export default {
|
|
19
|
+
name: 'AppBasePopover',
|
|
20
|
+
data() {
|
|
21
|
+
return {
|
|
22
|
+
show: false,
|
|
23
|
+
alertContainer: null
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
watch: {
|
|
27
|
+
show: {
|
|
28
|
+
handler(newValue) {
|
|
29
|
+
if (newValue) {
|
|
30
|
+
const content = this.$refs.tooltip.contentEl.textContent
|
|
31
|
+
this.alertContainer.textContent = ''
|
|
32
|
+
this.alertContainer.textContent = content
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
mounted() {
|
|
38
|
+
this.alertContainer = document.getElementById('hiddenAlertContainer')
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
@@ -1,152 +1,152 @@
|
|
|
1
|
-
<!-- About this Component--
|
|
2
|
-
* Renders a RADIO BUTTON input to display choices of response for the Quiz component
|
|
3
|
-
* Related Quiz to question: REPONSE_UNIQUE
|
|
4
|
-
* Receives the a data object defined by user
|
|
5
|
-
* Used by AppCompQuizNext
|
|
6
|
-
* Uses useQuiz composable
|
|
7
|
-
-->
|
|
8
|
-
|
|
9
|
-
<template>
|
|
10
|
-
<div class="input-box">
|
|
11
|
-
<fieldset>
|
|
12
|
-
<legend
|
|
13
|
-
:id="`lgd_${inputDataId}`"
|
|
14
|
-
class="sr-only"
|
|
15
|
-
tabindex="-1"
|
|
16
|
-
v-html="$t('quizState.answers')"
|
|
17
|
-
/>
|
|
18
|
-
|
|
19
|
-
<template
|
|
20
|
-
v-for="choixReponse in quizInputDataValue"
|
|
21
|
-
:Key="`div_chx_${inputDataId}-${choixReponse.id}`"
|
|
22
|
-
>
|
|
23
|
-
<div class="box-radio" role="group">
|
|
24
|
-
<label
|
|
25
|
-
:key="`lbl_chx_${inputDataId}_${choixReponse.id}`"
|
|
26
|
-
:for="`chx_${inputDataId}_${choixReponse.id}`"
|
|
27
|
-
:class="classInput(choixReponse.id)"
|
|
28
|
-
class="radio-label"
|
|
29
|
-
>
|
|
30
|
-
<input
|
|
31
|
-
:id="`chx_${inputDataId}_${choixReponse.id}`"
|
|
32
|
-
:key="`chx_${inputDataId}_${choixReponse.id}`"
|
|
33
|
-
v-model="inputUniqueValue"
|
|
34
|
-
:disabled="quizLimitActive"
|
|
35
|
-
type="radio"
|
|
36
|
-
:value="choixReponse.id"
|
|
37
|
-
:name="`btn-radios-${inputDataId}`"
|
|
38
|
-
class="radio-input"
|
|
39
|
-
:aria-labelledby="`span_${inputDataId}_${choixReponse.id}`"
|
|
40
|
-
/>
|
|
41
|
-
|
|
42
|
-
<span
|
|
43
|
-
:id="`span_${inputDataId}_${choixReponse.id}`"
|
|
44
|
-
aria-hidden="true"
|
|
45
|
-
class="radio-contenu"
|
|
46
|
-
v-html="choixReponse.value"
|
|
47
|
-
/>
|
|
48
|
-
<span
|
|
49
|
-
:id="`${inputDataId}_${choixReponse.id}-msg-erreur`"
|
|
50
|
-
:key="`msg_chx_${inputDataId}_${choixReponse.id}`"
|
|
51
|
-
class="sr-only"
|
|
52
|
-
>
|
|
53
|
-
{{ messageAccessibility(choixReponse.id) }}
|
|
54
|
-
</span>
|
|
55
|
-
</label>
|
|
56
|
-
</div>
|
|
57
|
-
</template>
|
|
58
|
-
</fieldset>
|
|
59
|
-
</div>
|
|
60
|
-
</template>
|
|
61
|
-
<script>
|
|
62
|
-
import { useQuiz } from '../composables/useQuiz'
|
|
63
|
-
import { toRefs } from 'vue'
|
|
64
|
-
export default {
|
|
65
|
-
name: 'AppCompInputRadioNext',
|
|
66
|
-
|
|
67
|
-
props: {
|
|
68
|
-
quizType: {
|
|
69
|
-
type: String,
|
|
70
|
-
default: ''
|
|
71
|
-
},
|
|
72
|
-
inputDataId: {
|
|
73
|
-
type: String,
|
|
74
|
-
default: ''
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
inputData: {
|
|
78
|
-
type: Array,
|
|
79
|
-
default: () => []
|
|
80
|
-
},
|
|
81
|
-
quizInputType: {
|
|
82
|
-
type: String,
|
|
83
|
-
default: ''
|
|
84
|
-
},
|
|
85
|
-
solution: {
|
|
86
|
-
type: String,
|
|
87
|
-
default: ''
|
|
88
|
-
}, //may be null
|
|
89
|
-
showSolution: {
|
|
90
|
-
type: Boolean,
|
|
91
|
-
default: false
|
|
92
|
-
},
|
|
93
|
-
shuffleAnswers: {
|
|
94
|
-
type: Boolean,
|
|
95
|
-
default: false
|
|
96
|
-
},
|
|
97
|
-
quizLimitActive: {
|
|
98
|
-
type: Boolean,
|
|
99
|
-
default: false
|
|
100
|
-
}, //use to set if quiz should be active or not
|
|
101
|
-
|
|
102
|
-
quizSubmit: {
|
|
103
|
-
type: Boolean,
|
|
104
|
-
default: false
|
|
105
|
-
} //use to call a submit
|
|
106
|
-
},
|
|
107
|
-
emits: ['input-change'],
|
|
108
|
-
setup(props) {
|
|
109
|
-
const { shuffleArray, classInput, messageAccessibility } = useQuiz(
|
|
110
|
-
toRefs(props)
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
return { shuffleArray, classInput, messageAccessibility }
|
|
114
|
-
},
|
|
115
|
-
data() {
|
|
116
|
-
return {
|
|
117
|
-
quizInputDataValue: [],
|
|
118
|
-
inputUniqueValue: null //not using quizInputUnique because quizInputUnique is a prop
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
computed: {},
|
|
123
|
-
|
|
124
|
-
watch: {
|
|
125
|
-
// /**
|
|
126
|
-
// * @description to pass value to AppCompQuiz
|
|
127
|
-
// * @fires input-change to AppCompQuiz.vue
|
|
128
|
-
// */
|
|
129
|
-
inputUniqueValue: {
|
|
130
|
-
deep: true,
|
|
131
|
-
handler(newValue) {
|
|
132
|
-
this.$emit('input-change', newValue)
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
mounted() {
|
|
138
|
-
this.initQuiz()
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
methods: {
|
|
142
|
-
initQuiz() {
|
|
143
|
-
this.inputUniqueValue = this.quizInputType
|
|
144
|
-
if (this.shuffleAnswers) {
|
|
145
|
-
this.quizInputDataValue = this.shuffleArray(this.inputData)
|
|
146
|
-
} else {
|
|
147
|
-
this.quizInputDataValue = this.inputData
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
</script>
|
|
1
|
+
<!-- About this Component--
|
|
2
|
+
* Renders a RADIO BUTTON input to display choices of response for the Quiz component
|
|
3
|
+
* Related Quiz to question: REPONSE_UNIQUE
|
|
4
|
+
* Receives the a data object defined by user
|
|
5
|
+
* Used by AppCompQuizNext
|
|
6
|
+
* Uses useQuiz composable
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<div class="input-box">
|
|
11
|
+
<fieldset>
|
|
12
|
+
<legend
|
|
13
|
+
:id="`lgd_${inputDataId}`"
|
|
14
|
+
class="sr-only"
|
|
15
|
+
tabindex="-1"
|
|
16
|
+
v-html="$t('quizState.answers')"
|
|
17
|
+
/>
|
|
18
|
+
|
|
19
|
+
<template
|
|
20
|
+
v-for="choixReponse in quizInputDataValue"
|
|
21
|
+
:Key="`div_chx_${inputDataId}-${choixReponse.id}`"
|
|
22
|
+
>
|
|
23
|
+
<div class="box-radio" role="group">
|
|
24
|
+
<label
|
|
25
|
+
:key="`lbl_chx_${inputDataId}_${choixReponse.id}`"
|
|
26
|
+
:for="`chx_${inputDataId}_${choixReponse.id}`"
|
|
27
|
+
:class="classInput(choixReponse.id)"
|
|
28
|
+
class="radio-label"
|
|
29
|
+
>
|
|
30
|
+
<input
|
|
31
|
+
:id="`chx_${inputDataId}_${choixReponse.id}`"
|
|
32
|
+
:key="`chx_${inputDataId}_${choixReponse.id}`"
|
|
33
|
+
v-model="inputUniqueValue"
|
|
34
|
+
:disabled="quizLimitActive"
|
|
35
|
+
type="radio"
|
|
36
|
+
:value="choixReponse.id"
|
|
37
|
+
:name="`btn-radios-${inputDataId}`"
|
|
38
|
+
class="radio-input"
|
|
39
|
+
:aria-labelledby="`span_${inputDataId}_${choixReponse.id}`"
|
|
40
|
+
/>
|
|
41
|
+
|
|
42
|
+
<span
|
|
43
|
+
:id="`span_${inputDataId}_${choixReponse.id}`"
|
|
44
|
+
aria-hidden="true"
|
|
45
|
+
class="radio-contenu"
|
|
46
|
+
v-html="choixReponse.value"
|
|
47
|
+
/>
|
|
48
|
+
<span
|
|
49
|
+
:id="`${inputDataId}_${choixReponse.id}-msg-erreur`"
|
|
50
|
+
:key="`msg_chx_${inputDataId}_${choixReponse.id}`"
|
|
51
|
+
class="sr-only"
|
|
52
|
+
>
|
|
53
|
+
{{ messageAccessibility(choixReponse.id) }}
|
|
54
|
+
</span>
|
|
55
|
+
</label>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
</fieldset>
|
|
59
|
+
</div>
|
|
60
|
+
</template>
|
|
61
|
+
<script>
|
|
62
|
+
import { useQuiz } from '../composables/useQuiz'
|
|
63
|
+
import { toRefs } from 'vue'
|
|
64
|
+
export default {
|
|
65
|
+
name: 'AppCompInputRadioNext',
|
|
66
|
+
|
|
67
|
+
props: {
|
|
68
|
+
quizType: {
|
|
69
|
+
type: String,
|
|
70
|
+
default: ''
|
|
71
|
+
},
|
|
72
|
+
inputDataId: {
|
|
73
|
+
type: String,
|
|
74
|
+
default: ''
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
inputData: {
|
|
78
|
+
type: Array,
|
|
79
|
+
default: () => []
|
|
80
|
+
},
|
|
81
|
+
quizInputType: {
|
|
82
|
+
type: String,
|
|
83
|
+
default: ''
|
|
84
|
+
},
|
|
85
|
+
solution: {
|
|
86
|
+
type: String,
|
|
87
|
+
default: ''
|
|
88
|
+
}, //may be null
|
|
89
|
+
showSolution: {
|
|
90
|
+
type: Boolean,
|
|
91
|
+
default: false
|
|
92
|
+
},
|
|
93
|
+
shuffleAnswers: {
|
|
94
|
+
type: Boolean,
|
|
95
|
+
default: false
|
|
96
|
+
},
|
|
97
|
+
quizLimitActive: {
|
|
98
|
+
type: Boolean,
|
|
99
|
+
default: false
|
|
100
|
+
}, //use to set if quiz should be active or not
|
|
101
|
+
|
|
102
|
+
quizSubmit: {
|
|
103
|
+
type: Boolean,
|
|
104
|
+
default: false
|
|
105
|
+
} //use to call a submit
|
|
106
|
+
},
|
|
107
|
+
emits: ['input-change'],
|
|
108
|
+
setup(props) {
|
|
109
|
+
const { shuffleArray, classInput, messageAccessibility } = useQuiz(
|
|
110
|
+
toRefs(props)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return { shuffleArray, classInput, messageAccessibility }
|
|
114
|
+
},
|
|
115
|
+
data() {
|
|
116
|
+
return {
|
|
117
|
+
quizInputDataValue: [],
|
|
118
|
+
inputUniqueValue: null //not using quizInputUnique because quizInputUnique is a prop
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
computed: {},
|
|
123
|
+
|
|
124
|
+
watch: {
|
|
125
|
+
// /**
|
|
126
|
+
// * @description to pass value to AppCompQuiz
|
|
127
|
+
// * @fires input-change to AppCompQuiz.vue
|
|
128
|
+
// */
|
|
129
|
+
inputUniqueValue: {
|
|
130
|
+
deep: true,
|
|
131
|
+
handler(newValue) {
|
|
132
|
+
this.$emit('input-change', newValue)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
mounted() {
|
|
138
|
+
this.initQuiz()
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
methods: {
|
|
142
|
+
initQuiz() {
|
|
143
|
+
this.inputUniqueValue = this.quizInputType
|
|
144
|
+
if (this.shuffleAnswers) {
|
|
145
|
+
this.quizInputDataValue = this.shuffleArray(this.inputData)
|
|
146
|
+
} else {
|
|
147
|
+
this.quizInputDataValue = this.inputData
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
</script>
|