Commit e8708605 by Braden MacDonald

Simplify mutation of state in JS code, make reset instant

parent 91335bc1
...@@ -155,6 +155,8 @@ class DragAndDropBlock(XBlock): ...@@ -155,6 +155,8 @@ class DragAndDropBlock(XBlock):
"targetImg": self.target_img_expanded_url, "targetImg": self.target_img_expanded_url,
"item_background_color": self.item_background_color or None, "item_background_color": self.item_background_color or None,
"item_text_color": self.item_text_color or None, "item_text_color": self.item_text_color or None,
"initial_feedback": self.data['feedback']['start'],
# final feedback (data.feedback.finish) is not included - it may give away answers.
} }
def studio_view(self, context): def studio_view(self, context):
......
...@@ -13,7 +13,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -13,7 +13,7 @@ function DragAndDropBlock(runtime, element, configuration) {
var root = $element.find('.xblock--drag-and-drop')[0]; var root = $element.find('.xblock--drag-and-drop')[0];
var $root = $(root); var $root = $(root);
var __state; var state = undefined;
var __vdom = virtualDom.h(); // blank virtual DOM var __vdom = virtualDom.h(); // blank virtual DOM
var init = function() { var init = function() {
...@@ -30,13 +30,15 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -30,13 +30,15 @@ function DragAndDropBlock(runtime, element, configuration) {
configuration.zones.forEach(function (zone) { configuration.zones.forEach(function (zone) {
computeZoneDimension(zone, bgImg.width, bgImg.height); computeZoneDimension(zone, bgImg.width, bgImg.height);
}); });
setState(stateResult[0]); // stateResult is an array of [data, statusText, jqXHR] state = stateResult[0]; // stateResult is an array of [data, statusText, jqXHR]
applyState();
initDroppable(); initDroppable();
publishEvent({event_type: 'xblock.drag-and-drop-v2.loaded'});
$(document).on('mousedown touchstart', closePopup); $(document).on('mousedown touchstart', closePopup);
$element.on('click', '.reset-button', resetExercise); $element.on('click', '.reset-button', resetExercise);
$element.on('click', '.submit-input', submitInput); $element.on('click', '.submit-input', submitInput);
publishEvent({event_type: 'xblock.drag-and-drop-v2.loaded'});
}).fail(function() { }).fail(function() {
$root.text(gettext("An error occurred. Unable to load drag and drop exercise.")); $root.text(gettext("An error occurred. Unable to load drag and drop exercise."));
}); });
...@@ -74,30 +76,39 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -74,30 +76,39 @@ function DragAndDropBlock(runtime, element, configuration) {
} }
}; };
var getState = function() {
return __state;
};
var setState = function(new_state) { var previousFeedback = undefined;
/**
* Update the DOM to reflect 'state'.
*/
var applyState = function() {
// Is there a change to the feedback popup? // Is there a change to the feedback popup?
if (new_state.feedback) { if (state.feedback !== previousFeedback) {
if (new_state.feedback !== __state.feedback) { if (state.feedback) {
if (previousFeedback) {
publishEvent({ publishEvent({
event_type: 'xblock.drag-and-drop-v2.feedback.closed', event_type: 'xblock.drag-and-drop-v2.feedback.closed',
content: __state.feedback, content: previousFeedback,
manually: false manually: false,
}); });
} }
publishEvent({ publishEvent({
event_type: 'xblock.drag-and-drop-v2.feedback.opened', event_type: 'xblock.drag-and-drop-v2.feedback.opened',
content: new_state.feedback content: state.feedback,
});
} else {
publishEvent({
event_type: 'xblock.drag-and-drop-v2.feedback.closed',
content: state.feedback,
manually: true,
}); });
} }
__state = new_state; previousFeedback = state.feedback;
}
updateDOM(new_state); updateDOM();
destroyDraggable(); destroyDraggable();
if (!new_state.finished) { if (!state.finished) {
initDraggable(); initDraggable();
} }
}; };
...@@ -134,7 +145,6 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -134,7 +145,6 @@ function DragAndDropBlock(runtime, element, configuration) {
var y_pos = (ui.helper.offset().top + (ui.helper.outerHeight()/2) - $target_img.offset().top); var y_pos = (ui.helper.offset().top + (ui.helper.outerHeight()/2) - $target_img.offset().top);
var y_pos_percent = y_pos / $target_img.height() * 100; var y_pos_percent = y_pos / $target_img.height() * 100;
var state = getState();
state.items[item_id] = { state.items[item_id] = {
x_percent: x_pos_percent, x_percent: x_pos_percent,
y_percent: y_pos_percent, y_percent: y_pos_percent,
...@@ -142,7 +152,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -142,7 +152,7 @@ function DragAndDropBlock(runtime, element, configuration) {
}; };
// Wrap in setTimeout to let the droppable event finish. // Wrap in setTimeout to let the droppable event finish.
setTimeout(function() { setTimeout(function() {
setState(state); applyState();
submitLocation(item_id, zone, x_pos_percent, y_pos_percent); submitLocation(item_id, zone, x_pos_percent, y_pos_percent);
}, 0); }, 0);
} }
...@@ -196,7 +206,6 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -196,7 +206,6 @@ function DragAndDropBlock(runtime, element, configuration) {
y_percent: y_percent, y_percent: y_percent,
}; };
$.post(url, JSON.stringify(data), 'json').done(function(data){ $.post(url, JSON.stringify(data), 'json').done(function(data){
var state = getState();
if (data.correct_location) { if (data.correct_location) {
state.items[item_id].correct_input = Boolean(data.correct); state.items[item_id].correct_input = Boolean(data.correct);
state.items[item_id].submitting_location = false; state.items[item_id].submitting_location = false;
...@@ -208,7 +217,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -208,7 +217,7 @@ function DragAndDropBlock(runtime, element, configuration) {
state.finished = true; state.finished = true;
state.overall_feedback = data.overall_feedback; state.overall_feedback = data.overall_feedback;
} }
setState(state); applyState();
}); });
}; };
...@@ -224,10 +233,9 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -224,10 +233,9 @@ function DragAndDropBlock(runtime, element, configuration) {
return; return;
} }
var state = getState();
state.items[item_id].input = input_value; state.items[item_id].input = input_value;
state.items[item_id].submitting_input = true; state.items[item_id].submitting_input = true;
setState(state); applyState();
var url = runtime.handlerUrl(element, 'do_attempt'); var url = runtime.handlerUrl(element, 'do_attempt');
var data = {val: item_id, input: input_value}; var data = {val: item_id, input: input_value};
...@@ -239,20 +247,20 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -239,20 +247,20 @@ function DragAndDropBlock(runtime, element, configuration) {
state.finished = true; state.finished = true;
state.overall_feedback = data.overall_feedback; state.overall_feedback = data.overall_feedback;
} }
setState(state); applyState();
}); });
}; };
var closePopup = function(evt) { var closePopup = function(evt) {
if (!state.feedback) {
return;
}
var target = $(evt.target); var target = $(evt.target);
var popup_box = '.xblock--drag-and-drop .popup'; var popup_box = '.xblock--drag-and-drop .popup';
var close_button = '.xblock--drag-and-drop .popup .close'; var close_button = '.xblock--drag-and-drop .popup .close';
var submit_input_button = '.xblock--drag-and-drop .submit-input'; var submit_input_button = '.xblock--drag-and-drop .submit-input';
var state = getState();
if (!state.feedback) {
return;
}
if (target.is(popup_box) || target.is(submit_input_button)) { if (target.is(popup_box) || target.is(submit_input_button)) {
return; return;
} }
...@@ -260,14 +268,8 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -260,14 +268,8 @@ function DragAndDropBlock(runtime, element, configuration) {
return; return;
} }
publishEvent({
event_type: 'xblock.drag-and-drop-v2.feedback.closed',
content: state.feedback,
manually: true
});
delete state.feedback; delete state.feedback;
setState(state); applyState();
}; };
var resetExercise = function() { var resetExercise = function() {
...@@ -275,13 +277,16 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -275,13 +277,16 @@ function DragAndDropBlock(runtime, element, configuration) {
type: 'POST', type: 'POST',
url: runtime.handlerUrl(element, 'reset'), url: runtime.handlerUrl(element, 'reset'),
data: '{}', data: '{}',
success: function(new_state) {
setState(new_state);
}
}); });
state = {
'items': [],
'finished': false,
'overall_feedback': configuration.initial_feedback,
};
applyState();
}; };
var render = function(state) { var render = function() {
var items = configuration.items.map(function(item) { var items = configuration.items.map(function(item) {
var input = null; var input = null;
var item_user_state = state.items[item.id]; var item_user_state = state.items[item.id];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment