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
1fe66eff
Commit
1fe66eff
authored
Jul 04, 2014
by
Filippo Valsorda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add server-side checking, feedback and saved state
parent
b42f4f5e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
105 additions
and
59 deletions
+105
-59
drag_and_drop_v2/drag_and_drop_v2.py
+51
-3
drag_and_drop_v2/public/css/drag_and_drop.css
+2
-1
drag_and_drop_v2/public/js/drag_and_drop.js
+52
-55
No files found.
drag_and_drop_v2/drag_and_drop_v2.py
View file @
1fe66eff
...
...
@@ -6,12 +6,13 @@
import
logging
import
json
import
webob
import
copy
from
xblock.core
import
XBlock
from
xblock.fields
import
Scope
,
String
,
Dict
from
xblock.fragment
import
Fragment
from
.utils
import
render_template
,
load_resource
from
.utils
import
render_template
# Globals ###########################################################
...
...
@@ -44,13 +45,22 @@ class DragAndDropBlock(XBlock):
help
=
"JSON spec as generated by the builder"
,
scope
=
Scope
.
content
,
default
=
{
'feedback'
:
{},
'feedback'
:
{
'start'
:
''
,
'finish'
:
''
},
'items'
:
[],
'zones'
:
[],
'targetImg'
:
None
}
)
item_state
=
Dict
(
help
=
"How the student has interacted with the problem"
,
scope
=
Scope
.
user_state
,
default
=
{}
)
def
student_view
(
self
,
context
):
"""
Player view, displayed to the student
...
...
@@ -121,4 +131,42 @@ class DragAndDropBlock(XBlock):
@XBlock.handler
def
get_data
(
self
,
request
,
suffix
=
''
):
return
webob
.
response
.
Response
(
body
=
json
.
dumps
(
self
.
data
))
data
=
copy
.
deepcopy
(
self
.
data
)
for
item
in
data
[
'items'
]:
# Strip answers
del
item
[
'feedback'
]
del
item
[
'zone'
]
tot_items
=
sum
(
1
for
i
in
self
.
data
[
'items'
]
if
i
[
'zone'
]
!=
'none'
)
if
len
(
self
.
item_state
)
!=
tot_items
:
del
data
[
'feedback'
][
'finish'
]
data
[
'state'
]
=
self
.
item_state
return
webob
.
response
.
Response
(
body
=
json
.
dumps
(
data
))
@XBlock.json_handler
def
do_attempt
(
self
,
attempt
,
suffix
=
''
):
item
=
next
(
i
for
i
in
self
.
data
[
'items'
]
if
i
[
'id'
]
==
attempt
[
'val'
])
tot_items
=
sum
(
1
for
i
in
self
.
data
[
'items'
]
if
i
[
'zone'
]
!=
'none'
)
if
item
[
'zone'
]
==
attempt
[
'zone'
]:
self
.
item_state
[
item
[
'id'
]]
=
(
attempt
[
'top'
],
attempt
[
'left'
])
if
len
(
self
.
item_state
)
==
tot_items
:
final_feedback
=
self
.
data
[
'feedback'
][
'finish'
]
else
:
final_feedback
=
None
return
{
'correct'
:
True
,
'final_feedback'
:
final_feedback
,
'feedback'
:
item
[
'feedback'
][
'correct'
]
}
else
:
return
{
'correct'
:
False
,
'final_feedback'
:
None
,
'feedback'
:
item
[
'feedback'
][
'incorrect'
]
}
drag_and_drop_v2/public/css/drag_and_drop.css
View file @
1fe66eff
...
...
@@ -52,7 +52,8 @@
position
:
relative
;
float
:
left
;
display
:
inline
;
z-index
:
100
;
/* Some versions of the drag and drop library try to fiddle with this */
z-index
:
10
!important
;
margin-bottom
:
5px
;
padding
:
10px
;
}
...
...
drag_and_drop_v2/public/js/drag_and_drop.js
View file @
1fe66eff
...
...
@@ -64,9 +64,6 @@ function DragAndDropBlock(runtime, element) {
_fn
.
items
.
draw
();
_fn
.
zones
.
draw
();
// Load welcome feedback
_fn
.
feedback
.
set
(
_fn
.
data
.
feedback
.
start
);
// Init drag and drop plugin
_fn
.
$items
.
draggable
(
_fn
.
options
.
drag
);
_fn
.
$zones
.
droppable
(
_fn
.
options
.
drop
);
...
...
@@ -74,20 +71,26 @@ function DragAndDropBlock(runtime, element) {
// Init click handlers
_fn
.
clickHandlers
.
init
(
_fn
.
$items
,
_fn
.
$zones
);
//
Get count of all active
items
//
Position the already correct
items
_fn
.
items
.
init
();
// Load welcome or final feedback
if
(
_fn
.
data
.
feedback
.
finish
)
_fn
.
finish
(
_fn
.
data
.
feedback
.
finish
);
else
_fn
.
feedback
.
set
(
_fn
.
data
.
feedback
.
start
);
// Set the target image
if
(
_fn
.
data
.
targetImg
)
_fn
.
$target
.
css
(
'background'
,
'url('
+
_fn
.
data
.
targetImg
+
') no-repeat'
);
},
finish
:
function
()
{
finish
:
function
(
final_feedback
)
{
// Disable any decoy items
_fn
.
$items
.
draggable
(
'disable'
);
// Show final feedback
_fn
.
feedback
.
set
(
_fn
.
data
.
feedback
.
finish
);
_fn
.
feedback
.
set
(
final_feedback
);
},
clickHandlers
:
{
...
...
@@ -111,21 +114,44 @@ function DragAndDropBlock(runtime, element) {
val
=
$el
.
data
(
'value'
),
zone
=
$el
.
data
(
'zone'
)
||
null
;
if
(
$el
.
hasClass
(
'within-dropzone'
)
&&
_fn
.
test
.
match
(
val
,
zone
))
{
$el
.
removeClass
(
'hover'
)
.
draggable
(
'disable'
);
_fn
.
test
.
completed
++
;
_fn
.
feedback
.
popup
(
_fn
.
feedback
.
get
(
val
,
true
),
true
);
if
(
_fn
.
items
.
allSubmitted
())
{
_fn
.
finish
();
}
}
else
{
if
(
!
$el
.
hasClass
(
'within-dropzone'
))
{
// Return to original position
_fn
.
clickHandlers
.
drag
.
reset
(
$el
);
_fn
.
feedback
.
popup
(
_fn
.
feedback
.
get
(
val
,
false
),
false
)
;
return
;
}
$
.
post
(
runtime
.
handlerUrl
(
element
,
'do_attempt'
),
JSON
.
stringify
({
val
:
val
,
zone
:
zone
,
top
:
$el
.
css
(
'top'
),
left
:
$el
.
css
(
'left'
)
})).
done
(
function
(
data
){
if
(
data
.
correct
)
{
$el
.
removeClass
(
'hover'
)
.
draggable
(
'disable'
);
if
(
data
.
final_feedback
)
{
_fn
.
finish
(
data
.
final_feedback
);
}
}
else
{
// Return to original position
_fn
.
clickHandlers
.
drag
.
reset
(
$el
);
}
if
(
data
.
feedback
)
{
_fn
.
feedback
.
popup
(
data
.
feedback
,
data
.
correct
);
}
});
},
set
:
function
(
$el
,
top
,
left
)
{
$el
.
addClass
(
'within-dropzone fade'
)
.
css
({
top
:
top
,
left
:
left
})
.
draggable
(
'disable'
);
},
reset
:
function
(
$el
)
{
...
...
@@ -154,23 +180,15 @@ function DragAndDropBlock(runtime, element) {
},
items
:
{
count
:
0
,
init
:
function
()
{
var
items
=
_fn
.
data
.
items
,
i
,
len
=
items
.
length
,
total
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
items
[
i
].
zone
!==
'none'
)
{
total
++
;
_fn
.
$items
.
each
(
function
(){
var
$el
=
$
(
this
),
saved_entry
=
_fn
.
data
.
state
[
$el
.
data
(
'value'
)];
if
(
saved_entry
)
{
_fn
.
clickHandlers
.
drag
.
set
(
$el
,
saved_entry
[
0
],
saved_entry
[
1
]);
}
}
_fn
.
items
.
count
=
total
;
},
allSubmitted
:
function
()
{
return
_fn
.
test
.
completed
===
_fn
.
items
.
count
;
});
},
draw
:
function
()
{
var
list
=
[],
...
...
@@ -215,31 +233,10 @@ function DragAndDropBlock(runtime, element) {
},
test
:
{
completed
:
0
,
match
:
function
(
id
,
zone
)
{
var
item
=
_
.
findWhere
(
_fn
.
data
.
items
,
{
id
:
id
});
return
item
.
zone
===
zone
;
}
completed
:
0
},
feedback
:
{
// Returns string based on user's answer
get
:
function
(
id
,
boo
)
{
var
item
,
type
=
boo
?
'correct'
:
'incorrect'
;
// Null loses its string-ness
if
(
id
===
null
)
{
id
=
'null'
;
}
// Get object from data.items that matches val
item
=
_
.
findWhere
(
_fn
.
data
.
items
,
{
id
:
id
});
return
item
.
feedback
[
type
];
},
// Update DOM with feedback
set
:
function
(
str
)
{
return
_fn
.
$feedback
.
html
(
str
);
...
...
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