Browse Source

Merge pull request #944 from AngelFQC/7705

Fix Hotspot question edition - refs 7705
Angel Fernando Quiroz Campos 9 years ago
parent
commit
cf7ce472e0

+ 2 - 0
main/exercice/admin.php

@@ -344,6 +344,8 @@ $template = new Template();
 $htmlHeadXtra[] = $template->fetch('default/exercise/submit.js.tpl');
 $htmlHeadXtra[] = api_get_js('d3/jquery.xcolor.js');
 
+$htmlHeadXtra[] = '<script src="../plugin/hotspot2/js/hotspot.js"></script>';
+
 $htmlHeadXtra[] = "<script type=\"text/javascript\" src=\"../plugin/hotspot/JavaScriptFlashGateway.js\"></script>
 <script src=\"../plugin/hotspot/hotspot.js\" type=\"text/javascript\"></script>
 <script language=\"JavaScript\" type=\"text/javascript\">

+ 21 - 22
main/exercice/exercise.class.php

@@ -3128,7 +3128,7 @@ class Exercise
                                 WHERE
                                     hotspot_exe_id = '".$exeId."' AND
                                     hotspot_question_id= '".$questionId."' AND
-                                    hotspot_answer_id = ".intval($answerId)."";
+                                    hotspot_answer_id = ".intval($answerAutoId)."";
                         $result = Database::query($sql);
                         $studentChoice = Database::result($result, 0, "hotspot_correct");
 
