Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xblock-drag-and-drop-v2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
xblock-drag-and-drop-v2
Commits
0a69b4c1
Commit
0a69b4c1
authored
Dec 15, 2016
by
Matjaz Gregoric
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[TNL-6027] Fix bug where user could select multiple items.
parent
13ecee01
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
49 additions
and
34 deletions
+49
-34
drag_and_drop_v2/public/js/drag_and_drop.js
+28
-32
tests/integration/test_base.py
+5
-2
tests/integration/test_interaction.py
+16
-0
No files found.
drag_and_drop_v2/public/js/drag_and_drop.js
View file @
0a69b4c1
...
@@ -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
;
release
Item
(
$selectedItem
);
release
GrabbedItems
(
);
}
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
);
place
Grabbed
Item
(
$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'
);
release
Item
(
$item
);
release
GrabbedItems
(
);
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'
));
release
Item
(
$
(
this
)
);
release
GrabbedItems
(
);
}
}
});
});
}
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
);
closePopup
(
false
);
// applyState(true) skips destroying and initializing draggable
applyState
(
true
);
};
var
releaseItem
=
function
(
$item
)
{
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
)
{
if
(
item
.
id
===
item_id
)
{
if
(
grabbed
)
{
item
.
grabbed
=
true
;
item
.
grabbed
=
true
;
item
.
grabbed_with
=
interaction_type
;
item
.
grabbed_with
=
interaction_type
;
}
else
{
}
else
{
item
.
grabbed
=
false
;
item
.
grabbed
=
false
;
delete
item
.
grabbed_with
;
delete
item
.
grabbed_with
;
}
}
}
});
});
closePopup
(
false
);
// applyState(true) skips destroying and initializing draggable
applyState
(
true
);
};
var
releaseGrabbedItems
=
function
()
{
configuration
.
items
.
forEach
(
function
(
item
)
{
item
.
grabbed
=
false
;
delete
item
.
grabbed_with
;
});
// applyState(true) skips destroying and initializing draggable
applyState
(
true
);
};
};
var
destroyDraggable
=
function
()
{
var
destroyDraggable
=
function
()
{
...
...
tests/integration/test_base.py
View file @
0a69b4c1
...
@@ -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
)
...
...
tests/integration/test_interaction.py
View file @
0a69b4c1
...
@@ -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
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment