2 //JMMIX-SPECIFIC SCORM-RELATED JAVASCRIPT CODE
4 function SetScormScore(){
5 //Reports the current score and any other information back to the LMS
7 API.LMSSetValue('cmi.core.score.raw', Score);
9 //Now send a detailed reports on the item
10 var ItemLabel = 'Item_1';
11 API.LMSSetValue('cmi.objectives.0.id', 'obj'+ItemLabel);
12 API.LMSSetValue('cmi.interactions.0.id', 'int'+ItemLabel);
13 if (Finished == true){
14 API.LMSSetValue('cmi.objectives.0.status', 'completed');
17 API.LMSSetValue('cmi.objectives.0.status', 'incomplete');
20 API.LMSSetValue('cmi.objectives.0.score.min', '0');
21 API.LMSSetValue('cmi.objectives.0.score.max', '100');
22 API.LMSSetValue('cmi.objectives.0.score.raw', Score);
23 //We can only use the performance type, because we're storing multiple responses of various types.
24 API.LMSSetValue('cmi.interactions.0.type', 'performance');
25 API.LMSSetValue('cmi.interactions.0.student_response', AnswersTried);
33 //JMIX DRAG-DROP OUTPUT FORMAT CODE
35 var Punctuation = '[strPunctuation]';
37 var Openers = '[strOpenPunctuation]';
38 var CorrectResponse = '[strGuessCorrect]';
39 var IncorrectResponse = '[strGuessIncorrect]';
40 var ThisMuchCorrect = '[strThisMuch]';
41 var TheseAnswersToo = '[strTheseAnswersToo]';
42 var YourScoreIs = '[strYourScoreIs]';
43 var NextCorrect = '[strNextCorrect]';
44 var FeedbackWidth = 200; //default
45 var ExBGColor = '[strExBGColor]';
46 var PageBGColor = '[strPageBGColor]';
47 var TextColor = '[strTextColor]';
48 var TitleColor = '[strTitleColor]';
49 var DropTotal = 3; // number of lines that will be available for dropping on
50 var Gap = 4; //Gap between two segments when they're next to each other on a line
52 var CapitalizeFirst = [boolCapitalizeFirst];
53 var CompiledOutput = '';
55 var FirstSegment = -1;
63 var Cds = new Array();
72 var AnswersTried = '';
76 function CapFirst(InString){
78 if ((Openers.indexOf(InString.charAt(i))>-1)||(InString.charAt(i) == ' ')){
81 if ((Openers.indexOf(InString.charAt(i))>-1)||(InString.charAt(i) == ' ')){
84 var Temp = InString.charAt(i);
85 Temp = Temp.toUpperCase();
86 InString = InString.substring(0, i) + Temp + InString.substring(i+1, InString.length);
90 function CheckResults(ChkType){
91 //Get sequence student has chosen
95 CompiledOutput = CompileString(GuessSequence);
101 function GetGuessSequence(){
102 //Put pointers to draggables in arrays based on the lines they're sitting on
103 var Drops = new Array();
104 for (var i=0; i<L.length; i++){
105 Drops[i] = new Array();
110 for (i=0; i<Cds.length; i++){
111 for (var j=0; j<L.length; j++){
112 //Slight modification for 6.0.4: allow some leeway for 1px inaccuracy in card placing by browser.
113 CardPos = L[j].GetB() - (Cds[i].GetH()+2);
114 if (((Cds[i].GetT() - CardPos) < 4)&&((Cds[i].GetT() - CardPos) > -4)){
115 Drops[j][Drops[j].length] = Cds[i];
120 //Sort the drop arrays based on the Left of each div
121 for (i=0; i<Drops.length; i++){
122 Drops[i].sort(CompDrags);
125 //Put the tags into the GuessSequence array
126 GuessSequence.length = 0;
127 for (i=0; i<Drops.length; i++){
128 for (j=0; j<Drops[i].length; j++){
129 GuessSequence[GuessSequence.length] = Drops[i][j].tag;
133 //Set the variable recording which div is first
134 var NewFirstDiv = -1;
135 for (i=0; i<Drops.length; i++){
136 if (Drops[i].length > 0){
137 NewFirstDiv = Drops[i][0].index;
144 function CompDrags(a,b){
145 return a.GetL() - b.GetL();
148 function FindSegment(SegID){
150 for (var i=0; i<Segments.length; i++){
151 if (Segments[i][1] == SegID){
152 Seg = Segments[i][0];
159 function CompileString(InArray){
162 OutArray = new Array();
164 for (i=0; i<InArray.length; i++){
165 OutArray[OutArray.length] = FindSegment(InArray[i]);
168 if (OutArray.length > 0){
169 OutString = OutArray[0];
176 for (i=1; i<OutArray.length; i++){
178 if ((Openers.indexOf(OutString.charAt(OutString.length-1)) > -1)||(Punctuation.indexOf(OutArray[i].charAt(0)) > -1)){
181 OutString = OutString + Spacer + OutArray[i];
184 //Capitalize the first letter if necessary
185 if (CapitalizeFirst == true){
186 OutString = CapFirst(OutString);
191 function CheckAnswer(CheckType){
192 if (Locked == true){return;}
193 if (GuessSequence.length < 1){
196 ShowMessage(NextCorrect + '<br /><br />' + FindSegment(Answers[0][0]));
204 var WhichCorrect = -1;
206 var LongestCorrectBit = '';
207 TempCorrect = new Array();
208 LongestCorrect = new Array();
210 var HintToReturn = 1;
211 var OtherAnswers = '';
214 for (i=0; i<Answers.length; i++){
215 TempCorrect.length = 0;
216 for (j=0; j<Answers[i].length; j++){
217 if (Answers[i][j] == GuessSequence[j]){
218 TempCorrect[j] = GuessSequence[j];
221 TempHint = Answers[i][j];
225 if ((TempCorrect.length == GuessSequence.length)&&(TempCorrect.length == Answers[i].length)){
230 if (TempCorrect.length > LongestCorrect.length){
231 LongestCorrect.length = 0;
232 for (k=0; k<TempCorrect.length; k++){
233 LongestCorrect[k] = TempCorrect[k];
235 HintToReturn = TempHint;
239 if (WhichCorrect > -1){
241 for (i=0; i<Answers.length; i++){
242 if (i!=WhichCorrect){
243 OtherAnswers += '<br />' + CompileString(Answers[i]);
246 WellDone = '<span class="CorrectAnswer">' + CompiledOutput + '</span><br /><br />' + CorrectResponse + '<br />';
248 if (AnswersTried.length > 0){AnswersTried += ' | ';}
249 AnswersTried += CompiledOutput;
251 //Do score calculation here
252 Score = Math.floor(((Segments.length-Penalties) * 100)/Segments.length);
253 WellDone += YourScoreIs + ' ' + Score + '%.<br />';
256 if (OtherAnswers.length > 0){
257 WellDone += TheseAnswersToo + '<span class="CorrectAnswer">' + OtherAnswers + '</span>';
261 ShowMessage(WellDone);
262 WriteToInstructions(YourScoreIs + ' ' + Score + '%.');
266 var WrongGuess = CompileString(GuessSequence);
267 if (AnswersTried.length > 0){AnswersTried += ' | ';}
268 AnswersTried += WrongGuess;
269 TryAgain = '<span class="Guess">' + WrongGuess + '</span><br /><br />';
270 if ((CheckType == 0)||(LongestCorrect.length==0)){
271 TryAgain += IncorrectResponse + '<br />';
274 if (LongestCorrect.length > 0){
275 LongestCorrectBit = CompileString(LongestCorrect);
276 GuessSequence.length = LongestCorrect.length;
277 TryAgain += '<br />' + ThisMuchCorrect + '<br /><span class="Guess">' + LongestCorrectBit + '</span><br />';
281 TryAgain += '<br />' + NextCorrect + '<br />' + FindSegment(HintToReturn);
285 if (TimeOver == true){
286 Score = Math.floor(((LongestCorrect.length-Penalties) * 100)/Segments.length);
287 if (Score < 0){Score = 0;}
288 TryAgain += YourScoreIs + ' ' + Score + '%.<br />';
291 Penalties++; //Penalty for inaccurate check
292 ShowMessage(TryAgain);
295 //If the exercise is over, deal with that
296 if ((AllDone == true)||(TimeOver == true)){
298 setTimeout('SendResults(' + Score + ')', 50);
301 window.clearInterval(Interval);
306 setTimeout('Finish()', SubmissionTimeout);
307 WriteToInstructions(YourScoreIs + ' ' + Score + '%.');
311 if (AllDone == true){
315 SetScormIncomplete();
321 var Segments = new Array();
324 var GuessSequence = new Array();
326 var Answers = new Array();
330 if (CurrDrag == -1) {return};
331 if (C.ie){var Ev = window.event}else{var Ev = e}
332 var difX = Ev.clientX-window.lastX;
333 var difY = Ev.clientY-window.lastY;
334 var newX = Cds[CurrDrag].GetL()+difX;
335 var newY = Cds[CurrDrag].GetT()+difY;
336 Cds[CurrDrag].SetL(newX);
337 Cds[CurrDrag].SetT(newY);
338 window.lastX = Ev.clientX;
339 window.lastY = Ev.clientY;
343 function beginDrag(e, DragNum) {
346 var Ev = window.event;
347 document.onmousemove=doDrag;
348 document.onmouseup=endDrag;
352 window.onmousemove=doDrag;
353 window.onmouseup=endDrag;
355 Cds[CurrDrag].SwapColours();
357 Cds[CurrDrag].css.zIndex = topZ;
358 window.lastX=Ev.clientX;
359 window.lastY=Ev.clientY;
363 function endDrag(e) {
364 if (CurrDrag == -1) {return};
365 Cds[CurrDrag].SwapColours();
366 if (C.ie){document.onmousemove=null}else{window.onmousemove=null;}
372 function onEndDrag(){
375 var SnapLine = Cds[CurrDrag].GetT();
376 var BiggestOverlap = -1;
378 for (i=0; i<L.length; i++){
379 if (Cds[CurrDrag].Overlap(L[i]) > OverlapRect){
380 OverlapRect = Cds[CurrDrag].Overlap(L[i]);
384 if (BiggestOverlap > -1){
385 SnapLine = L[BiggestOverlap].GetB() - (Cds[CurrDrag].GetH() + 2);
386 Cds[CurrDrag].SetT(SnapLine);
389 if (CapitalizeFirst==true){
390 setTimeout('DoCapitalization()', 50);
394 function DoCapitalization(){
395 //Capitalize first segment if necessary
396 var FD = GetGuessSequence();
397 if ((FD == -1)&&(FirstDiv > -1)){
398 Cds[FirstDiv].elm.innerHTML = Segments[FirstDiv][0];
400 if (((FD != FirstDiv)&&(CapitalizeFirst == true))&&(FD > -1)){
402 Cds[FirstDiv].elm.innerHTML = Segments[FirstDiv][0];
405 if ((FD > -1)&&(CapitalizeFirst == true)){
406 var Temp = CapFirst(Segments[FD][0]);
407 Cds[FD].elm.innerHTML = Temp;
412 function CheckOver(NoMove){
413 //This recursive function spreads out the Cards on a line if two of them are overlapping;
414 //if the spread operation moves one beyond the end of a line, it wraps it to the next line.
415 for (var i=0; i<Cds.length; i++){
416 for (var j=0; j<Cds.length; j++){
418 if (Cds[i].Overlap(Cds[j]) > 0){
419 if ((i==NoMove)||(Cds[i].GetL() < Cds[j].GetL())){
420 Cds[j].DockToR(Cds[i]);
421 if (Cds[j].GetR() > (LeftColPos + DivWidth)){
422 Cds[j].SetL(LeftColPos);
423 Cds[j].SetT(Cds[j].GetT() + DropHeight);
428 Cds[i].DockToR(Cds[j]);
429 if (Cds[i].GetR() > (LeftColPos + DivWidth)){
430 Cds[i].SetL(LeftColPos);
431 Cds[i].SetT(Cds[i].GetT() + DropHeight);
452 PreloadImages([PreloadImageList]);
455 Segments = Shuffle(Segments);
457 //Calculate page dimensions and positions
459 DivWidth = Math.floor((pg.W*4)/5);
460 LeftColPos = Math.floor(pg.W/10);
461 DragTop = parseInt(document.getElementById('CheckButtonDiv').offsetHeight) + parseInt(document.getElementById('CheckButtonDiv').offsetTop) + 10;
463 var CurrTop = DragTop + 10;
465 //Position the drop divs
466 for (var i=0; i<DropTotal; i++){
467 L[i] = new Card('Drop' + i, 0);
469 L[i].tag = CurrTop-5;
470 L[i].SetL(LeftColPos);
471 L[i].css.backgroundColor = '[strPageBGColor]';
472 CurrTop += L[i].GetH();
474 L[i].css.zIndex = topZ;
476 DropHeight = L[0].GetH();
482 for (i=0; i<Segments.length; i++){
483 //Create a new pointer in the C array to ref the card div
484 Cds[i] = new Card('D'+i, 0);
485 Cds[i].elm.innerHTML = Segments[i][0];
486 Cds[i].SetT(CurrTop);
487 Cds[i].SetL(LeftColPos);
488 Cds[i].css.cursor = 'move';
489 TempInt = Cds[i].GetH();
490 CurrTop = CurrTop + TempInt + 5;
491 Cds[i].css.backgroundColor = '[strExBGColor]';
492 Cds[i].css.color = '[strTextColor]';
494 Cds[i].css.zIndex = topZ;
495 Cds[i].tag = Segments[i][1];
498 //Place them at the bottom of the page
499 SetInitialPositions();
506 function SetInitialPositions(){
507 //Places all the divs at the bottom of the page in centred rows
508 //First, get the vertical position of the first row
509 var RTop = L[L.length-1].GetB() + 10;
511 //Create an array to hold the numbers of Cards for each row
513 CRows[0] = new Array();
514 Widths = new Array();
518 //Sort the Cards into rows, storing their numbers in the array
520 while (i<Cds.length){
521 //if it fits on this row, add it
522 if ((RowWidth + Cds[i].GetW() + 5) < DivWidth){
523 CRows[r][CRows[r].length] = i;
524 RowWidth += Cds[i].GetW() + 5;
525 //Store the width in the Widths array for later
526 Widths[r] = RowWidth;
528 //if not, increment the row number, and add it to the next row
531 CRows[r] = new Array();
532 CRows[r][CRows[r].length] = i;
533 RowWidth = Cds[i].GetW() + 5;
534 //Store the width in the Widths array for later
535 Widths[r] = RowWidth;
537 //move to the next Card
540 //Now we have the numbers in rows, set out each row
543 for (r=0; r<CRows.length; r++){
544 //Get the required indent for this row
545 Indent = Math.floor((DivWidth-Widths[r])/2);
546 //Set the first card in position
547 Cds[CRows[r][0]].SetL(Indent + LeftColPos);
548 Cds[CRows[r][0]].SetT(RTop);
549 Cds[CRows[r][0]].SetHome();
550 for (i=1; i<CRows[r].length; i++){
551 Cds[CRows[r][i]].DockToR(Cds[CRows[r][i-1]]);
552 Cds[CRows[r][i]].SetHome();
554 //Increment the row height
555 RTop += Cds[0].GetH() + 5;
559 function TimerStartUp(){
560 setTimeout('StartUp()', 300);
565 document.getElementById('Timer').innerHTML = '[strTimesUp]';