@@ -3137,7 +3137,7 @@ class Exercise
                             $totalScore     += $answerWeighting;
                         }
                     } else {
-                        $studentChoice = $choice[$answerId];
+                        $studentChoice = $choice[$answerAutoId];
                         if ($studentChoice) {
                             $questionScore  += $answerWeighting;
                             $totalScore     += $answerWeighting;
@@ -4036,25 +4036,24 @@ class Exercise
                 if ($show_result) {
                     //	if ($origin != 'learnpath') {
                     echo '</table></td></tr>';
-                    echo '<tr>
-                            <td colspan="2">';
-                    echo '<i>'.get_lang('HotSpot').'</i><br /><br />';
-
-                    echo '<object type="application/x-shockwave-flash" data="'
-                        . api_get_path(WEB_CODE_PATH)
-                        . 'plugin/hotspot/hotspot_solution.swf?modifyAnswers='
-                        . Security::remove_XSS($questionId)
-                        . '&exe_id='
-                        . $exeId
-                        . '&from_db=1" width="552" height="352">
-                                <param name="movie" value="../plugin/hotspot/hotspot_solution.swf?modifyAnswers='
-                            . Security::remove_XSS($questionId)
-                            . '&exe_id='
-                            . $exeId
-                            . '&from_db=1" />
-                        </object>';
-                    echo '</td>
-                        </tr>';
+                    echo "
+                        <tr>
+                            <td colspan=\"2\">
+                                <p><em>" . get_lang('HotSpot') . "</em></p>
+                                <div id=\"hotspot-solution\"></div>
+
+                                <script>
+                                    $(document).on('ready', function () {
+                                        HotSpotSolution.init({
+                                            questionId: $questionId,
+                                            exerciseId: $exeId,
+                                            selector: '#hotspot-solution'
+                                        });
+                                    });
+                                </script>
+                            </td>
+                        </tr>
+                    ";
                     //	}
                 }
             }
@@ -4143,7 +4142,7 @@ class Exercise
                 Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
                 if (isset($exerciseResultCoordinates[$questionId]) && !empty($exerciseResultCoordinates[$questionId])) {
                     foreach ($exerciseResultCoordinates[$questionId] as $idx => $val) {
-                        Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val, $this->id);
+                        Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val, false, $this->id);
                     }
                 }
             } else {

+ 2 - 0
main/exercice/exercise_result.php

@@ -75,6 +75,8 @@ $interbreadcrumb[] = array(
     "name" => get_lang('Exercises'),
 );
 
+$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_CODE_PATH) . 'plugin/hotspot2/js/hotspot_solution.js"></script>';
+
 if ($origin != 'learnpath') {
 	// So we are not in learnpath tool
 	Display::display_header($nameTools, get_lang('Exercise'));

+ 39 - 16
main/exercice/exercise_show.php

@@ -120,6 +120,8 @@ $interbreadcrumb[]= array("url" => "#","name" => get_lang('Result'));
 
 $this_section = SECTION_COURSES;
 
+$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_CODE_PATH) . 'plugin/hotspot2/js/hotspot_solution.js"></script>';
+
 if ($origin != 'learnpath') {
 	Display::display_header('');
 } else {
@@ -367,14 +369,25 @@ foreach ($questionList as $questionId) {
 
         if ($show_results) {
 			echo '</table></td></tr>';
-		 	echo '<tr>
-				<td colspan="2">'.
-					'<object type="application/x-shockwave-flash" data="'.api_get_path(WEB_CODE_PATH).'plugin/hotspot/hotspot_solution.swf?modifyAnswers='.Security::remove_XSS($questionId).'&exe_id='.$id.'&from_db=1" width="552" height="352">
-						<param name="movie" value="../plugin/hotspot/hotspot_solution.swf?modifyAnswers='.Security::remove_XSS($questionId).'&exe_id='.$id.'&from_db=1" />
-					</object>
-				</td>
-			</tr>
-			</table><br/>';
+
+            echo "
+                    <tr>
+                        <td colspan=\"2\">
+                            <div id=\"hotspot-solution\"></div>
+                            <script>
+                                $(document).on('ready', function () {
+                                    HotSpotSolution.init({
+                                        questionId: $questionId,
+                                        exerciseId: $id,
+                                        selector: '#hotspot-solution'
+                                    });
+                                });
+                            </script>
+                        </td>
+                    </tr>
+                </table>
+                <br>
+            ";
         }
 	} else if($answerType == HOT_SPOT_DELINEATION) {
 
@@ -497,14 +510,24 @@ foreach ($questionList as $questionId) {
             $questionScore= Database::result($resfree,0,"marks");
             $totalScore+=$questionScore;
             echo '</table></td></tr>';
-            echo '<tr>
-                    <td colspan="2">
-                        <object type="application/x-shockwave-flash" data="../plugin/hotspot/hotspot_solution.swf?modifyAnswers='.$questionId.'&exe_id='.$id.'&from_db=1" width="556" height="350">
-                            <param name="movie" value="../plugin/hotspot/hotspot_solution.swf?modifyAnswers='.$questionId.'&exe_id='.$id.'&from_db=1" />
-                        </object>
-                    </td>
-                </tr>
-                </table>';
+
+            echo "
+                    <tr>
+                        <td colspan=\"2\">
+                            <div id=\"hotspot-solution\"></div>
+                            <script>
+                                $(document).on('ready', function () {
+                                    HotSpotSolution.init({
+                                        questionId: $questionId,
+                                        exerciseId: $id,
+                                        selector: '#hotspot-solution'
+                                    });
+                                });
+                            </script>
+                        </td>
+                    </tr>
+                </table>
+            ";
         }
 	}
 

+ 1 - 0
main/exercice/exercise_submit.php

@@ -60,6 +60,7 @@ $htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/epicloc
 $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.dateformat.min.js');
 $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.epiclock.min.js');
 $htmlHeadXtra[] = api_get_js('epiclock/renderers/minute/epiclock.minute.js');
+$htmlHeadXtra[] = '<script src="../plugin/hotspot2/js/hotspot_user.js"></script>';
 
 $template = new Template();
 

+ 44 - 24
main/exercice/hotspot_actionscript.as.php

@@ -24,11 +24,6 @@ $pictureSize   = getimagesize($picturePath.'/'.$objQuestion->selectPicture());
 $pictureWidth  = $pictureSize[0];
 $pictureHeight = $pictureSize[1];
 
-$courseLang = $_course['language'];
-$courseCode = $_course['sysCode'];
-$coursePath = $_course['path'];
-
-
 $course_id = api_get_course_int_id();
 
 // Query db for answers
@@ -40,39 +35,63 @@ if ($answer_type==HOT_SPOT_DELINEATION) {
 	        WHERE c_id = $course_id AND question_id = ".intval($questionId)." ORDER BY id";
 }
 $result = Database::query($sql);
-// Init
-$output = "hotspot_lang=$courseLang&hotspot_image=$pictureName&hotspot_image_width=$pictureWidth&hotspot_image_height=$pictureHeight&courseCode=$coursePath";
-$i = 0;
+
+$data = [];
+$data['lang'] = [
+    'Square' => get_lang('Square'),
+    'Circle' => get_lang('Circle'),
+    'Poly' => get_lang('Poly'),
+    'HotspotStatus1' => get_lang('HotspotStatus1'),
+    'HotspotStatus2Polygon' => get_lang('HotspotStatus2Polygon'),
+    'HotspotStatus2Other' => get_lang('HotspotStatus2Other'),
+    'HotspotStatus3' => get_lang('HotspotStatus3'),
+    'HotspotShowUserPoints' => get_lang('HotspotShowUserPoints'),
+    'ShowHotspots' => get_lang('ShowHotspots'),
+    'Triesleft' => get_lang('Triesleft'),
+    'ExerciseFinished' => get_lang('ExerciseFinished'),
+    'NextAnswer' => get_lang('NextAnswer'),
+    'Delineation' => get_lang('Delineation'),
+    'CloseDelineation' => get_lang('CloseDelineation'),
+    'Oar' => get_lang('oar')
+];
+$data['image'] = $objQuestion->selectPicturePath();
+$data['image_width'] = $pictureWidth;
+$data['image_height'] = $pictureHeight;
+$data['courseCode'] = $_course['path'];
+$data['hotspots'] = [];
+
 $nmbrTries = 0;
 
 while ($hotspot = Database::fetch_assoc($result))
 {
-   	$output .= "&hotspot_".$hotspot['id']."=true";
-	$output .= "&hotspot_".$hotspot['id']."_answer=".str_replace('&','{amp}',$hotspot['answer']);
+    $hotSpot = [];
+    $hotSpot['id'] = $hotspot['id'];
+    $hotSpot['answer'] = $hotspot['answer'];
+
 	// Square or rectancle
 	if ($hotspot['hotspot_type'] == 'square' )
 	{
-		$output .= "&hotspot_".$hotspot['id']."_type=square";
+        $hotSpot['type'] = 'square';
 	}
 	// Circle or ovale
 	if ($hotspot['hotspot_type'] == 'circle')
 	{
-		$output .= "&hotspot_".$hotspot['id']."_type=circle";
+        $hotSpot['type'] = 'circle';
 	}
 	// Polygon
 	if ($hotspot['hotspot_type'] == 'poly')
 	{
-		$output .= "&hotspot_".$hotspot['id']."_type=poly";
+        $hotSpot['type'] = 'poly';
 	}
 	// Delineation
 	if ($hotspot['hotspot_type'] == 'delineation')
 	{
-		$output .= "&hotspot_".$hotspot['id']."_type=delineation";
+        $hotSpot['type'] = 'delineation';
 	}
 	// No error
 	if ($hotspot['hotspot_type'] == 'noerror')
 	{
-		$output .= "&hotspot_".$hotspot['id']."_type=noerror";
+        $hotSpot['type'] = 'noerror';
 	}
 
 	// This is a good answer, count + 1 for nmbr of clicks
@@ -80,14 +99,15 @@ while ($hotspot = Database::fetch_assoc($result))
 	{
 		$nmbrTries++;
 	}
-	$output .= "&hotspot_".$hotspot['id']."_coord=".$hotspot['hotspot_coordinates']."";
-	$i++;
-}
 
-// Generate empty
-$i++;
-for ($i; $i <= 12; $i++) {
-	$output .= "&hotspot_".$i."=false";
+    $hotSpot['coord'] = $hotspot['hotspot_coordinates'];
+
+    $data['hotspots'][] = $hotSpot;
 }
-// Output
-echo $output."&nmbrTries=".$nmbrTries."&done=done";
+
+$data['nmbrTries'] = $nmbrTries;
+$data['done'] = 'done';
+
+header('Content-Type: application/json');
+
+echo json_encode($data);

+ 24 - 20
main/exercice/hotspot_actionscript_admin.as.php

@@ -21,12 +21,15 @@ $pictureSize = getimagesize($picturePath.'/'.$objQuestion->selectPicture());
 $pictureWidth = $pictureSize[0];
 $pictureHeight = $pictureSize[1];
 
-$courseLang = $_course['language'];
-$courseCode = $_course['code'];
-$coursePath = $_course['path'];
+$data = [];
+$data['hotspot_lang'] = $_course['language'];
+$data['hotspot_image'] = $pictureName;
+$data['hotspot_image_width'] = $pictureWidth;
+$data['hotspot_image_height'] = $pictureHeight;
+$data['courseCode'] = $_course['path'];
+$data['hotspots'] = [];
 
 // Init
-$output = "hotspot_lang=$courseLang&hotspot_image=$pictureName&hotspot_image_width=$pictureWidth&hotspot_image_height=$pictureHeight&courseCode=$coursePath";
 $i = 0;
 $nmbrTries = 0;
 $answer_type = $objQuestion->type;
@@ -35,28 +38,29 @@ $answers = $_SESSION['tmp_answers'];
 $nbrAnswers = count($answers['answer']);
 
 for ($i=1;$i <= $nbrAnswers; $i++) {
-    $output .= "&hotspot_".$i."=true";
-    $output .= "&hotspot_".$i."_answer=".$answers['answer'][$i];
+    $hotSpot = [];
+    $hotSpot['answer']= $answers['answer'][$i];
 
     if ($answer_type == HOT_SPOT_DELINEATION) {
         if ($i==1) {
-            $output .= "&hotspot_".$i."_type=delineation";
-        } else
-            {$output .= "&hotspot_".$i."_type=oar";}
+            $hotSpot['type'] = 'delineation';
+        } else {
+            $hotSpot['type'] = 'oar';
+        }
     } else {
         // Square or rectancle
         if ($answers['hotspot_type'][$i] == 'square') {
-            $output .= "&hotspot_".$i."_type=square";
+            $hotSpot['type'] = 'square';
         }
 
         // Circle or ovale
         if ($answers['hotspot_type'][$i] == 'circle') {
-            $output .= "&hotspot_".$i."_type=circle";
+            $hotSpot['type'] = 'circle';
         }
 
         // Polygon
         if ($answers['hotspot_type'][$i] == 'poly') {
-            $output .= "&hotspot_".$i."_type=poly";
+            $hotSpot['type'] = 'poly';
         }
         /*// Delineation
         if ($answers['hotspot_type'][$i] == 'delineation')
@@ -70,14 +74,14 @@ for ($i=1;$i <= $nbrAnswers; $i++) {
 		$nmbrTries++;
 	}
 
-	$output .= "&hotspot_".$i."_coord=".$answers['hotspot_coordinates'][$i]."";
-}
-
-// Generate empty
-$i++;
-for ($i; $i <= 12; $i++) {
-	$output .= "&hotspot_".$i."=false";
+    $hotSpot['coord'] = $answers['hotspot_coordinates'][$i];
+    $data['hotspots'][] = $hotSpot;
 }
 
 // Output
-echo $output."&nmbrTries=".$nmbrTries."&done=done";
+$data['nmbrTries'] = $nmbrTries;
+$data['done'] = 'done';
+
+header('Content-Type: application/json');
+
+echo json_encode($data);

+ 33 - 39
main/exercice/hotspot_admin.inc.php

@@ -585,12 +585,11 @@ if ($modifyAnswers) {
                 </button>
             </div>
         </div>
-        <table border="0" cellpadding="0" cellspacing="2" width="100%">
-            <tr>
-                <td>
-                    <input type="hidden" name="formSent" value="1" />
-                    <input type="hidden" name="nbrAnswers" value="<?php echo $nbrAnswers; ?>" />
+        <input type="hidden" name="formSent" value="1" />
+        <input type="hidden" name="nbrAnswers" value="<?php echo $nbrAnswers; ?>" />
+        <div class="table-responsive">
                     <table class="table table-striped table-hover">
+                        <thead>
                         <tr>
                             <th width="5">&nbsp;</th>
                             <th> <?php echo get_lang('HotspotDescription'); ?> *</th>
@@ -614,6 +613,8 @@ if ($modifyAnswers) {
                             <?php } ?>
                             <th><?php echo get_lang('QuestionWeighting'); ?> *</th>
                         </tr>
+                        </thead>
+                        <tbody>
                         <?php
                         $list = new LearnpathList(api_get_user_id());
                         // Loading list of LPs
@@ -818,7 +819,7 @@ if ($modifyAnswers) {
                                             <div style="height: 15px; width: 15px; background-color: <?php echo $hotspot_colors[$i]; ?>"> </div>
                                         </td>
                                         <td>
-                                            <input type="text" name="reponse[<?php echo $i; ?>]" value="<?php echo Security::remove_XSS($reponse[$i]); ?>" size="20" />
+                                            <input class="form-control" type="text" name="reponse[<?php echo $i; ?>]" value="<?php echo Security::remove_XSS($reponse[$i]); ?>" />
                                         </td>
 
                                         <td colspan="2"  align="left">
@@ -864,15 +865,16 @@ if ($modifyAnswers) {
                                     ?>
                                 <tr>
                                     <td>
-                                        <div style="height: 15px; width: 15px; background-color: <?php echo $hotspot_colors[$i]; ?>"> </div>
+                                        <span class="fa fa-square fa-2x" style="color: <?php echo $hotspot_colors[$i]; ?>" aria-hidden="true"></span>
                                     </td>
                                     <td>
-                                        <input type="text" name="reponse[<?php echo $i; ?>]" value="<?php echo Security::remove_XSS($responseValue); ?>" size="45" />
+                                        <input class="form-control" type="text" name="reponse[<?php echo $i; ?>]" value="<?php echo Security::remove_XSS($responseValue); ?>" />
                                     </td>
                                     <?php
                                     $form = new FormValidator('form_' . $i);
                                     $config = array(
-                                        'ToolbarSet' => 'TestProposedAnswer'
+                                        'ToolbarSet' => 'TestProposedAnswer',
+                                        'cols-size' => [0, 12, 0]
                                     );
                                     $form->addHtmlEditor('comment[' . $i . ']', null, false, false, $config);
                                     $renderer = $form->defaultRenderer();
@@ -886,8 +888,7 @@ if ($modifyAnswers) {
                                     $form->setDefaults(array('comment[' . $i . ']' => $commentValue));
                                     $return = $form->return_form();
                                     ?>
-                                    <td>&nbsp;</td>
-                                    <td align="left" ><?php echo $return; ?></td>
+                                    <td colspan="2" align="left" ><?php echo $return; ?></td>
                                 <?php } ?>
                                 <td>
                                     <?php
@@ -896,13 +897,13 @@ if ($modifyAnswers) {
                                             ?>
                                             <input type="hidden" name="weighting[<?php echo $i; ?>]" class="span3" value="0" />
                                         <?php } else { ?>
-                                            <input type="text" name="weighting[<?php echo $i; ?>]" class="span3" value="<?php echo (isset($weighting[$i]) ? $weighting[$i] : 10); ?>" />
+                                            <input class="form-control" type="text" name="weighting[<?php echo $i; ?>]" value="<?php echo (isset($weighting[$i]) ? $weighting[$i] : 10); ?>" />
                                                    <?php
                                                }
                                            }
                                            if ($answerType == HOT_SPOT) {
                                                ?>
-                                        <input type="text" name="weighting[<?php echo $i; ?>]" class="span3" value="<?php echo (isset($weighting[$i]) ? $weighting[$i] : 10); ?>" />
+                                        <input class="form-control" type="text" name="weighting[<?php echo $i; ?>]" value="<?php echo (isset($weighting[$i]) ? $weighting[$i] : 10); ?>" />
                                         <input type="hidden" name="hotspot_coordinates[<?php echo $i; ?>]" value="<?php echo (empty($hotspot_coordinates[$i]) ? '0;0|0|0' : $hotspot_coordinates[$i]); ?>" />
                                         <input type="hidden" name="hotspot_type[<?php echo $i; ?>]" value="<?php echo (empty($hotspot_type[$i]) ? 'square' : $hotspot_type[$i]); ?>" />
                                         <?php } ?>
@@ -1004,38 +1005,31 @@ if ($modifyAnswers) {
                                 <?php } ?>
                             </tr>
                         <?php } ?>
+                        </tbody>
                     </table>
-                </td>
-            </tr>
-            <tr>
-                <td>
-                    <script>
-                        <!--
-                        // Version check based upon the values entered above in "Globals"
-                        var hasReqestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
+        </div>
+        <div class="row">
+            <div class="col-xs-12" id="hotspot-selectors"></div>
+        </div>
+        <div class="row">
+            <div class="col-xs-12">
     <?php
     $swf_loaded = $answerType == HOT_SPOT_DELINEATION ? 'hotspot_delineation_admin' : 'hotspot_admin';
     $height = 450;
     ?>
-                        // Check to see if the version meets the requirements for playback
-                        if (hasReqestedVersion) {  // if we've detected an acceptable version
-                            var oeTags = '<object type="application/x-shockwave-flash" data="../plugin/hotspot/<?php echo $swf_loaded ?>.swf?modifyAnswers=<?php echo $modifyAnswers ?>" width="600" height="<?php echo $height ?>">'
-                                    + '<param name="movie" value="../plugin/hotspot/<?php echo $swf_loaded ?>.swf?modifyAnswers=<?php echo $modifyAnswers ?>" />'
-                                    + '<param name="test" value="OOoowww fo shooww" />'
-                                    + '</object>';
-                            document.write(oeTags);   // embed the Flash Content SWF when all tests are passed
-                        } else {  // flash is too old or we can't detect the plugin
-                            var alternateContent = 'Error<br \/>'
-                                    + 'This content requires the Macromedia Flash Player.<br \/>'
-                                    + '<a href=http://www.macromedia.com/go/getflash/>Get Flash<\/a>';
-                            document.write(alternateContent);  // insert non-flash content
-                        }
-                        // -->
-                    </script>
-                </td>
-            </tr>
-        </table>
+                <div id="hotspot-container" class="center-block">
+                    <div id="hotspot-alert"></div>
+                    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 0 0">
+                    </svg>
+                </div>
+            </div>
+        </div>
     </form>
+    <script>
+        $(document).on('ready', function () {
+            HotSpotAdmin.init(<?php echo $modifyAnswers ?>, '<?php echo $objQuestion->selectPicturePath(); ?>');
+        });
+    </script>
     <?php
     if ($debug > 0) {
         echo str_repeat('&nbsp;', 0) . '$modifyAnswers was set - end' . "<br />\n";

+ 51 - 41
main/exercice/hotspot_answers.as.php

@@ -13,7 +13,6 @@ include('../inc/global.inc.php');
 // Set vars
 $questionId    = intval($_GET['modifyAnswers']);
 $exe_id        = intval($_GET['exe_id']);
-$from_db 	   = isset($_GET['from_db']) ? $_GET['from_db'] : 0;
 $objQuestion   = Question :: read($questionId);
 $TBL_ANSWERS   = Database::get_course_table(TABLE_QUIZ_ANSWER);
 $documentPath  = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document';
@@ -24,10 +23,6 @@ $pictureSize   = getimagesize($picturePath.'/'.$objQuestion->selectPicture());
 $pictureWidth  = $pictureSize[0];
 $pictureHeight = $pictureSize[1];
 
-$courseLang    = $_course['language'];
-$course_code   = Database::escape_string($_course['id']);
-
-$coursePath    = $_course['path'];
 $answer_type   = $objQuestion->selectType();
 
 $course_id     = api_get_course_int_id();
@@ -42,64 +37,79 @@ if ($answer_type == HOT_SPOT_DELINEATION) {
 }
 $result = Database::query($sql);
 // Init
-$output = "hotspot_lang=$courseLang&hotspot_image=$pictureName&hotspot_image_width=$pictureWidth&hotspot_image_height=$pictureHeight&courseCode=$coursePath";
-$i = 0;
+$data['lang'] = [
+    'Square' => get_lang('Square'),
+    'Circle' => get_lang('Circle'),
+    'Poly' => get_lang('Poly'),
+    'HotspotStatus1' => get_lang('HotspotStatus1'),
+    'HotspotStatus2Polygon' => get_lang('HotspotStatus2Polygon'),
+    'HotspotStatus2Other' => get_lang('HotspotStatus2Other'),
+    'HotspotStatus3' => get_lang('HotspotStatus3'),
+    'HotspotShowUserPoints' => get_lang('HotspotShowUserPoints'),
+    'ShowHotspots' => get_lang('ShowHotspots'),
+    'Triesleft' => get_lang('Triesleft'),
+    'ExerciseFinished' => get_lang('ExerciseFinished'),
+    'NextAnswer' => get_lang('NextAnswer'),
+    'Delineation' => get_lang('Delineation'),
+    'CloseDelineation' => get_lang('CloseDelineation'),
+    'Oar' => get_lang('oar')
+];
+$data['image'] = $objQuestion->selectPicturePath();
+$data['image_width'] = $pictureWidth;
+$data['image_height'] = $pictureHeight;
+$data['courseCode'] = $_course['path'];
+$data['hotspots'] = [];
 
 while ($hotspot = Database::fetch_array($result)) {
-	$output .= "&hotspot_".$hotspot['id']."=true";
+    $hotSpot = [];
+    $hotSpot['id'] = $hotspot['id'];
+
 	// Square or rectancle
 	if ($hotspot['hotspot_type'] == 'square' ) {
-		$output .= "&hotspot_".$hotspot['id']."_type=square";
+        $hotSpot['type'] = 'square';
 	}
 
 	// Circle or ovale
 	if ($hotspot['hotspot_type'] == 'circle') {
-		$output .= "&hotspot_".$hotspot['id']."_type=circle";
+        $hotSpot['type'] = 'circle';
 	}
 
 	// Polygon
 	if ($hotspot['hotspot_type'] == 'poly') {
-		$output .= "&hotspot_".$hotspot['id']."_type=poly";
+        $hotSpot['type'] = 'poly';
 	}
 
 	// Delineation
 	if ($hotspot['hotspot_type'] == 'delineation') {
-		$output .= "&hotspot_".$hotspot['id']."_type=delineation";
+        $hotSpot['type'] = 'delineation';
 	}
 	// oar
 	if ($hotspot['hotspot_type'] == 'oar') {
-		$output .= "&hotspot_".$hotspot['id']."_type=delineation";
+        $hotSpot['type'] = 'delineation';
 	}
-	$output .= "&hotspot_".$hotspot['id']."_coord=".$hotspot['hotspot_coordinates']."";
-	$i++;
-}
 
-// Generate empty (the maximum number of points is 12 - it is said so in the user interface)
-$i++;
-for ($i; $i <= 12; $i++) {
-	$output .= "&hotspot_".$i."=false";
+    $hotSpot['coord'] = $hotspot['hotspot_coordinates'];
+
+    $data['hotspots'][] = $hotSpot;
 }
 
+$data['answers'] = [];
 
-// Get clicks
-if(isset($_SESSION['exerciseResultCoordinates']) && $from_db==0) {
-	foreach ($_SESSION['exerciseResultCoordinates'][$questionId] as $coordinate) {
-		$output2 .= $coordinate."|";
-	}
-} else {
-	// get it from db
-	$tbl_track_e_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
-	$sql = "SELECT hotspot_coordinate
-            FROM $tbl_track_e_hotspot
-            WHERE   hotspot_question_id = $questionId AND
-                    c_id = $course_id AND
-                    hotspot_exe_id = $exe_id
-            ORDER by hotspot_id";
-	$rs = @Database::query($sql); // don't output error because we are in Flash execution.
-	while($row = Database :: fetch_array($rs)) {
-		$output2 .= $row['hotspot_coordinate']."|";
-	}
+$tbl_track_e_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
+$sql = "SELECT hotspot_coordinate
+        FROM $tbl_track_e_hotspot
+        WHERE   hotspot_question_id = $questionId AND
+                c_id = $course_id AND
+                hotspot_exe_id = $exe_id
+        ORDER by hotspot_id";
+$rs = Database::query($sql); // don't output error because we are in Flash execution.
+
+while($row = Database :: fetch_array($rs, 'ASSOC')) {
+    $data['answers'][] = $row['hotspot_coordinate'];
 }
-$output .= "&p_hotspot_answers=".api_substr($output2,0,-1)."&done=done";
-$explode = explode('&', $output);
-echo $output;
+
+$data['done'] = 'done';
+
+header('Content-Type: application/json');
+
+echo json_encode($data);

+ 2 - 0
main/exercice/result.php

@@ -53,6 +53,8 @@ if (!$is_allowedToEdit) {
     }
 }
 
+$htmlHeadXtra[] = '<script src="' . api_get_path(WEB_CODE_PATH) . 'plugin/hotspot2/js/hotspot_solution.js"></script>';
+
 if ($show_headers) {
     $interbreadcrumb[] = array(
         "url" => "exercise.php?".api_get_cidreq(),

+ 13 - 11
main/inc/lib/events.lib.php

@@ -613,17 +613,19 @@ class Event
                 )));
 
         } else {
-            $sql = "INSERT INTO $tbl_track_e_hotspot (hotspot_course_code, hotspot_user_id, c_id, hotspot_exe_id, hotspot_question_id, hotspot_answer_id, hotspot_correct, hotspot_coordinate)
-                VALUES (
-                '".api_get_course_id()."',
-                ".api_get_user_id()."',".
-                " ".api_get_course_int_id().", ".
-                " '".Database :: escape_string($exe_id)."', ".
-                " '".Database :: escape_string($question_id)."',".
-                " '".Database :: escape_string($answer_id)."',".
-                " '".Database :: escape_string($correct)."',".
-                " '".Database :: escape_string($coords)."')";
-            return $result = Database::query($sql);
+            return Database::insert(
+                $tbl_track_e_hotspot,
+                [
+                    'hotspot_course_code' => api_get_course_id(),
+                    'hotspot_user_id' => api_get_user_id(),
+                    'c_id' => api_get_course_int_id(),
+                    'hotspot_exe_id' => $exe_id,
+                    'hotspot_question_id' => $question_id,
+                    'hotspot_answer_id' => $answer_id,
+                    'hotspot_correct' => $correct,
+                    'hotspot_coordinate' => $coords
+                ]
+            );
         }
     }
 

+ 27 - 143
main/inc/lib/exercise.lib.php

@@ -1156,153 +1156,37 @@ HTML;
                     echo '<div class="question_title">' . $current_item . '. ' . $questionName . '</div>';
                 }
                 //@todo I need to the get the feedback type
-                echo '<input type="hidden" name="hidden_hotspot_id" value="' . $questionId . '" />';
-                echo '<table class="exercise_questions" >
-                      <tr>
-                        <td valign="top" colspan="2">';
-                echo $questionDescription;
-                echo '</td></tr>';
+                echo <<<HOTSPOT
+                    <input type="hidden" name="hidden_hotspot_id" value="$questionId" />
+                    <div class="exercise_questions">
+                        $questionDescription
+                        <div class="row">
+HOTSPOT;
             }
 
             $canClick = isset($_GET['editQuestion']) ? '0' : (isset($_GET['modifyAnswers']) ? '0' : '1');
 
-            $s .= '<script type="text/javascript" src="../plugin/hotspot/JavaScriptFlashGateway.js"></script>
-                            <script src="../plugin/hotspot/hotspot.js" type="text/javascript" ></script>
-                            <script type="text/javascript">
-                            <!--
-                            // Globals
-                            // Major version of Flash required
-                            var requiredMajorVersion = 7;
-                            // Minor version of Flash required
-                            var requiredMinorVersion = 0;
-                            // Minor version of Flash required
-                            var requiredRevision = 0;
-                            // the version of javascript supported
-                            var jsVersion = 1.0;
-                            // -->
-                            </script>
-                            <script language="VBScript" type="text/vbscript">
-                            <!-- // Visual basic helper required to detect Flash Player ActiveX control version information
-                            Function VBGetSwfVer(i)
-                              on error resume next
-                              Dim swControl, swVersion
-                              swVersion = 0
-
-                              set swControl = CreateObject("ShockwaveFlash.ShockwaveFlash." + CStr(i))
-                              if (IsObject(swControl)) then
-                                swVersion = swControl.GetVariable("$version")
-                              end if
-                              VBGetSwfVer = swVersion
-                            End Function
-                            // -->
-                            </script>
-
-                            <script language="JavaScript1.1" type="text/javascript">
-                            <!-- // Detect Client Browser type
-                            var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
-                            var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
-                            var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;
-                            jsVersion = 1.1;
-                            // JavaScript helper required to detect Flash Player PlugIn version information
-                            function JSGetSwfVer(i) {
-                                // NS/Opera version >= 3 check for Flash plugin in plugin array
-                                if (navigator.plugins != null && navigator.plugins.length > 0) {
-                                    if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
-                                        var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
-                                        var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
-                                        descArray = flashDescription.split(" ");
-                                        tempArrayMajor = descArray[2].split(".");
-                                        versionMajor = tempArrayMajor[0];
-                                        versionMinor = tempArrayMajor[1];
-                                        if ( descArray[3] != "" ) {
-                                            tempArrayMinor = descArray[3].split("r");
-                                        } else {
-                                            tempArrayMinor = descArray[4].split("r");
-                                        }
-                                        versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
-                                        flashVer = versionMajor + "." + versionMinor + "." + versionRevision;
-                                    } else {
-                                        flashVer = -1;
-                                    }
-                                }
-                                // MSN/WebTV 2.6 supports Flash 4
-                                else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4;
-                                // WebTV 2.5 supports Flash 3
-                                else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3;
-                                // older WebTV supports Flash 2
-                                else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2;
-                                // Can\'t detect in all other cases
-                                else
-                                {
-                                    flashVer = -1;
-                                }
-                                return flashVer;
-                            }
-                            // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available
-
-                            function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) {
-                                reqVer = parseFloat(reqMajorVer + "." + reqRevision);
-                                // loop backwards through the versions until we find the newest version
-                                for (i=25;i>0;i--) {
-                                    if (isIE && isWin && !isOpera) {
-                                        versionStr = VBGetSwfVer(i);
-                                    } else {
-                                        versionStr = JSGetSwfVer(i);
-                                    }
-                                    if (versionStr == -1 ) {
-                                        return false;
-                                    } else if (versionStr != 0) {
-                                        if(isIE && isWin && !isOpera) {
-                                            tempArray         = versionStr.split(" ");
-                                            tempString        = tempArray[1];
-                                            versionArray      = tempString .split(",");
-                                        } else {
-                                            versionArray      = versionStr.split(".");
-                                        }
-                                        versionMajor      = versionArray[0];
-                                        versionMinor      = versionArray[1];
-                                        versionRevision   = versionArray[2];
-
-                                        versionString     = versionMajor + "." + versionRevision;   // 7.0r24 == 7.24
-                                        versionNum        = parseFloat(versionString);
-                                        // is the major.revision >= requested major.revision AND the minor version >= requested minor
-                                        if ( (versionMajor > reqMajorVer) && (versionNum >= reqVer) ) {
-                                            return true;
-                                        } else {
-                                            return ((versionNum >= reqVer && versionMinor >= reqMinorVer) ? true : false );
-                                        }
-                                    }
-                                }
-                            }
-                            // -->
-                            </script>';
-            $s .= '<tr><td valign="top" colspan="2" width="520"><table><tr><td width="520">
-                        <script>
-                            <!--
-                            // Version check based upon the values entered above in "Globals"
-                            var hasReqestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
-
-                            // Check to see if the version meets the requirements for playback
-                            if (hasReqestedVersion) {  // if we\'ve detected an acceptable version
-                                var oeTags = \'<object type="application/x-shockwave-flash" data="../plugin/hotspot/' . $swf_file . '.swf?modifyAnswers=' . $questionId . '&canClick:' . $canClick . '" width="600" height="' . $swf_height . '">\'
-                                            + \'<param name="wmode" value="transparent">\'
-                                            + \'<param name="movie" value="../plugin/hotspot/' . $swf_file . '.swf?modifyAnswers=' . $questionId . '&canClick:' . $canClick . '" />\'
-                                            + \'<\/object>\';
-                                document.write(oeTags);   // embed the Flash Content SWF when all tests are passed
-                            } else {  // flash is too old or we can\'t detect the plugin
-                                var alternateContent = "Error<br \/>"
-                                    + "Hotspots requires Macromedia Flash 7.<br \/>"
-                                    + "<a href=\"http://www.macromedia.com/go/getflash/\">Get Flash<\/a>";
-                                document.write(alternateContent);  // insert non-flash content
-                            }
-                            // -->
-                        </script>
-                        </td>
-                        <td valign="top" align="left">' . $answer_list . '</td></tr>
-                        </table>
-            </td></tr>';
-            echo $s;
-            echo '</table>';
+            $s .= <<<HOTSPOT
+                            <div class="col-sm-8 col-md-9">
+                                <div class="hotspot-image"></div>
+                                <script>
+                                    $(document).on('ready', function () {
+                                        HotSpotUser.init({
+                                            questionId: $questionId,
+                                            selector: '#question_div_' + $questionId + ' .hotspot-image'
+                                        });
+                                    });
+                                </script>
+                            </div>
+                            <div class="col-sm-4 col-md-3">
+                                $answer_list
+                            </div>
+HOTSPOT;
+            echo <<<HOTSPOT
+                            $s
+                        </div>
+                    </div>
+HOTSPOT;
         }
         return $nbrAnswers;
     }

+ 15 - 0
main/plugin/hotspot2/css/hotspot.css

@@ -0,0 +1,15 @@
+#hotspot-container {
+    line-height: 0;
+    /*position: relative;
+    width: 100%;
+    vertical-align: middle;
+    padding-bottom: 408px;
+    margin: 0;
+    overflow: hidden;*/
+}
+#hotspot-container svg {
+    /*display: inline-block;
+    position: absolute;
+    top: 0;
+    left: 0;*/
+}

