Commit | Line | Data |
---|---|---|
435371c7 | 1 | Vue.component("statements", { |
8a51dbf7 BA |
2 | // 'answers' is an object containing |
3 | // 'inputs'(array), | |
e49ec3e4 | 4 | // 'displayAll'(bool), //TODO: should be in questions! |
8a51dbf7 BA |
5 | // 'showSolution'(bool), |
6 | // 'indices': order of appearance | |
7 | // 'index': current integer index (focused question) | |
8 | props: ['questions','answers'], | |
435371c7 BA |
9 | // TODO: general render function for nested exercises |
10 | // There should be a questions navigator below, or next (visible if display=='all') | |
11 | // Full questions tree is rendered, but some parts hidden depending on display settings | |
12 | render(h) { | |
8a51dbf7 | 13 | // TODO: render nothing if answers is empty |
71d1ca9c | 14 | let domTree = (this.questions || [ ]).map( (q,i) => { |
435371c7 BA |
15 | let questionContent = [ ]; |
16 | questionContent.push( | |
17 | h( | |
18 | "div", | |
19 | { | |
20 | "class": { | |
21 | wording: true, | |
22 | }, | |
23 | domProps: { | |
24 | innerHTML: q.wording, | |
25 | }, | |
26 | } | |
27 | ) | |
28 | ); | |
29 | let optionsOrder = _.range(q.options.length); | |
30 | if (!q.fixed) | |
31 | optionsOrder = _.shuffle(optionsOrder); | |
32 | let optionList = [ ]; | |
33 | optionsOrder.forEach( idx => { | |
34 | let option = [ ]; | |
35 | option.push( | |
36 | h( | |
37 | "input", | |
38 | { | |
39 | domProps: { | |
8a51dbf7 | 40 | checked: this.answers.inputs.length > 0 && this.answers.inputs[i][idx], |
435371c7 BA |
41 | disabled: monitoring, |
42 | }, | |
43 | attrs: { | |
44 | id: this.inputId(i,idx), | |
45 | type: "checkbox", | |
46 | }, | |
47 | on: { | |
8a51dbf7 | 48 | change: e => { this.answers.inputs[i][idx] = e.target.checked; }, |
435371c7 BA |
49 | }, |
50 | }, | |
51 | ) | |
52 | ); | |
53 | option.push( | |
54 | h( | |
55 | "label", | |
56 | { | |
57 | domProps: { | |
58 | innerHTML: q.options[idx], | |
59 | }, | |
60 | attrs: { | |
61 | "for": this.inputId(i,idx), | |
62 | }, | |
63 | } | |
64 | ) | |
65 | ); | |
66 | optionList.push( | |
67 | h( | |
68 | "div", | |
69 | { | |
70 | "class": { | |
71 | option: true, | |
8a51dbf7 | 72 | choiceCorrect: this.answers.showSolution && this.questions[i].answer.includes(idx), |
71d1ca9c | 73 | choiceWrong: this.answers.showSolution && this.answers.inputs[i][idx] && !q.answer.includes(idx), |
435371c7 BA |
74 | }, |
75 | }, | |
76 | option | |
77 | ) | |
78 | ); | |
79 | }); | |
80 | questionContent.push( | |
81 | h( | |
82 | "div", | |
83 | { | |
84 | "class": { | |
85 | optionList: true, | |
86 | }, | |
87 | }, | |
88 | optionList | |
89 | ) | |
90 | ); | |
e49ec3e4 BA |
91 | if (this.answers.displayAll && i < this.questions.length-1) |
92 | questionContent.push( h("hr") ); | |
435371c7 BA |
93 | return h( |
94 | "div", | |
95 | { | |
96 | "class": { | |
97 | "question": true, | |
71d1ca9c | 98 | "hide": !this.answers.displayAll && this.answers.indices[this.answers.index] != i, |
435371c7 BA |
99 | }, |
100 | }, | |
101 | questionContent | |
102 | ); | |
103 | }); | |
104 | return h( | |
105 | "div", | |
106 | { | |
107 | attrs: { | |
108 | id: "statements", | |
109 | }, | |
110 | }, | |
71d1ca9c | 111 | domTree |
435371c7 BA |
112 | ); |
113 | }, | |
3b8117c5 BA |
114 | mounted: function() { |
115 | statementsLibsRefresh(); | |
116 | }, | |
435371c7 BA |
117 | updated: function() { |
118 | // TODO: next line shouldn't be required: questions wordings + answer + options | |
119 | // are processed earlier; their content should be updated at this time. | |
120 | statementsLibsRefresh(); | |
121 | }, | |
122 | methods: { | |
123 | inputId: function(i,j) { | |
124 | return "q" + i + "_" + "input" + j; | |
125 | }, | |
126 | }, | |
127 | }); |