diff --git a/common/static/js/capa/drag_and_drop/draggables.js b/common/static/js/capa/drag_and_drop/draggables.js index 9186c0d837..01fc612c5c 100644 --- a/common/static/js/capa/drag_and_drop/draggables.js +++ b/common/static/js/capa/drag_and_drop/draggables.js @@ -8,16 +8,21 @@ define(['logme', 'update_input'], function (logme, updateInput) { return Draggables; function Draggables(state) { - var _draggables; + var _draggables, numDraggables; + numDraggables = state.config.draggables.length; _draggables = []; state.draggables = []; (function (i) { - while (i < state.config.draggables.length) { + while (i < numDraggables) { processDraggable(state.config.draggables[i], i + 1); i += 1; } + + if (state.individualTargets === false) { + updateInput(state, true); + } }(0)); state.currentMovingDraggable = null; @@ -33,7 +38,7 @@ define(['logme', 'update_input'], function (logme, updateInput) { return; - function processDraggable(obj, index) { + function processDraggable(obj, objIndex) { var draggableContainerEl, imgEl, inContainer, ousePressed, onTarget, draggableObj, marginCss; @@ -45,10 +50,10 @@ define(['logme', 'update_input'], function (logme, updateInput) { 'display: inline; ' + 'float: left; ' + 'overflow: hidden; ' + - 'z-index: ' + index + '; ' + + 'z-index: ' + objIndex + '; ' + 'border: 1px solid gray; ' + '" ' + - 'data-draggable-position-index="' + index + '" ' + + 'data-draggable-position-index="' + objIndex + '" ' + '>' ); @@ -84,18 +89,21 @@ define(['logme', 'update_input'], function (logme, updateInput) { draggableObj = { 'id': obj.id, + 'el': draggableContainerEl, 'x': -1, - 'y': -1 + 'y': -1, + + 'setInContainer': function (val) { inContainer = val; }, + 'setOnTarget': function (val) { onTarget = val; }, }; state.draggables.push(draggableObj); draggableContainerEl.mousedown(mouseDown); draggableContainerEl.mouseup(mouseUp); draggableContainerEl.mousemove(mouseMove); - // draggableContainerEl.mouseleave(mouseLeave); - if (state.individualTargets === false) { - updateInput(state); + if (objIndex + 1 === numDraggables) { + state.draggablesLoaded = true; } return; @@ -140,14 +148,6 @@ define(['logme', 'update_input'], function (logme, updateInput) { } } - // function mouseLeave(event) { - // if (mousePressed === true) { - // normalizeEvent(event); - // - // checkLandingElement(event); - // } - // } - function checkLandingElement(event) { var offsetDE, indexes, DEindex, targetFound; diff --git a/common/static/js/capa/drag_and_drop/scroller.js b/common/static/js/capa/drag_and_drop/scroller.js index 6c2950e458..fcd68613cb 100644 --- a/common/static/js/capa/drag_and_drop/scroller.js +++ b/common/static/js/capa/drag_and_drop/scroller.js @@ -59,7 +59,16 @@ define(['logme'], function (logme) { ); moveLeftEl.appendTo(parentEl); - moveLeftEl.click(function () { + // The below is necessary to prevent the browser thinking that we want + // to perform a drag operation, or a highlight operation. If we don't + // do this, the browser will then highlight with a gray shade the + // element. + moveLeftEl.mousemove(function (event) { event.preventDefault(); }); + moveLeftEl.mousedown(function (event) { event.preventDefault(); }); + + moveLeftEl.mouseup(function (event) { + event.preventDefault(); + if (showElLeftMargin > -102) { return; } @@ -135,7 +144,16 @@ define(['logme'], function (logme) { ); moveRightEl.appendTo(parentEl); - moveRightEl.click(function () { + // The below is necessary to prevent the browser thinking that we want + // to perform a drag operation, or a highlight operation. If we don't + // do this, the browser will then highlight with a gray shade the + // element. + moveRightEl.mousemove(function (event) { event.preventDefault(); }); + moveRightEl.mousedown(function (event) { event.preventDefault(); }); + + moveRightEl.mouseup(function (event) { + event.preventDefault(); + if (showElLeftMargin < -102 * (state.sliderEl.children().length - 6)) { return; } diff --git a/common/static/js/capa/drag_and_drop/state.js b/common/static/js/capa/drag_and_drop/state.js index 7ebf89d023..eb693347d7 100644 --- a/common/static/js/capa/drag_and_drop/state.js +++ b/common/static/js/capa/drag_and_drop/state.js @@ -9,7 +9,10 @@ define([], function () { function State(problemId) { return { - 'problemId': problemId + 'problemId': problemId, + + 'targetsLoaded': false, + 'draggablesLoaded': false }; } }); diff --git a/common/static/js/capa/drag_and_drop/targets.js b/common/static/js/capa/drag_and_drop/targets.js index c1a5b5e265..8a98cee473 100644 --- a/common/static/js/capa/drag_and_drop/targets.js +++ b/common/static/js/capa/drag_and_drop/targets.js @@ -8,28 +8,37 @@ define(['logme', 'update_input'], function (logme, updateInput) { return Targets; function Targets(state) { + var numTargets; + + numTargets = state.config.targets.length; state.targets = []; (function (c1) { - while (c1 < state.config.targets.length) { - processTarget(state.config.targets[c1]); + while (c1 < numTargets) { + processTarget(state.config.targets[c1], c1); c1 += 1; } + + if (state.individualTargets === true) { + updateInput(state, true); + } }(0)); return; - function processTarget(obj) { + function processTarget(obj, objIndex) { var baseImageElOffset, tEl, left, borderCss; - if (state.baseImageElWidth === null) { - window.setTimeout(function () { - processTarget(obj); - }, 50); - return; - } + // if (state.baseImageElWidth === null) { + // window.setTimeout(function () { + // processTarget(obj); + // }, 50); + // + // return; + // } - left = obj.x + 0.5 * (state.baseImageEl.parent().width() - state.baseImageElWidth); + // left = obj.x + 0.5 * (state.baseImageEl.parent().width() - state.baseImageElWidth); + left = obj.x; borderCss = ''; if (state.config.target_outline === true) { @@ -62,8 +71,8 @@ define(['logme', 'update_input'], function (logme, updateInput) { 'draggable': [] }); - if (state.individualTargets === true) { - updateInput(state); + if (objIndex + 1 === numTargets) { + state.targetsLoaded = true; } } } diff --git a/common/static/js/capa/drag_and_drop/update_input.js b/common/static/js/capa/drag_and_drop/update_input.js index 60057e2674..ed49f3dd85 100644 --- a/common/static/js/capa/drag_and_drop/update_input.js +++ b/common/static/js/capa/drag_and_drop/update_input.js @@ -7,9 +7,15 @@ define(['logme'], function (logme) { return updateInput; - function updateInput(state) { + function updateInput(state, checkFirst) { var inputEl, stateStr, targets, draggables, c1, c2, tempObj; + if (checkFirst === true) { + if (checkIfHasAnswer() === true) { + return; + } + } + draggables = []; if (state.individualTargets === false) { @@ -47,8 +53,134 @@ define(['logme'], function (logme) { inputEl = $('#input_' + state.problemId); inputEl.val(stateStr); - } + return; + + // Check if input has an answer from server. If yes, then position + // all draggables according to answer. + function checkIfHasAnswer() { + var inputElVal; + + inputElVal = $('#input_' + state.problemId).val(); + if (inputElVal.length === 0) { + return false; + } + + repositionDraggables(JSON.parse(inputElVal)); + + return true; + } + + function repositionDraggables(answer) { + var draggableId, draggable, targetId, target, draggablePosition, + c1; + + if ( + ((state.individualTargets === true) && (state.targetsLoaded === false)) || + (state.draggablesLoaded === false) + ) { + window.setTimeout(function () { + repositionDraggables(answer); + }, 50); + + return; + } + + if ( + ((typeof answer.use_targets === 'boolean') && (answer.use_targets === true)) || + ((typeof answer.use_targets === 'string') && (answer.use_targets === 'true')) + ) { + for (c1 = 0; c1 < answer.draggables.length; c1++) { + for (draggableId in answer.draggables[c1]) { + if ((draggable = getDraggableById(draggableId)) === null) { + logme('ERROR: In answer there exists a draggable ID "' + draggableId + '". No draggable with this ID could be found.'); + + continue; + } + + targetId = answer.draggables[c1][draggableId]; + if ((target = getTargetById(targetId)) === null) { + logme('ERROR: In answer there exists a target ID "' + targetId + '". No target with this ID could be found.'); + + continue; + } + + + draggable.setInContainer(false); + + draggable.el.detach(); + draggable.el.css('border', 'none'); + draggable.el.css('position', 'absolute'); + draggable.el.css('left', answer.draggables[c1][draggableId][0] - 50); + draggable.el.css('top', answer.draggables[c1][draggableId][1] - 50); + + draggable.el.css('left', target.offset.left + 0.5 * target.w - 50); + draggable.el.css('top', target.offset.top + 0.5 * target.h - 50); + + draggable.el.appendTo(state.baseImageEl.parent()); + + draggable.setOnTarget(target); + target.draggable.push(draggableId); + } + } + } else if ( + ((typeof answer.use_targets === 'boolean') && (answer.use_targets === false)) || + ((typeof answer.use_targets === 'string') && (answer.use_targets === 'false')) + ) { + for (c1 = 0; c1 < answer.draggables.length; c1++) { + for (draggableId in answer.draggables[c1]) { + if ((draggable = getDraggableById(draggableId)) === null) { + logme('ERROR: In answer there exists a draggable ID "' + draggableId + '". No draggable with this ID could be found.'); + + continue; + } + + draggable.setInContainer(false); + + draggable.el.detach(); + draggable.el.css('border', 'none'); + draggable.el.css('position', 'absolute'); + draggable.el.css('left', answer.draggables[c1][draggableId][0] - 50); + draggable.el.css('top', answer.draggables[c1][draggableId][1] - 50); + draggable.el.appendTo(state.baseImageEl.parent()); + + draggable.x = answer.draggables[c1][draggableId][0]; + draggable.y = answer.draggables[c1][draggableId][1]; + } + } + } else { + logme('ERROR: The type of answer.targets is not supported. answer.targets = ', answer.targets); + + return; + } + } + + return; + + function getDraggableById(id) { + var c1; + + for (c1 = 0; c1 < state.draggables.length; c1 += 1) { + if (state.draggables[c1].id === id) { + return state.draggables[c1]; + } + } + + return null; + } + + function getTargetById(id) { + var c1; + + for (c1 = 0; c1 < state.targets.length; c1 += 1) { + if (state.targets[c1].id === id) { + return state.targets[c1]; + } + } + + return null; + } + } }); // End of wrapper for RequireJS. As you can see, we are passing