From ea9fd2eafb65cda70a20441cbc204b80d657833c Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 19 Oct 2017 14:08:49 +0200
Subject: [PATCH] OO-2926: choose cardinality of hotspot interaction in editor

---
 .../model/xml/AssessmentItemFactory.java      |   7 +-
 .../HotspotAssessmentItemBuilder.java         |  21 +-
 ...sessmentObjectVelocityRenderDecorator.java |   8 +
 .../_content/hotspotInteraction.html          |   2 +
 .../editor/_i18n/LocalStrings_de.properties   |   4 +
 .../editor/_i18n/LocalStrings_en.properties   |   4 +
 .../editor/_i18n/LocalStrings_fr.properties   |   1 +
 .../interactions/HotspotEditorController.java |  22 ++
 .../static/js/jquery/qti/jquery.hotspot.js    | 232 +++++++++---------
 9 files changed, 185 insertions(+), 116 deletions(-)

diff --git a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java
index a2d956b7f71..af53e6b42a4 100644
--- a/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java
+++ b/src/main/java/org/olat/ims/qti21/model/xml/AssessmentItemFactory.java
@@ -325,10 +325,13 @@ public class AssessmentItemFactory {
 		return responseDeclaration;
 	}
 	
-	public static ResponseDeclaration createHotspotCorrectResponseDeclaration(AssessmentItem assessmentItem, Identifier declarationId, List<Identifier> correctResponseIds) {
+	public static ResponseDeclaration createHotspotCorrectResponseDeclaration(AssessmentItem assessmentItem, Identifier declarationId,
+			List<Identifier> correctResponseIds, Cardinality cardinality) {
 		ResponseDeclaration responseDeclaration = new ResponseDeclaration(assessmentItem);
 		responseDeclaration.setIdentifier(declarationId);
-		if(correctResponseIds == null || correctResponseIds.size() == 0 || correctResponseIds.size() > 1) {
+		if(cardinality != null && (cardinality == Cardinality.SINGLE || cardinality == Cardinality.MULTIPLE)) {
+			responseDeclaration.setCardinality(cardinality);
+		} else if(correctResponseIds == null || correctResponseIds.size() == 0 || correctResponseIds.size() > 1) {
 			responseDeclaration.setCardinality(Cardinality.MULTIPLE);
 		} else {
 			responseDeclaration.setCardinality(Cardinality.SINGLE);
diff --git a/src/main/java/org/olat/ims/qti21/model/xml/interactions/HotspotAssessmentItemBuilder.java b/src/main/java/org/olat/ims/qti21/model/xml/interactions/HotspotAssessmentItemBuilder.java
index 32ccf6a7158..f3c2882ea52 100644
--- a/src/main/java/org/olat/ims/qti21/model/xml/interactions/HotspotAssessmentItemBuilder.java
+++ b/src/main/java/org/olat/ims/qti21/model/xml/interactions/HotspotAssessmentItemBuilder.java
@@ -74,6 +74,7 @@ import uk.ac.ed.ph.jqtiplus.serialization.QtiSerializer;
 import uk.ac.ed.ph.jqtiplus.types.ComplexReferenceIdentifier;
 import uk.ac.ed.ph.jqtiplus.types.Identifier;
 import uk.ac.ed.ph.jqtiplus.value.BaseType;
+import uk.ac.ed.ph.jqtiplus.value.Cardinality;
 import uk.ac.ed.ph.jqtiplus.value.IdentifierValue;
 import uk.ac.ed.ph.jqtiplus.value.SingleValue;
 
@@ -86,6 +87,7 @@ import uk.ac.ed.ph.jqtiplus.value.SingleValue;
 public class HotspotAssessmentItemBuilder extends AssessmentItemBuilder implements ResponseIdentifierForFeedback {
 	
 	private String question;
+	private Cardinality cardinality;
 	private Identifier responseIdentifier;
 	private List<Identifier> correctAnswers;
 	protected ScoreEvaluation scoreEvaluation;
@@ -152,9 +154,12 @@ public class HotspotAssessmentItemBuilder extends AssessmentItemBuilder implemen
 		if(hotspotInteraction != null) {
 			ResponseDeclaration responseDeclaration = assessmentItem
 					.getResponseDeclaration(hotspotInteraction.getResponseIdentifier());
-			if(responseDeclaration != null && responseDeclaration.getCorrectResponse() != null) {
-				CorrectResponse correctResponse = responseDeclaration.getCorrectResponse();
-				extractIdentifiersFromCorrectResponse(correctResponse, correctAnswers);
+			if(responseDeclaration != null) {
+				if(responseDeclaration.getCorrectResponse() != null) {
+					CorrectResponse correctResponse = responseDeclaration.getCorrectResponse();
+					extractIdentifiersFromCorrectResponse(correctResponse, correctAnswers);
+				}
+				cardinality = responseDeclaration.getCardinality();
 			}
 		}
 	}
@@ -188,6 +193,14 @@ public class HotspotAssessmentItemBuilder extends AssessmentItemBuilder implemen
 		return responseIdentifier;
 	}
 	
+	public boolean isSingleChoice() {
+		return cardinality == Cardinality.SINGLE;
+	}
+	
+	public void setCardinality(Cardinality cardinality) {
+		this.cardinality = cardinality;
+	}
+	
 	@Override
 	public List<Answer> getAnswers() {
 		List<HotspotChoice> hotspotChoices = getHotspotChoices();
@@ -345,7 +358,7 @@ public class HotspotAssessmentItemBuilder extends AssessmentItemBuilder implemen
 	@Override
 	protected void buildResponseAndOutcomeDeclarations() {
 		ResponseDeclaration responseDeclaration = AssessmentItemFactory
-				.createHotspotCorrectResponseDeclaration(assessmentItem, responseIdentifier, correctAnswers);
+				.createHotspotCorrectResponseDeclaration(assessmentItem, responseIdentifier, correctAnswers, cardinality);
 		if(scoreEvaluation == ScoreEvaluation.perAnswer) {
 			AssessmentItemFactory.appendMapping(responseDeclaration, scoreMapping);
 		}
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java
index 8f4a4aa8ee8..b77adac94de 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectVelocityRenderDecorator.java
@@ -55,6 +55,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.interaction.GapMatchInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.GraphicAssociateInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.GraphicGapMatchInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.GraphicOrderInteraction;
+import uk.ac.ed.ph.jqtiplus.node.item.interaction.HotspotInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.HottextInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.InlineChoiceInteraction;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction;
@@ -249,6 +250,13 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
 				return false;
 			}
 			return sc;
+		} else if(interaction instanceof HotspotInteraction) {
+			HotspotInteraction hotspotInteraction = (HotspotInteraction)interaction;
+			ResponseDeclaration responseDeclaration = assessmentItem.getResponseDeclaration(hotspotInteraction.getResponseIdentifier());
+			if(responseDeclaration != null && responseDeclaration.hasCardinality(Cardinality.SINGLE)) {
+				return true;
+			}
+			return false;
 		}
 		return false;
 	}
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/_content/hotspotInteraction.html b/src/main/java/org/olat/ims/qti21/ui/components/_content/hotspotInteraction.html
index 429eea6d4f0..afc1290c450 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/_content/hotspotInteraction.html
+++ b/src/main/java/org/olat/ims/qti21/ui/components/_content/hotspotInteraction.html
@@ -2,6 +2,7 @@
 #set($qtiContainerId = "oc_" + $responseIdentifier)
 #set($responseValue = $r.getResponseValue($interaction.responseIdentifier))
 #set($isResponsive = $r.hasCssClass($interaction, "interaction-responsive"))
+#set($singleChoice = $r.isSingleChoice($interaction))
 
 <input name="qtiworks_presented_${responseIdentifier}" type="hidden" value="1"/>
 <div class="$localName">
@@ -44,6 +45,7 @@
 			responseIdentifier: '$responseIdentifier',
 			formDispatchFieldId: '$r.formDispatchFieldId',
 			maxChoices: $interaction.maxChoices,
+			singleChoice: $singleChoice,
 			responseValue: '$r.toString($responseValue,",")',
 			opened: $isItemSessionOpen
 		});
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
index c954c1df36c..50cd4c726c6 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
@@ -26,6 +26,7 @@ editor.unkown.title=Unbekanntes interaction
 error.assessment.test=Die Datei konnte nicht gelesen werden. Sie ist entweder korrupt oder mit dem falschen Format gespeichert.
 error.cannot.create.section=Sie k\u00F6nnen hier keine Sektion erstellen.
 error.cannot.delete=Sie d\u00FCrfen diese Ressource nicht l\u00F6schen.
+error.cardinality.answer=Single choice erlaubt nur eine korrekte Antwort.
 error.double=$org.olat.ims.qti21.ui\:error.double
 error.import.question=Die Frage konnte wegen eine unerwartete Fehler nicht importiert werden
 error.integer=$org.olat.ims.qti21.ui\:error.integer
@@ -87,6 +88,7 @@ form.imd.answered.title=Titel
 form.imd.background=Hintergrund
 form.imd.background.resize=Bildgr\u00F6sse f\u00FCr das Web optimieren
 form.imd.background.resize.no=Nicht anpassen
+form.imd.cardinality=Typ
 form.imd.condition=Bedingung(en)
 form.imd.correct.kprim=Richtig
 form.imd.correct.spots=Korrekte Spots
@@ -177,6 +179,7 @@ min.choices=Min. Anzahl von m
 min.choices.unlimited=Nicht begrenzet
 min.score=Minimal erreichbare Punktzahl
 minute.short=m
+MULTIPLE=Multiple choice
 new.answer=Neue Antwort
 new.circle=Kreis
 new.drawing=Zeichnen
@@ -200,6 +203,7 @@ new.testpart=Test-Part
 new.upload=Datei hochladen
 preview=Vorschau
 preview.solution=Vorschau L\u00F6sung
+SINGLE=Single choice
 time.limit.max=Zeitbeschr\u00E4nkung
 title.add=$org.olat.ims.qti.editor\:title.add
 tools.change.copy=$org.olat.ims.qti.editor\:tools.change.copy
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
index 1e4a26a9cbc..863fbe58986 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
@@ -27,6 +27,7 @@ editor.unkown.title=Unkown interaction
 error.assessment.test=The file cannot be interpreted. It seems corrupted or with the wrong format.
 error.cannot.create.section=A section cannot be created everywhere\!
 error.cannot.delete=You cannot delete this object.
+error.cardinality.answer=Single choice allow only one correct answer.
 error.double=$org.olat.ims.qti21.ui\:error.double
 error.import.question=An unexpected error happens during import of a question.
 error.integer=$org.olat.ims.qti21.ui\:error.integer
@@ -88,6 +89,7 @@ form.imd.answered.title=Title
 form.imd.background=Background
 form.imd.background.resize=Optimize an image size for the Web
 form.imd.background.resize.no=Don't change
+form.imd.cardinality=Type
 form.imd.condition=Condition(s)
 form.imd.correct.kprim=True
 form.imd.correct.spots=Correct spots
@@ -178,6 +180,7 @@ min.choices=Min. number of possible answers
 min.choices.unlimited=Not limited
 min.score=Min. score
 minute.short=m
+MULTIPLE=Multiple choice
 new.answer=New answer
 new.circle=Circle
 new.drawing=Drawing
@@ -203,6 +206,7 @@ preview=Preview
 preview.solution=Preview solution
 time.limit.max=Time limit
 title.add=$org.olat.ims.qti.editor\:title.add
+SINGLE=Single choice
 tools.change.copy=$org.olat.ims.qti.editor\:tools.change.copy
 tools.change.delete=$org.olat.ims.qti.editor\:tools.change.delete
 tools.export.docx=$org.olat.ims.qti.editor\:tools.export.docx
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties
index 15872870ef2..a6556b3732c 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_fr.properties
@@ -66,6 +66,7 @@ form.imd.answered.title=Titre
 form.imd.background=Image de fond
 form.imd.background.resize=Optimiser la taille de l'image pour le web
 form.imd.background.resize.no=Laisser inchang\u00E9
+form.imd.cardinality=Type
 form.imd.correct.kprim=Vrai
 form.imd.correctSolution.text=Solution correcte
 form.imd.correctSolution.text.word=$\:form.imd.correctSolution.text (seulement pour export Word)
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java
index ee268dc3120..307f80227c5 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java
@@ -69,6 +69,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import uk.ac.ed.ph.jqtiplus.node.expression.operator.Shape;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.HotspotChoice;
 import uk.ac.ed.ph.jqtiplus.types.Identifier;
+import uk.ac.ed.ph.jqtiplus.value.Cardinality;
 
 /**
  * 
@@ -92,6 +93,7 @@ public class HotspotEditorController extends FormBasicController {
 	private RichTextElement textEl;
 	private FileElement backgroundEl;
 	private SingleSelection resizeEl;
+	private SingleSelection cardinalityEl;
 	private FormLayoutContainer hotspotsCont;
 	private MultipleSelectionElement responsiveEl;
 	private FormLink newCircleButton, newRectButton;
@@ -143,6 +145,15 @@ public class HotspotEditorController extends FormBasicController {
 				formLayout, ureq.getUserSession(), getWindowControl());
 		textEl.addActionListener(FormEvent.ONCLICK);
 		
+		String[] cardinalityKeys = new String[] { Cardinality.SINGLE.name(), Cardinality.MULTIPLE.name() };
+		String[] cardinalityValues = new String[] { translate(Cardinality.SINGLE.name()), translate(Cardinality.MULTIPLE.name()) };
+		cardinalityEl = uifactory.addRadiosHorizontal("form.imd.cardinality", formLayout, cardinalityKeys, cardinalityValues);
+		if(itemBuilder.isSingleChoice()) {
+			cardinalityEl.select(cardinalityKeys[0], true);
+		} else {
+			cardinalityEl.select(cardinalityKeys[1], true);
+		}
+		
 		responsiveEl = uifactory.addCheckboxesHorizontal("form.imd.responsive", formLayout, onKeys, new String[] {""});
 		responsiveEl.setHelpText(translate("form.imd.responsive.hint"));
 		if(itemBuilder.isResponsive()) {
@@ -240,6 +251,12 @@ public class HotspotEditorController extends FormBasicController {
 			}
 		}
 		
+		cardinalityEl.clearError();
+		if(cardinalityEl.isSelected(0) && correctHotspotsEl.getSelectedKeys().size() > 1) {
+			cardinalityEl.setErrorKey("error.cardinality.answer", null);
+			allOk &= false;
+		}
+		
 		return allOk & super.validateFormLogic(ureq);
 	}
 
@@ -418,6 +435,11 @@ public class HotspotEditorController extends FormBasicController {
 			objectImg = initialBackgroundImage;
 		}
 		
+		if(cardinalityEl.isOneSelected()) {
+			String selectedCardinality = cardinalityEl.getSelectedKey();
+			itemBuilder.setCardinality(Cardinality.valueOf(selectedCardinality));
+		}
+		
 		boolean updateHotspot = true;
 		
 		if(objectImg != null) {
diff --git a/src/main/webapp/static/js/jquery/qti/jquery.hotspot.js b/src/main/webapp/static/js/jquery/qti/jquery.hotspot.js
index 2d35266e6ce..d7737fc0fb9 100644
--- a/src/main/webapp/static/js/jquery/qti/jquery.hotspot.js
+++ b/src/main/webapp/static/js/jquery/qti/jquery.hotspot.js
@@ -1,117 +1,129 @@
 (function ($) {
-    $.fn.hotspotInteraction = function(options) {
-    	var settings = $.extend({
-    		responseIdentifier: null,
-    		formDispatchFieldId: null,
-    		maxChoices: 1,
-    		responseValue: null,
-    		opened: false
-        }, options );
-    	
-    	try {
-    		if(!(typeof settings.responseValue === "undefined") && settings.responseValue.length > 0) {
-    			drawHotspotAreas(this, settings);
-    		} 
-    		if(settings.opened) {
-    			hotspots(this, settings);
-    		}
-    	} catch(e) {
-    		if(window.console) console.log(e);
-    	}
-        return this;
-    };
-    
-    function drawHotspotAreas($obj, settings) {
-    	var containerId = $obj.attr('id');
-    	var divContainer = jQuery('#' + containerId);
-    	
-    	var areaIds = settings.responseValue.split(',');
-    	for(i=areaIds.length; i-->0; ) {
-    		var areaEl = jQuery('#ac_' + settings.responseIdentifier + '_' + areaIds[i]);
-    		var data = areaEl.data('maphilight') || {};
-    		data.selectedOn = true;
-    		colorData(data);
-    		areaEl.data('maphilight', data).trigger('alwaysOn.maphilight');
-    		
-    		var inputElement = jQuery('<input type="hidden"/>')
+	$.fn.hotspotInteraction = function(options) {
+		var settings = $.extend({
+			responseIdentifier: null,
+			formDispatchFieldId: null,
+			maxChoices: 1,
+			singleChoice: false,
+			responseValue: null,
+			opened: false
+		}, options );
+		
+		try {
+			if(!(typeof settings.responseValue === "undefined") && settings.responseValue.length > 0) {
+				drawHotspotAreas(this, settings);
+			} 
+			if(settings.opened) {
+				hotspots(this, settings);
+			}
+		} catch(e) {
+			if(window.console) console.log(e);
+		}
+		return this;
+	};
+	
+	function drawHotspotAreas($obj, settings) {
+		var containerId = $obj.attr('id');
+		var divContainer = jQuery('#' + containerId);
+		
+		var areaIds = settings.responseValue.split(',');
+		for(i=areaIds.length; i-->0; ) {
+			var areaEl = jQuery('#ac_' + settings.responseIdentifier + '_' + areaIds[i]);
+			var data = areaEl.data('maphilight') || {};
+			data.selectedOn = true;
+			colorData(data);
+			areaEl.data('maphilight', data).trigger('alwaysOn.maphilight');
+			
+			var inputElement = jQuery('<input type="hidden"/>')
 				.attr('name', 'qtiworks_response_' + settings.responseIdentifier)
 				.attr('value', areaEl.data('qti-id'));
-    		divContainer.append(inputElement);
-    	}
-    }
-    
-    function hotspots($obj, settings) {
-    	var containerId = $obj.attr('id');
-    	jQuery('#' + containerId + " map area").each(function(index, el) {
-    		jQuery(el).on('click', function() {
-    			clickHotspotArea(this, containerId, settings.responseIdentifier, settings.maxChoices);
-    		});
-    	})
-    };
+			divContainer.append(inputElement);
+		}
+	}
+	
+	function hotspots($obj, settings) {
+		var containerId = $obj.attr('id');
+		jQuery('#' + containerId + " map area").each(function(index, el) {
+			jQuery(el).on('click', function() {
+				clickHotspotArea(this, containerId, settings.responseIdentifier, settings.maxChoices, settings.singleChoice);
+			});
+		})
+	};
 
-    function clickHotspotArea(spot, containerId, responseIdentifier, maxChoices) {
-    	var areaEl = jQuery(spot);
-    	var data = areaEl.data('maphilight') || {};
-    	if((typeof data.selectedOn === "undefined") || !data.selectedOn) {
-    		var numOfChoices = maxChoices;
-    		if(numOfChoices > 0) {
-    			var countChoices = 0;
-    			jQuery("area", "map[name='" + containerId + "_map']").each(function(index, el) {
-    				var cData = jQuery(el).data('maphilight') || {};
-    				if(cData.selectedOn) {
-    					countChoices++;
-    				}
-    			});
-    			if(countChoices >= numOfChoices) {
-    				return false;
-    			}
-    		}
-    	}
-    	
-    	if(typeof data.selectedOn === "undefined") {
-    		data.selectedOn = true;
-    	} else {
-    		data.selectedOn = !data.selectedOn;
-    	}
-    	colorData(data);
-    	areaEl.data('maphilight', data).trigger('alwaysOn.maphilight');
+	function clickHotspotArea(spot, containerId, responseIdentifier, maxChoices, singleChoice) {
+		var areaEl = jQuery(spot);
+		var data = areaEl.data('maphilight') || {};
+		if((typeof data.selectedOn === "undefined") || !data.selectedOn) {
+			if(singleChoice) {
+				jQuery("area", "map[name='" + containerId + "_map']").each(function(index, el) {
+					var cData = jQuery(el).data('maphilight') || {};
+					if(cData.selectedOn) {
+						cData.selectedOn = false;
+						colorData(cData);
+						jQuery(el).data('maphilight', cData).trigger('alwaysOn.maphilight');
+					}
+				});
+			}
+			
+			var numOfChoices = maxChoices;
+			if(numOfChoices > 0) {
+				var countChoices = 0;
+				jQuery("area", "map[name='" + containerId + "_map']").each(function(index, el) {
+					var cData = jQuery(el).data('maphilight') || {};
+					if(cData.selectedOn) {
+						countChoices++;
+					}
+				});
+				if(countChoices >= numOfChoices) {
+					return false;
+				}
+			}
+		}
+		
+		if(typeof data.selectedOn === "undefined") {
+			data.selectedOn = true;
+		} else {
+			data.selectedOn = !data.selectedOn;
+		}
+		colorData(data);
+		areaEl.data('maphilight', data).trigger('alwaysOn.maphilight');
 
-    	var divContainer = jQuery('#' + containerId);
-    	divContainer.find("input[type='hidden']").remove();
-    	jQuery("area", "map[name='" + containerId + "_map']").each(function(index, el) {
-    		var cAreaEl = jQuery(el);
-    		var cData = cAreaEl.data('maphilight') || {};
-    		if(cData.selectedOn) {
-    			var inputElement = jQuery('<input type="hidden"/>')
-    				.attr('name', 'qtiworks_response_' + responseIdentifier)
-    				.attr('value', cAreaEl.data('qti-id'));
-    			divContainer.append(inputElement);
-    		}
-    	});
-    };
-    
-    /*
-     * Color the data based on the selectedOn flag
-     */
-    function colorData(data) {
-    	if(data.selectedOn) {
-        	data.fillColor = '0000ff';
-        	data.fillOpacity = 0.5;
-    		data.strokeColor = '0000ff';
-    		data.strokeOpacity = 1;
-    		data.shadow = true;
-    		data.shadowX = 0;
-    		data.shadowY = 0;
-    		data.shadowRadius = 7;
-    		data.shadowColor = '000000';
-    		data.shadowOpacity = 0.8;
-    		data.shadowPosition = 'outside';
-    	} else {
+		var divContainer = jQuery('#' + containerId);
+		divContainer.find("input[type='hidden']").remove();
+		jQuery("area", "map[name='" + containerId + "_map']").each(function(index, el) {
+			var cAreaEl = jQuery(el);
+			var cData = cAreaEl.data('maphilight') || {};
+			if(cData.selectedOn) {
+				var inputElement = jQuery('<input type="hidden"/>')
+					.attr('name', 'qtiworks_response_' + responseIdentifier)
+					.attr('value', cAreaEl.data('qti-id'));
+				divContainer.append(inputElement);
+			}
+		});
+	};
+	
+	/*
+	 * Color the data based on the selectedOn flag
+	 */
+	function colorData(data) {
+		if(data.selectedOn) {
+			data.fillColor = '0000ff';
+			data.fillOpacity = 0.5;
+			data.strokeColor = '0000ff';
+			data.strokeOpacity = 1;
+			data.shadow = true;
+			data.shadowX = 0;
+			data.shadowY = 0;
+			data.shadowRadius = 7;
+			data.shadowColor = '000000';
+			data.shadowOpacity = 0.8;
+			data.shadowPosition = 'outside';
+		} else {
 			data.fillColor = 'bbbbbb';
-        	data.fillOpacity = 0.5;
-    		data.strokeColor = '666666';
-    		data.strokeOpacity = 0.8;
-    		data.shadow = false;
-    	}
-    }
+			data.fillOpacity = 0.5;
+			data.strokeColor = '666666';
+			data.strokeOpacity = 0.8;
+			data.shadow = false;
+		}
+	}
 }( jQuery ));
-- 
GitLab