+ 506 - 0
main/plugin/hotspot2/js/hotspot.js

@@ -0,0 +1,506 @@
+var HotSpotAdmin = (function () {
+    var HotSpotSquare = function () {
+        this.x = 0;
+        this.y = 0;
+        this.width = 0;
+        this.height = 0;
+    };
+    HotSpotSquare.prototype.setStartPoint = function (x, y) {
+        this.x = parseInt(x);
+        this.y = parseInt(y);
+    };
+    HotSpotSquare.prototype.setEndPoint = function (x, y) {
+        var x2, y2;
+
+        x = parseInt(x);
+        y = parseInt(y);
+
+        if (x < this.x) {
+            x2 = this.x;
+            this.x = x;
+        } else {
+            x2 = x;
+        }
+
+        if (y < this.y) {
+            y2 = this.y;
+            this.y = y;
+        } else {
+            y2 = y;
+        }
+
+        this.width = Math.round(x2 - this.x);
+        this.height = Math.round(y2 - this.y);
+    };
+    HotSpotSquare.prototype.encode = function () {
+        var encodedPosition = [this.x, this.y].join(';');
+
+        return [
+            encodedPosition,
+            this.width,
+            this.height
+        ].join('|');
+    }
+
+    var HotSpotEllipse = function () {
+        this.centerX = 0;
+        this.centerY = 0;
+        this.radiusX = 0;
+        this.radiusY = 0;
+    };
+    HotSpotEllipse.prototype.setStartPoint = function (x, y) {
+        this.centerX = parseInt(x);
+        this.centerY = parseInt(y);
+    };
+    HotSpotEllipse.prototype.setEndPoint = function (x, y) {
+        var startX = this.centerX,
+            startY = this.centerY,
+            endX = 0,
+            endY = 0;
+
+        x = parseInt(x);
+        y = parseInt(y);
+
+        if (x < startX) {
+            endX = startX;
+            startX = x;
+        } else {
+            endX = x;
+        }
+
+        if (y < startY) {
+            endY = startY;
+            startY = y;
+        } else {
+            endY = y;
+        }
+
+        var width = Math.round(endX - startX);
+        var height = Math.round(endY - startY);
+
+        this.radiusX = Math.round(width / 2);
+        this.radiusY = Math.round(height / 2);
+        this.centerX = startX + this.radiusX;
+        this.centerY = startY + this.radiusY;
+    };
+    HotSpotEllipse.prototype.encode = function () {
+        var encodedCenter = [this.centerX, this.centerY].join(';');
+
+        return [
+            encodedCenter,
+            this.radiusX,
+            this.radiusY
+        ].join('|');
+    };
+
+    var HotSpotPolygon = function () {
+        this.points = [];
+    };
+    HotSpotPolygon.prototype.addPoint = function (x, y) {
+        this.points.push([
+            parseInt(x),
+            parseInt(y)
+        ]);
+    };
+    HotSpotPolygon.prototype.encode = function () {
+        var encodedPoints = [];
+
+        this.points.forEach(function (point) {
+            encodedPoints.push(point.join(';'));
+        });
+
+        return encodedPoints.join('|');
+    };
+
+    var HotSpotEl = function (hotspot, color) {
+        this.hotspot = hotspot;
+        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+        this.elStroke = 'rgb(' + color + ')';
+        this.elFill = 'rgba(' + color + ', 0.5)';
+    };
+    HotSpotEl.prototype.render = function () {
+        return this;
+    };
+    HotSpotEl.prototype.remove = function () {
+        if (!this.element) {
+            return;
+        }
+
+        this.element.parentNode.removeChild(this.element);
+        this.hotspot = null;
+    };
+
+    var SquareEl = function (hotspot, color) {
+        HotSpotEl.call(this, hotspot, color);
+
+        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+        this.element.setAttribute('stroke-width', 2);
+        this.element.setAttribute('stroke', this.elStroke);
+        this.element.setAttribute('fill', this.elFill);
+    };
+    SquareEl.prototype = Object.create(HotSpotEl.prototype);
+    SquareEl.prototype.render = function () {
+        this.element.setAttribute('x', this.hotspot.x);
+        this.element.setAttribute('y', this.hotspot.y);
+        this.element.setAttribute('width', this.hotspot.width);
+        this.element.setAttribute('height', this.hotspot.height);
+
+        return this.element;
+    };
+
+    var EllipseEl = function (hotspot, color) {
+        HotSpotEl.call(this, hotspot, color);
+
+        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse');
+        this.element.setAttribute('stroke-width', 2);
+        this.element.setAttribute('stroke', this.elStroke);
+        this.element.setAttribute('fill', this.elFill);
+    };
+    EllipseEl.prototype = Object.create(HotSpotEl.prototype);
+    EllipseEl.prototype.render = function () {
+        this.element.setAttribute('cx', this.hotspot.centerX);
+        this.element.setAttribute('cy', this.hotspot.centerY);
+        this.element.setAttribute('rx', this.hotspot.radiusX);
+        this.element.setAttribute('ry', this.hotspot.radiusY);
+
+        return this.element;
+    };
+
+    var PolygonEl = function (hotspot, color) {
+        HotSpotEl.call(this, hotspot, color);
+
+        this.element = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
+        this.element.setAttribute('stroke-width', 2);
+        this.element.setAttribute('stroke', this.elStroke);
+        this.element.setAttribute('fill', this.elFill);
+    };
+    PolygonEl.prototype = Object.create(HotSpotEl.prototype);
+    PolygonEl.prototype.render = function () {
+        var pointsPaired = [];
+
+        this.hotspot.points.forEach(function (point) {
+            pointsPaired.push(point.join(','));
+        });
+
+        this.element.setAttribute(
+            'points',
+            pointsPaired.join(' ')
+        );
+
+        return this.element;
+    };
+
+    var HotSpotSelectorEl = function (color, index, selectedValue) {
+        this.hotSpotIndex = parseInt(index);
+        this.elStroke = 'rgb(' + color + ')';
+        this.elFill = 'rgba(' + color + ', 0.5)';
+
+        switch (selectedValue) {
+            case 'square':
+            default:
+                this.selectedValue = 'square';
+                break;
+
+            case 'circle':
+                this.selectedValue = 'ellipse';
+                break;
+
+            case 'poly':
+                this.selectedValue = 'polygon';
+                break;
+        }
+    };
+    HotSpotSelectorEl.prototype.render = function () {
+        var self = this;
+
+        this.el = document.createElement('div');
+        this.el.className = 'col-xs-6 col-sm-3 col-md-2';
+        this.el.innerHTML = '\n\
+            <div class="input-group">\n\
+                <span class="input-group-addon" id="hotspot-' + this.hotSpotIndex + '">\n\
+                    <span class="fa fa-square fa-fw" data-hidden="true" style="color: ' + this.elStroke + '"></span>\n\
+                </span>\n\
+                <select class="form-control" aria-describedby="hotspot-' + this.hotSpotIndex + '">\n\
+                    <option value="">Select</option>\n\
+                    <option value="square">Square</option>\n\
+                    <option value="ellipse">Ellipse</option>\n\
+                    <option value="polygon">Polygon</option>\n\
+                </select>\n\
+            </div>\n\
+        ';
+
+        $(this.el).find('select').val(this.selectedValue);
+
+        var selectShapeEvent = function (e) {
+            switch (this.value) {
+                case 'square':
+                    //no break
+                case 'ellipse':
+                    //no break
+                case 'polygon':
+                    currentShapeType = this.value;
+                    currentHotSpotIndex = self.hotSpotIndex;
+                    break;
+
+                default:
+                    break;
+            }
+        };
+
+        $(this.el).on('click', selectShapeEvent);
+        $(this.el).find('select').on('change', selectShapeEvent);
+
+        return this.el;
+    };
+
+    var colors = [
+        '66, 113, 181',
+        '254, 142, 22',
+        '69, 199, 240',
+        '188, 214, 49',
+        '214, 49, 115',
+        '215, 215, 215',
+        '144, 175, 221',
+        '174, 134, 64',
+        '79, 146, 66',
+        '244, 235, 36',
+        '237, 32, 36',
+        '59, 59, 59',
+        '247, 189, 226'
+    ];
+
+    var getPointOnImage = function (x, y) {
+        var pointerPosition = {
+            left: x + window.scrollX,
+            top: y + window.scrollY
+        },
+            canvasOffset = {
+                x: canvas.getBoundingClientRect().x + window.scrollX,
+                y: canvas.getBoundingClientRect().y + window.scrollY
+            };
+
+        return {
+            x: Math.round(pointerPosition.left - canvasOffset.x),
+            y: Math.round(pointerPosition.top - canvasOffset.y)
+        };
+    };
+
+    var startCanvas = function () {
+        var newHotSpotEl = null,
+            pressingShift = false;
+
+        document.addEventListener('keydown', function (e) {
+            if (e.keyCode === 16) {
+                pressingShift = true;
+            }
+        }, false);
+        document.addEventListener('keyup', function (e) {
+            if (e.keyCode === 16) {
+                pressingShift = false;
+            }
+        }, false);
+
+        canvas.addEventListener('click', function (e) {
+            e.preventDefault();
+        }, false);
+
+        container.addEventListener('dragstart', function (e) {
+            e.preventDefault();
+        }, false);
+        container.addEventListener('click', function (e) {
+            if (shapes.length >= colors.length) {
+                return;
+            }
+
+            newHotSpotEl = draw(newHotSpotEl, e.clientX, e.clientY, pressingShift);
+
+            if (!newHotSpotEl) {
+                updateValues();
+            }
+        }, false);
+    };
+
+    var draw = function (hotSpotEl, x, y, isPressingShift) {
+        var pointerPosition = getPointOnImage(x, y),
+            hotSpot = null;
+
+        if (!hotSpotEl) {
+            switch (currentShapeType) {
+                case 'square':
+                    //no break
+                case 'ellipse':
+                    if (currentShapeType === 'ellipse') {
+                        hotSpot = new HotSpotEllipse();
+                        hotSpotEl = new EllipseEl(hotSpot, colors[currentHotSpotIndex]);
+                    } else {
+                        hotSpot = new HotSpotSquare();
+                        hotSpotEl = new SquareEl(hotSpot, colors[currentHotSpotIndex]);
+                    }
+
+                    hotSpot.setStartPoint(pointerPosition.x, pointerPosition.y);
+                    break;
+
+                case 'polygon':
+                    hotSpot = new HotSpotPolygon();
+                    hotSpotEl = new PolygonEl(hotSpot, colors[currentHotSpotIndex]);
+
+                    hotSpot.addPoint(pointerPosition.x, pointerPosition.y);
+                    break;
+            }
+
+            shapes[currentHotSpotIndex].remove();
+            shapes.splice(currentHotSpotIndex, 1, hotSpotEl);
+
+            canvas.appendChild(hotSpotEl.render());
+
+            return hotSpotEl;
+        }
+
+        switch (currentShapeType) {
+            case 'square':
+                //no break
+            case 'ellipse':
+                hotSpotEl.hotspot.setEndPoint(pointerPosition.x, pointerPosition.y);
+                hotSpotEl.render();
+
+                hotSpotEl = null;
+                break;
+
+            case 'polygon':
+                $(container).find('#hotspot-alert').text('Keed pressed the SHIFT key and click the image to close the polygon');
+
+                hotSpotEl.hotspot.addPoint(pointerPosition.x, pointerPosition.y);
+                hotSpotEl.render();
+
+                if (isPressingShift) {
+                    hotSpotEl = null;
+                    $(container).find('#hotspot-alert').text('');
+                }
+                break;
+        }
+
+        return hotSpotEl;
+    };
+
+    var updateValues = function () {
+        var currentHotSpotEl = shapes[currentHotSpotIndex];
+
+        if (currentHotSpotIndex === undefined) {
+            return;
+        }
+
+        if (currentHotSpotEl.hotspot instanceof HotSpotSquare) {
+            $('[name="hotspot_type[' + (currentHotSpotIndex + 1) + ']"]').val('square');
+        } else if (currentHotSpotEl.hotspot instanceof HotSpotEllipse) {
+            $('[name="hotspot_type[' + (currentHotSpotIndex + 1) + ']"]').val('circle');
+        } else if (currentHotSpotEl.hotspot instanceof HotSpotPolygon) {
+            $('[name="hotspot_type[' + (currentHotSpotIndex + 1) + ']"]').val('poly');
+        }
+
+        $('[name="hotspot_coordinates[' + (currentHotSpotIndex + 1) + ']"]').val(
+            currentHotSpotEl.hotspot.encode()
+        );
+    };
+
+    var loadHotSpots = function (hotSpotList) {
+        hotSpotList.forEach(function (hotSpotData, index) {
+            var hotSpot = null,
+                hotSpotEl = null,
+                color = colors[shapes.length];
+
+            switch (hotSpotData.type) {
+                case 'square':
+                    hotSpot = new HotSpotSquare();
+                    hotSpotEl = new SquareEl(hotSpot, color);
+
+                    var coords = hotSpotData.coord.split('|'),
+                        position = coords[0].split(';'),
+                        x = parseInt(position[0]),
+                        y = parseInt(position[1]),
+                        width = parseInt(coords[1]),
+                        height = parseInt(coords[2]);
+
+                    hotSpot.setStartPoint(x, y);
+                    hotSpot.setEndPoint(x + width, y + height);
+                    break;
+                case 'circle':
+                    hotSpot = new HotSpotEllipse();
+                    hotSpotEl = new EllipseEl(hotSpot, color);
+
+                    var coords = hotSpotData.coord.split('|'),
+                        position = coords[0].split(';'),
+                        x = parseInt(position[0] - coords[1]),
+                        y = parseInt(position[1] - coords[2]),
+                        width = parseInt(coords[1]) * 2,
+                        height = parseInt(coords[2]) * 2;
+
+                    hotSpot.setStartPoint(x, y);
+                    hotSpot.setEndPoint(x + width, y + height);
+                    break;
+
+                case 'poly':
+                    hotSpot = new HotSpotPolygon();
+                    hotSpotEl = new PolygonEl(hotSpot, color);
+
+                    hotSpotData.coord.split('|').forEach(function (point) {
+                        var exis = point.split(';');
+
+                        hotSpot.addPoint(exis[0], exis[1]);
+                    });
+                    break;
+            }
+
+            if (hotSpotEl) {
+                var hotSpotSelector = new HotSpotSelectorEl(color, index, hotSpotData.type);
+
+                selectors.appendChild(hotSpotSelector.render());
+                canvas.appendChild(hotSpotEl.render());
+                shapes.push(hotSpotEl);
+            }
+        });
+    };
+
+    var container, canvas, selectors, currentShapeType, currentHotSpotIndex, shapes = [];
+
+    return {
+        init: function (questionId, imageSrc) {
+            if (!questionId || !imageSrc) {
+                return;
+            }
+
+            selectors = document.querySelector('#hotspot-selectors');
+            container = document.querySelector('#hotspot-container');
+            canvas = document.querySelector('#hotspot-container svg');
+            currentShapeType = 'square';
+
+            var xhrImage = new $.Deferred();
+
+            var image = new Image();
+            image.onload = function () {
+                xhrImage.resolve(this);
+            };
+            image.onerror = function () {
+                xhrImage.reject();
+            };
+            image.src = imageSrc;
+
+            var xhrHotSpots = $.get('/main/exercice/hotspot_actionscript_admin.as.php', {
+                modifyAnswers: parseInt(questionId)
+            });
+
+            $.when.apply($, [xhrImage, xhrHotSpots]).done(function (imageRequest, hotSpotsRequest) {
+                var imageSvg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
+                imageSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', imageRequest.src);
+                imageSvg.setAttribute('width', imageRequest.width);
+                imageSvg.setAttribute('height', imageRequest.height);
+
+                container.style.width = imageRequest.width + 'px';
+                canvas.setAttribute('viewBox', '0 0 ' + imageRequest.width + ' ' + imageRequest.height);
+                canvas.appendChild(imageSvg);
+
+                loadHotSpots(hotSpotsRequest[0].hotspots);
+                startCanvas();
+            });
+        }
+    };
+})();

