diff --git a/common/lib/capa/capa/javascript_problem_generator.js b/common/lib/capa/capa/javascript_problem_generator.js deleted file mode 100644 index 473a5d8e8c..0000000000 --- a/common/lib/capa/capa/javascript_problem_generator.js +++ /dev/null @@ -1,28 +0,0 @@ -require('coffee-script'); -var importAll = function(modulePath) { - module = require(modulePath); - for (key in module) { - global[key] = module[key]; - } -}; - -importAll('mersenne-twister-min'); -importAll('xproblem'); - -generatorModulePath = process.argv[2]; -dependencies = JSON.parse(process.argv[3]); -seed = JSON.parse(process.argv[4]); -params = JSON.parse(process.argv[5]); - -if (seed == null) { - seed = 4; -} - -for (var i = 0; i < dependencies.length; i++) { - importAll(dependencies[i]); -} - -generatorModule = require(generatorModulePath); -generatorClass = generatorModule.generatorClass; -generator = new generatorClass(seed, params); -console.log(JSON.stringify(generator.generate())); diff --git a/common/lib/capa/capa/javascript_problem_grader.js b/common/lib/capa/capa/javascript_problem_grader.js deleted file mode 100644 index 02cb7da7f2..0000000000 --- a/common/lib/capa/capa/javascript_problem_grader.js +++ /dev/null @@ -1,26 +0,0 @@ -require('coffee-script'); -var importAll = function(modulePath) { - module = require(modulePath); - for (key in module) { - global[key] = module[key]; - } -}; - -importAll('xproblem'); - -graderModulePath = process.argv[2]; -dependencies = JSON.parse(process.argv[3]); -submission = JSON.parse(process.argv[4]); -problemState = JSON.parse(process.argv[5]); -params = JSON.parse(process.argv[6]); - -for (var i = 0; i < dependencies.length; i++) { - importAll(dependencies[i]); -} - -graderModule = require(graderModulePath); -graderClass = graderModule.graderClass; -grader = new graderClass(submission, problemState, params); -console.log(JSON.stringify(grader.grade())); -console.log(JSON.stringify(grader.evaluation)); -console.log(JSON.stringify(grader.solution)); diff --git a/common/lib/capa/capa/templates/chemicalequationinput.html b/common/lib/capa/capa/templates/chemicalequationinput.html index b61172951a..3f18a699e6 100644 --- a/common/lib/capa/capa/templates/chemicalequationinput.html +++ b/common/lib/capa/capa/templates/chemicalequationinput.html @@ -11,7 +11,7 @@ % endif /> -

+

${value|h} <%include file="status_span.html" args="status=status, status_id=id"/>

diff --git a/common/lib/capa/capa/templates/drag_and_drop_input.html b/common/lib/capa/capa/templates/drag_and_drop_input.html index a955453416..758968937e 100644 --- a/common/lib/capa/capa/templates/drag_and_drop_input.html +++ b/common/lib/capa/capa/templates/drag_and_drop_input.html @@ -18,7 +18,7 @@ style="display:none;"/> -

+

<%include file="status_span.html" args="status=status, status_id=id"/>

diff --git a/common/lib/capa/capa/templates/editageneinput.html b/common/lib/capa/capa/templates/editageneinput.html index c3dd75a3da..ae211835e0 100644 --- a/common/lib/capa/capa/templates/editageneinput.html +++ b/common/lib/capa/capa/templates/editageneinput.html @@ -11,7 +11,7 @@ -

+

<%include file="status_span.html" args="status=status, status_id=id"/>

diff --git a/common/lib/capa/capa/templates/editamolecule.html b/common/lib/capa/capa/templates/editamolecule.html index 83ca14a4f0..b4db77ab0c 100644 --- a/common/lib/capa/capa/templates/editamolecule.html +++ b/common/lib/capa/capa/templates/editamolecule.html @@ -16,7 +16,7 @@

-

+

