From 37462c206fc59eb4d09863e86909befa7b62e30e Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Thu, 19 May 2016 16:39:08 +0200 Subject: [PATCH] OO-1593: add drag and drop to graphicGapMatchInteraction --- .../components/AssessmentObjectComponent.java | 1 - .../_content/graphicGapMatchInteraction.html | 7 + .../_content/hotspotInteraction.html | 4 +- .../static/js/jquery/qti/jquery.graphicGap.js | 153 +++++++++++++++++- 4 files changed, 157 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponent.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponent.java index 2159fd98d80..9239dfd92f9 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponent.java +++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponent.java @@ -169,7 +169,6 @@ public abstract class AssessmentObjectComponent extends AbstractComponent implem jsa.addRequiredStaticJsFile("js/jquery/maphilight/jquery.maphilight.js"); jsa.addRequiredStaticJsFile("js/jquery/ui/jquery-ui-1.11.4.custom.qti.min.js"); - //jsa.addRequiredStaticJsFile("js/openolat/qti21.js"); jsa.addRequiredStaticJsFile("js/jquery/qti/jquery.associate.js"); jsa.addRequiredStaticJsFile("js/jquery/qti/jquery.graphicAssociate.js"); diff --git a/src/main/java/org/olat/ims/qti21/ui/components/_content/graphicGapMatchInteraction.html b/src/main/java/org/olat/ims/qti21/ui/components/_content/graphicGapMatchInteraction.html index dbcd067c2e6..49e845ede84 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/_content/graphicGapMatchInteraction.html +++ b/src/main/java/org/olat/ims/qti21/ui/components/_content/graphicGapMatchInteraction.html @@ -31,7 +31,14 @@ </div> <script type="text/javascript"> jQuery(function() { + var map = jQuery('#${containerId}_img').maphilight({ + fillColor: '888888', + strokeColor: '0000ff', + strokeWidth: 3 + }); + jQuery('#${containerId}').graphicGapInteraction({ + maphilight: map, responseIdentifier: '$responseIdentifier', formDispatchFieldId: '$r.formDispatchFieldId', responseValue: '$r.toString($responseValue,","," ")', 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 891255777fc..589a58351b8 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 @@ -28,9 +28,7 @@ strokeColor: '0000ff', strokeWidth: 3 }); - }); - - jQuery(function() { + jQuery('#${qtiContainerId}').hotspotInteraction({ responseIdentifier: '$responseIdentifier', formDispatchFieldId: '$r.formDispatchFieldId', diff --git a/src/main/webapp/static/js/jquery/qti/jquery.graphicGap.js b/src/main/webapp/static/js/jquery/qti/jquery.graphicGap.js index 2f2bc9ab502..2b07b01a156 100644 --- a/src/main/webapp/static/js/jquery/qti/jquery.graphicGap.js +++ b/src/main/webapp/static/js/jquery/qti/jquery.graphicGap.js @@ -1,6 +1,7 @@ (function ($) { $.fn.graphicGapInteraction = function(options) { var settings = $.extend({ + maphilight: null, responseIdentifier: null, formDispatchFieldId: null, responseValue: null, @@ -59,11 +60,16 @@ var gapitem = jQuery(this); if(gapitem.hasClass('oo-choosed')) { + //timestamp + var dropTimestamp = gapitem.data('drop-timestamp'); + if(!(typeof dropTimestamp === "undefined") && dropTimestamp != null) { + if((Date.now() - dropTimestamp) < 1500) { + gapitem.data('drop-timestamp', null) + return; + } + } + gapitem.removeClass('oo-choosed'); - //gapitem.css('position','relative'); - //gapitem.css('left','auto'); - //gapitem.css('top','auto'); - var gapitemId = gapitem.attr('id'); //remove jQuery('#' + containerId).find("input[type='hidden']").each(function(index, el) { @@ -72,10 +78,84 @@ jQuery(el).remove(); } }); + gapitem.css({'position':'relative', 'left': '0px', 'top': '0px' }); } else { //gapitem.css('border','3px solid grey'); gapitem.addClass('oo-selected'); } + }).draggable({ + containment: "#" + containerId, + scroll: false, + revert: "invalid", + stop: function(event, ui) { + if(!jQuery(this).hasClass('oo-choosed')) { + console.log('stopped'); + jQuery(this).css({'position':'relative', 'left': '0px', 'top': '0px' }); + } + console.log('stopped'); + } + }).mousemove(function(event, ui) { + var itemEl = jQuery(this); + if(itemEl.hasClass("ui-draggable-dragging")) { + var containerEl = jQuery("#" + containerId + "_img"); + var containerOffset = containerEl.offset(); + var offset = itemEl.offset(); + var x1 = offset.left + (itemEl.width() / 2) - containerOffset.left; + var y1 = offset.top + (itemEl.height() / 2) - containerOffset.top; + var target = dropTarget(x1, y1, containerId); + + if("invalid" != target) { + jQuery("#" + containerId + " area").each(function(index, el) { + var areaEl = jQuery(el); + var areaId = areaEl.attr('id'); + if(target == areaId) { + areaEl.mouseover(); + } else { + areaEl.mouseout(); + } + }); + jQuery('#' + target).mouseover(); + } else { + jQuery("#" + containerId + " area").each(function(index, el) { + jQuery(el).mouseout(); + }); + } + } + }); + + jQuery("#" + containerId).droppable({ + drop: function(event, ui) { + var containerEl = jQuery("#" + containerId + "_img"); + var containerOffset = containerEl.offset(); + + var gapitem = jQuery(ui.draggable); + var offset = gapitem.offset(); + var x1 = offset.left + (gapitem.width() / 2) - containerOffset.left; + var y1 = offset.top + (gapitem.height() / 2) - containerOffset.top; + var target = dropTarget(x1, y1, containerId); + if("invalid" != target) { + var areaEl = jQuery('#' + target); + var coords = toCoords(areaEl); + var areaId = areaEl.data('qti-id'); + var gapitemId = gapitem.data('qti-id'); + + gapitem.css('position','absolute'); + gapitem.css('left', coords[0] + 'px'); + gapitem.css('top', coords[1] + 'px'); + + gapitem.css('border', 'none'); + gapitem.removeClass('oo-selected'); + gapitem.addClass('oo-choosed'); + + //add + var inputElement = jQuery('<input type="hidden"/>') + .attr('name', 'qtiworks_response_' + settings.responseIdentifier) + .attr('value', gapitemId + " " + areaId); + jQuery(this).prepend(inputElement); + jQuery(areaEl).mouseout(); + gapitem.data('drop-timestamp', Date.now()); + } + } }); jQuery("#" + containerId + " area").on('click', function(e, el) { @@ -104,6 +184,71 @@ }); }; + function dropTarget(dropX, dropY, containerId) { + var target = 'invalid'; + jQuery("#" + containerId + " area").each(function(index, el) { + var areaEl = jQuery(el); + var areaId = areaEl.attr("id"); + var coords = areaEl.attr('coords'); + var shape = areaEl.attr('shape'); + + var coordsArr = toCoords(areaEl); + if("circle" == shape) { + if(pncircle(dropX, dropY, coordsArr[0], coordsArr[1], coordsArr[2])) { + target = areaId; + } + } else if("rect" == shape) { + if(pnrect(dropX, dropY, coordsArr[0], coordsArr[1], coordsArr[2], coordsArr[3])) { + target = areaId; + } + } else if("poly" == shape) { + var area = {}; + area.x = []; + area.y = []; + var totalPairs = coordsArr.length / 2; + var coordCounter = 0; //variable to double iterate + for (ix = 0; ix < totalPairs; ix++) { //fill arrays of x/y coordinates for pnpoly + area.x[ix] = coordsArr[coordCounter]; + area.y[ix] = coordsArr[coordCounter + 1]; + coordCounter += 2; + } + + for (i = 0; i < area.length; i++) { //iterate through all of our area objects + if (pnpoly(area.x.length, area.x, area.y, dropX, dropY)) { + target = area.id; + break; + } + } + } + }); + return target; + } + + function pncircle(x, y, centerx, centery, radius) { + var c = Math.pow(x - centerx, 2) + Math.pow(y - centery, 2); + return Math.pow(radius, 2) >= c; + }; + + function pnrect(x, y, leftx, topy, rightx, bottomy) { + if ((leftx <= x ) && ( x <= rightx) && (topy <= y) && (y <= bottomy)) { + return true; + } else { + return false; + } + }; + + //Point in Poly Test http://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html + function pnpoly(nvert, vertx, verty, testx, testy) { + var i, j, c = false; + for (i = 0, j = nvert - 1; i < nvert; j = i++) { + if (((verty[i] > testy) != (verty[j] > testy)) && + (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) { + c = !c; + } + } + return c; + } + function toCoords(area) { var coords = area.attr('coords').split(','); for (i=coords.length; i-->0; ) { -- GitLab