Commit 8554c3f0 by Anton Stupak

Merge pull request #1914 from edx/anton/show-answer-imageresponse

Show answer for imageresponse
parents 9c8e90a6 335a36f1
...@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes, ...@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected. the top. Include a label indicating the component affected.
Blades: Show answer for imageresponse. BLD-21.
Blades: LTI additional Python tests. LTI must use HTTPS for Blades: LTI additional Python tests. LTI must use HTTPS for
lis_outcome_service_url. BLD-564. lis_outcome_service_url. BLD-564.
......
...@@ -34,6 +34,7 @@ requirejs.config({ ...@@ -34,6 +34,7 @@ requirejs.config({
"sinon": "xmodule_js/common_static/js/vendor/sinon-1.7.1", "sinon": "xmodule_js/common_static/js/vendor/sinon-1.7.1",
"squire": "xmodule_js/common_static/js/vendor/Squire", "squire": "xmodule_js/common_static/js/vendor/Squire",
"jasmine-jquery": "xmodule_js/common_static/js/vendor/jasmine-jquery", "jasmine-jquery": "xmodule_js/common_static/js/vendor/jasmine-jquery",
"jasmine-imagediff": "xmodule_js/common_static/js/vendor/jasmine-imagediff",
"jasmine-stealth": "xmodule_js/common_static/js/vendor/jasmine-stealth", "jasmine-stealth": "xmodule_js/common_static/js/vendor/jasmine-stealth",
"jasmine.async": "xmodule_js/common_static/js/vendor/jasmine.async", "jasmine.async": "xmodule_js/common_static/js/vendor/jasmine.async",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly.pkgd", "draggabilly": "xmodule_js/common_static/js/vendor/draggabilly.pkgd",
...@@ -151,6 +152,9 @@ requirejs.config({ ...@@ -151,6 +152,9 @@ requirejs.config({
"jasmine-jquery": { "jasmine-jquery": {
deps: ["jasmine"] deps: ["jasmine"]
}, },
"jasmine-imagediff": {
deps: ["jasmine"]
},
"jasmine-stealth": { "jasmine-stealth": {
deps: ["jasmine"] deps: ["jasmine"]
}, },
......
...@@ -47,6 +47,7 @@ lib_paths: ...@@ -47,6 +47,7 @@ lib_paths:
- xmodule_js/common_static/js/vendor/Squire.js - xmodule_js/common_static/js/vendor/Squire.js
- xmodule_js/common_static/js/vendor/jasmine-jquery.js - xmodule_js/common_static/js/vendor/jasmine-jquery.js
- xmodule_js/common_static/js/vendor/jasmine-stealth.js - xmodule_js/common_static/js/vendor/jasmine-stealth.js
- xmodule_js/common_static/js/vendor/jasmine-imagediff.js
- xmodule_js/common_static/js/vendor/jasmine.async.js - xmodule_js/common_static/js/vendor/jasmine.async.js
- xmodule_js/common_static/js/vendor/jquery.maskedinput.min.js - xmodule_js/common_static/js/vendor/jquery.maskedinput.min.js
- xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js - xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js
......
...@@ -46,6 +46,7 @@ lib_paths: ...@@ -46,6 +46,7 @@ lib_paths:
- xmodule_js/common_static/js/vendor/Squire.js - xmodule_js/common_static/js/vendor/Squire.js
- xmodule_js/common_static/js/vendor/jasmine-jquery.js - xmodule_js/common_static/js/vendor/jasmine-jquery.js
- xmodule_js/common_static/js/vendor/jasmine-stealth.js - xmodule_js/common_static/js/vendor/jasmine-stealth.js
- xmodule_js/common_static/js/vendor/jasmine-imagediff.js
- xmodule_js/common_static/js/vendor/jasmine.async.js - xmodule_js/common_static/js/vendor/jasmine.async.js
- xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js - xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js
- xmodule_js/src/xmodule.js - xmodule_js/src/xmodule.js
......
...@@ -2167,7 +2167,7 @@ class ImageResponse(LoncapaResponse): ...@@ -2167,7 +2167,7 @@ class ImageResponse(LoncapaResponse):
answers = {} answers = {}
for ielt in self.ielements: for ielt in self.ielements:
ie_id = ielt.get('id') ie_id = ielt.get('id')
answers[ie_id] = (ielt.get('rectangle'), ielt.get('regions')) answers[ie_id] = {'rectangle': ielt.get('rectangle'), 'regions': ielt.get('regions')}
return answers return answers
......
<span> <div class="imageinput capa_inputtype" id="inputtype_${id}">
<input <input
type="hidden" type="hidden"
class="imageinput" class="imageinput"
...@@ -7,10 +7,16 @@ ...@@ -7,10 +7,16 @@
id="input_${id}" id="input_${id}"
value="${value}" value="${value}"
/> />
<div style="position:relative;">
<div <div
id="imageinput_${id}" id="imageinput_${id}"
style="background-image: url('${src}'); width: ${width}px; height: ${height}px; position: relative; left: 0; top: 0;" style="
background-image: url('${src}');
width: ${width}px;
height: ${height}px;
position: relative;
left: 0;
top: 0;"
> >
<img <img
src="${STATIC_URL}green-pointer.png" src="${STATIC_URL}green-pointer.png"
...@@ -18,6 +24,16 @@ ...@@ -18,6 +24,16 @@
style="position: absolute; top: ${gy}px; left: ${gx}px;" style="position: absolute; top: ${gy}px; left: ${gx}px;"
/> />
</div> </div>
<div
data-width="${width}"
data-height="${height}"
id="answer_${id}"
style="
position: absolute;
left: 0;
top: 0;"
></div>
</div>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
(new ImageInput('${id}')); (new ImageInput('${id}'));
...@@ -57,4 +73,4 @@ ...@@ -57,4 +73,4 @@
<span class="sr">Status: incorrect</span> <span class="sr">Status: incorrect</span>
</span> </span>
% endif % endif
</span> </div>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<!-- ${width} = 300 --> <!-- ${width} = 300 -->
<!-- ${height} = 400 --> <!-- ${height} = 400 -->
<span> <div class="imageinput capa_inputtype" id="inputtype_12345">
<input <input
type="hidden" type="hidden"
class="imageinput" class="imageinput"
...@@ -12,12 +12,16 @@ ...@@ -12,12 +12,16 @@
value="" value=""
/> />
<div style="position:relative;">
<div <div
id="imageinput_12345" id="imageinput_12345"
style="width: 300px; height: 400px; position: relative; left: 0; top: 0; visibility: hidden;" style="width: 300px; height: 400px; position: relative; left: 0; top: 0; visibility: hidden;"
> >
<!-- image will go here --> <!-- image will go here -->
</div> </div>
<div id="answer_12345" data-width="100" data-height="100"></div>
</div>
<!-- status == 'unsubmitted' --> <!-- status == 'unsubmitted' -->
<span <span
...@@ -28,4 +32,4 @@ ...@@ -28,4 +32,4 @@
> >
<span class="sr">Status: unanswered</span> <span class="sr">Status: unanswered</span>
</span> </span>
</span> </div>
...@@ -36,6 +36,7 @@ lib_paths: ...@@ -36,6 +36,7 @@ lib_paths:
- common_static/coffee/src/ajax_prefix.js - common_static/coffee/src/ajax_prefix.js
- common_static/coffee/src/logger.js - common_static/coffee/src/logger.js
- common_static/js/vendor/jasmine-jquery.js - common_static/js/vendor/jasmine-jquery.js
- common_static/js/vendor/jasmine-imagediff.js
- common_static/js/vendor/require.js - common_static/js/vendor/require.js
- RequireJS-namespace-undefine.js - RequireJS-namespace-undefine.js
- common_static/js/vendor/jquery.min.js - common_static/js/vendor/jquery.min.js
......
...@@ -303,6 +303,102 @@ describe 'Problem', -> ...@@ -303,6 +303,102 @@ describe 'Problem', ->
expect($('input#1_2_1_choiceinput_2bc').attr('disabled')).not.toEqual('disabled') expect($('input#1_2_1_choiceinput_2bc').attr('disabled')).not.toEqual('disabled')
expect($('input#1_2_1').attr('disabled')).not.toEqual('disabled') expect($('input#1_2_1').attr('disabled')).not.toEqual('disabled')
describe 'imageinput', ->
imageinput_html = readFixtures('imageinput.html')
states = [
{
desc: 'rectangle is drawn correctly',
data: {'rectangle': '(10,10)-(30,30)'}
},
{
desc: 'region is drawn correctly',
data: {'regions': '[[10,10],[30,30],[70,30],[20,30]]'}
},
{
desc: 'mixed shapes are drawn correctly',
data: {
'rectangle': '(10,10)-(30,30);(5,5)-(20,20)',
'regions': '''[
[[50,50],[40,40],[70,30],[50,70]],
[[90,95],[95,95],[90,70],[70,70]]
]'''
}
},
]
beforeEach ->
@problem = new Problem($('.xblock-student_view'))
@problem.el.prepend imageinput_html
stubRequest = (data) =>
spyOn($, 'postWithPrefix').andCallFake (url, callback) ->
callback answers: "12345": data
getImage = (coords, c_width, c_height) =>
types =
rectangle: (coords) =>
reg = /^\(([0-9]+),([0-9]+)\)-\(([0-9]+),([0-9]+)\)$/
rects = coords.replace(/\s*/g, '').split(/;/)
$.each rects, (index, rect) =>
abs = Math.abs
points = reg.exec(rect)
if points
width = abs(points[3] - points[1])
height = abs(points[4] - points[2])
ctx.rect(points[1], points[2], width, height)
ctx.stroke()
ctx.fill()
regions: (coords) =>
parseCoords = (coords) =>
reg = JSON.parse(coords)
if typeof reg[0][0][0] == "undefined"
reg = [reg]
return reg
$.each parseCoords(coords), (index, region) =>
ctx.beginPath()
$.each region, (index, point) =>
if index is 0
ctx.moveTo(point[0], point[1])
else
ctx.lineTo(point[0], point[1]);
ctx.closePath()
ctx.stroke()
ctx.fill()
canvas = document.createElement('canvas')
canvas.width = c_width or 100
canvas.height = c_height or 100
if canvas.getContext
ctx = canvas.getContext('2d')
else
return console.log 'Canvas is not supported.'
ctx.fillStyle = 'rgba(255,255,255,.3)';
ctx.strokeStyle = "#FF0000";
ctx.lineWidth = "2";
$.each coords, (key, value) =>
types[key](value) if types[key]?
return canvas
$.each states, (index, state) =>
it state.desc, ->
stubRequest(state.data)
@problem.show()
img = getImage(state.data)
expect(img).toImageDiffEqual($('canvas')[0])
describe 'when the answers are already shown', -> describe 'when the answers are already shown', ->
beforeEach -> beforeEach ->
@problem.el.addClass 'showed' @problem.el.addClass 'showed'
...@@ -409,4 +505,3 @@ describe 'Problem', -> ...@@ -409,4 +505,3 @@ describe 'Problem', ->
expect(@problem.answers).toEqual "input_1_1=one&input_1_2=two" expect(@problem.answers).toEqual "input_1_1=one&input_1_2=two"
...@@ -162,6 +162,8 @@ beforeEach -> ...@@ -162,6 +162,8 @@ beforeEach ->
toBeInArray: (array) -> toBeInArray: (array) ->
return $.inArray(@.actual, array) > -1 return $.inArray(@.actual, array) > -1
@addMatchers imagediff.jasmine
# Stub jQuery.cookie # Stub jQuery.cookie
$.cookie = jasmine.createSpy('jQuery.cookie').andReturn '1.0' $.cookie = jasmine.createSpy('jQuery.cookie').andReturn '1.0'
......
...@@ -482,6 +482,82 @@ class @Problem ...@@ -482,6 +482,82 @@ class @Problem
for choice in answer for choice in answer
element.find("section#forinput#{choice}").addClass 'choicetextgroup_show_correct' element.find("section#forinput#{choice}").addClass 'choicetextgroup_show_correct'
imageinput: (element, display, answers) =>
# answers is a dict of (answer_id, answer_text) for each answer for this
# question.
# @Examples:
# {'anwser_id': {
# 'rectangle': '(10,10)-(20,30);(12,12)-(40,60)',
# 'regions': '[[10,10], [30,30], [10, 30], [30, 10]]'
# } }
types =
rectangle: (coords) =>
reg = /^\(([0-9]+),([0-9]+)\)-\(([0-9]+),([0-9]+)\)$/
rects = coords.replace(/\s*/g, '').split(/;/)
$.each rects, (index, rect) =>
abs = Math.abs
points = reg.exec(rect)
if points
width = abs(points[3] - points[1])
height = abs(points[4] - points[2])
ctx.rect(points[1], points[2], width, height)
ctx.stroke()
ctx.fill()
regions: (coords) =>
parseCoords = (coords) =>
reg = JSON.parse(coords)
# Regions is list of lists [region1, region2, region3, ...] where regionN
# is disordered list of points: [[1,1], [100,100], [50,50], [20, 70]].
# If there is only one region in the list, simpler notation can be used:
# regions="[[10,10], [30,30], [10, 30], [30, 10]]" (without explicitly
# setting outer list)
if typeof reg[0][0][0] == "undefined"
# we have [[1,2],[3,4],[5,6]] - single region
# instead of [[[1,2],[3,4],[5,6], [[1,2],[3,4],[5,6]]]
# or [[[1,2],[3,4],[5,6]]] - multiple regions syntax
reg = [reg]
return reg
$.each parseCoords(coords), (index, region) =>
ctx.beginPath()
$.each region, (index, point) =>
if index is 0
ctx.moveTo(point[0], point[1])
else
ctx.lineTo(point[0], point[1]);
ctx.closePath()
ctx.stroke()
ctx.fill()
element = $(element)
id = element.attr('id').replace(/inputtype_/,'')
container = element.find("#answer_#{id}")
canvas = document.createElement('canvas')
canvas.width = container.data('width')
canvas.height = container.data('height')
if canvas.getContext
ctx = canvas.getContext('2d')
else
return console.log 'Canvas is not supported.'
ctx.fillStyle = 'rgba(255,255,255,.3)';
ctx.strokeStyle = "#FF0000";
ctx.lineWidth = "2";
$.each answers, (key, answer) =>
$.each answer, (key, value) =>
types[key](value) if types[key]?
container.html(canvas)
inputtypeHideAnswerMethods: inputtypeHideAnswerMethods:
choicegroup: (element, display) => choicegroup: (element, display) =>
element = $(element) element = $(element)
......
...@@ -30,6 +30,7 @@ prepend_path: common/static ...@@ -30,6 +30,7 @@ prepend_path: common/static
lib_paths: lib_paths:
- js/vendor/jquery.min.js - js/vendor/jquery.min.js
- js/vendor/jasmine-jquery.js - js/vendor/jasmine-jquery.js
- js/vendor/jasmine-imagediff.js
- js/vendor/underscore-min.js - js/vendor/underscore-min.js
- js/vendor/backbone-min.js - js/vendor/backbone-min.js
- js/vendor/jquery.timeago.js - js/vendor/jquery.timeago.js
......
...@@ -31,6 +31,7 @@ lib_paths: ...@@ -31,6 +31,7 @@ lib_paths:
- xmodule_js/common_static/coffee/src/ajax_prefix.js - xmodule_js/common_static/coffee/src/ajax_prefix.js
- xmodule_js/common_static/coffee/src/logger.js - xmodule_js/common_static/coffee/src/logger.js
- xmodule_js/common_static/js/vendor/jasmine-jquery.js - xmodule_js/common_static/js/vendor/jasmine-jquery.js
- xmodule_js/common_static/js/vendor/jasmine-imagediff.js
- xmodule_js/common_static/js/vendor/require.js - xmodule_js/common_static/js/vendor/require.js
- js/RequireJS-namespace-undefine.js - js/RequireJS-namespace-undefine.js
- xmodule_js/common_static/js/vendor/jquery.min.js - xmodule_js/common_static/js/vendor/jquery.min.js
......
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