<%include file="status_span.html" args="status=status, status_id=id"/>

diff --git a/common/lib/capa/capa/templates/jsinput.html b/common/lib/capa/capa/templates/jsinput.html index 7c108817a8..61a04a40eb 100644 --- a/common/lib/capa/capa/templates/jsinput.html +++ b/common/lib/capa/capa/templates/jsinput.html @@ -43,9 +43,9 @@

-

- <%include file="status_span.html" args="status=status, status_id=id"/> -

+
+ <%include file="status_span.html" args="status=status, status_id=id"/> +
diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index 8e24e08b66..ea5a2f0769 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -389,64 +389,31 @@ div.problem { } } - .unanswered { - p.status.drag-and-drop--status { - @include margin(8px, 0, 0, ($baseline/2)); - text-indent: 100%; - white-space: nowrap; - overflow: hidden; - } - } - &.correct, &.ui-icon-check { - p.status { - @include status-icon($correct, $checkmark-icon); - } - input { border-color: $correct; } } &.partially-correct, &.ui-icon-check { - p.status { - @include status-icon($partially-correct, $asterisk-icon); - } - input { border-color: $partially-correct; } } &.processing { - p.status { - display: inline-block; - width: 20px; - height: 20px; - background: url('#{$static-path}/images/spinner.gif') center center no-repeat; - } - input { border-color: #aaa; } } &.ui-icon-close { - p.status { - @include status-icon($incorrect, $cross-icon); - } - input { border-color: $incorrect; } } &.incorrect, &.incomplete { - - p.status { - @include status-icon($incorrect, $cross-icon); - } - input { border-color: $incorrect; } diff --git a/common/lib/xmodule/xmodule/templates/problem/jsinput_response.yaml b/common/lib/xmodule/xmodule/templates/problem/jsinput_response.yaml index 5a37b6ede3..20e7874695 100644 --- a/common/lib/xmodule/xmodule/templates/problem/jsinput_response.yaml +++ b/common/lib/xmodule/xmodule/templates/problem/jsinput_response.yaml @@ -1,6 +1,6 @@ --- metadata: - display_name: Custom Javascript Display and Grading + display_name: Custom JavaScript Display and Grading markdown: !!null showanswer: never data: | @@ -8,8 +8,8 @@ data: |

In these problems (also called custom JavaScript problems or JS Input problems), you add a problem or tool that uses JavaScript in Studio. - Studio embeds the problem in an IFrame so that your students can - interact with it in the LMS. You can grade your students' work using + Studio embeds the problem in an IFrame so that your learners can + interact with it in the LMS. You can grade your learners' work using JavaScript and some basic Python, and the grading is integrated into the edX grading system.

@@ -31,42 +31,47 @@ data: |

When you add the problem, be sure to select Settings to specify a Display Name and other values that apply. + Also, be sure to specify a title attribute on the jsinput tag; + this title is used for the title attribute on the generated IFrame. Generally, + the title attribute on the IFrame should match the title tag of the HTML hosted + within the IFrame, which is specified by the html_file attribute.

You can use the following example problem as a model.

- + -

In the following image, click the objects until the cone is yellow and the cube is blue.

- This is paragraph text displayed before the IFrame.

+
diff --git a/common/static/css/capa/jsinput_css.css b/common/static/css/capa/jsinput_css.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/common/static/js/capa/jsinput/jsinput_example.css b/common/static/js/capa/jsinput/jsinput_example.css new file mode 100644 index 0000000000..8f1144ac40 --- /dev/null +++ b/common/static/js/capa/jsinput/jsinput_example.css @@ -0,0 +1,9 @@ +.directions { + font-size: large +} + +.feedback { + font-size: medium; + border: 2px solid cornflowerblue; + padding: 5px; +} diff --git a/common/static/js/capa/jsinput/jsinput_example.html b/common/static/js/capa/jsinput/jsinput_example.html new file mode 100644 index 0000000000..caa034fff9 --- /dev/null +++ b/common/static/js/capa/jsinput/jsinput_example.html @@ -0,0 +1,15 @@ + + + + Dropdown with Dynamic Text + + + + + + +

+ + diff --git a/common/static/js/capa/jsinput/jsinput_example.js b/common/static/js/capa/jsinput/jsinput_example.js new file mode 100644 index 0000000000..6aa125fd69 --- /dev/null +++ b/common/static/js/capa/jsinput/jsinput_example.js @@ -0,0 +1,86 @@ +/* globals Channel */ + +(function() { + 'use strict'; + + // state will be populated via initial_state via the `setState` method. Defining dummy values here + // to make the expected structure clear. + var state = { + availableChoices: [], + selectedChoice: '' + }, + channel, + select = document.getElementsByClassName('choices')[0], + feedback = document.getElementsByClassName('feedback')[0]; + + function populateSelect() { + // Populate the select from `state.availableChoices`. + var i, option; + + // Clear out any pre-existing options. + while (select.firstChild) { + select.removeChild(select.firstChild); + } + + // Populate the select with the available choices. + for (i = 0; i < state.availableChoices.length; i++) { + option = document.createElement('option'); + option.value = i; + option.innerHTML = state.availableChoices[i]; + if (state.availableChoices[i] === state.selectedChoice) { + option.selected = true; + } + select.appendChild(option); + } + feedback.innerText = "The currently selected answer is '" + state.selectedChoice + "'."; + } + + function getGrade() { + // The following return value may or may not be used to grade server-side. + // If getState and setState are used, then the Python grader also gets access + // to the return value of getState and can choose it instead to grade. + return JSON.stringify(state.selectedChoice); + } + + function getState() { + // Returns the current state (which can be used for grading). + return JSON.stringify(state); + } + + // This function will be called with 1 argument when JSChannel is not used, + // 2 otherwise. In the latter case, the first argument is a transaction + // object that will not be used here + // (see http://mozilla.github.io/jschannel/docs/) + function setState() { + var stateString = arguments.length === 1 ? arguments[0] : arguments[1]; + state = JSON.parse(stateString); + populateSelect(); + } + + // Establish a channel only if this application is embedded in an iframe. + // This will let the parent window communicate with this application using + // RPC and bypass SOP restrictions. + if (window.parent !== window) { + channel = Channel.build({ + window: window.parent, + origin: '*', + scope: 'JSInput' + }); + + channel.bind('getGrade', getGrade); + channel.bind('getState', getState); + channel.bind('setState', setState); + } + + select.addEventListener('change', function() { + state.selectedChoice = select.options[select.selectedIndex].text; + feedback.innerText = "You have selected '" + state.selectedChoice + + "'. Click Submit to grade your answer."; + }); + + return { + getState: getState, + setState: setState, + getGrade: getGrade + }; +}()); diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index 238bf9e699..84c7cc2e1d 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -53,7 +53,7 @@ git+https://github.com/edx/MongoDBProxy.git@25b99097615bda06bd7cdfe5669ed80dc2a7 git+https://github.com/edx/nltk.git@2.0.6#egg=nltk==2.0.6 -e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev -e git+https://github.com/appliedsec/pygeoip.git@95e69341cebf5a6a9fbf7c4f5439d458898bdc3b#egg=pygeoip --e git+https://github.com/jazkarta/edx-jsme.git@0908b4db16168382be5685e7e9b7b4747ac410e0#egg=edx-jsme +-e git+https://github.com/jazkarta/edx-jsme.git@690dbf75441fa91c7c4899df0b83d77f7deb5458#egg=edx-jsme git+https://github.com/edx/django-pyfs.git@1.0.3#egg=django-pyfs==1.0.3 git+https://github.com/mitodl/django-cas.git@v2.1.1#egg=django-cas -e git+https://github.com/dgrtwo/ParsePy.git@7949b9f754d1445eff8e8f20d0e967b9a6420639#egg=parse_rest