Skip to content

Commit 8675340

Browse files
committed
Add main html file
1 parent 1127359 commit 8675340

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed

QuestionToMoodleXML.html

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
<html>
2+
<header>
3+
<title>Text questions to Moodle XML format</title>
4+
</header>
5+
<body>
6+
<script>
7+
8+
// Global variables
9+
var QuestionNumber = 1;
10+
var AllMultichoiceBool = true;
11+
var NumberingChoice = "123";
12+
var ShuffledAnswersBool = true;
13+
14+
function CDataExtra(Text)
15+
{
16+
return ('<![CDATA[' + Text + ']]>' );
17+
}
18+
19+
function GenerateXMLQuestion( Question, Answers )
20+
{
21+
if ( Question === '' && Answers.length == 0 )
22+
{
23+
// nothing to do
24+
return;
25+
}
26+
27+
// Working variables
28+
NumberOfAnswers = Answers.length;
29+
NumberOfGoodAnswers = 0;
30+
31+
// Question with 1 or no answer
32+
if ( Question !== '' && NumberOfAnswers <= 1 )
33+
{
34+
alertstr = "Question with only 1 answer or without answer!!!!!!\n\nQuestion was:\n" + Question + "\n";
35+
for (var i = 0; i < NumberOfAnswers; i++)
36+
{
37+
alertstr += Answers[i] + "\n";
38+
}
39+
alert( alertstr );
40+
throw( alertstr );
41+
}
42+
43+
// Count number of good answers
44+
for (var i = 0; i < NumberOfAnswers; i++)
45+
{
46+
if ( Answers[i][0] == '+' )
47+
{
48+
NumberOfGoodAnswers++;
49+
continue;
50+
}
51+
}
52+
53+
// No good answers?
54+
if ( NumberOfGoodAnswers == 0 )
55+
{
56+
alertstr = "Question without a good answer!!!!!!\n\n" + Question + "\n";
57+
for (var i = 0; i < NumberOfAnswers; i++)
58+
{
59+
alertstr += Answers[i] + "\n";
60+
}
61+
alert( alertstr );
62+
throw( alertstr );
63+
}
64+
65+
// Ok, at least 1 good answer and 2 answers in total, generate the question
66+
XMLQuestion = '<question type="multichoice">\n';
67+
XMLQuestion += '\t<name><text>' + CDataExtra(Question) + '</text></name>\n'; QuestionNumber++;
68+
XMLQuestion += '\t<generalfeedback format="html"><text></text></generalfeedback>\n';
69+
XMLQuestion += '\t<correctfeedback format="html"><text></text></correctfeedback>\n\t<partiallycorrectfeedback format="html"><text></text></partiallycorrectfeedback>\n\t<incorrectfeedback format="html"><text></text></incorrectfeedback>\n';
70+
71+
XMLQuestion += '\t<questiontext format="html">\n\t\t<text>' + CDataExtra(Question) + '</text>\n\t</questiontext>\n';
72+
XMLQuestion += '\t<defaultgrade>1.0000000</defaultgrade>\n';
73+
XMLQuestion += '\t<penalty>0.333333333</penalty>\n';
74+
XMLQuestion += '\t<answernumbering>' + NumberingChoice + '</answernumbering>\n';
75+
76+
XMLQuestion += '\t<hidden>0</hidden>\n';
77+
if ( AllMultichoiceBool === true || NumberOfGoodAnswers > 1 )
78+
{
79+
XMLQuestion += '\t<single>false</single>\n';
80+
}
81+
else
82+
{
83+
XMLQuestion += '\t<single>true</single>\n';
84+
}
85+
XMLQuestion += '\t<shuffleanswers>' + ShuffledAnswersBool.toString() + '</shuffleanswers>\n';
86+
87+
// Fraction
88+
Fraction = (100/NumberOfGoodAnswers).toString();
89+
90+
// Generate questions
91+
for (var i = 0; i < NumberOfAnswers; i++)
92+
{
93+
// Good answer
94+
if ( Answers[i][0] == '+' )
95+
{
96+
XMLQuestion += '\t<answer fraction="' + Fraction + '"';
97+
}
98+
else
99+
{
100+
XMLQuestion += '\t<answer fraction="0" ';
101+
}
102+
103+
XMLQuestion += ' format="html">\n\t\t<text>' + CDataExtra(Answers[i].replace( /^[+-]\s*/, '' )) + '</text>\n\t\t<feedback format="html"><text></text></feedback>\n\t</answer>\n';
104+
}
105+
106+
XMLQuestion += '</question>\n';
107+
108+
return XMLQuestion;
109+
}
110+
111+
function CreateXMLFile()
112+
{
113+
// Get values from the form
114+
filename = document.getElementById('filename').value;
115+
questionlist = document.getElementById('questionlist').value;
116+
117+
if ( questionlist.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ') === '' )
118+
{
119+
alert( "No questions given!!!" );
120+
return;
121+
}
122+
123+
// Working variables
124+
CurrentQuestion = '';
125+
CurrentAnswers = [];
126+
127+
// Reset global question number to 1
128+
QuestionNumber = 1;
129+
AllMultichoiceBool = document.getElementById("multichoice").checked;
130+
NumberingChoice = document.getElementById("Numbering").value;
131+
ShuffledAnswersBool = document.getElementById("shuffled").value;
132+
133+
// Start document with XML Prolog
134+
QuestionList = '<?xml version="1.0" encoding="UTF-8"?>\n<quiz>\n\n';
135+
136+
// Is there a category?
137+
Category = document.getElementById("category").value;
138+
if ( Category != '' )
139+
{
140+
QuestionList += '<!-- question: 0 -->\n<question type="category">\n\t<category><text>$course$/top</text></category>\n</question>\n';
141+
QuestionList += '<!-- question: 0 -->\n<question type="category">\n\t<category><text>$course$/top/' + CDataExtra(Category) + '</text></category>\n</question>\n\n';
142+
}
143+
144+
// parse text to make list of questions
145+
var lines = questionlist.split('\n');
146+
for( var i = 0; i < lines.length; i++ )
147+
{
148+
// Current line without extra spaces
149+
CurrentLine = lines[i].replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ');
150+
151+
// If current line is empty, go to next lines
152+
if ( CurrentLine === '' )
153+
{
154+
continue;
155+
}
156+
157+
// console.log( CurrentLine );
158+
159+
// Is it an answer line ?
160+
if ( CurrentLine[0] === '+' || CurrentLine[0] === '-' )
161+
{
162+
if ( CurrentLine.replace( /^[+-]\s*/, '' ).replace( /\s+/, '' ) === '' )
163+
{
164+
alert( "Answer (line starting with + or -) but no answer label:\nQuestion was:\n" + CurrentQuestion + "\n\nCurrent line:\n" + lines[i] );
165+
return;
166+
}
167+
168+
// If CurrentQuestion is empty, answer before the question
169+
if ( CurrentQuestion === '' )
170+
{
171+
alert( "Answer (line starting with + or -) before question label\n\nCurrent line:\n" + lines[i] );
172+
return;
173+
}
174+
CurrentAnswers.push(CurrentLine);
175+
}
176+
else
177+
{
178+
// We consider it is a question
179+
if ( CurrentQuestion !== '' )
180+
{
181+
// Ok, we have a previous question
182+
183+
// Check if previous question have answers
184+
if ( CurrentAnswers.length <= 1 )
185+
{
186+
// Ok, we have a question but no answer from the previous one
187+
alert( "Question with only 1 answer or without answer!!!!!!\n\nQuestion was:\n" + CurrentQuestion + "\n\nCurrent line:\n" + lines[i] );
188+
return;
189+
}
190+
191+
// Generate question (with its answer) before setting the new one
192+
QuestionList += GenerateXMLQuestion( CurrentQuestion, CurrentAnswers );
193+
// CurrentQuestion = ''; => Useless here, we will set it just below to its new value
194+
CurrentAnswers = [];
195+
}
196+
197+
CurrentQuestion = CurrentLine;
198+
continue;
199+
}
200+
}
201+
202+
// Call with last (or no) question if text area is empty
203+
QuestionList += GenerateXMLQuestion( CurrentQuestion, CurrentAnswers );
204+
QuestionList += '\n\n</quiz>\n';
205+
206+
// download the generated xml into a file called filename
207+
// Code from https://ourcodeworld.com/articles/read/189/how-to-create-a-file-and-generate-a-download-with-javascript-in-the-browser-without-a-server
208+
var element = document.createElement('a');
209+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(QuestionList));
210+
element.setAttribute('download', filename);
211+
212+
element.style.display = 'none';
213+
document.body.appendChild(element);
214+
215+
element.click();
216+
217+
document.body.removeChild(element);
218+
}
219+
</script>
220+
221+
<p>Step 1: You need to copy/paste the list of question within the following text area. :</p>
222+
<textarea id="questionlist" style="width: 80%;height:20em;display:block;"></textarea>
223+
<p>Step 2: Setup (or not) the category. If set, the category is a sub-bank of the question bank (category name can contain up to 20 letters, numbers, underscore and space):</p>
224+
<input type="text" id="category" style="display:block;" size="50" pattern="[A-Za-z_0-9 ]{20}" value="">
225+
<p>Step 3: Select if all questions are multichoice (thus, questions with 1 good answer will let student choose more than 1 answer):</p>
226+
<input type="checkbox" id="multichoice" name="multichoice" checked><label for="multichoice">All questions are multichoice</label>
227+
<p>Step 4: Select numbering of answers (default is none):</p>
228+
<select id="Numbering">
229+
<option value="123">1, 2, 3, ...</option>
230+
<option value="abc">a, b, c, ...</option>
231+
<option value="ABCD">A, B, C, ...</option>
232+
<option value="iii">i, ii, iii, ...</option>
233+
<option value="IIII">I, II, III, ...</option>
234+
<option value="none" selected>No numbering</option>
235+
</select>
236+
<p>Step 5: Select if answer should be shuffled (default: yes):</p>
237+
<input type="checkbox" id="shuffled" name="shuffled" checked><label for="shuffled">Shuffled answers</label>
238+
<p>Step 6: Setup (or not) filename:</p>
239+
<input type="text" id="filename" style="display:block;" size="50" value="QuestionInMoodleFormat.xml">
240+
<p>Step 7: Click on the button to get your file. You will be able to import it Excel, LibreOffice, Google docs, ...</p>
241+
<button onclick="CreateXMLFile();">Create import File!</button>
242+
</body>
243+
</html>

0 commit comments

Comments
 (0)