X-Git-Url: https://git.auder.net/?p=qomet.git;a=blobdiff_plain;f=public%2Fjavascripts%2Fcomponents%2Fstatements.js;h=64057f9122661a19973fc3d10795ec90f061d09f;hp=900a5e7c698720220266d44bd36f436ccf67fdc2;hb=73609d3bc662cf4c8a21746c5d1ad736ea0eecbd;hpb=a80c6a3b87f75653725f54caca1f24abc556afc7 diff --git a/public/javascripts/components/statements.js b/public/javascripts/components/statements.js index 900a5e7..64057f9 100644 --- a/public/javascripts/components/statements.js +++ b/public/javascripts/components/statements.js @@ -14,10 +14,14 @@ Imaginary example: (using math.js)
Calculer le déterminant de $$\begin{matrix}7 & x\\y & -3\end{matrix}$$
* ... + +--> input of type text (number, or vector, or matrix e.g. in R syntax) +--> parameter stored in question.param (TODO) + */ Vue.component("statements", { - // 'inputs': array of index (as in questions) + input (text or array of ints) + // 'inputs': object with key = question index and value = text or boolean array // display: 'all', 'one', 'solution' // iidx: current level-0 integer index (can match a group of questions / inputs) props: ['questions','inputs','display','iidx'], @@ -28,113 +32,139 @@ Vue.component("statements", { } // Full questions tree is rendered, but some parts hidden depending on display settings render(h) { - let domTree = (this.questions || [ ]).map( (q,i) => { - let questionContent = [ ]; - questionContent.push( - h( - "h4", - { - "class": { - "questionIndex": true, - } - }, - q.index - ) - ); - questionContent.push( - h( - "div", - { - "class": { - wording: true, - - }, - domProps: { - innerHTML: q.wording, + // Prepare questions groups, ordered + let questions = this.questions || [ ] + let questionGroups = _.groupBy(questions, q => { + const dotPos = q.index.indexOf("."); + return dotPos === -1 ? q.index : q.index.substring(0,dotPos); + }); + let domTree = questionGroups.map( (qg,i) => { + // Re-order questions 1.1.1 then 1.1.2 then... + const orderedQg = qg.sort( (a,b) => { + let aParts = a.split('.').map(Number); + let bParts = b.split('.').map(Number); + const La = aParts.length, Lb = bParts.length; + for (let i=0; i { + let questionContent = [ ]; + questionContent.push( + h( + "h4", + { + "class": { + "questionIndex": true, + } }, - } - ) - ); - if (!!q.options) - { - // quiz-like question - let optionsOrder = _.range(q.options.length); - if (!q.fixed) - optionsOrder = _.shuffle(optionsOrder); - let optionList = [ ]; - optionsOrder.forEach( idx => { - let option = [ ]; - option.push( - h( - "input", - { - domProps: { - checked: this.answers.inputs.length > 0 && this.answers.inputs[i][idx], - disabled: monitoring, - }, - attrs: { - id: this.inputId(i,idx), - type: "checkbox", - }, - on: { - change: e => { this.answers.inputs[i][idx] = e.target.checked; }, - }, + q.index + ) + ); + questionContent.push( + h( + "div", + { + "class": { + wording: true, }, - [ '' ] //to work in Firefox 45.9 ESR @ ENSTA... - ) - ); - option.push( - h( - "label", - { - domProps: { - innerHTML: q.options[idx], + domProps: { + innerHTML: q.wording, + }, + } + ) + ); + if (!!q.options) + { + // quiz-like question + let optionsOrder = _.range(q.options.length); + if (!q.fixed) + optionsOrder = _.shuffle(optionsOrder); + let optionList = [ ]; + optionsOrder.forEach( idx => { + let option = [ ]; + option.push( + h( + "input", + { + domProps: { + checked: this.inputs[q.index][idx], + disabled: monitoring, + }, + attrs: { + id: this.inputId(q.index,idx), + type: "checkbox", + }, + on: { + change: e => { this.inputs[q.index][idx] = e.target.checked; }, + }, }, - attrs: { - "for": this.inputId(i,idx), + [ '' ] //to work in Firefox 45.9 ESR @ ENSTA... + ) + ); + option.push( + h( + "label", + { + domProps: { + innerHTML: q.options[idx], + }, + attrs: { + "for": this.inputId(q.index,idx), + }, + } + ) + ); + optionList.push( + h( + "div", + { + "class": { + option: true, + choiceCorrect: this.display == "solution" && q.answer.includes(idx), + choiceWrong: this.display == "solution" && this.inputs[q.index][idx] && !q.answer.includes(idx), + }, }, - } - ) - ); - optionList.push( + option + ) + ); + }); + questionContent.push( h( "div", { "class": { - option: true, - choiceCorrect: this.answers.showSolution && this.questions[i].answer.includes(idx), - choiceWrong: this.answers.showSolution && this.answers.inputs[i][idx] && !q.answer.includes(idx), + optionList: true, }, }, - option + optionList ) ); - }); - questionContent.push( - h( - "div", - { - "class": { - optionList: true, - }, + } + const depth = (q.index.match(/\./g) || []).length; + return h( + "div", + { + "class": { + "question": true, + "depth" + depth: true, }, - optionList - ) + }, + questionContent ); - } - if (this.display == "all" && !this.navigator && i < this.questions.length-1) - questionContent.push( h("hr") ); - const depth = (q.index.match(/\./g) || []).length; + }); return h( "div", { "class": { - "question": true, + "questionGroup": true, "hide": this.display == "one" && this.iidx != i, - "depth" + depth: true, }, - }, - questionContent + } + qgDom ); }); const navigator = h( @@ -158,7 +188,7 @@ Vue.component("statements", { }, }, [ h("span", { "class": { "material-icon": true } }, "fast_rewind") ] - ), //onclick: index = max(0,index-1) + ), h("span",{ },(this.iidx+1).toString()), h( "button",