JSinput input type
This commit is contained in:
@@ -451,6 +451,68 @@ class JavascriptInput(InputTypeBase):
|
||||
registry.register(JavascriptInput)
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class JSInput(InputTypeBase):
|
||||
"""
|
||||
DO NOT USE! HAS NOT BEEN TESTED BEYOND 700X PROBLEMS, AND MAY CHANGE IN
|
||||
BACKWARDS-INCOMPATIBLE WAYS.
|
||||
Inputtype for general javascript inputs. Intended to be used with
|
||||
customresponse.
|
||||
Loads in a sandboxed iframe to help prevent css and js conflicts between
|
||||
frame and top-level window.
|
||||
|
||||
iframe sandbox whitelist:
|
||||
- allow-scripts
|
||||
- allow-popups
|
||||
- allow-forms
|
||||
- allow-pointer-lock
|
||||
|
||||
This in turn means that the iframe cannot directly access the top-level
|
||||
window elements.
|
||||
Example:
|
||||
|
||||
<jsinput html_file="/static/test.html"
|
||||
gradefn="grade"
|
||||
height="500"
|
||||
width="400"/>
|
||||
|
||||
See the documentation in the /doc/public folder for more information.
|
||||
"""
|
||||
|
||||
template = "jsinput.html"
|
||||
tags = ['jsinput']
|
||||
|
||||
@classmethod
|
||||
def get_attributes(cls):
|
||||
"""
|
||||
Register the attributes.
|
||||
"""
|
||||
return [Attribute('params', None), # extra iframe params
|
||||
Attribute('html_file', None),
|
||||
Attribute('gradefn', "gradefn"),
|
||||
Attribute('get_statefn', None), # Function to call in iframe
|
||||
# to get current state.
|
||||
Attribute('set_statefn', None), # Function to call iframe to
|
||||
# set state
|
||||
Attribute('width', "400"), # iframe width
|
||||
Attribute('height', "300")] # iframe height
|
||||
|
||||
|
||||
|
||||
def _extra_context(self):
|
||||
context = {
|
||||
'applet_loader': '/static/js/capa/jsinput.js',
|
||||
'saved_state': self.value
|
||||
}
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
registry.register(JSInput)
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class TextLine(InputTypeBase):
|
||||
|
||||
@@ -929,7 +929,7 @@ class CustomResponse(LoncapaResponse):
|
||||
'chemicalequationinput', 'vsepr_input',
|
||||
'drag_and_drop_input', 'editamoleculeinput',
|
||||
'designprotein2dinput', 'editageneinput',
|
||||
'annotationinput']
|
||||
'annotationinput', 'jsinput']
|
||||
|
||||
def setup_response(self):
|
||||
xml = self.xml
|
||||
|
||||
64
common/lib/capa/capa/templates/jsinput.html
Normal file
64
common/lib/capa/capa/templates/jsinput.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<section id="inputtype_${id}" class="jsinput"
|
||||
data="${gradefn}"
|
||||
% if saved_state:
|
||||
data-stored="${saved_state|x}"
|
||||
% endif
|
||||
% if get_statefn:
|
||||
data-getstate="${get_statefn}"
|
||||
% endif
|
||||
% if set_statefn:
|
||||
data-setstate="${set_statefn}"
|
||||
% endif
|
||||
>
|
||||
|
||||
|
||||
<div class="script_placeholder" data-src="${applet_loader}"/>
|
||||
% if status == 'unsubmitted':
|
||||
<div class="unanswered" id="status_${id}">
|
||||
% elif status == 'correct':
|
||||
<div class="correct" id="status_${id}">
|
||||
% elif status == 'incorrect':
|
||||
<div class="incorrect" id="status_${id}">
|
||||
% elif status == 'incomplete':
|
||||
<div class="incorrect" id="status_${id}">
|
||||
% endif
|
||||
|
||||
<iframe name="iframe_${id}"
|
||||
id="iframe_${id}"
|
||||
sandbox="allow-scripts allow-popups allow-same-origin allow-forms allow-pointer-lock"
|
||||
seamless="seamless"
|
||||
frameborder="0"
|
||||
src="${html_file}"
|
||||
height="${height}"
|
||||
width="${width}"
|
||||
/>
|
||||
<input type="hidden" name="input_${id}" id="input_${id}"
|
||||
waitfor=""
|
||||
value="${value|h}"/>
|
||||
|
||||
<br/>
|
||||
<p id="answer_${id}" class="answer"></p>
|
||||
|
||||
<p class="status">
|
||||
% if status == 'unsubmitted':
|
||||
unanswered
|
||||
% elif status == 'correct':
|
||||
correct
|
||||
% elif status == 'incorrect':
|
||||
incorrect
|
||||
% elif status == 'incomplete':
|
||||
incomplete
|
||||
% endif
|
||||
</p>
|
||||
<br/> <br/>
|
||||
|
||||
<div class="error_message" style="padding: 5px 5px 5px 5px; background-color:#FA6666; height:60px;width:400px; display: none"></div>
|
||||
|
||||
% if status in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
|
||||
</div>
|
||||
% endif
|
||||
|
||||
% if msg:
|
||||
<span class="message">${msg|n}</span>
|
||||
% endif
|
||||
</section>
|
||||
@@ -140,6 +140,11 @@ class @Problem
|
||||
check_fd: =>
|
||||
Logger.log 'problem_check', @answers
|
||||
|
||||
# If some function wants to be called before sending the answer to the
|
||||
# server, give it a chance to do so.
|
||||
if $('input[waitfor]').length != 0
|
||||
($(lcall).data("waitfor").call() for lcall in $('input[waitfor]'))
|
||||
@refreshAnswers()
|
||||
# If there are no file inputs in the problem, we can fall back on @check
|
||||
if $('input:file').length == 0
|
||||
@check()
|
||||
|
||||
Reference in New Issue
Block a user