Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx
edx-platform
Commits
7af36eb6
Commit
7af36eb6
authored
Mar 06, 2013
by
Victor Shnayder
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1598 from MITx/diana/capa-input-ajax
Give InputTypes the ability to handle their own AJAX
parents
69601047
4b7d1deb
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
75 additions
and
7 deletions
+75
-7
common/lib/capa/capa/capa_problem.py
+37
-6
common/lib/capa/capa/inputtypes.py
+12
-0
common/lib/capa/capa/tests/test_html_render.py
+2
-0
common/lib/xmodule/xmodule/capa_module.py
+2
-0
common/lib/xmodule/xmodule/js/src/capa/display.coffee
+18
-0
common/lib/xmodule/xmodule/tests/test_capa_module.py
+4
-1
No files found.
common/lib/capa/capa/capa_problem.py
View file @
7af36eb6
...
...
@@ -146,6 +146,13 @@ class LoncapaProblem(object):
if
not
self
.
student_answers
:
# True when student_answers is an empty dict
self
.
set_initial_display
()
# dictionary of InputType objects associated with this problem
# input_id string -> InputType object
self
.
inputs
=
{}
self
.
extracted_tree
=
self
.
_extract_html
(
self
.
tree
)
def
do_reset
(
self
):
'''
Reset internal state to unfinished, with no answers
...
...
@@ -324,7 +331,27 @@ class LoncapaProblem(object):
'''
Main method called externally to get the HTML to be rendered for this capa Problem.
'''
return
contextualize_text
(
etree
.
tostring
(
self
.
_extract_html
(
self
.
tree
)),
self
.
context
)
html
=
contextualize_text
(
etree
.
tostring
(
self
.
_extract_html
(
self
.
tree
)),
self
.
context
)
return
html
def
handle_input_ajax
(
self
,
get
):
'''
InputTypes can support specialized AJAX calls. Find the correct input and pass along the correct data
Also, parse out the dispatch from the get so that it can be passed onto the input type nicely
'''
# pull out the id
input_id
=
get
[
'input_id'
]
if
self
.
inputs
[
input_id
]:
dispatch
=
get
[
'dispatch'
]
return
self
.
inputs
[
input_id
]
.
handle_ajax
(
dispatch
,
get
)
else
:
log
.
warning
(
"Could not find matching input for id:
%
s"
%
problem_id
)
return
{}
# ======= Private Methods Below ========
...
...
@@ -458,6 +485,8 @@ class LoncapaProblem(object):
finally
:
sys
.
path
=
original_path
def
_extract_html
(
self
,
problemtree
):
# private
'''
Main (private) function which converts Problem XML tree to HTML.
...
...
@@ -468,6 +497,7 @@ class LoncapaProblem(object):
Used by get_html.
'''
if
(
problemtree
.
tag
==
'script'
and
problemtree
.
get
(
'type'
)
and
'javascript'
in
problemtree
.
get
(
'type'
)):
# leave javascript intact.
...
...
@@ -484,8 +514,9 @@ class LoncapaProblem(object):
msg
=
''
hint
=
''
hintmode
=
None
input_id
=
problemtree
.
get
(
'id'
)
if
problemid
in
self
.
correct_map
:
pid
=
problemtree
.
get
(
'id'
)
pid
=
input_id
status
=
self
.
correct_map
.
get_correctness
(
pid
)
msg
=
self
.
correct_map
.
get_msg
(
pid
)
hint
=
self
.
correct_map
.
get_hint
(
pid
)
...
...
@@ -496,17 +527,17 @@ class LoncapaProblem(object):
value
=
self
.
student_answers
[
problemid
]
# do the rendering
state
=
{
'value'
:
value
,
'status'
:
status
,
'id'
:
problemtree
.
get
(
'id'
)
,
'id'
:
input_id
,
'feedback'
:
{
'message'
:
msg
,
'hint'
:
hint
,
'hintmode'
:
hintmode
,
}}
input_type_cls
=
inputtypes
.
registry
.
get_class_for_tag
(
problemtree
.
tag
)
the_input
=
input_type_cls
(
self
.
system
,
problemtree
,
state
)
return
the_input
.
get_html
()
# save the input type so that we can make ajax calls on it if we need to
self
.
inputs
[
input_id
]
=
input_type_cls
(
self
.
system
,
problemtree
,
state
)
return
self
.
inputs
[
input_id
]
.
get_html
()
# let each Response render itself
if
problemtree
in
self
.
responders
:
...
...
common/lib/capa/capa/inputtypes.py
View file @
7af36eb6
...
...
@@ -215,6 +215,18 @@ class InputTypeBase(object):
"""
pass
def
handle_ajax
(
self
,
dispatch
,
get
):
"""
InputTypes that need to handle specialized AJAX should override this.
Input:
dispatch: a string that can be used to determine how to handle the data passed in
get: a dictionary containing the data that was sent with the ajax call
Output:
a dictionary object that can be serialized into JSON. This will be sent back to the Javascript.
"""
pass
def
_get_render_context
(
self
):
"""
...
...
common/lib/capa/capa/tests/test_html_render.py
View file @
7af36eb6
...
...
@@ -125,6 +125,8 @@ class CapaHtmlRenderTest(unittest.TestCase):
expected_solution_context
=
{
'id'
:
'1_solution_1'
}
expected_calls
=
[
mock
.
call
(
'textline.html'
,
expected_textline_context
),
mock
.
call
(
'solutionspan.html'
,
expected_solution_context
),
mock
.
call
(
'textline.html'
,
expected_textline_context
),
mock
.
call
(
'solutionspan.html'
,
expected_solution_context
)]
self
.
assertEqual
(
test_system
.
render_template
.
call_args_list
,
...
...
common/lib/xmodule/xmodule/capa_module.py
View file @
7af36eb6
...
...
@@ -412,6 +412,7 @@ class CapaModule(XModule):
'weight'
:
self
.
descriptor
.
weight
,
}
context
=
{
'problem'
:
content
,
'id'
:
self
.
id
,
'check_button'
:
check_button
,
...
...
@@ -449,6 +450,7 @@ class CapaModule(XModule):
'problem_save'
:
self
.
save_problem
,
'problem_show'
:
self
.
get_answer
,
'score_update'
:
self
.
update_score
,
'input_ajax'
:
self
.
lcp
.
handle_input_ajax
}
if
dispatch
not
in
handlers
:
...
...
common/lib/xmodule/xmodule/js/src/capa/display.coffee
View file @
7af36eb6
...
...
@@ -76,6 +76,24 @@ class @Problem
# TODO: Some logic to dynamically adjust polling rate based on queuelen
window
.
queuePollerID
=
window
.
setTimeout
(
@
poll
,
1000
)
# Use this if you want to make an ajax call on the input type object
# static method so you don't have to instantiate a Problem in order to use it
# Input:
# url: the AJAX url of the problem
# input_id: the input_id of the input you would like to make the call on
# NOTE: the id is the ${id} part of "input_${id}" during rendering
# If this function is passed the entire prefixed id, the backend may have trouble
# finding the correct input
# dispatch: string that indicates how this data should be handled by the inputtype
# callback: the function that will be called once the AJAX call has been completed.
# It will be passed a response object
@
inputAjax
:
(
url
,
input_id
,
dispatch
,
data
,
callback
)
->
data
[
'dispatch'
]
=
dispatch
data
[
'input_id'
]
=
input_id
$
.
postWithPrefix
"
#{
url
}
/input_ajax"
,
data
,
callback
render
:
(
content
)
->
if
content
@
el
.
html
(
content
)
...
...
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
7af36eb6
...
...
@@ -108,7 +108,9 @@ class CapaFactory(object):
else
:
instance_state
=
None
module
=
CapaModule
(
test_system
(),
location
,
system
=
test_system
()
system
.
render_template
=
Mock
(
return_value
=
"<div>Test Template HTML</div>"
)
module
=
CapaModule
(
system
,
location
,
definition
,
descriptor
,
instance_state
,
None
,
metadata
=
metadata
)
...
...
@@ -185,6 +187,7 @@ class CapaModuleTest(unittest.TestCase):
max_attempts
=
"1"
,
attempts
=
"0"
,
due
=
self
.
yesterday_str
)
self
.
assertTrue
(
after_due_date
.
answer_available
())
...
...
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