+ 231 - 0
main/plugin/hotspot2/js/hotspot_solution.js

@@ -0,0 +1,231 @@
+var HotSpotSolution = (function () {
+    var Answer = function () {
+        this.x = 0;
+        this.y = 0;
+    };
+
+    var HotSpot = function () {
+        this.id = 0;
+        this.name = '';
+    };
+
+    var Square = function () {
+        HotSpot.call(this);
+
+        this.x = 0,
+        this.y = 0,
+        this.width = 0,
+        this.height = 0;
+    };
+    Square.prototype = Object.create(HotSpot.prototype);
+
+    var Ellipse = function () {
+        HotSpot.call(this);
+
+        this.centerX = 0;
+        this.centerY = 0;
+        this.radiusX = 0;
+        this.radiusY = 0;
+    };
+    Ellipse.prototype = Object.create(HotSpot.prototype);
+
+    var Polygon = function () {
+        HotSpot.call(this);
+
+        this.points = [];
+    };
+    Polygon.prototype = Object.create(HotSpot.prototype);
+
+    var config, lang, hotSpots = [], answers = [];
+
+    var CanvasSVG = function (image) {
+        var imageSvg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
+        imageSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image.src);
+        imageSvg.setAttribute('width', image.width);
+        imageSvg.setAttribute('height', image.height);
+
+        this.el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+        this.el.setAttribute('version', '1.1');
+        this.el.setAttribute('viewBox', '0 0 ' + image.width + ' ' + image.height);
+        this.el.appendChild(imageSvg);
+    };
+    CanvasSVG.prototype.addHotSpot = function (hotSpot) {
+        var hotSpotSVG = null;
+
+        if (hotSpot instanceof Square) {
+            hotSpotSVG = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+            hotSpotSVG.setAttribute('x', hotSpot.x);
+            hotSpotSVG.setAttribute('y', hotSpot.y);
+            hotSpotSVG.setAttribute('width', hotSpot.width);
+            hotSpotSVG.setAttribute('height', hotSpot.height);
+        } else if (hotSpot instanceof Ellipse) {
+            hotSpotSVG = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse');
+            hotSpotSVG.setAttribute('cx', hotSpot.centerX);
+            hotSpotSVG.setAttribute('cy', hotSpot.centerY);
+            hotSpotSVG.setAttribute('rx', hotSpot.radiusX);
+            hotSpotSVG.setAttribute('ry', hotSpot.radiusY);
+        } else if (hotSpot instanceof Polygon) {
+            var pointsPaired = [];
+
+            hotSpot.points.forEach(function (point) {
+                pointsPaired.push(point.join(','));
+            });
+
+            hotSpotSVG = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
+            hotSpotSVG.setAttribute(
+                'points',
+                pointsPaired.join(' ')
+            );
+        }
+
+        if (!hotSpotSVG) {
+            return;
+        }
+
+        var color = colors[hotSpots.length - 1];
+
+        hotSpotSVG.setAttribute('stroke-width', 2);
+        hotSpotSVG.setAttribute('stroke', 'rgb(' + color + ')');
+        hotSpotSVG.setAttribute('fill', 'rgba(' + color + ', 0.75)');
+
+        this.el.appendChild(hotSpotSVG);
+    };
+    CanvasSVG.prototype.addAnswer = function (answer) {
+        var pointSVG = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
+        pointSVG.setAttribute('cx', answer.x);
+        pointSVG.setAttribute('cy', answer.y);
+        pointSVG.setAttribute('r', 15);
+        pointSVG.setAttribute('fill', '#00677C');
+
+        var textSVG = document.createElementNS('http://www.w3.org/2000/svg', 'text');
+        textSVG.setAttribute('x', answer.x);
+        textSVG.setAttribute('y', answer.y);
+        textSVG.setAttribute('dy', 5);
+        textSVG.setAttribute('font-family', 'sans-serif');
+        textSVG.setAttribute('text-anchor', 'middle');
+        textSVG.setAttribute('fill', 'white');
+        textSVG.textContent = answers.length;
+
+        this.el.appendChild(pointSVG);
+        this.el.appendChild(textSVG);
+    };
+
+    var decodeHotSpot = function (hotSpotInfo) {
+        var hotSpot = null,
+            coords = hotSpotInfo.coord.split('|');
+
+        switch (hotSpotInfo.type) {
+            case 'square':
+                var position = coords[0].split(';');
+
+                hotSpot = new Square();
+                hotSpot.x = parseInt(position[0]);
+                hotSpot.y = parseInt(position[1]);
+                hotSpot.width = parseInt(coords[1]);
+                hotSpot.height = parseInt(coords[2]);
+                break;
+            case 'circle':
+                var center = coords[0].split(';');
+
+                hotSpot = new Ellipse();
+                hotSpot.centerX = parseInt(center[0]);
+                hotSpot.centerY = parseInt(center[1]);
+                hotSpot.radiusX = parseInt(coords[1]);
+                hotSpot.radiusY = parseInt(coords[2]);
+                break;
+            case 'poly':
+                hotSpot = new Polygon();
+
+                coords.forEach(function (pairedCoord) {
+                    var coord = pairedCoord.split(';');
+
+                    hotSpot.points.push([
+                        parseInt(coord[0]),
+                        parseInt(coord[1])
+                    ]);
+                });
+                break;
+        }
+
+        return hotSpot;
+    };
+
+    var decodeAnswer = function (answerInfo) {
+        var answer = null,
+            coords = answerInfo.split(';');
+
+        answer = new Answer();
+        answer.x = coords[0];
+        answer.y = coords[1];
+
+        return answer;
+    };
+
+    var colors = [
+        '66, 113, 181',
+        '254, 142, 22',
+        '69, 199, 240',
+        '188, 214, 49',
+        '214, 49, 115',
+        '215, 215, 215',
+        '144, 175, 221',
+        '174, 134, 64',
+        '79, 146, 66',
+        '244, 235, 36',
+        '237, 32, 36',
+        '59, 59, 59'
+    ];
+
+    var startAnswer = function (hotSpotAnswerInfo) {
+        var image = new Image();
+        image.onload = function () {
+            var canvasSVG = new CanvasSVG(this);
+
+            hotSpotAnswerInfo.hotspots.forEach(function (hotSpotInfo) {
+                var hotSpot = decodeHotSpot(hotSpotInfo);
+
+                if (!hotSpot) {
+                    return;
+                }
+
+                hotSpots.push(hotSpot);
+                canvasSVG.addHotSpot(hotSpot);
+            });
+
+            hotSpotAnswerInfo.answers.forEach(function (answerInfo) {
+               var answer = decodeAnswer(answerInfo);
+
+               answers.push(answer);
+               canvasSVG.addAnswer(answer);
+            });
+
+            $(config.selector)
+                .css('width', this.width)
+                .append(canvasSVG.el);
+        };
+        image.src = hotSpotAnswerInfo.image;
+
+        lang = hotSpotAnswerInfo.lang;
+    };
+
+    return {
+        init: function (settings) {
+            config = $.extend({
+                questionId: 0,
+                exerciseId: 0,
+                selector: ''
+            }, settings);
+
+            if (!config.questionId || !config.selector) {
+                return;
+            }
+
+            var xhrHotSpotAnswers = $.getJSON('/main/exercice/hotspot_answers.as.php', {
+                modifyAnswers: parseInt(config.questionId),
+                exe_id: parseInt(config.exerciseId)
+            });
+
+            $.when(xhrHotSpotAnswers).done(startAnswer);
+        }
+    };
+})();

