Commit 0a69b4c1 by Matjaz Gregoric

[TNL-6027] Fix bug where user could select multiple items.

parent 13ecee01
...@@ -1015,16 +1015,18 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -1015,16 +1015,18 @@ function DragAndDropBlock(runtime, element, configuration) {
return false; return false;
}; };
var placeItem = function($zone, $item) { var placeGrabbedItem = function($zone) {
var item_id;
if ($item !== undefined) {
item_id = $item.data('value');
} else {
item_id = $selectedItem.data('value');
}
var zone = String($zone.data('uid')); var zone = String($zone.data('uid'));
var zone_align = $zone.data('zone_align'); var zone_align = $zone.data('zone_align');
var items = configuration.items;
var item_id;
for (var i = 0; i < items.length; i++) {
if (items[i].grabbed) {
item_id = items[i].id;
break;
}
}
var items_in_zone_count = countItemsInZone(zone, [item_id.toString()]); var items_in_zone_count = countItemsInZone(zone, [item_id.toString()]);
if (configuration.max_items_per_zone && configuration.max_items_per_zone <= items_in_zone_count) { if (configuration.max_items_per_zone && configuration.max_items_per_zone <= items_in_zone_count) {
...@@ -1070,18 +1072,17 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -1070,18 +1072,17 @@ function DragAndDropBlock(runtime, element, configuration) {
} else if (isCancelKey(evt)) { } else if (isCancelKey(evt)) {
evt.preventDefault(); evt.preventDefault();
state.keyboard_placement_mode = false; state.keyboard_placement_mode = false;
releaseItem($selectedItem); releaseGrabbedItems();
} else if (isActionKey(evt)) { } else if (isActionKey(evt)) {
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
state.keyboard_placement_mode = false; state.keyboard_placement_mode = false;
releaseItem($selectedItem);
if ($zone.is('.item-bank')) { if ($zone.is('.item-bank')) {
delete state.items[$selectedItem.data('value')]; delete state.items[$selectedItem.data('value')];
applyState();
} else { } else {
placeItem($zone); placeGrabbedItem($zone);
} }
releaseGrabbedItems();
} }
} else if (isTabKey(evt) && !evt.shiftKey) { } else if (isTabKey(evt) && !evt.shiftKey) {
// If the user just dropped an item to this zone, next TAB keypress // If the user just dropped an item to this zone, next TAB keypress
...@@ -1108,8 +1109,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -1108,8 +1109,7 @@ function DragAndDropBlock(runtime, element, configuration) {
tolerance: 'pointer', tolerance: 'pointer',
drop: function(evt, ui) { drop: function(evt, ui) {
var $zone = $(this); var $zone = $(this);
var $item = ui.helper; placeGrabbedItem($zone);
placeItem($zone, $item);
} }
}); });
...@@ -1121,7 +1121,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -1121,7 +1121,7 @@ function DragAndDropBlock(runtime, element, configuration) {
drop: function(evt, ui) { drop: function(evt, ui) {
var $item = ui.helper; var $item = ui.helper;
var item_id = $item.data('value'); var item_id = $item.data('value');
releaseItem($item); releaseGrabbedItems();
delete state.items[item_id]; delete state.items[item_id];
applyState(); applyState();
} }
...@@ -1174,7 +1174,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -1174,7 +1174,7 @@ function DragAndDropBlock(runtime, element, configuration) {
stop: function(evt, ui) { stop: function(evt, ui) {
// Revert to original position. // Revert to original position.
$item.css($item.data('initial-position')); $item.css($item.data('initial-position'));
releaseItem($(this)); releaseGrabbedItems();
} }
}); });
} catch (e) { } catch (e) {
...@@ -1186,31 +1186,27 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -1186,31 +1186,27 @@ function DragAndDropBlock(runtime, element, configuration) {
var grabItem = function($item, interaction_type) { var grabItem = function($item, interaction_type) {
var item_id = $item.data('value'); var item_id = $item.data('value');
setGrabbedState(item_id, true, interaction_type); configuration.items.forEach(function(item) {
if (item.id === item_id) {
item.grabbed = true;
item.grabbed_with = interaction_type;
} else {
item.grabbed = false;
delete item.grabbed_with;
}
});
closePopup(false); closePopup(false);
// applyState(true) skips destroying and initializing draggable // applyState(true) skips destroying and initializing draggable
applyState(true); applyState(true);
}; };
var releaseItem = function($item) { var releaseGrabbedItems = function() {
var item_id = $item.data('value');
setGrabbedState(item_id, false);
// applyState(true) skips destroying and initializing draggable
applyState(true);
};
var setGrabbedState = function(item_id, grabbed, interaction_type) {
configuration.items.forEach(function(item) { configuration.items.forEach(function(item) {
if (item.id === item_id) { item.grabbed = false;
if (grabbed) { delete item.grabbed_with;
item.grabbed = true;
item.grabbed_with = interaction_type;
} else {
item.grabbed = false;
delete item.grabbed_with;
}
}
}); });
// applyState(true) skips destroying and initializing draggable
applyState(true);
}; };
var destroyDraggable = function() { var destroyDraggable = function() {
......
...@@ -403,7 +403,7 @@ class InteractionTestBase(object): ...@@ -403,7 +403,7 @@ class InteractionTestBase(object):
item.send_keys("") item.send_keys("")
item.send_keys(action_key) item.send_keys(action_key)
# Focus is on first *zone* now # Focus is on first *zone* now
self.assert_grabbed_item(item) self.assert_item_grabbed(item)
# Get desired zone and figure out how many times we have to press Tab to focus the zone. # Get desired zone and figure out how many times we have to press Tab to focus the zone.
if zone_id is None: # moving back to the bank if zone_id is None: # moving back to the bank
zone = self._get_item_bank() zone = self._get_item_bank()
...@@ -420,9 +420,12 @@ class InteractionTestBase(object): ...@@ -420,9 +420,12 @@ class InteractionTestBase(object):
ActionChains(self.browser).send_keys(Keys.TAB).perform() ActionChains(self.browser).send_keys(Keys.TAB).perform()
zone.send_keys(action_key) zone.send_keys(action_key)
def assert_grabbed_item(self, item): def assert_item_grabbed(self, item):
self.assertEqual(item.get_attribute('aria-grabbed'), 'true') self.assertEqual(item.get_attribute('aria-grabbed'), 'true')
def assert_item_not_grabbed(self, item):
self.assertEqual(item.get_attribute('aria-grabbed'), 'false')
def assert_placed_item(self, item_value, zone_title, assessment_mode=False): def assert_placed_item(self, item_value, zone_title, assessment_mode=False):
item = self._get_placed_item_by_value(item_value) item = self._get_placed_item_by_value(item_value)
self.wait_until_visible(item) self.wait_until_visible(item)
......
...@@ -382,6 +382,22 @@ class StandardInteractionTest(DefaultDataTestMixin, InteractionTestBase, Paramet ...@@ -382,6 +382,22 @@ class StandardInteractionTest(DefaultDataTestMixin, InteractionTestBase, Paramet
# After placing all items, we get the full score. # After placing all items, we get the full score.
self.assertEqual(progress.text, '1/1 point (ungraded)') self.assertEqual(progress.text, '1/1 point (ungraded)')
@data(*ITEM_DRAG_KEYBOARD_KEYS)
def test_cannot_select_multiple_items(self, action_key):
all_item_ids = self.items_map.keys()
# Go through all items and select them all using the keyboard action key.
for item_id in all_item_ids:
item = self._get_item_by_value(item_id)
item.send_keys('')
item.send_keys(action_key)
# Item should be grabbed.
self.assert_item_grabbed(item)
# Other items should NOT be grabbed.
for other_item_id in all_item_ids:
if other_item_id != item_id:
other_item = self._get_item_by_value(other_item_id)
self.assert_item_not_grabbed(other_item)
class MultipleValidOptionsInteractionTest(DefaultDataTestMixin, InteractionTestBase, BaseIntegrationTest): class MultipleValidOptionsInteractionTest(DefaultDataTestMixin, InteractionTestBase, BaseIntegrationTest):
......
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