+ 269 - 0
main/plugin/hotspot2/js/hotspot_user.js

@@ -0,0 +1,269 @@
+var HotSpotUser = (function () {
+    var Answer = function () {
+        this.x = 0;
+        this.y = 0;
+    };
+
+    var HotSpot = function () {
+        this.id = 0;
+        this.name = '';
+    };
+    HotSpot.prototype.checkPoint = function (x, y) {
+        return false;
+    };
+
+    var Square = function () {
+        HotSpot.call(this);
+
+        this.x = 0,
+        this.y = 0,
+        this.width = 0,
+        this.height = 0;
+    };
+    Square.prototype = Object.create(HotSpot.prototype);
+    Square.prototype.checkPoint = function (x, y) {
+        var left = this.x,
+            right = this.x + this.width,
+            top = this.y,
+            bottom = this.y + this.height;
+
+        var xIsValid = x >= left && x <= right,
+            yIsValid = y >= top && y <= bottom;
+
+        return xIsValid && yIsValid;
+    };
+
+    var Ellipse = function () {
+        HotSpot.call(this);
+
+        this.centerX = 0;
+        this.centerY = 0;
+        this.radiusX = 0;
+        this.radiusY = 0;
+    };
+    Ellipse.prototype = Object.create(HotSpot.prototype);
+    Ellipse.prototype.checkPoint = function (x, y) {
+        var dX = x - this.centerX,
+            dY = y - this.centerY;
+
+        return Math.pow(dX, 2) / Math.pow(this.radiusX, 2) + Math.pow(dY, 2) / Math.pow(this.radiusY, 2) <= 1;
+    };
+
+    var Polygon = function () {
+        HotSpot.call(this);
+
+        this.points = [];
+    };
+    Polygon.prototype = Object.create(HotSpot.prototype);
+    Polygon.prototype.checkPoint = function (x, y) {
+        var isInside = false;
+
+        for (var i = 0, j = this.points.length - 1; i < this.points.length; j = i++) {
+            var xi = this.points[i][0],
+                yi = this.points[i][1],
+                xj = this.points[j][0],
+                yj = this.points[j][1];
+
+            var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
+
+            if (intersect) {
+                isInside = !isInside;
+            }
+        }
+
+        return isInside;
+    };
+
+    var CanvasSVG = function (image) {
+        var imageSvg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
+        imageSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image.src);
+        imageSvg.setAttribute('width', image.width);
+        imageSvg.setAttribute('height', image.height);
+
+        this.el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+        this.el.setAttribute('version', '1.1');
+        this.el.setAttribute('viewBox', '0 0 ' + image.width + ' ' + image.height);
+        this.el.appendChild(imageSvg);
+
+        this.messagesEl = document.createElement('div');
+    };
+    CanvasSVG.prototype.setEvents = function () {
+        var self = this;
+
+        var getPointOnImage = function (x, y) {
+            var pointerPosition = {
+                    left: x + window.scrollX,
+                    top: y + window.scrollY
+                },
+                canvasOffset = {
+                    x: self.el.getBoundingClientRect().x + window.scrollX,
+                    y: self.el.getBoundingClientRect().y + window.scrollY
+                };
+
+            return {
+                x: Math.round(pointerPosition.left - canvasOffset.x),
+                y: Math.round(pointerPosition.top - canvasOffset.y)
+            };
+        };
+
+        this.el.addEventListener('dragstart', function (e) {
+            e.preventDefault();
+        }, false);
+        this.el.addEventListener('click', function (e) {
+            e.preventDefault();
+
+            if (answers.length >= hotSpots.length) {
+                return;
+            }
+
+            var point = getPointOnImage(e.clientX, e.clientY);
+
+            var answer = new Answer();
+            answer.x = point.x;
+            answer.y = point.y;
+
+            answers.push(answer);
+            self.addAnswer(answer);
+
+            if (answers.length === hotSpots.length) {
+                self.messagesEl.textContent = lang.ExeFinished;
+
+                return;
+            }
+
+            self.messagesEl.textContent = lang.NextAnswer + ' ' + hotSpots[answers.length].name;
+        });
+    };
+    CanvasSVG.prototype.addAnswer = function (answer) {
+        var pointSVG = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
+        pointSVG.setAttribute('cx', answer.x);
+        pointSVG.setAttribute('cy', answer.y);
+        pointSVG.setAttribute('r', 15);
+        pointSVG.setAttribute('fill', '#00677C');
+
+        var textSVG = document.createElementNS('http://www.w3.org/2000/svg', 'text');
+        textSVG.setAttribute('x', answer.x);
+        textSVG.setAttribute('y', answer.y);
+        textSVG.setAttribute('dy', 5);
+        textSVG.setAttribute('font-family', 'sans-serif');
+        textSVG.setAttribute('text-anchor', 'middle');
+        textSVG.setAttribute('fill', 'white');
+        textSVG.textContent = answers.length;
+
+        this.el.appendChild(pointSVG);
+        this.el.appendChild(textSVG);
+
+        var hotSpot = hotSpots[answers.length - 1];
+
+        var hotspotTxt = document.createElement('input');
+        hotspotTxt.type = 'hidden';
+        hotspotTxt.name = 'hotspot[' + config.questionId + '][' + hotSpot.id + ']';
+        hotspotTxt.value = [answer.x, answer.y].join(';');
+
+        var choiceTxt = document.createElement('input');
+        choiceTxt.type = 'hidden';
+        choiceTxt.name = 'choice[' + config.questionId + '][' + hotSpot.id + ']';
+        choiceTxt.value = hotSpot.checkPoint(answer.x, answer.y) ? 1 : 0;
+
+        this.el.parentNode.appendChild(hotspotTxt);
+        this.el.parentNode.appendChild(choiceTxt);
+    };
+    CanvasSVG.prototype.startMessagesPanel = function () {
+        this.messagesEl.textContent = lang.NextAnswer + ' ' + hotSpots[0].name;
+
+        this.el.parentNode.parentNode.appendChild(this.messagesEl);
+    };
+
+    var decodeHotSpot = function (hotSpotInfo) {
+        var hotSpot = null,
+            coords = hotSpotInfo.coord.split('|');
+
+        switch (hotSpotInfo.type) {
+            case 'square':
+                var position = coords[0].split(';');
+
+                hotSpot = new Square();
+                hotSpot.x = parseInt(position[0]);
+                hotSpot.y = parseInt(position[1]);
+                hotSpot.width = parseInt(coords[1]);
+                hotSpot.height = parseInt(coords[2]);
+                break;
+            case 'circle':
+                var center = coords[0].split(';');
+
+                hotSpot = new Ellipse();
+                hotSpot.centerX = parseInt(center[0]);
+                hotSpot.centerY = parseInt(center[1]);
+                hotSpot.radiusX = parseInt(coords[1]);
+                hotSpot.radiusY = parseInt(coords[2]);
+                break;
+            case 'poly':
+                hotSpot = new Polygon();
+
+                coords.forEach(function (pairedCoord) {
+                    var coord = pairedCoord.split(';');
+
+                    hotSpot.points.push([
+                        parseInt(coord[0]),
+                        parseInt(coord[1])
+                    ]);
+                });
+                break;
+        }
+
+        if (hotSpot) {
+            hotSpot.id = parseInt(hotSpotInfo.id);
+            hotSpot.name = hotSpotInfo.answer;
+        }
+
+        return hotSpot;
+    };
+
+    var config, lang, hotSpots = [], answers = [];
+
+    var startQuestion = function (hotSpotQuestionInfo) {
+        var image = new Image();
+        image.onload = function () {
+            var canvasSVG = new CanvasSVG(this);
+
+            hotSpotQuestionInfo.hotspots.forEach(function (hotSpotInfo) {
+                var hotSpot = decodeHotSpot(hotSpotInfo);
+
+                if (!hotSpot) {
+                    return;
+                }
+
+                hotSpots.push(hotSpot);
+            });
+
+            $(config.selector)
+                .css('width', this.width)
+                .append(canvasSVG.el);
+
+            canvasSVG.setEvents();
+            canvasSVG.startMessagesPanel();
+        };
+        image.src = hotSpotQuestionInfo.image;
+
+        lang = hotSpotQuestionInfo.lang;
+    };
+
+    return {
+        init: function (settings) {
+            config = $.extend({
+                questionId: 0,
+                selector: ''
+            }, settings);
+
+            if (!config.questionId || !config.selector) {
+                return;
+            }
+
+            var xhrHotSpotQuestion = $.getJSON('/main/exercice/hotspot_actionscript.as.php', {
+                modifyAnswers: parseInt(config.questionId)
+            });
+
+            $.when(xhrHotSpotQuestion).done(startQuestion);
+        } 
+    };
+})();

+ 5 - 87
src/Chamilo/CoreBundle/Component/Editor/CkEditor/Toolbar/TestProposedAnswer.php

@@ -16,32 +16,8 @@ class TestProposedAnswer extends Basic
      */
     public function getConfig()
     {
-        $config['toolbarGroups'] = array(
-            array('name' => 'document'),
-            array(
-                'name' => 'clipboard',
-                'groups' => array('clipboard', 'undo',)
-            ),
-            array(
-                'name' => 'basicstyles',
-                'groups' => array('basicstyles', 'cleanup',)
-            ),
-            array(
-                'name' => 'paragraph',
-                'groups' => array('list', 'indent', 'blocks', 'align')
-            ),
-            array('name' => 'links'),
-            array('name' => 'insert'),
-            '/',
-            array('name' => 'styles'),
-            array('name' => 'colors'),
-            array('name' => 'mode'),
-            array('name' => 'others')
-        );
-
         $config['toolbarCanCollapse'] = true;
         $config['toolbarStartupExpanded'] = false;
-        $config['extraPlugins'] = $this->getPluginsToString();
         //$config['width'] = '100';
         //$config['height'] = '200';
         if (api_get_setting('more_buttons_maximized_mode') != 'true') {
@@ -54,54 +30,13 @@ class TestProposedAnswer extends Basic
         return $config;
     }
 
-    /**
-     * @return array
-     */
-    public function getConditionalPlugins()
-    {
-        $plugins = array();
-        if (api_get_setting('show_glossary_in_documents') == 'ismanual') {
-            $plugins[] = 'glossary';
-        }
-
-        return $plugins;
-    }
-
     /**
      * Get the toolbar configuration when CKEditor is maximized
      * @return array
      */
     protected function getMaximizedToolbar()
     {
-        return [
-            ['NewPage', 'Templates', '-', 'Preview', 'Print'],
-            ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord'],
-            ['Undo', 'Redo', '-', 'SelectAll', 'Find', '-', 'RemoveFormat'],
-            ['Link', 'Unlink', 'Anchor', 'Glossary'],
-            [
-                'Image',
-                'Mapping',
-                'Video',
-                'Flash',
-                'Youtube',
-                'Oembed',
-                'Audio',
-                'leaflet',
-                'Smiley',
-                'SpecialChar',
-                'Asciimath',
-                'Asciisvg'
-            ],
-            '/',
-            ['Table', '-', 'CreateDiv'],
-            ['BulletedList', 'NumberedList', 'HorizontalRule', '-', 'Outdent', 'Indent', 'Blockquote'],
-            ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
-            ['Bold', 'Italic', 'Underline', 'Strike', '-', 'Subscript', 'Superscript', '-', 'TextColor', 'BGColor'],
-            [api_get_setting('allow_spellcheck') == 'true' ? 'Scayt' : ''],
-            ['Styles', 'Format', 'Font', 'FontSize'],
-            ['PageBreak', 'ShowBlocks', 'Source'],
-            ['Toolbarswitch'],
-        ];
+        return $this->getNormalToolbar();
     }
 
     /**
@@ -111,18 +46,9 @@ class TestProposedAnswer extends Basic
     protected function getNormalToolbar()
     {
         return [
-            [
-                'Maximize',
-                'Bold',
-                'Image',
-                'Link',
-                'PasteFromWord',
-                'Audio',
-                'Table',
-                'Subscript',
-                'Superscript',
-                'Source'
-            ]
+            ['Bold', 'Subscript', 'Superscript'],
+            ['Image', 'Link', 'Audio', 'Table', 'PasteFromWord'],
+            ['Maximize', 'Source'],
         ];
     }
 
@@ -132,14 +58,6 @@ class TestProposedAnswer extends Basic
      */
     protected function getMinimizedToolbar()
     {
-        return [
-            ['Templates'],
-            ['PasteFromWord'],
-            ['Link'],
-            ['Image', 'Video', 'Flash', 'Audio', 'Asciimath', 'Asciisvg'],
-            ['Table'],
-            ['Bold'],
-            ['Source', 'Toolbarswitch']
-        ];
+        return $this->getNormalToolbar();
     }
 }