Commit aba4abd5 by Andy Armstrong

Miscellaneous small improvements

* Bump version numbers
* Introduce JSCS style validation
* Address style failures
parent 582a4a4f
{
"preset": "google",
// edX specific rules
"validateIndentation": 4,
"maximumLineLength": 120,
"disallowMultipleVarDecl": false,
"requireCamelCaseOrUpperCaseIdentifiers": {"ignoreProperties": true},
// Temporary overrides until we clean up further...
"validateQuoteMarks": null, // We should standardize on single quotes
"disallowKeywordsOnNewLine": [] // Other repos disallow lines starting with "else"
}
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
"forin" : true, // Requires all for in loops to filter object's items. "forin" : true, // Requires all for in loops to filter object's items.
"freeze" : true, // Prohibits overwriting prototypes of native objects such as Array, Date and so on. "freeze" : true, // Prohibits overwriting prototypes of native objects such as Array, Date and so on.
"immed" : true, // Prohibits the use of immediate function invocations without wrapping them in parentheses. "immed" : true, // Prohibits the use of immediate function invocations without wrapping them in parentheses.
// "indent" : 4, // Enforces specific tab width for your code. Has no effect when "white" option is not used.
"latedef" : "nofunc", // Prohibits the use of a variable before it was defined. Setting this option to "nofunc" will allow function declarations to be ignored. "latedef" : "nofunc", // Prohibits the use of a variable before it was defined. Setting this option to "nofunc" will allow function declarations to be ignored.
"newcap" : true, // Requires you to capitalize names of constructor functions. "newcap" : true, // Requires you to capitalize names of constructor functions.
"noarg" : true, // Prohibits the use of arguments.caller and arguments.callee. "noarg" : true, // Prohibits the use of arguments.caller and arguments.callee.
...@@ -27,11 +26,6 @@ ...@@ -27,11 +26,6 @@
"unused" : true, // Warns when you define and never use your variables. "unused" : true, // Warns when you define and never use your variables.
"strict" : false, // Requires all functions to run in ECMAScript 5's strict mode. "strict" : false, // Requires all functions to run in ECMAScript 5's strict mode.
"trailing" : true, // Makes it an error to leave a trailing whitespace in your code. "trailing" : true, // Makes it an error to leave a trailing whitespace in your code.
"maxlen" : 120, // Lets you set the maximum length of a line.
//"maxparams" : 4, // Lets you set the max number of formal parameters allowed per function.
//"maxdepth" : 4, // Lets you control how nested do you want your blocks to be.
//"maxstatements" : 4, // Lets you set the max number of statements allowed per function.
//"maxcomplexity" : 4, // Lets you control cyclomatic complexity throughout your code.
// == Relaxing Options ================================================ // == Relaxing Options ================================================
......
...@@ -21,7 +21,6 @@ install-python: ...@@ -21,7 +21,6 @@ install-python:
./scripts/install-python.sh ./scripts/install-python.sh
install-js: install-js:
npm config set loglevel warn
npm install npm install
install-nltk-data: install-nltk-data:
...@@ -43,6 +42,7 @@ install-test: ...@@ -43,6 +42,7 @@ install-test:
pip install -q -r requirements/test.txt pip install -q -r requirements/test.txt
install-sys-requirements: install-system install-node install-sys-requirements: install-system install-node
npm config set loglevel warn
install-dev: install-dev:
gem install sass gem install sass
...@@ -52,9 +52,12 @@ install: install-wheels install-python install-js install-nltk-data install-test ...@@ -52,9 +52,12 @@ install: install-wheels install-python install-js install-nltk-data install-test
quality: quality:
jshint openassessment/xblock/static/js/src -c .jshintrc --verbose jshint openassessment/xblock/static/js/src -c .jshintrc --verbose
./node_modules/jscs/bin/jscs openassessment/xblock/static/js/src --verbose
test: quality test: quality test-python test-js
./scripts/test.sh
test-python:
./scripts/test-python.sh
render-templates: render-templates:
./scripts/render-templates.sh ./scripts/render-templates.sh
...@@ -65,6 +68,8 @@ test-js: render-templates ...@@ -65,6 +68,8 @@ test-js: render-templates
test-js-debug: render-templates test-js-debug: render-templates
./scripts/js-debugger.sh ./scripts/js-debugger.sh
test-sandbox: test-acceptance test-a11y
test-acceptance: test-acceptance:
./scripts/test-acceptance.sh tests ./scripts/test-acceptance.sh tests
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Tests for the Openassessment Container Object. Tests for the Openassessment Container Object.
**/ **/
describe("OpenAssessment.Container", function () { describe("OpenAssessment.Container", function() {
var counter = 0; var counter = 0;
var StubContainerItem = function(element) { var StubContainerItem = function(element) {
...@@ -38,7 +38,7 @@ describe("OpenAssessment.Container", function () { ...@@ -38,7 +38,7 @@ describe("OpenAssessment.Container", function () {
); );
}; };
beforeEach(function () { beforeEach(function() {
// Reset the counter before each test // Reset the counter before each test
counter = 0; counter = 0;
......
...@@ -174,7 +174,7 @@ describe("OpenAssessment edit assessment views", function() { ...@@ -174,7 +174,7 @@ describe("OpenAssessment edit assessment views", function() {
}); });
it("enables and disables", function() { testEnableAndDisable(view); }); it("enables and disables", function() { testEnableAndDisable(view); });
it("loads a description", function () { it("loads a description", function() {
// This assumes a particular structure of the DOM, // This assumes a particular structure of the DOM,
// which is set by the HTML fixture. // which is set by the HTML fixture.
expect(view.description()).toEqual({ expect(view.description()).toEqual({
...@@ -192,7 +192,7 @@ describe("OpenAssessment edit assessment views", function() { ...@@ -192,7 +192,7 @@ describe("OpenAssessment edit assessment views", function() {
}); });
}); });
it("modifies a description", function () { it("modifies a description", function() {
view.exampleContainer.add(); view.exampleContainer.add();
expect(view.description()).toEqual({ expect(view.description()).toEqual({
examples: [ examples: [
......
...@@ -429,7 +429,7 @@ describe("OpenAssessment.StudentTrainingListenerWithTrainingExamples", function( ...@@ -429,7 +429,7 @@ describe("OpenAssessment.StudentTrainingListenerWithTrainingExamples", function(
}); });
it("adds a criterion and an option, then adds a training example", function (){ it("adds a criterion and an option, then adds a training example", function(){
// Initial state, set by the fixture // Initial state, set by the fixture
assertExampleLabels( assertExampleLabels(
listener.examplesOptionsLabels(), listener.examplesOptionsLabels(),
......
...@@ -208,7 +208,7 @@ describe("OpenAssessment.EditRubricView", function() { ...@@ -208,7 +208,7 @@ describe("OpenAssessment.EditRubricView", function() {
}); });
}); });
it("validates option points", function () { it("validates option points", function() {
// Test that a particular value is marked as valid/invalid // Test that a particular value is marked as valid/invalid
var testValidateOptionPoints = function(value, isValid) { var testValidateOptionPoints = function(value, isValid) {
var option = view.getOptionItem(0, 0); var option = view.getOptionItem(0, 0);
......
...@@ -27,7 +27,6 @@ OpenAssessment.BaseView = function(runtime, element, server, data) { ...@@ -27,7 +27,6 @@ OpenAssessment.BaseView = function(runtime, element, server, data) {
this.staffAreaView = new OpenAssessment.StaffAreaView(this.element, this.server, this); this.staffAreaView = new OpenAssessment.StaffAreaView(this.element, this.server, this);
}; };
OpenAssessment.BaseView.prototype = { OpenAssessment.BaseView.prototype = {
/** /**
...@@ -39,7 +38,7 @@ OpenAssessment.BaseView.prototype = { ...@@ -39,7 +38,7 @@ OpenAssessment.BaseView.prototype = {
*/ */
scrollToTop: function() { scrollToTop: function() {
if ($.scrollTo instanceof Function) { if ($.scrollTo instanceof Function) {
$(window).scrollTo($("#openassessment__steps", this.element), 800, {offset:-50}); $(window).scrollTo($("#openassessment__steps", this.element), 800, {offset: -50});
} }
}, },
...@@ -49,8 +48,8 @@ OpenAssessment.BaseView.prototype = { ...@@ -49,8 +48,8 @@ OpenAssessment.BaseView.prototype = {
Args: Args:
parentSel (JQuery selector): CSS selector for the container element. parentSel (JQuery selector): CSS selector for the container element.
**/ **/
setUpCollapseExpand: function (parentSel) { setUpCollapseExpand: function(parentSel) {
parentSel.on('click', '.ui-toggle-visibility__control', function (eventData) { parentSel.on('click', '.ui-toggle-visibility__control', function(eventData) {
var sel = $(eventData.target).closest('.ui-toggle-visibility'); var sel = $(eventData.target).closest('.ui-toggle-visibility');
sel.toggleClass('is--collapsed'); sel.toggleClass('is--collapsed');
} }
......
...@@ -15,7 +15,6 @@ OpenAssessment.GradeView = function(element, server, baseView) { ...@@ -15,7 +15,6 @@ OpenAssessment.GradeView = function(element, server, baseView) {
this.baseView = baseView; this.baseView = baseView;
}; };
OpenAssessment.GradeView.prototype = { OpenAssessment.GradeView.prototype = {
/** /**
Load the grade view. Load the grade view.
......
...@@ -15,7 +15,6 @@ OpenAssessment.LeaderboardView = function(element, server, baseView) { ...@@ -15,7 +15,6 @@ OpenAssessment.LeaderboardView = function(element, server, baseView) {
this.baseView = baseView; this.baseView = baseView;
}; };
OpenAssessment.LeaderboardView.prototype = { OpenAssessment.LeaderboardView.prototype = {
/** /**
Load the leaderboard view. Load the leaderboard view.
...@@ -32,5 +31,5 @@ OpenAssessment.LeaderboardView.prototype = { ...@@ -32,5 +31,5 @@ OpenAssessment.LeaderboardView.prototype = {
).fail(function(errMsg) { ).fail(function(errMsg) {
baseView.showLoadError('leaderboard', errMsg); baseView.showLoadError('leaderboard', errMsg);
}); });
}, }
}; };
...@@ -31,5 +31,5 @@ OpenAssessment.MessageView.prototype = { ...@@ -31,5 +31,5 @@ OpenAssessment.MessageView.prototype = {
).fail(function(errMsg) { ).fail(function(errMsg) {
baseView.showLoadError('message', errMsg); baseView.showLoadError('message', errMsg);
}); });
} }
}; };
...@@ -16,7 +16,6 @@ OpenAssessment.PeerView = function(element, server, baseView) { ...@@ -16,7 +16,6 @@ OpenAssessment.PeerView = function(element, server, baseView) {
this.rubric = null; this.rubric = null;
}; };
OpenAssessment.PeerView.prototype = { OpenAssessment.PeerView.prototype = {
/** /**
...@@ -184,7 +183,7 @@ OpenAssessment.PeerView.prototype = { ...@@ -184,7 +183,7 @@ OpenAssessment.PeerView.prototype = {
Common peer assessment request building, used for all types of peer assessments. Common peer assessment request building, used for all types of peer assessments.
Args: Args:
successFunction (function): The function called if the request is successfunction(function): The function called if the request is
successful. This varies based on the type of request to submit successful. This varies based on the type of request to submit
a peer assessment. a peer assessment.
......
/** /**
Interface for response (submission) view. Interface for response (submission) view.
Args: Args:
element (DOM element): The DOM element representing the XBlock. element (DOM element): The DOM element representing the XBlock.
server (OpenAssessment.Server): The interface to the XBlock server. server (OpenAssessment.Server): The interface to the XBlock server.
fileUploader (OpenAssessment.FileUploader): File uploader instance. fileUploader (OpenAssessment.FileUploader): File uploader instance.
baseView (OpenAssessment.BaseView): Container view. baseView (OpenAssessment.BaseView): Container view.
data (Object): The data object passed from XBlock backend. data (Object): The data object passed from XBlock backend.
Returns: Returns:
OpenAssessment.ResponseView OpenAssessment.ResponseView
**/ **/
OpenAssessment.ResponseView = function(element, server, fileUploader, baseView, data) { OpenAssessment.ResponseView = function(element, server, fileUploader, baseView, data) {
this.element = element; this.element = element;
this.server = server; this.server = server;
...@@ -26,7 +26,6 @@ OpenAssessment.ResponseView = function(element, server, fileUploader, baseView, ...@@ -26,7 +26,6 @@ OpenAssessment.ResponseView = function(element, server, fileUploader, baseView,
this.fileUploaded = false; this.fileUploaded = false;
}; };
OpenAssessment.ResponseView.prototype = { OpenAssessment.ResponseView.prototype = {
// Milliseconds between checks for whether we should autosave. // Milliseconds between checks for whether we should autosave.
...@@ -40,8 +39,8 @@ OpenAssessment.ResponseView.prototype = { ...@@ -40,8 +39,8 @@ OpenAssessment.ResponseView.prototype = {
MAX_FILE_SIZE: 5242880, MAX_FILE_SIZE: 5242880,
/** /**
Load the response (submission) view. Load the response (submission) view.
**/ **/
load: function() { load: function() {
var view = this; var view = this;
this.server.render('submission').done( this.server.render('submission').done(
...@@ -58,8 +57,8 @@ OpenAssessment.ResponseView.prototype = { ...@@ -58,8 +57,8 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Install event handlers for the view. Install event handlers for the view.
**/ **/
installHandlers: function() { installHandlers: function() {
var sel = $('#openassessment__response', this.element); var sel = $('#openassessment__response', this.element);
var view = this; var view = this;
...@@ -104,13 +103,13 @@ OpenAssessment.ResponseView.prototype = { ...@@ -104,13 +103,13 @@ OpenAssessment.ResponseView.prototype = {
function(eventObject) { function(eventObject) {
eventObject.preventDefault(); eventObject.preventDefault();
// extract typed-in response and replace newline with br // extract typed-in response and replace newline with br
var preview_text = sel.find('.submission__answer__part__text__value').val(); var previewText = sel.find('.submission__answer__part__text__value').val();
var preview_container = sel.find('#preview_content'); var previewContainer = sel.find('#preview_content');
preview_container.html(preview_text.replace(/\r\n|\r|\n/g,"<br />")); previewContainer.html(previewText.replace(/\r\n|\r|\n/g,"<br />"));
// Render in mathjax // Render in mathjax
sel.find('#submission__preview__item').show(); sel.find('#submission__preview__item').show();
MathJax.Hub.Queue(['Typeset', MathJax.Hub, preview_container[0]]); MathJax.Hub.Queue(['Typeset', MathJax.Hub, previewContainer[0]]);
} }
); );
...@@ -126,12 +125,12 @@ OpenAssessment.ResponseView.prototype = { ...@@ -126,12 +125,12 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Enable or disable autosave polling. Enable or disable autosave polling.
Args: Args:
enabled (boolean): If true, start polling for whether we need to autosave. enabled (boolean): If true, start polling for whether we need to autosave.
Otherwise, stop polling. Otherwise, stop polling.
**/ **/
setAutoSaveEnabled: function(enabled) { setAutoSaveEnabled: function(enabled) {
if (enabled) { if (enabled) {
if (this.autoSaveTimerId === null) { if (this.autoSaveTimerId === null) {
...@@ -149,20 +148,20 @@ OpenAssessment.ResponseView.prototype = { ...@@ -149,20 +148,20 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Enable/disable the submit button. Enable/disable the submit button.
Check that whether the submit button is enabled. Check that whether the submit button is enabled.
Args: Args:
enabled (bool): If specified, set the state of the button. enabled (bool): If specified, set the state of the button.
Returns: Returns:
bool: Whether the button is enabled. bool: Whether the button is enabled.
Examples: Examples:
>> view.submitEnabled(true); // enable the button >> view.submitEnabled(true); // enable the button
>> view.submitEnabled(); // check whether the button is enabled >> view.submitEnabled(); // check whether the button is enabled
>> true >> true
**/ **/
submitEnabled: function(enabled) { submitEnabled: function(enabled) {
var sel = $('#step--response__submit', this.element); var sel = $('#step--response__submit', this.element);
if (typeof enabled === 'undefined') { if (typeof enabled === 'undefined') {
...@@ -173,23 +172,23 @@ OpenAssessment.ResponseView.prototype = { ...@@ -173,23 +172,23 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Enable/disable the save button. Enable/disable the save button.
Check whether the save button is enabled. Check whether the save button is enabled.
Also enables/disables a beforeunload handler to warn Also enables/disables a beforeunload handler to warn
users about navigating away from the page with unsaved changes. users about navigating away from the page with unsaved changes.
Args: Args:
enabled (bool): If specified, set the state of the button. enabled (bool): If specified, set the state of the button.
Returns: Returns:
bool: Whether the button is enabled. bool: Whether the button is enabled.
Examples: Examples:
>> view.submitEnabled(true); // enable the button >> view.submitEnabled(true); // enable the button
>> view.submitEnabled(); // check whether the button is enabled >> view.submitEnabled(); // check whether the button is enabled
>> true >> true
**/ **/
saveEnabled: function(enabled) { saveEnabled: function(enabled) {
var sel = $('#submission__save', this.element); var sel = $('#submission__save', this.element);
if (typeof enabled === 'undefined') { if (typeof enabled === 'undefined') {
...@@ -200,10 +199,10 @@ OpenAssessment.ResponseView.prototype = { ...@@ -200,10 +199,10 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Enable/disable the preview button. Enable/disable the preview button.
Works exactly the same way as saveEnabled method. Works exactly the same way as saveEnabled method.
**/ **/
previewEnabled: function(enabled) { previewEnabled: function(enabled) {
var sel = $('#submission__preview', this.element); var sel = $('#submission__preview', this.element);
if (typeof enabled === 'undefined') { if (typeof enabled === 'undefined') {
...@@ -213,15 +212,15 @@ OpenAssessment.ResponseView.prototype = { ...@@ -213,15 +212,15 @@ OpenAssessment.ResponseView.prototype = {
} }
}, },
/** /**
Set the save status message. Set the save status message.
Retrieve the save status message. Retrieve the save status message.
Args: Args:
msg (string): If specified, the message to display. msg (string): If specified, the message to display.
Returns: Returns:
string: The current status message. string: The current status message.
**/ **/
saveStatus: function(msg) { saveStatus: function(msg) {
var sel = $('#response__save_status h3', this.element); var sel = $('#response__save_status h3', this.element);
if (typeof msg === 'undefined') { if (typeof msg === 'undefined') {
...@@ -235,19 +234,19 @@ OpenAssessment.ResponseView.prototype = { ...@@ -235,19 +234,19 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Enable/disable the "navigate away" warning to alert the user of unsaved changes. Enable/disable the "navigate away" warning to alert the user of unsaved changes.
Args: Args:
enabled (bool): If specified, set whether the warning is enabled. enabled (bool): If specified, set whether the warning is enabled.
Returns: Returns:
bool: Whether the warning is enabled. bool: Whether the warning is enabled.
Examples: Examples:
>> view.unsavedWarningEnabled(true); // enable the "unsaved" warning >> view.unsavedWarningEnabled(true); // enable the "unsaved" warning
>> view.unsavedWarningEnabled(); >> view.unsavedWarningEnabled();
>> true >> true
**/ **/
unsavedWarningEnabled: function(enabled) { unsavedWarningEnabled: function(enabled) {
if (typeof enabled === 'undefined') { if (typeof enabled === 'undefined') {
return (window.onbeforeunload !== null); return (window.onbeforeunload !== null);
...@@ -256,8 +255,7 @@ OpenAssessment.ResponseView.prototype = { ...@@ -256,8 +255,7 @@ OpenAssessment.ResponseView.prototype = {
if (enabled) { if (enabled) {
window.onbeforeunload = function() { window.onbeforeunload = function() {
// Keep this on one big line to avoid gettext bug: http://stackoverflow.com/a/24579117 // Keep this on one big line to avoid gettext bug: http://stackoverflow.com/a/24579117
/* jshint maxlen:300 */ return gettext("If you leave this page without saving or submitting your response, you'll lose any work you've done on the response."); // jscs:ignore maximumLineLength
return gettext("If you leave this page without saving or submitting your response, you'll lose any work you've done on the response.");
}; };
} }
else { else {
...@@ -267,15 +265,15 @@ OpenAssessment.ResponseView.prototype = { ...@@ -267,15 +265,15 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Set the response texts. Set the response texts.
Retrieve the response texts. Retrieve the response texts.
Args: Args:
texts (array of strings): If specified, the texts to set for the response. texts (array of strings): If specified, the texts to set for the response.
Returns: Returns:
array of strings: The current response texts. array of strings: The current response texts.
**/ **/
response: function(texts) { response: function(texts) {
var sel = $('.submission__answer__part__text__value', this.element); var sel = $('.submission__answer__part__text__value', this.element);
if (typeof texts === 'undefined') { if (typeof texts === 'undefined') {
...@@ -290,25 +288,25 @@ OpenAssessment.ResponseView.prototype = { ...@@ -290,25 +288,25 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Check whether the response texts have changed since the last save. Check whether the response texts have changed since the last save.
Returns: boolean Returns: boolean
**/ **/
responseChanged: function() { responseChanged: function() {
var savedResponse = this.savedResponse; var savedResponse = this.savedResponse;
return this.response().some(function(element, index) { return this.response().some(function(element, index) {
return element !== savedResponse[index]; return element !== savedResponse[index];
}); });
}, },
/** /**
Automatically save the user's response if certain conditions are met. Automatically save the user's response if certain conditions are met.
Usually, this would be called by a timer (see `setAutoSaveEnabled()`). Usually, this would be called by a timer (see `setAutoSaveEnabled()`).
For testing purposes, it's useful to disable the timer For testing purposes, it's useful to disable the timer
and call this function synchronously. and call this function synchronously.
**/ **/
autoSave: function() { autoSave: function() {
var timeSinceLastChange = Date.now() - this.lastChangeTime; var timeSinceLastChange = Date.now() - this.lastChangeTime;
...@@ -324,14 +322,14 @@ OpenAssessment.ResponseView.prototype = { ...@@ -324,14 +322,14 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Enable/disable the submission and save buttons based on whether Enable/disable the submission and save buttons based on whether
the user has entered a response. the user has entered a response.
**/ **/
handleResponseChanged: function() { handleResponseChanged: function() {
// Enable the save/submit button only for non-blank responses // Enable the save/submit button only for non-blank responses
var isNotBlank = !this.response().every(function(element) { var isNotBlank = !this.response().every(function(element) {
return $.trim(element) === ''; return $.trim(element) === '';
}); });
this.submitEnabled(isNotBlank); this.submitEnabled(isNotBlank);
// Update the save button, save status, and "unsaved changes" warning // Update the save button, save status, and "unsaved changes" warning
...@@ -348,8 +346,8 @@ OpenAssessment.ResponseView.prototype = { ...@@ -348,8 +346,8 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Save a response without submitting it. Save a response without submitting it.
**/ **/
save: function() { save: function() {
// If there were errors on previous calls to save, forget // If there were errors on previous calls to save, forget
// about them for now. If an error occurs on *this* save, // about them for now. If an error occurs on *this* save,
...@@ -396,8 +394,8 @@ OpenAssessment.ResponseView.prototype = { ...@@ -396,8 +394,8 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Send a response submission to the server and update the view. Send a response submission to the server and update the view.
**/ **/
submit: function() { submit: function() {
// Immediately disable the submit button to prevent multiple submission // Immediately disable the submit button to prevent multiple submission
this.submitEnabled(false); this.submitEnabled(false);
...@@ -409,7 +407,7 @@ OpenAssessment.ResponseView.prototype = { ...@@ -409,7 +407,7 @@ OpenAssessment.ResponseView.prototype = {
// check if there is a file selected but not uploaded yet // check if there is a file selected but not uploaded yet
if (view.files !== null && !view.fileUploaded) { if (view.files !== null && !view.fileUploaded) {
var msg = gettext('Do you want to upload your file before submitting?'); var msg = gettext('Do you want to upload your file before submitting?');
if(confirm(msg)) { if (confirm(msg)) {
fileDefer = view.fileUpload(); fileDefer = view.fileUpload();
} else { } else {
view.submitEnabled(true); view.submitEnabled(true);
...@@ -456,8 +454,8 @@ OpenAssessment.ResponseView.prototype = { ...@@ -456,8 +454,8 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Transition the user to the next step in the workflow. Transition the user to the next step in the workflow.
**/ **/
moveToNextStep: function() { moveToNextStep: function() {
this.load(); this.load();
this.baseView.loadAssessmentModules(); this.baseView.loadAssessmentModules();
...@@ -468,17 +466,16 @@ OpenAssessment.ResponseView.prototype = { ...@@ -468,17 +466,16 @@ OpenAssessment.ResponseView.prototype = {
}, },
/** /**
Make the user confirm before submitting a response. Make the user confirm before submitting a response.
Returns: Returns:
JQuery deferred object, which is: JQuery deferred object, which is:
* resolved if the user confirms the submission * resolved if the user confirms the submission
* rejected if the user cancels the submission * rejected if the user cancels the submission
**/ **/
confirmSubmission: function() { confirmSubmission: function() {
// Keep this on one big line to avoid gettext bug: http://stackoverflow.com/a/24579117 // Keep this on one big line to avoid gettext bug: http://stackoverflow.com/a/24579117
/* jshint maxlen:300 */ var msg = gettext("You're about to submit your response for this assignment. After you submit this response, you can't change it or submit a new response."); // jscs:ignore maximumLineLength
var msg = gettext("You're about to submit your response for this assignment. After you submit this response, you can't change it or submit a new response.");
// TODO -- UI for confirmation dialog instead of JS confirm // TODO -- UI for confirmation dialog instead of JS confirm
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
if (confirm(msg)) { defer.resolve(); } if (confirm(msg)) { defer.resolve(); }
...@@ -492,11 +489,11 @@ OpenAssessment.ResponseView.prototype = { ...@@ -492,11 +489,11 @@ OpenAssessment.ResponseView.prototype = {
larger than the maximum file size. larger than the maximum file size.
Args: Args:
files (list): A collection of files used for upload. This function assumes files (list): A collection of files used for upload. This function assumes
there is only one file being uploaded at any time. This file must there is only one file being uploaded at any time. This file must
be less than 5 MB and an image, PDF or other allowed types. be less than 5 MB and an image, PDF or other allowed types.
uploadType (string): uploaded file type allowed, could be none, image, uploadType (string): uploaded file type allowed, could be none, image,
file or custom. file or custom.
**/ **/
prepareUpload: function(files, uploadType) { prepareUpload: function(files, uploadType) {
...@@ -536,7 +533,6 @@ OpenAssessment.ResponseView.prototype = { ...@@ -536,7 +533,6 @@ OpenAssessment.ResponseView.prototype = {
$("#file__upload").toggleClass("is--disabled", this.files === null); $("#file__upload").toggleClass("is--disabled", this.files === null);
}, },
/** /**
Manages file uploads for submission attachments. Retrieves a one-time Manages file uploads for submission attachments. Retrieves a one-time
upload URL from the server, and uses it to upload images to a designated upload URL from the server, and uses it to upload images to a designated
......
...@@ -11,7 +11,6 @@ OpenAssessment.Rubric = function(element) { ...@@ -11,7 +11,6 @@ OpenAssessment.Rubric = function(element) {
this.element = element; this.element = element;
}; };
OpenAssessment.Rubric.prototype = { OpenAssessment.Rubric.prototype = {
/** /**
Get or set per-criterion feedback. Get or set per-criterion feedback.
......
...@@ -16,7 +16,6 @@ OpenAssessment.SelfView = function(element, server, baseView) { ...@@ -16,7 +16,6 @@ OpenAssessment.SelfView = function(element, server, baseView) {
this.rubric = null; this.rubric = null;
}; };
OpenAssessment.SelfView.prototype = { OpenAssessment.SelfView.prototype = {
/** /**
......
...@@ -52,15 +52,15 @@ ...@@ -52,15 +52,15 @@
loadStudentInfo: function() { loadStudentInfo: function() {
var view = this; var view = this;
var sel = $('#openassessment__staff-tools', this.element); var sel = $('#openassessment__staff-tools', this.element);
var student_username = sel.find('#openassessment__student_username').val(); var studentUsername = sel.find('#openassessment__student_username').val();
this.server.studentInfo(student_username).done( this.server.studentInfo(studentUsername).done(
function(html) { function(html) {
// Load the HTML and install event handlers // Load the HTML and install event handlers
$('#openassessment__student-info', view.element).replaceWith(html); $('#openassessment__student-info', view.element).replaceWith(html);
// Install key handler for new staff grade Save button. // Install key handler for new staff grade Save button.
var selCancelSub = $('#openassessment__staff-info__cancel__submission', view.element); var selCancelSub = $('#openassessment__staff-info__cancel__submission', view.element);
selCancelSub.on('click', '#submit_cancel_submission', function (eventObject) { selCancelSub.on('click', '#submit_cancel_submission', function(eventObject) {
eventObject.preventDefault(); eventObject.preventDefault();
view.cancelSubmission($(this).data('submission-uuid')); view.cancelSubmission($(this).data('submission-uuid'));
} }
......
...@@ -16,7 +16,6 @@ OpenAssessment.StudentTrainingView = function(element, server, baseView) { ...@@ -16,7 +16,6 @@ OpenAssessment.StudentTrainingView = function(element, server, baseView) {
this.rubric = null; this.rubric = null;
}; };
OpenAssessment.StudentTrainingView.prototype = { OpenAssessment.StudentTrainingView.prototype = {
/** /**
......
/** /**
Encapsulate interactions with OpenAssessment XBlock handlers. Encapsulate interactions with OpenAssessment XBlock handlers.
**/ **/
// Since the server is included by both LMS and Studio views, // Since the server is included by both LMS and Studio views,
// skip loading it the second time. // skip loading it the second time.
if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
/** /**
Interface for server-side XBlock handlers. Interface for server-side XBlock handlers.
Args: Args:
runtime (Runtime): An XBlock runtime instance. runtime (Runtime): An XBlock runtime instance.
element (DOM element): The DOM element representing this XBlock. element (DOM element): The DOM element representing this XBlock.
Returns: Returns:
OpenAssessment.Server OpenAssessment.Server
**/ **/
OpenAssessment.Server = function(runtime, element) { OpenAssessment.Server = function(runtime, element) {
this.runtime = runtime; this.runtime = runtime;
this.element = element; this.element = element;
...@@ -26,35 +26,35 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -26,35 +26,35 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
OpenAssessment.Server.prototype = { OpenAssessment.Server.prototype = {
/** /**
Construct the URL for the handler, specific to one instance of the XBlock on the page. Construct the URL for the handler, specific to one instance of the XBlock on the page.
Args: Args:
handler (string): The name of the XBlock handler. handler (string): The name of the XBlock handler.
Returns: Returns:
URL (string) URL (string)
**/ **/
url: function(handler) { url: function(handler) {
return this.runtime.handlerUrl(this.element, handler); return this.runtime.handlerUrl(this.element, handler);
}, },
/** /**
Render the XBlock. Render the XBlock.
Args: Args:
component (string): The component to render. component (string): The component to render.
Returns: Returns:
A JQuery promise, which resolves with the HTML of the rendered XBlock A JQuery promise, which resolves with the HTML of the rendered XBlock
and fails with an error message. and fails with an error message.
Example: Example:
server.render('submission').done( server.render('submission').done(
function(html) { console.log(html); } function(html) { console.log(html); }
).fail( ).fail(
function(err) { console.log(err); } function(err) { console.log(err); }
) )
**/ **/
render: function(component) { render: function(component) {
var view = this; var view = this;
var url = this.url('render_' + component); var url = this.url('render_' + component);
...@@ -72,11 +72,11 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -72,11 +72,11 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
}, },
/** /**
Render Latex for all new DOM elements with class 'allow--latex'. Render Latex for all new DOM elements with class 'allow--latex'.
Args: Args:
element: The element to modify. element: The element to modify.
**/ **/
renderLatex: function(element) { renderLatex: function(element) {
element.filter(".allow--latex").each(function() { element.filter(".allow--latex").each(function() {
MathJax.Hub.Queue(['Typeset', MathJax.Hub, this]); MathJax.Hub.Queue(['Typeset', MathJax.Hub, this]);
...@@ -88,15 +88,15 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -88,15 +88,15 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
continue grading peers. continue grading peers.
Returns: Returns:
A JQuery promise, which resolves with the HTML of the rendered peer A JQuery promise, which resolves with the HTML of the rendered peer
assessment section or fails with an error message. assessment section or fails with an error message.
Example: Example:
server.render_continued_peer().done( server.render_continued_peer().done(
function(html) { console.log(html); } function(html) { console.log(html); }
).fail( ).fail(
function(err) { console.log(err); } function(err) { console.log(err); }
) )
**/ **/
renderContinuedPeer: function() { renderContinuedPeer: function() {
var view = this; var view = this;
...@@ -108,42 +108,42 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -108,42 +108,42 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
dataType: "html", dataType: "html",
data: {continue_grading: true} data: {continue_grading: true}
}).done(function(data) { }).done(function(data) {
defer.resolveWith(view, [data]); defer.resolveWith(view, [data]);
}).fail(function() { }).fail(function() {
defer.rejectWith(view, [gettext('This section could not be loaded.')]); defer.rejectWith(view, [gettext('This section could not be loaded.')]);
}); });
}).promise(); }).promise();
}, },
/** /**
Load the Student Info section in Staff Info. Load the Student Info section in Staff Info.
**/ **/
studentInfo: function(student_username) { studentInfo: function(studentUsername) {
var url = this.url('render_student_info'); var url = this.url('render_student_info');
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
$.ajax({ $.ajax({
url: url, url: url,
type: "POST", type: "POST",
dataType: "html", dataType: "html",
data: {student_username: student_username} data: {student_username: studentUsername}
}).done(function(data) { }).done(function(data) {
defer.resolveWith(this, [data]); defer.resolveWith(this, [data]);
}).fail(function() { }).fail(function() {
defer.rejectWith(this, [gettext('This section could not be loaded.')]); defer.rejectWith(this, [gettext('This section could not be loaded.')]);
}); });
}).promise(); }).promise();
}, },
/** /**
Send a submission to the XBlock. Send a submission to the XBlock.
Args: Args:
submission (string): The text of the student's submission. submission (string): The text of the student's submission.
Returns: Returns:
A JQuery promise, which resolves with the student's ID and attempt number A JQuery promise, which resolves with the student's ID and attempt number
if the call was successful and fails with an status code and error message otherwise. if the call was successful and fails with an status code and error message otherwise.
**/ **/
submit: function(submission) { submit: function(submission) {
var url = this.url('submit'); var url = this.url('submit');
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
...@@ -171,15 +171,15 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -171,15 +171,15 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
}, },
/** /**
Save a response without submitting it. Save a response without submitting it.
Args: Args:
submission (string): The text of the student's response. submission (string): The text of the student's response.
Returns: Returns:
A JQuery promise, which resolves with no arguments on success and A JQuery promise, which resolves with no arguments on success and
fails with an error message. fails with an error message.
**/ **/
save: function(submission) { save: function(submission) {
var url = this.url('save_submission'); var url = this.url('save_submission');
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
...@@ -216,14 +216,14 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -216,14 +216,14 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
* console.log("Error: " + errMsg); * console.log("Error: " + errMsg);
* }); * });
*/ */
submitFeedbackOnAssessment: function(text, options) { submitFeedbackOnAssessment: function(text, options) {
var url = this.url('submit_feedback'); var url = this.url('submit_feedback');
var payload = JSON.stringify({ var payload = JSON.stringify({
'feedback_text': text, 'feedback_text': text,
'feedback_options': options 'feedback_options': options
}); });
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
$.ajax({ type: "POST", url: url, data: payload, contentType: jsonContentType }).done( $.ajax({type: "POST", url: url, data: payload, contentType: jsonContentType}).done(
function(data) { function(data) {
if (data.success) { defer.resolve(); } if (data.success) { defer.resolve(); }
else { defer.rejectWith(this, [data.msg]); } else { defer.rejectWith(this, [data.msg]); }
...@@ -235,28 +235,28 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -235,28 +235,28 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
}, },
/** /**
Send a peer assessment to the XBlock. Send a peer assessment to the XBlock.
Args: Args:
optionsSelected (object literal): Keys are criteria names, optionsSelected (object literal): Keys are criteria names,
values are the option text the user selected for the criterion. values are the option text the user selected for the criterion.
criterionFeedback (object literal): Written feedback on a particular criterion, criterionFeedback (object literal): Written feedback on a particular criterion,
where keys are criteria names and values are the feedback strings. where keys are criteria names and values are the feedback strings.
overallFeedback (string): Written feedback on the submission as a whole. overallFeedback (string): Written feedback on the submission as a whole.
Returns: Returns:
A JQuery promise, which resolves with no args if successful A JQuery promise, which resolves with no args if successful
and fails with an error message otherise. and fails with an error message otherise.
Example: Example:
var options = { clarity: "Very clear", precision: "Somewhat precise" }; var options = { clarity: "Very clear", precision: "Somewhat precise" };
var criterionFeedback = { clarity: "The essay was very clear." }; var criterionFeedback = { clarity: "The essay was very clear." };
var overallFeedback = "Good job!"; var overallFeedback = "Good job!";
server.peerAssess(options, criterionFeedback, overallFeedback).done( server.peerAssess(options, criterionFeedback, overallFeedback).done(
function() { console.log("Success!"); } function() { console.log("Success!"); }
).fail( ).fail(
function(errorMsg) { console.log(errorMsg); } function(errorMsg) { console.log(errorMsg); }
); );
**/ **/
peerAssess: function(optionsSelected, criterionFeedback, overallFeedback, uuid) { peerAssess: function(optionsSelected, criterionFeedback, overallFeedback, uuid) {
var url = this.url('peer_assess'); var url = this.url('peer_assess');
var payload = JSON.stringify({ var payload = JSON.stringify({
...@@ -266,7 +266,7 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -266,7 +266,7 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
submission_uuid: uuid submission_uuid: uuid
}); });
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
$.ajax({ type: "POST", url: url, data: payload, contentType: jsonContentType }).done( $.ajax({type: "POST", url: url, data: payload, contentType: jsonContentType}).done(
function(data) { function(data) {
if (data.success) { if (data.success) {
defer.resolve(); defer.resolve();
...@@ -282,26 +282,26 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -282,26 +282,26 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
}, },
/** /**
Send a self-assessment to the XBlock. Send a self-assessment to the XBlock.
Args: Args:
optionsSelected (object literal): Keys are criteria names, optionsSelected (object literal): Keys are criteria names,
values are the option text the user selected for the criterion. values are the option text the user selected for the criterion.
var criterionFeedback = { clarity: "The essay was very clear." }; var criterionFeedback = { clarity: "The essay was very clear." };
var overallFeedback = "Good job!"; var overallFeedback = "Good job!";
Returns: Returns:
A JQuery promise, which resolves with no args if successful A JQuery promise, which resolves with no args if successful
and fails with an error message otherwise. and fails with an error message otherwise.
Example: Example:
var options = { clarity: "Very clear", precision: "Somewhat precise" }; var options = { clarity: "Very clear", precision: "Somewhat precise" };
server.selfAssess(options).done( server.selfAssess(options).done(
function() { console.log("Success!"); } function() { console.log("Success!"); }
).fail( ).fail(
function(errorMsg) { console.log(errorMsg); } function(errorMsg) { console.log(errorMsg); }
); );
**/ **/
selfAssess: function(optionsSelected, criterionFeedback, overallFeedback) { selfAssess: function(optionsSelected, criterionFeedback, overallFeedback) {
var url = this.url('self_assess'); var url = this.url('self_assess');
var payload = JSON.stringify({ var payload = JSON.stringify({
...@@ -310,7 +310,7 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -310,7 +310,7 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
overall_feedback: overallFeedback overall_feedback: overallFeedback
}); });
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
$.ajax({ type: "POST", url: url, data: payload, contentType: jsonContentType }).done( $.ajax({type: "POST", url: url, data: payload, contentType: jsonContentType}).done(
function(data) { function(data) {
if (data.success) { if (data.success) {
defer.resolve(); defer.resolve();
...@@ -326,32 +326,32 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -326,32 +326,32 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
}, },
/** /**
Assess an instructor-provided training example. Assess an instructor-provided training example.
Args: Args:
optionsSelected (object literal): Keys are criteria names, optionsSelected (object literal): Keys are criteria names,
values are the option text the user selected for the criterion. values are the option text the user selected for the criterion.
Returns: Returns:
A JQuery promise, which resolves with a list of corrections if A JQuery promise, which resolves with a list of corrections if
successful and fails with an error message otherwise. successful and fails with an error message otherwise.
Example: Example:
var options = { clarity: "Very clear", precision: "Somewhat precise" }; var options = { clarity: "Very clear", precision: "Somewhat precise" };
server.trainingAssess(options).done( server.trainingAssess(options).done(
function(corrections) { console.log("Success!"); } function(corrections) { console.log("Success!"); }
alert(corrections); alert(corrections);
).fail( ).fail(
function(errorMsg) { console.log(errorMsg); } function(errorMsg) { console.log(errorMsg); }
); );
**/ **/
trainingAssess: function(optionsSelected) { trainingAssess: function(optionsSelected) {
var url = this.url('training_assess'); var url = this.url('training_assess');
var payload = JSON.stringify({ var payload = JSON.stringify({
options_selected: optionsSelected options_selected: optionsSelected
}); });
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
$.ajax({ type: "POST", url: url, data: payload, contentType: jsonContentType }).done( $.ajax({type: "POST", url: url, data: payload, contentType: jsonContentType}).done(
function(data) { function(data) {
if (data.success) { if (data.success) {
defer.resolveWith(this, [data.corrections]); defer.resolveWith(this, [data.corrections]);
...@@ -367,25 +367,25 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -367,25 +367,25 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
}, },
/** /**
Schedules classifier training for Example Based Assessment for this Schedules classifier training for Example Based Assessment for this
Location. Location.
Returns: Returns:
A JQuery promise, which resolves with a message indicating the results A JQuery promise, which resolves with a message indicating the results
of the scheduling request. of the scheduling request.
Example: Example:
server.scheduleTraining().done( server.scheduleTraining().done(
function(msg) { console.log("Success!"); } function(msg) { console.log("Success!"); }
alert(msg); alert(msg);
).fail( ).fail(
function(errorMsg) { console.log(errorMsg); } function(errorMsg) { console.log(errorMsg); }
); );
**/ **/
scheduleTraining: function() { scheduleTraining: function() {
var url = this.url('schedule_training'); var url = this.url('schedule_training');
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
$.ajax({ type: "POST", url: url, data: "\"\"", contentType: jsonContentType}).done( $.ajax({type: "POST", url: url, data: "\"\"", contentType: jsonContentType}).done(
function(data) { function(data) {
if (data.success) { if (data.success) {
defer.resolveWith(this, [data.msg]); defer.resolveWith(this, [data.msg]);
...@@ -395,21 +395,21 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -395,21 +395,21 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
} }
} }
).fail(function() { ).fail(function() {
defer.rejectWith(this, [gettext('This assessment could not be submitted.')]); defer.rejectWith(this, [gettext('This assessment could not be submitted.')]);
}); });
}); });
}, },
/** /**
Reschedules grading tasks for example based assessments Reschedules grading tasks for example based assessments
Returns: Returns:
JQuery Promise which will resolve with a message indicating success or failure of the scheduling JQuery Promise which will resolve with a message indicating success or failure of the scheduling
**/ **/
rescheduleUnfinishedTasks: function() { rescheduleUnfinishedTasks: function() {
var url = this.url('reschedule_unfinished_tasks'); var url = this.url('reschedule_unfinished_tasks');
return $.Deferred(function(defer) { return $.Deferred(function(defer) {
$.ajax({ type: "POST", url: url, data: "\"\"", contentType: jsonContentType}).done( $.ajax({type: "POST", url: url, data: "\"\"", contentType: jsonContentType}).done(
function(data) { function(data) {
if (data.success) { if (data.success) {
defer.resolveWith(this, [data.msg]); defer.resolveWith(this, [data.msg]);
...@@ -419,34 +419,34 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -419,34 +419,34 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
} }
} }
).fail(function() { ).fail(function() {
defer.rejectWith(this, [gettext('One or more rescheduling tasks failed.')]); defer.rejectWith(this, [gettext('One or more rescheduling tasks failed.')]);
}); });
}); });
}, },
/** /**
Update the XBlock's XML definition on the server. Update the XBlock's XML definition on the server.
Kwargs: Kwargs:
title (string): The title of the problem. title (string): The title of the problem.
prompt (string): The question prompt. prompt (string): The question prompt.
feedbackPrompt (string): The directions to the student for giving overall feedback on a submission. feedbackPrompt (string): The directions to the student for giving overall feedback on a submission.
feedback_default_text (string): The default feedback text used as the student's feedback response feedback_default_text (string): The default feedback text used as the student's feedback response
submissionStart (ISO-formatted datetime string or null): The start date of the submission. submissionStart (ISO-formatted datetime string or null): The start date of the submission.
submissionDue (ISO-formatted datetime string or null): The date the submission is due. submissionDue (ISO-formatted datetime string or null): The date the submission is due.
criteria (list of object literals): The rubric criteria. criteria (list of object literals): The rubric criteria.
assessments (list of object literals): The assessments the student will be evaluated on. assessments (list of object literals): The assessments the student will be evaluated on.
fileUploadType (string): 'image' if image attachments are allowed, 'pdf-and-image' if pdf and fileUploadType (string): 'image' if image attachments are allowed, 'pdf-and-image' if pdf and
image attachments are allowed, 'custom' if file type is restricted by a white list. image attachments are allowed, 'custom' if file type is restricted by a white list.
fileTypeWhiteList (string): Comma separated file type white list fileTypeWhiteList (string): Comma separated file type white list
latexEnabled: TRUE if latex rendering is enabled. latexEnabled: TRUE if latex rendering is enabled.
leaderboardNum (int): The number of scores to show in the leaderboard. leaderboardNum (int): The number of scores to show in the leaderboard.
Returns: Returns:
A JQuery promise, which resolves with no arguments A JQuery promise, which resolves with no arguments
and fails with an error message. and fails with an error message.
**/ **/
updateEditorContext: function(kwargs) { updateEditorContext: function(kwargs) {
var url = this.url('update_editor_context'); var url = this.url('update_editor_context');
var payload = JSON.stringify({ var payload = JSON.stringify({
...@@ -477,20 +477,20 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -477,20 +477,20 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
}, },
/** /**
Check whether the XBlock has been released. Check whether the XBlock has been released.
Returns: Returns:
A JQuery promise, which resolves with a boolean indicating A JQuery promise, which resolves with a boolean indicating
whether the XBlock has been released. On failure, the promise whether the XBlock has been released. On failure, the promise
provides an error message. provides an error message.
Example: Example:
server.checkReleased().done( server.checkReleased().done(
function(isReleased) {} function(isReleased) {}
).fail( ).fail(
function(errMsg) {} function(errMsg) {}
) )
**/ **/
checkReleased: function() { checkReleased: function() {
var url = this.url('check_released'); var url = this.url('check_released');
var payload = "\"\""; var payload = "\"\"";
...@@ -511,12 +511,12 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -511,12 +511,12 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
submission. submission.
Args: Args:
contentType (str): The Content Type for the file being uploaded. contentType (str): The Content Type for the file being uploaded.
filename (str): The name of the file to be uploaded. filename (str): The name of the file to be uploaded.
Returns: Returns:
A presigned upload URL from the specified service used for uploading A presigned upload URL from the specified service used for uploading
files. files.
**/ **/
getUploadUrl: function(contentType, filename) { getUploadUrl: function(contentType, filename) {
...@@ -528,11 +528,11 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -528,11 +528,11 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
data: JSON.stringify({contentType: contentType, filename: filename}), data: JSON.stringify({contentType: contentType, filename: filename}),
contentType: jsonContentType contentType: jsonContentType
}).done(function(data) { }).done(function(data) {
if (data.success) { defer.resolve(data.url); } if (data.success) { defer.resolve(data.url); }
else { defer.rejectWith(this, [data.msg]); } else { defer.rejectWith(this, [data.msg]); }
}).fail(function() { }).fail(function() {
defer.rejectWith(this, [gettext('Could not retrieve upload url.')]); defer.rejectWith(this, [gettext('Could not retrieve upload url.')]);
}); });
}).promise(); }).promise();
}, },
...@@ -540,7 +540,7 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -540,7 +540,7 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
Get a download url used to download related files for the submission. Get a download url used to download related files for the submission.
Returns: Returns:
A temporary download URL for retrieving documents from s3. A temporary download URL for retrieving documents from s3.
**/ **/
getDownloadUrl: function() { getDownloadUrl: function() {
...@@ -549,28 +549,28 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) { ...@@ -549,28 +549,28 @@ if (typeof OpenAssessment.Server === "undefined" || !OpenAssessment.Server) {
$.ajax({ $.ajax({
type: "POST", url: url, data: JSON.stringify({}), contentType: jsonContentType type: "POST", url: url, data: JSON.stringify({}), contentType: jsonContentType
}).done(function(data) { }).done(function(data) {
if (data.success) { defer.resolve(data.url); } if (data.success) { defer.resolve(data.url); }
else { defer.rejectWith(this, [data.msg]); } else { defer.rejectWith(this, [data.msg]); }
}).fail(function() { }).fail(function() {
defer.rejectWith(this, [gettext('Could not retrieve download url.')]); defer.rejectWith(this, [gettext('Could not retrieve download url.')]);
}); });
}).promise(); }).promise();
}, },
/** /**
Cancel the submission from peer grading pool. Cancel the submission from peer grading pool.
Args: Args:
submissionUUID: ID for submission to be cancelled from pool. submissionUUID: ID for submission to be cancelled from pool.
comments: reason to cancel the submission comments: reason to cancel the submission
         **/          **/
cancelSubmission: function (submissionUUID, comments) { cancelSubmission: function(submissionUUID, comments) {
var url = this.url('cancel_submission'); var url = this.url('cancel_submission');
var payload = JSON.stringify({ var payload = JSON.stringify({
submission_uuid: submissionUUID, submission_uuid: submissionUUID,
comments: comments comments: comments
}); });
return $.Deferred(function (defer) { return $.Deferred(function(defer) {
$.ajax({ type: "POST", url: url, data: payload, contentType: jsonContentType }).done( $.ajax({type: "POST", url: url, data: payload, contentType: jsonContentType}).done(
function(data) { function(data) {
if (data.success) { if (data.success) {
defer.resolveWith(this, [data.msg]); defer.resolveWith(this, [data.msg]);
......
/** /**
JavaScript shared between all open assessment modules. JavaScript shared between all open assessment modules.
WARNING: Don't add anything to this file until you're
absolutely sure there isn't a way to encapsulate it in
an object!
**/
WARNING: Don't add anything to this file until you're
absolutely sure there isn't a way to encapsulate it in
an object!
**/
/* Namespace for open assessment */ /* Namespace for open assessment */
/* jshint ignore:start */ /* jshint ignore:start */
...@@ -14,25 +13,22 @@ if (typeof OpenAssessment == "undefined" || !OpenAssessment) { ...@@ -14,25 +13,22 @@ if (typeof OpenAssessment == "undefined" || !OpenAssessment) {
} }
/* jshint ignore:end */ /* jshint ignore:end */
// Stub gettext if the runtime doesn't provide it // Stub gettext if the runtime doesn't provide it
if (typeof window.gettext === 'undefined') { if (typeof window.gettext === 'undefined') {
window.gettext = function(text) { return text; }; window.gettext = function(text) { return text; };
} }
// If ngettext isn't found (workbench, testing, etc.), return the simplistic english version // If ngettext isn't found (workbench, testing, etc.), return the simplistic english version
if (typeof window.ngetgext === 'undefined') { if (typeof window.ngetgext === 'undefined') {
window.ngettext = function (singular_text, plural_text, n) { window.ngettext = function(singularText, pluralText, n) {
if (n > 1) { if (n > 1) {
return plural_text; return pluralText;
} else { } else {
return singular_text; return singularText;
} }
}; };
} }
// Stub event logging if the runtime doesn't provide it // Stub event logging if the runtime doesn't provide it
if (typeof window.Logger === 'undefined') { if (typeof window.Logger === 'undefined') {
window.Logger = { window.Logger = {
...@@ -40,7 +36,6 @@ if (typeof window.Logger === 'undefined') { ...@@ -40,7 +36,6 @@ if (typeof window.Logger === 'undefined') {
}; };
} }
// Stub MathJax is the runtime doesn't provide it // Stub MathJax is the runtime doesn't provide it
if (typeof window.MathJax === 'undefined') { if (typeof window.MathJax === 'undefined') {
window.MathJax = { window.MathJax = {
...@@ -49,4 +44,4 @@ if (typeof window.MathJax === 'undefined') { ...@@ -49,4 +44,4 @@ if (typeof window.MathJax === 'undefined') {
Queue: function() {} Queue: function() {}
} }
}; };
} }
\ No newline at end of file
...@@ -92,7 +92,7 @@ OpenAssessment.Container.prototype = { ...@@ -92,7 +92,7 @@ OpenAssessment.Container.prototype = {
// Find items already in the container and install click // Find items already in the container and install click
// handlers for the delete buttons. // handlers for the delete buttons.
$("." + this.removeButtonClass, this.containerElement).click( $("." + this.removeButtonClass, this.containerElement).click(
function (eventData) { function(eventData) {
var item = container.createContainerItem(eventData.target); var item = container.createContainerItem(eventData.target);
container.remove(item); container.remove(item);
} }
...@@ -137,7 +137,7 @@ OpenAssessment.Container.prototype = { ...@@ -137,7 +137,7 @@ OpenAssessment.Container.prototype = {
// Install a click handler for the delete button // Install a click handler for the delete button
if (this.addRemoveEnabled) { if (this.addRemoveEnabled) {
containerItem.find('.' + this.removeButtonClass) containerItem.find('.' + this.removeButtonClass)
.click(function (eventData) { .click(function(eventData) {
var containerItem = container.createContainerItem(eventData.target); var containerItem = container.createContainerItem(eventData.target);
container.remove(containerItem); container.remove(containerItem);
}); });
...@@ -176,7 +176,7 @@ OpenAssessment.Container.prototype = { ...@@ -176,7 +176,7 @@ OpenAssessment.Container.prototype = {
array: The values representing each container item. array: The values representing each container item.
**/ **/
getItemValues: function () { getItemValues: function() {
var values = []; var values = [];
var container = this; var container = this;
......
...@@ -35,7 +35,7 @@ OpenAssessment.ItemUtilities = { ...@@ -35,7 +35,7 @@ OpenAssessment.ItemUtilities = {
var label = $(element).attr('data-label'); var label = $(element).attr('data-label');
var name = $(element).val(); var name = $(element).val();
// We don't want the lack of a label to make it look like - 1 points. // We don't want the lack of a label to make it look like - 1 points.
if (label === ""){ if (label === "") {
label = gettext('Unnamed Option'); label = gettext('Unnamed Option');
} }
var singularString = label + " - " + points + " point"; var singularString = label + " - " + points + " point";
...@@ -65,16 +65,16 @@ OpenAssessment.ItemUtilities = { ...@@ -65,16 +65,16 @@ OpenAssessment.ItemUtilities = {
}; };
/** /**
The Prompt Class is used to construct and maintain references to prompts from within a prompts The Prompt Class is used to construct and maintain references to prompts from within a prompts
container object. Constructs a new Prompt element. container object. Constructs a new Prompt element.
Args: Args:
element (OpenAssessment.Container): The container that the prompt is a member of. element (OpenAssessment.Container): The container that the prompt is a member of.
notifier (OpenAssessment.Notifier): Used to send notifications of updates to prompts. notifier (OpenAssessment.Notifier): Used to send notifications of updates to prompts.
Returns: Returns:
OpenAssessment.Prompt OpenAssessment.Prompt
**/ **/
OpenAssessment.Prompt = function(element, notifier) { OpenAssessment.Prompt = function(element, notifier) {
this.element = element; this.element = element;
this.notifier = notifier; this.notifier = notifier;
...@@ -82,15 +82,15 @@ OpenAssessment.Prompt = function(element, notifier) { ...@@ -82,15 +82,15 @@ OpenAssessment.Prompt = function(element, notifier) {
OpenAssessment.Prompt.prototype = { OpenAssessment.Prompt.prototype = {
/** /**
Finds the values currently entered in the Prompts's fields, and returns them. Finds the values currently entered in the Prompts's fields, and returns them.
Returns: Returns:
object literal of the form: object literal of the form:
{ {
'description': 'Write a nice long essay about anything.' 'description': 'Write a nice long essay about anything.'
} }
**/ **/
getFieldValues: function () { getFieldValues: function() {
var fields = { var fields = {
description: this.description() description: this.description()
}; };
...@@ -98,15 +98,15 @@ OpenAssessment.Prompt.prototype = { ...@@ -98,15 +98,15 @@ OpenAssessment.Prompt.prototype = {
}, },
/** /**
Get or set the description of the prompt. Get or set the description of the prompt.
Args: Args:
text (string, optional): If provided, set the description of the prompt. text (string, optional): If provided, set the description of the prompt.
Returns: Returns:
string string
**/ **/
description: function(text) { description: function(text) {
var sel = $('.openassessment_prompt_description', this.element); var sel = $('.openassessment_prompt_description', this.element);
return OpenAssessment.Fields.stringField(sel, text); return OpenAssessment.Fields.stringField(sel, text);
...@@ -115,10 +115,10 @@ OpenAssessment.Prompt.prototype = { ...@@ -115,10 +115,10 @@ OpenAssessment.Prompt.prototype = {
addEventListeners: function() {}, addEventListeners: function() {},
/** /**
Hook into the event handler for addition of a prompt. Hook into the event handler for addition of a prompt.
*/ */
addHandler: function (){ addHandler: function() {
this.notifier.notificationFired( this.notifier.notificationFired(
"promptAdd", "promptAdd",
{ {
...@@ -128,10 +128,10 @@ OpenAssessment.Prompt.prototype = { ...@@ -128,10 +128,10 @@ OpenAssessment.Prompt.prototype = {
}, },
/** /**
Hook into the event handler for removal of a prompt. Hook into the event handler for removal of a prompt.
*/ */
removeHandler: function (){ removeHandler: function() {
this.notifier.notificationFired( this.notifier.notificationFired(
"promptRemove", "promptRemove",
{ {
...@@ -143,75 +143,75 @@ OpenAssessment.Prompt.prototype = { ...@@ -143,75 +143,75 @@ OpenAssessment.Prompt.prototype = {
updateHandler: function() {}, updateHandler: function() {},
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the option is valid. Boolean indicating whether the option is valid.
**/ **/
validate: function() { validate: function() {
return true; return true;
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of strings list of strings
**/ **/
validationErrors: function() { validationErrors: function() {
return []; return [];
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() {} clearValidationErrors: function() {}
}; };
/** /**
The RubricOption Class used to construct and maintain references to rubric options from within an options The RubricOption Class used to construct and maintain references to rubric options from within an options
container object. Constructs a new RubricOption element. container object. Constructs a new RubricOption element.
Args: Args:
element (OpenAssessment.Container): The container that the option is a member of. element (OpenAssessment.Container): The container that the option is a member of.
notifier (OpenAssessment.Notifier): Used to send notifications of updates to rubric options. notifier (OpenAssessment.Notifier): Used to send notifications of updates to rubric options.
Returns: Returns:
OpenAssessment.RubricOption OpenAssessment.RubricOption
**/ **/
OpenAssessment.RubricOption = function(element, notifier) { OpenAssessment.RubricOption = function(element, notifier) {
this.element = element; this.element = element;
this.notifier = notifier; this.notifier = notifier;
this.pointsField = new OpenAssessment.IntField( this.pointsField = new OpenAssessment.IntField(
$(".openassessment_criterion_option_points", this.element), $(".openassessment_criterion_option_points", this.element),
{ min: 0, max: 999 } {min: 0, max: 999}
); );
}; };
OpenAssessment.RubricOption.prototype = { OpenAssessment.RubricOption.prototype = {
/** /**
Adds event listeners specific to this container item. Adds event listeners specific to this container item.
**/ **/
addEventListeners: function() { addEventListeners: function() {
// Install a focus out handler for container changes. // Install a focus out handler for container changes.
$(this.element).focusout($.proxy(this.updateHandler, this)); $(this.element).focusout($.proxy(this.updateHandler, this));
}, },
/** /**
Finds the values currently entered in the Option's fields, and returns them. Finds the values currently entered in the Option's fields, and returns them.
Returns: Returns:
object literal of the form: object literal of the form:
{ {
'name': 'Real Bad', 'name': 'Real Bad',
'points': 1, 'points': 1,
'explanation': 'Essay was primarily composed of emojis.' 'explanation': 'Essay was primarily composed of emojis.'
} }
**/ **/
getFieldValues: function () { getFieldValues: function() {
var fields = { var fields = {
label: this.label(), label: this.label(),
points: this.points(), points: this.points(),
...@@ -230,45 +230,45 @@ OpenAssessment.RubricOption.prototype = { ...@@ -230,45 +230,45 @@ OpenAssessment.RubricOption.prototype = {
}, },
/** /**
Get or set the label of the option. Get or set the label of the option.
Args: Args:
label (string, optional): If provided, set the label to this string. label (string, optional): If provided, set the label to this string.
Returns: Returns:
string string
**/ **/
label: function(label) { label: function(label) {
var sel = $('.openassessment_criterion_option_label', this.element); var sel = $('.openassessment_criterion_option_label', this.element);
return OpenAssessment.Fields.stringField(sel, label); return OpenAssessment.Fields.stringField(sel, label);
}, },
/** /**
Get or set the point value of the option. Get or set the point value of the option.
Args: Args:
points (int, optional): If provided, set the point value of the option. points (int, optional): If provided, set the point value of the option.
Returns: Returns:
int int
**/ **/
points: function(points) { points: function(points) {
if (points !== undefined) { this.pointsField.set(points); } if (points !== undefined) { this.pointsField.set(points); }
return this.pointsField.get(); return this.pointsField.get();
}, },
/** /**
Get or set the explanation for the option. Get or set the explanation for the option.
Args: Args:
explanation (string, optional): If provided, set the explanation to this string. explanation (string, optional): If provided, set the explanation to this string.
Returns: Returns:
string string
**/ **/
explanation: function(explanation) { explanation: function(explanation) {
var sel = $('.openassessment_criterion_option_explanation', this.element); var sel = $('.openassessment_criterion_option_explanation', this.element);
return OpenAssessment.Fields.stringField(sel, explanation); return OpenAssessment.Fields.stringField(sel, explanation);
...@@ -278,7 +278,7 @@ OpenAssessment.RubricOption.prototype = { ...@@ -278,7 +278,7 @@ OpenAssessment.RubricOption.prototype = {
Hook into the event handler for addition of a criterion option. Hook into the event handler for addition of a criterion option.
*/ */
addHandler: function (){ addHandler: function() {
var criterionElement = $(this.element).closest(".openassessment_criterion"); var criterionElement = $(this.element).closest(".openassessment_criterion");
var criterionName = $(criterionElement).data('criterion'); var criterionName = $(criterionElement).data('criterion');
...@@ -310,7 +310,7 @@ OpenAssessment.RubricOption.prototype = { ...@@ -310,7 +310,7 @@ OpenAssessment.RubricOption.prototype = {
Hook into the event handler for removal of a criterion option. Hook into the event handler for removal of a criterion option.
*/ */
removeHandler: function (){ removeHandler: function() {
var criterionName = $(this.element).data('criterion'); var criterionName = $(this.element).data('criterion');
var optionName = $(this.element).data('option'); var optionName = $(this.element).data('option');
this.notifier.notificationFired( this.notifier.notificationFired(
...@@ -327,7 +327,7 @@ OpenAssessment.RubricOption.prototype = { ...@@ -327,7 +327,7 @@ OpenAssessment.RubricOption.prototype = {
modified. modified.
*/ */
updateHandler: function(){ updateHandler: function() {
var fields = this.getFieldValues(); var fields = this.getFieldValues();
var criterionName = $(this.element).data('criterion'); var criterionName = $(this.element).data('criterion');
var optionName = $(this.element).data('option'); var optionName = $(this.element).data('option');
...@@ -345,47 +345,47 @@ OpenAssessment.RubricOption.prototype = { ...@@ -345,47 +345,47 @@ OpenAssessment.RubricOption.prototype = {
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the option is valid. Boolean indicating whether the option is valid.
**/ **/
validate: function() { validate: function() {
return this.pointsField.validate(); return this.pointsField.validate();
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var hasError = (this.pointsField.validationErrors().length > 0); var hasError = (this.pointsField.validationErrors().length > 0);
return hasError ? ["Option points are invalid"] : []; return hasError ? ["Option points are invalid"] : [];
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
this.pointsField.clearValidationErrors(); this.pointsField.clearValidationErrors();
} }
}; };
/** /**
The RubricCriterion Class is used to construct and get information from a rubric element within The RubricCriterion Class is used to construct and get information from a rubric element within
the DOM. the DOM.
Args: Args:
element (JQuery Object): The selection which describes the scope of the criterion. element (JQuery Object): The selection which describes the scope of the criterion.
notifier (OpenAssessment.Notifier): Used to send notifications of updates to rubric criteria. notifier (OpenAssessment.Notifier): Used to send notifications of updates to rubric criteria.
Returns: Returns:
OpenAssessment.RubricCriterion OpenAssessment.RubricCriterion
**/ **/
OpenAssessment.RubricCriterion = function(element, notifier) { OpenAssessment.RubricCriterion = function(element, notifier) {
this.element = element; this.element = element;
...@@ -404,13 +404,12 @@ OpenAssessment.RubricCriterion = function(element, notifier) { ...@@ -404,13 +404,12 @@ OpenAssessment.RubricCriterion = function(element, notifier) {
); );
}; };
OpenAssessment.RubricCriterion.prototype = { OpenAssessment.RubricCriterion.prototype = {
/** /**
Invoked by the container to add event listeners to all child containers Invoked by the container to add event listeners to all child containers
of this item, and add event listeners specific to this container item. of this item, and add event listeners specific to this container item.
**/ **/
addEventListeners: function() { addEventListeners: function() {
this.optionContainer.addEventListeners(); this.optionContainer.addEventListeners();
// Install a focus out handler for container changes. // Install a focus out handler for container changes.
...@@ -418,25 +417,25 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -418,25 +417,25 @@ OpenAssessment.RubricCriterion.prototype = {
}, },
/** /**
Finds the values currently entered in the Criterion's fields, and returns them. Finds the values currently entered in the Criterion's fields, and returns them.
Returns: Returns:
object literal of the form: object literal of the form:
{ {
'name': 'Emoji Content', 'name': 'Emoji Content',
'prompt': 'How expressive was the author with their words, and how much did they rely on emojis?', 'prompt': 'How expressive was the author with their words, and how much did they rely on emojis?',
'feedback': 'optional', 'feedback': 'optional',
'options': [ 'options': [
{ {
'name': 'Real Bad', 'name': 'Real Bad',
'points': 1, 'points': 1,
'explanation': 'Essay was primarily composed of emojis.' 'explanation': 'Essay was primarily composed of emojis.'
}, },
... ...
] ]
} }
**/ **/
getFieldValues: function () { getFieldValues: function() {
var fields = { var fields = {
label: this.label(), label: this.label(),
prompt: this.prompt(), prompt: this.prompt(),
...@@ -456,49 +455,49 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -456,49 +455,49 @@ OpenAssessment.RubricCriterion.prototype = {
}, },
/** /**
Get or set the label of the criterion. Get or set the label of the criterion.
Args: Args:
label (string, optional): If provided, set the label to this string. label (string, optional): If provided, set the label to this string.
Returns: Returns:
string string
**/ **/
label: function(label) { label: function(label) {
return OpenAssessment.Fields.stringField(this.labelSel, label); return OpenAssessment.Fields.stringField(this.labelSel, label);
}, },
/** /**
Get or set the prompt of the criterion. Get or set the prompt of the criterion.
Args: Args:
prompt (string, optional): If provided, set the prompt to this string. prompt (string, optional): If provided, set the prompt to this string.
Returns: Returns:
string string
**/ **/
prompt: function(prompt) { prompt: function(prompt) {
return OpenAssessment.Fields.stringField(this.promptSel, prompt); return OpenAssessment.Fields.stringField(this.promptSel, prompt);
}, },
/** /**
Get the feedback value for the criterion. Get the feedback value for the criterion.
This is one of: "disabled", "optional", or "required". This is one of: "disabled", "optional", or "required".
Returns: Returns:
string string
**/ **/
feedback: function() { feedback: function() {
return $('.openassessment_criterion_feedback', this.element).val(); return $('.openassessment_criterion_feedback', this.element).val();
}, },
/** /**
Add an option to the criterion. Add an option to the criterion.
Uses the client-side template to create the new option. Uses the client-side template to create the new option.
**/ **/
addOption: function() { addOption: function() {
this.optionContainer.add(); this.optionContainer.add();
}, },
...@@ -507,7 +506,7 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -507,7 +506,7 @@ OpenAssessment.RubricCriterion.prototype = {
Hook into the event handler for addition of a criterion. Hook into the event handler for addition of a criterion.
*/ */
addHandler: function (){ addHandler: function() {
var criteria = $(".openassessment_criterion", this.element.parent()); var criteria = $(".openassessment_criterion", this.element.parent());
// Create the unique name for this option. // Create the unique name for this option.
var name = OpenAssessment.ItemUtilities.createUniqueName(criteria, "data-criterion"); var name = OpenAssessment.ItemUtilities.createUniqueName(criteria, "data-criterion");
...@@ -520,7 +519,7 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -520,7 +519,7 @@ OpenAssessment.RubricCriterion.prototype = {
Hook into the event handler for removal of a criterion. Hook into the event handler for removal of a criterion.
*/ */
removeHandler: function(){ removeHandler: function() {
var criterionName = $(this.element).data('criterion'); var criterionName = $(this.element).data('criterion');
this.notifier.notificationFired("criterionRemove", {'criterionName': criterionName}); this.notifier.notificationFired("criterionRemove", {'criterionName': criterionName});
}, },
...@@ -529,7 +528,7 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -529,7 +528,7 @@ OpenAssessment.RubricCriterion.prototype = {
Hook into the event handler when a rubric criterion is modified. Hook into the event handler when a rubric criterion is modified.
*/ */
updateHandler: function(){ updateHandler: function() {
var fields = this.getFieldValues(); var fields = this.getFieldValues();
var criterionName = fields.name; var criterionName = fields.name;
var criterionLabel = fields.label; var criterionLabel = fields.label;
...@@ -540,12 +539,12 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -540,12 +539,12 @@ OpenAssessment.RubricCriterion.prototype = {
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the criterion is valid. Boolean indicating whether the criterion is valid.
**/ **/
validate: function() { validate: function() {
// The criterion prompt is required. // The criterion prompt is required.
var isValid = (this.prompt() !== ""); var isValid = (this.prompt() !== "");
...@@ -561,14 +560,14 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -561,14 +560,14 @@ OpenAssessment.RubricCriterion.prototype = {
return isValid; return isValid;
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
...@@ -586,8 +585,8 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -586,8 +585,8 @@ OpenAssessment.RubricCriterion.prototype = {
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
// Clear criterion prompt errors // Clear criterion prompt errors
this.promptSel.removeClass("openassessment_highlighted_field"); this.promptSel.removeClass("openassessment_highlighted_field");
...@@ -599,18 +598,17 @@ OpenAssessment.RubricCriterion.prototype = { ...@@ -599,18 +598,17 @@ OpenAssessment.RubricCriterion.prototype = {
} }
}; };
/** /**
The TrainingExample class is used to construct and retrieve information from its element within the DOM The TrainingExample class is used to construct and retrieve information from its element within the DOM
Args: Args:
element (JQuery Object): the selection which identifies the scope of the training example. element (JQuery Object): the selection which identifies the scope of the training example.
Returns: Returns:
OpenAssessment.TrainingExample OpenAssessment.TrainingExample
**/ **/
OpenAssessment.TrainingExample = function(element){ OpenAssessment.TrainingExample = function(element) {
this.element = element; this.element = element;
this.criteria = $(".openassessment_training_example_criterion_option", this.element); this.criteria = $(".openassessment_training_example_criterion_option", this.element);
this.answer = $('.openassessment_training_example_essay_part textarea', this.element); this.answer = $('.openassessment_training_example_essay_part textarea', this.element);
...@@ -620,12 +618,12 @@ OpenAssessment.TrainingExample.prototype = { ...@@ -620,12 +618,12 @@ OpenAssessment.TrainingExample.prototype = {
/** /**
Returns the values currently stored in the fields associated with this training example. Returns the values currently stored in the fields associated with this training example.
**/ **/
getFieldValues: function () { getFieldValues: function() {
// Iterates through all of the options selected by the training example, and adds them // Iterates through all of the options selected by the training example, and adds them
// to a list. // to a list.
var optionsSelected = this.criteria.map( var optionsSelected = this.criteria.map(
function () { function() {
return { return {
criterion: $(this).data('criterion'), criterion: $(this).data('criterion'),
option: $(this).prop('value') option: $(this).prop('value')
...@@ -643,8 +641,8 @@ OpenAssessment.TrainingExample.prototype = { ...@@ -643,8 +641,8 @@ OpenAssessment.TrainingExample.prototype = {
addHandler: function() { addHandler: function() {
// Goes through and instantiates the option description in the training example for each option. // Goes through and instantiates the option description in the training example for each option.
$(".openassessment_training_example_criterion_option", this.element) .each( function () { $(".openassessment_training_example_criterion_option", this.element) .each(function() {
$('option', this).each(function(){ $('option', this).each(function() {
OpenAssessment.ItemUtilities.refreshOptionString($(this)); OpenAssessment.ItemUtilities.refreshOptionString($(this));
}); });
}); });
...@@ -654,12 +652,12 @@ OpenAssessment.TrainingExample.prototype = { ...@@ -654,12 +652,12 @@ OpenAssessment.TrainingExample.prototype = {
updateHandler: function() {}, updateHandler: function() {},
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the criterion is valid. Boolean indicating whether the criterion is valid.
**/ **/
validate: function() { validate: function() {
var isValid = true; var isValid = true;
...@@ -678,13 +676,13 @@ OpenAssessment.TrainingExample.prototype = { ...@@ -678,13 +676,13 @@ OpenAssessment.TrainingExample.prototype = {
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
this.criteria.each( this.criteria.each(
...@@ -699,15 +697,15 @@ OpenAssessment.TrainingExample.prototype = { ...@@ -699,15 +697,15 @@ OpenAssessment.TrainingExample.prototype = {
}, },
/** /**
Retrieve all elements representing items in this container. Retrieve all elements representing items in this container.
Returns: Returns:
array of container item objects array of container item objects
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
this.criteria.each( this.criteria.each(
function() { $(this).removeClass("openassessment_highlighted_field"); } function() { $(this).removeClass("openassessment_highlighted_field"); }
); );
} }
}; };
\ No newline at end of file
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
The constructor initializes the DOM for editing. The constructor initializes the DOM for editing.
Args: Args:
runtime (Runtime): an XBlock runtime instance. runtime (Runtime): an XBlock runtime instance.
element (DOM element): The DOM element representing this XBlock. element (DOM element): The DOM element representing this XBlock.
server (OpenAssessment.Server): The interface to the XBlock server. server (OpenAssessment.Server): The interface to the XBlock server.
data (Object literal): The data object passed from XBlock backend. data (Object literal): The data object passed from XBlock backend.
Returns: Returns:
OpenAssessment.StudioView OpenAssessment.StudioView
**/ **/
OpenAssessment.StudioView = function(runtime, element, server, data) { OpenAssessment.StudioView = function(runtime, element, server, data) {
this.element = element; this.element = element;
...@@ -63,7 +63,7 @@ OpenAssessment.StudioView = function(runtime, element, server, data) { ...@@ -63,7 +63,7 @@ OpenAssessment.StudioView = function(runtime, element, server, data) {
// Initialize the rubric tab view // Initialize the rubric tab view
this.rubricView = new OpenAssessment.EditRubricView( this.rubricView = new OpenAssessment.EditRubricView(
$("#oa_rubric_editor_wrapper", this.element).get(0), $("#oa_rubric_editor_wrapper", this.element).get(0),
new OpenAssessment.Notifier([ new OpenAssessment.Notifier([
studentTrainingListener studentTrainingListener
]) ])
); );
...@@ -76,9 +76,9 @@ OpenAssessment.StudioView = function(runtime, element, server, data) { ...@@ -76,9 +76,9 @@ OpenAssessment.StudioView = function(runtime, element, server, data) {
OpenAssessment.StudioView.prototype = { OpenAssessment.StudioView.prototype = {
/** /**
Adjusts the modal's height, position and padding to be larger for OA editing only (Does not impact other modals) Adjusts the modal's height, position and padding to be larger for OA editing only (Does not impact other modals)
**/ **/
fixModalHeight: function () { fixModalHeight: function() {
// Add the full height class to every element from the XBlock // Add the full height class to every element from the XBlock
// to the modal window in Studio. // to the modal window in Studio.
$(this.element) $(this.element)
...@@ -93,14 +93,14 @@ OpenAssessment.StudioView.prototype = { ...@@ -93,14 +93,14 @@ OpenAssessment.StudioView.prototype = {
}, },
/** /**
Initializes the tabs that seperate the sections of the editor. Initializes the tabs that seperate the sections of the editor.
Because this function relies on the OpenAssessment Name space, the tab that it first Because this function relies on the OpenAssessment Name space, the tab that it first
active will be the one that the USER was presented with, regardless of which editor they active will be the one that the USER was presented with, regardless of which editor they
were using. I.E. If I leave Editor A in the settings state, and enter editor B, editor B were using. I.E. If I leave Editor A in the settings state, and enter editor B, editor B
will automatically open with the settings state. will automatically open with the settings state.
**/ **/
initializeTabs: function() { initializeTabs: function() {
// If this is the first editor that the user has opened, default to the prompt view. // If this is the first editor that the user has opened, default to the prompt view.
if (typeof(OpenAssessment.lastOpenEditingTab) === "undefined") { if (typeof(OpenAssessment.lastOpenEditingTab) === "undefined") {
...@@ -124,10 +124,10 @@ OpenAssessment.StudioView.prototype = { ...@@ -124,10 +124,10 @@ OpenAssessment.StudioView.prototype = {
}, },
/** /**
Save the problem's XML definition to the server. Save the problem's XML definition to the server.
If the problem has been released, make the user confirm the save. If the problem has been released, make the user confirm the save.
**/ **/
save: function () { save: function() {
var view = this; var view = this;
this.saveTabState(); this.saveTabState();
...@@ -154,7 +154,7 @@ OpenAssessment.StudioView.prototype = { ...@@ -154,7 +154,7 @@ OpenAssessment.StudioView.prototype = {
// Check whether the problem has been released; if not, // Check whether the problem has been released; if not,
// warn the user and allow them to cancel. // warn the user and allow them to cancel.
this.server.checkReleased().done( this.server.checkReleased().done(
function (isReleased) { function(isReleased) {
if (isReleased) { if (isReleased) {
view.confirmPostReleaseUpdate($.proxy(view.updateEditorContext, view)); view.confirmPostReleaseUpdate($.proxy(view.updateEditorContext, view));
} }
...@@ -162,30 +162,30 @@ OpenAssessment.StudioView.prototype = { ...@@ -162,30 +162,30 @@ OpenAssessment.StudioView.prototype = {
view.updateEditorContext(); view.updateEditorContext();
} }
} }
).fail(function (errMsg) { ).fail(function(errMsg) {
view.showError(errMsg); view.showError(errMsg);
}); });
} }
}, },
/** /**
Make the user confirm that he/she wants to update a problem Make the user confirm that he/she wants to update a problem
that has already been released. that has already been released.
Args: Args:
onConfirm (function): A function that accepts no arguments, onConfirm (function): A function that accepts no arguments,
executed if the user confirms the update. executed if the user confirms the update.
**/ **/
confirmPostReleaseUpdate: function (onConfirm) { confirmPostReleaseUpdate: function(onConfirm) {
var msg = gettext("This problem has already been released. Any changes will apply only to future assessments."); var msg = gettext("This problem has already been released. Any changes will apply only to future assessments.");
// TODO: classier confirm dialog // TODO: classier confirm dialog
if (confirm(msg)) { onConfirm(); } if (confirm(msg)) { onConfirm(); }
}, },
/** /**
Save the updated problem definition to the server. Save the updated problem definition to the server.
**/ **/
updateEditorContext: function () { updateEditorContext: function() {
// Notify the client-side runtime that we are starting // Notify the client-side runtime that we are starting
// to save so it can show the "Saving..." notification // to save so it can show the "Saving..." notification
this.runtime.notify('save', {state: 'start'}); this.runtime.notify('save', {state: 'start'});
...@@ -209,16 +209,16 @@ OpenAssessment.StudioView.prototype = { ...@@ -209,16 +209,16 @@ OpenAssessment.StudioView.prototype = {
// Notify the client-side runtime that we finished saving // Notify the client-side runtime that we finished saving
// so it can hide the "Saving..." notification. // so it can hide the "Saving..." notification.
// Then reload the view. // Then reload the view.
function () { view.runtime.notify('save', {state: 'end'}); } function() { view.runtime.notify('save', {state: 'end'}); }
).fail( ).fail(
function (msg) { view.showError(msg); } function(msg) { view.showError(msg); }
); );
}, },
/** /**
Cancel editing. Cancel editing.
**/ **/
cancel: function () { cancel: function() {
// Notify the client-side runtime so it will close the editing modal // Notify the client-side runtime so it will close the editing modal
this.saveTabState(); this.saveTabState();
this.runtime.notify('cancel', {}); this.runtime.notify('cancel', {});
...@@ -228,19 +228,19 @@ OpenAssessment.StudioView.prototype = { ...@@ -228,19 +228,19 @@ OpenAssessment.StudioView.prototype = {
Display an error message to the user. Display an error message to the user.
Args: Args:
errorMsg (string): The error message to display. errorMsg (string): The error message to display.
**/ **/
showError: function (errorMsg) { showError: function(errorMsg) {
this.runtime.notify('error', {msg: errorMsg}); this.runtime.notify('error', {msg: errorMsg});
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the view is valid. Boolean indicating whether the view is valid.
**/ **/
validate: function() { validate: function() {
var settingsValid = this.settingsView.validate(); var settingsValid = this.settingsView.validate();
var rubricValid = this.rubricView.validate(); var rubricValid = this.rubricView.validate();
...@@ -248,14 +248,14 @@ OpenAssessment.StudioView.prototype = { ...@@ -248,14 +248,14 @@ OpenAssessment.StudioView.prototype = {
return settingsValid && rubricValid && promptsValid; return settingsValid && rubricValid && promptsValid;
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
return this.settingsView.validationErrors().concat( return this.settingsView.validationErrors().concat(
this.rubricView.validationErrors().concat( this.rubricView.validationErrors().concat(
...@@ -265,23 +265,22 @@ OpenAssessment.StudioView.prototype = { ...@@ -265,23 +265,22 @@ OpenAssessment.StudioView.prototype = {
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
this.settingsView.clearValidationErrors(); this.settingsView.clearValidationErrors();
this.rubricView.clearValidationErrors(); this.rubricView.clearValidationErrors();
this.promptsView.clearValidationErrors(); this.promptsView.clearValidationErrors();
}, }
}; };
/* XBlock entry point for Studio view */ /* XBlock entry point for Studio view */
/* jshint unused:false */ /* jshint unused:false */
function OpenAssessmentEditor(runtime, element, data) { function OpenAssessmentEditor(runtime, element, data) {
/** /**
Initialize the editing interface on page load. Initialize the editing interface on page load.
**/ **/
var server = new OpenAssessment.Server(runtime, element); var server = new OpenAssessment.Server(runtime, element);
new OpenAssessment.StudioView(runtime, element, server, data); new OpenAssessment.StudioView(runtime, element, server, data);
} }
/** /**
Interface for editing peer assessment settings. Interface for editing peer assessment settings.
Args: Args:
element (DOM element): The DOM element representing this view. element (DOM element): The DOM element representing this view.
Returns: Returns:
OpenAssessment.EditPeerAssessmentView OpenAssessment.EditPeerAssessmentView
**/ **/
OpenAssessment.EditPeerAssessmentView = function(element) { OpenAssessment.EditPeerAssessmentView = function(element) {
this.element = element; this.element = element;
this.name = "peer-assessment"; this.name = "peer-assessment";
this.mustGradeField = new OpenAssessment.IntField( this.mustGradeField = new OpenAssessment.IntField(
$("#peer_assessment_must_grade", this.element), $("#peer_assessment_must_grade", this.element),
{ min: 0, max: 99 } {min: 0, max: 99}
); );
this.mustBeGradedByField = new OpenAssessment.IntField( this.mustBeGradedByField = new OpenAssessment.IntField(
$("#peer_assessment_graded_by", this.element), $("#peer_assessment_graded_by", this.element),
{ min: 0, max: 99 } {min: 0, max: 99}
); );
// Configure the toggle checkbox to enable/disable this assessment // Configure the toggle checkbox to enable/disable this assessment
...@@ -47,20 +47,20 @@ OpenAssessment.EditPeerAssessmentView = function(element) { ...@@ -47,20 +47,20 @@ OpenAssessment.EditPeerAssessmentView = function(element) {
OpenAssessment.EditPeerAssessmentView.prototype = { OpenAssessment.EditPeerAssessmentView.prototype = {
/** /**
Return a description of the assessment. Return a description of the assessment.
Returns: Returns:
object literal object literal
Example usage: Example usage:
>>> editPeerView.description(); >>> editPeerView.description();
{ {
must_grade: 5, must_grade: 5,
must_be_graded_by: 2, must_be_graded_by: 2,
start: null, start: null,
due: "2014-04-1T00:00" due: "2014-04-1T00:00"
} }
**/ **/
description: function() { description: function() {
return { return {
must_grade: this.mustGradeNum(), must_grade: this.mustGradeNum(),
...@@ -71,100 +71,100 @@ OpenAssessment.EditPeerAssessmentView.prototype = { ...@@ -71,100 +71,100 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
}, },
/** /**
Get or set whether the assessment is enabled. Get or set whether the assessment is enabled.
Args: Args:
isEnabled (boolean, optional): If provided, set the enabled state of the assessment. isEnabled (boolean, optional): If provided, set the enabled state of the assessment.
Returns: Returns:
boolean boolean
***/ ***/
isEnabled: function(isEnabled) { isEnabled: function(isEnabled) {
var sel = $("#include_peer_assessment", this.element); var sel = $("#include_peer_assessment", this.element);
return OpenAssessment.Fields.booleanField(sel, isEnabled); return OpenAssessment.Fields.booleanField(sel, isEnabled);
}, },
/** /**
Toggle whether the assessment is enabled or disabled. Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing. This triggers the actual click event and is mainly useful for testing.
**/ **/
toggleEnabled: function() { toggleEnabled: function() {
$("#include_peer_assessment", this.element).click(); $("#include_peer_assessment", this.element).click();
}, },
/** /**
Get or set the required number of submissions a student must peer-assess. Get or set the required number of submissions a student must peer-assess.
Args: Args:
num (int, optional): If provided, set the required number of assessments. num (int, optional): If provided, set the required number of assessments.
Returns: Returns:
int int
**/ **/
mustGradeNum: function(num) { mustGradeNum: function(num) {
if (num !== undefined) { this.mustGradeField.set(num); } if (num !== undefined) { this.mustGradeField.set(num); }
return this.mustGradeField.get(); return this.mustGradeField.get();
}, },
/** /**
Get or set the required number of peer-assessments a student must receive. Get or set the required number of peer-assessments a student must receive.
Args: Args:
num (int, optional): If provided, set the required number of assessments. num (int, optional): If provided, set the required number of assessments.
Returns: Returns:
int int
**/ **/
mustBeGradedByNum: function(num) { mustBeGradedByNum: function(num) {
if (num !== undefined) { this.mustBeGradedByField.set(num); } if (num !== undefined) { this.mustBeGradedByField.set(num); }
return this.mustBeGradedByField.get(); return this.mustBeGradedByField.get();
}, },
/** /**
Get or set the start date and time of the assessment. Get or set the start date and time of the assessment.
Args: Args:
dateString (string, optional): If provided, set the date (YY-MM-DD). dateString (string, optional): If provided, set the date (YY-MM-DD).
timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock). timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).
Returns: Returns:
string (ISO-formatted UTC datetime) string (ISO-formatted UTC datetime)
**/ **/
startDatetime: function(dateString, timeString) { startDatetime: function(dateString, timeString) {
return this.startDatetimeControl.datetime(dateString, timeString); return this.startDatetimeControl.datetime(dateString, timeString);
}, },
/** /**
Get or set the due date and time of the assessment. Get or set the due date and time of the assessment.
Args: Args:
dateString (string, optional): If provided, set the date (YY-MM-DD). dateString (string, optional): If provided, set the date (YY-MM-DD).
timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock). timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).
Returns: Returns:
string (ISO-formatted UTC datetime) string (ISO-formatted UTC datetime)
**/ **/
dueDatetime: function(dateString, timeString) { dueDatetime: function(dateString, timeString) {
return this.dueDatetimeControl.datetime(dateString, timeString); return this.dueDatetimeControl.datetime(dateString, timeString);
}, },
/** /**
Gets the ID of the assessment Gets the ID of the assessment
Returns: Returns:
string (CSS ID of the Element object) string (CSS ID of the Element object)
**/ **/
getID: function() { getID: function() {
return $(this.element).attr('id'); return $(this.element).attr('id');
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the view is valid. Boolean indicating whether the view is valid.
**/ **/
validate: function() { validate: function() {
var startValid = this.startDatetimeControl.validate(); var startValid = this.startDatetimeControl.validate();
var dueValid = this.dueDatetimeControl.validate(); var dueValid = this.dueDatetimeControl.validate();
...@@ -173,14 +173,14 @@ OpenAssessment.EditPeerAssessmentView.prototype = { ...@@ -173,14 +173,14 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
return startValid && dueValid && mustGradeValid && mustBeGradedByValid; return startValid && dueValid && mustGradeValid && mustBeGradedByValid;
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
if (this.startDatetimeControl.validationErrors().length > 0) { if (this.startDatetimeControl.validationErrors().length > 0) {
...@@ -192,15 +192,15 @@ OpenAssessment.EditPeerAssessmentView.prototype = { ...@@ -192,15 +192,15 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
if (this.mustGradeField.validationErrors().length > 0) { if (this.mustGradeField.validationErrors().length > 0) {
errors.push("Peer assessment must grade is invalid"); errors.push("Peer assessment must grade is invalid");
} }
if(this.mustBeGradedByField.validationErrors().length > 0) { if (this.mustBeGradedByField.validationErrors().length > 0) {
errors.push("Peer assessment must be graded by is invalid"); errors.push("Peer assessment must be graded by is invalid");
} }
return errors; return errors;
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
this.startDatetimeControl.clearValidationErrors(); this.startDatetimeControl.clearValidationErrors();
this.dueDatetimeControl.clearValidationErrors(); this.dueDatetimeControl.clearValidationErrors();
...@@ -209,17 +209,16 @@ OpenAssessment.EditPeerAssessmentView.prototype = { ...@@ -209,17 +209,16 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
}, },
}; };
/** /**
Interface for editing self assessment settings. Interface for editing self assessment settings.
Args: Args:
element (DOM element): The DOM element representing this view. element (DOM element): The DOM element representing this view.
Returns: Returns:
OpenAssessment.EditSelfAssessmentView OpenAssessment.EditSelfAssessmentView
**/ **/
OpenAssessment.EditSelfAssessmentView = function(element) { OpenAssessment.EditSelfAssessmentView = function(element) {
this.element = element; this.element = element;
this.name = "self-assessment"; this.name = "self-assessment";
...@@ -251,19 +250,19 @@ OpenAssessment.EditSelfAssessmentView = function(element) { ...@@ -251,19 +250,19 @@ OpenAssessment.EditSelfAssessmentView = function(element) {
OpenAssessment.EditSelfAssessmentView.prototype = { OpenAssessment.EditSelfAssessmentView.prototype = {
/** /**
Return a description of the assessment. Return a description of the assessment.
Returns: Returns:
object literal object literal
Example usage: Example usage:
>>> editSelfView.description(); >>> editSelfView.description();
{ {
start: null, start: null,
due: "2014-04-1T00:00" due: "2014-04-1T00:00"
} }
**/ **/
description: function() { description: function() {
return { return {
start: this.startDatetime(), start: this.startDatetime(),
...@@ -272,86 +271,86 @@ OpenAssessment.EditSelfAssessmentView.prototype = { ...@@ -272,86 +271,86 @@ OpenAssessment.EditSelfAssessmentView.prototype = {
}, },
/** /**
Get or set whether the assessment is enabled. Get or set whether the assessment is enabled.
Args: Args:
isEnabled (boolean, optional): If provided, set the enabled state of the assessment. isEnabled (boolean, optional): If provided, set the enabled state of the assessment.
Returns: Returns:
boolean boolean
***/ ***/
isEnabled: function(isEnabled) { isEnabled: function(isEnabled) {
var sel = $("#include_self_assessment", this.element); var sel = $("#include_self_assessment", this.element);
return OpenAssessment.Fields.booleanField(sel, isEnabled); return OpenAssessment.Fields.booleanField(sel, isEnabled);
}, },
/** /**
Toggle whether the assessment is enabled or disabled. Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing. This triggers the actual click event and is mainly useful for testing.
**/ **/
toggleEnabled: function() { toggleEnabled: function() {
$("#include_self_assessment", this.element).click(); $("#include_self_assessment", this.element).click();
}, },
/** /**
Get or set the start date and time of the assessment. Get or set the start date and time of the assessment.
Args: Args:
dateString (string, optional): If provided, set the date (YY-MM-DD). dateString (string, optional): If provided, set the date (YY-MM-DD).
timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock). timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).
Returns: Returns:
string (ISO-formatted UTC datetime) string (ISO-formatted UTC datetime)
**/ **/
startDatetime: function(dateString, timeString) { startDatetime: function(dateString, timeString) {
return this.startDatetimeControl.datetime(dateString, timeString); return this.startDatetimeControl.datetime(dateString, timeString);
}, },
/** /**
Get or set the due date and time of the assessment. Get or set the due date and time of the assessment.
Args: Args:
dateString (string, optional): If provided, set the date (YY-MM-DD). dateString (string, optional): If provided, set the date (YY-MM-DD).
timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock). timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).
Returns: Returns:
string (ISO-formatted UTC datetime) string (ISO-formatted UTC datetime)
**/ **/
dueDatetime: function(dateString, timeString) { dueDatetime: function(dateString, timeString) {
return this.dueDatetimeControl.datetime(dateString, timeString); return this.dueDatetimeControl.datetime(dateString, timeString);
}, },
/** /**
Gets the ID of the assessment Gets the ID of the assessment
Returns: Returns:
string (CSS ID of the Element object) string (CSS ID of the Element object)
**/ **/
getID: function() { getID: function() {
return $(this.element).attr('id'); return $(this.element).attr('id');
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the view is valid. Boolean indicating whether the view is valid.
**/ **/
validate: function() { validate: function() {
var startValid = this.startDatetimeControl.validate(); var startValid = this.startDatetimeControl.validate();
var dueValid = this.dueDatetimeControl.validate(); var dueValid = this.dueDatetimeControl.validate();
return startValid && dueValid; return startValid && dueValid;
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
if (this.startDatetimeControl.validationErrors().length > 0) { if (this.startDatetimeControl.validationErrors().length > 0) {
...@@ -364,8 +363,8 @@ OpenAssessment.EditSelfAssessmentView.prototype = { ...@@ -364,8 +363,8 @@ OpenAssessment.EditSelfAssessmentView.prototype = {
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
this.startDatetimeControl.clearValidationErrors(); this.startDatetimeControl.clearValidationErrors();
this.dueDatetimeControl.clearValidationErrors(); this.dueDatetimeControl.clearValidationErrors();
...@@ -373,15 +372,15 @@ OpenAssessment.EditSelfAssessmentView.prototype = { ...@@ -373,15 +372,15 @@ OpenAssessment.EditSelfAssessmentView.prototype = {
}; };
/** /**
Interface for editing self assessment settings. Interface for editing self assessment settings.
Args: Args:
element (DOM element): The DOM element representing this view. element (DOM element): The DOM element representing this view.
Returns: Returns:
OpenAssessment.EditStudentTrainingView OpenAssessment.EditStudentTrainingView
**/ **/
OpenAssessment.EditStudentTrainingView = function(element) { OpenAssessment.EditStudentTrainingView = function(element) {
this.element = element; this.element = element;
this.name = "student-training"; this.name = "student-training";
...@@ -411,32 +410,32 @@ OpenAssessment.EditStudentTrainingView = function(element) { ...@@ -411,32 +410,32 @@ OpenAssessment.EditStudentTrainingView = function(element) {
OpenAssessment.EditStudentTrainingView.prototype = { OpenAssessment.EditStudentTrainingView.prototype = {
/** /**
Return a description of the assessment. Return a description of the assessment.
Returns: Returns:
object literal object literal
Example usage: Example usage:
>>> editTrainingView.description(); >>> editTrainingView.description();
{ {
examples: [ examples: [
{ {
answer: ("I love pokemon 1", "I love pokemon 2"), answer: ("I love pokemon 1", "I love pokemon 2"),
options_selected: [ options_selected: [
{ {
criterion: "brevity", criterion: "brevity",
option: "suberb" option: "suberb"
}, },
criterion: "accuracy", criterion: "accuracy",
option: "alright" option: "alright"
} }
... ...
] ]
}, },
... ...
] ]
} }
**/ **/
description: function() { description: function() {
return { return {
examples: this.exampleContainer.getItemValues() examples: this.exampleContainer.getItemValues()
...@@ -444,44 +443,44 @@ OpenAssessment.EditStudentTrainingView.prototype = { ...@@ -444,44 +443,44 @@ OpenAssessment.EditStudentTrainingView.prototype = {
}, },
/** /**
Get or set whether the assessment is enabled. Get or set whether the assessment is enabled.
Args: Args:
isEnabled (boolean, optional): If provided, set the enabled state of the assessment. isEnabled (boolean, optional): If provided, set the enabled state of the assessment.
Returns: Returns:
boolean boolean
***/ ***/
isEnabled: function(isEnabled) { isEnabled: function(isEnabled) {
var sel = $("#include_student_training", this.element); var sel = $("#include_student_training", this.element);
return OpenAssessment.Fields.booleanField(sel, isEnabled); return OpenAssessment.Fields.booleanField(sel, isEnabled);
}, },
/** /**
Toggle whether the assessment is enabled or disabled. Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing. This triggers the actual click event and is mainly useful for testing.
**/ **/
toggleEnabled: function() { toggleEnabled: function() {
$("#include_student_training", this.element).click(); $("#include_student_training", this.element).click();
}, },
/** /**
Gets the ID of the assessment Gets the ID of the assessment
Returns: Returns:
string (CSS ID of the Element object) string (CSS ID of the Element object)
**/ **/
getID: function() { getID: function() {
return $(this.element).attr('id'); return $(this.element).attr('id');
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the view is valid. Boolean indicating whether the view is valid.
**/ **/
validate: function() { validate: function() {
var isValid = true; var isValid = true;
...@@ -493,13 +492,13 @@ OpenAssessment.EditStudentTrainingView.prototype = { ...@@ -493,13 +492,13 @@ OpenAssessment.EditStudentTrainingView.prototype = {
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
$.each(this.exampleContainer.getAllItems(), function() { $.each(this.exampleContainer.getAllItems(), function() {
...@@ -509,8 +508,8 @@ OpenAssessment.EditStudentTrainingView.prototype = { ...@@ -509,8 +508,8 @@ OpenAssessment.EditStudentTrainingView.prototype = {
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
$.each(this.exampleContainer.getAllItems(), function() { $.each(this.exampleContainer.getAllItems(), function() {
this.clearValidationErrors(); this.clearValidationErrors();
...@@ -518,24 +517,24 @@ OpenAssessment.EditStudentTrainingView.prototype = { ...@@ -518,24 +517,24 @@ OpenAssessment.EditStudentTrainingView.prototype = {
}, },
/** /**
Adds a new training example by copying the training example template. Adds a new training example by copying the training example template.
Primarily used for testing. Primarily used for testing.
**/ **/
addTrainingExample: function() { addTrainingExample: function() {
this.exampleContainer.add(); this.exampleContainer.add();
} }
}; };
/** /**
Interface for editing example-based assessment settings. Interface for editing example-based assessment settings.
Args: Args:
element (DOM element): The DOM element representing this view. element (DOM element): The DOM element representing this view.
Returns: Returns:
OpenAssessment.EditExampleBasedAssessmentView OpenAssessment.EditExampleBasedAssessmentView
**/ **/
OpenAssessment.EditExampleBasedAssessmentView = function(element) { OpenAssessment.EditExampleBasedAssessmentView = function(element) {
this.element = element; this.element = element;
this.name = "example-based-assessment"; this.name = "example-based-assessment";
...@@ -553,18 +552,18 @@ OpenAssessment.EditExampleBasedAssessmentView = function(element) { ...@@ -553,18 +552,18 @@ OpenAssessment.EditExampleBasedAssessmentView = function(element) {
OpenAssessment.EditExampleBasedAssessmentView.prototype = { OpenAssessment.EditExampleBasedAssessmentView.prototype = {
/** /**
Return a description of the assessment. Return a description of the assessment.
Returns: Returns:
object literal object literal
Example usage: Example usage:
>>> editTrainingView.description(); >>> editTrainingView.description();
{ {
examples_xml: "XML DEFINITION HERE", examples_xml: "XML DEFINITION HERE",
} }
**/ **/
description: function() { description: function() {
return { return {
examples_xml: this.exampleDefinitions() examples_xml: this.exampleDefinitions()
...@@ -572,53 +571,53 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = { ...@@ -572,53 +571,53 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = {
}, },
/** /**
Get or set whether the assessment is enabled. Get or set whether the assessment is enabled.
Args: Args:
isEnabled (boolean, optional): If provided, set the enabled state of the assessment. isEnabled (boolean, optional): If provided, set the enabled state of the assessment.
Returns: Returns:
boolean boolean
***/ ***/
isEnabled: function(isEnabled) { isEnabled: function(isEnabled) {
var sel = $("#include_ai_assessment", this.element); var sel = $("#include_ai_assessment", this.element);
return OpenAssessment.Fields.booleanField(sel, isEnabled); return OpenAssessment.Fields.booleanField(sel, isEnabled);
}, },
/** /**
Toggle whether the assessment is enabled or disabled. Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing. This triggers the actual click event and is mainly useful for testing.
**/ **/
toggleEnabled: function() { toggleEnabled: function() {
$("#include_ai_assessment", this.element).click(); $("#include_ai_assessment", this.element).click();
}, },
/** /**
Get or set the XML defining the training examples. Get or set the XML defining the training examples.
Args: Args:
xml (string, optional): The XML of the training example definitions. xml (string, optional): The XML of the training example definitions.
Returns: Returns:
string string
**/ **/
exampleDefinitions: function(xml) { exampleDefinitions: function(xml) {
var sel = $("#ai_training_examples", this.element); var sel = $("#ai_training_examples", this.element);
return OpenAssessment.Fields.stringField(sel, xml); return OpenAssessment.Fields.stringField(sel, xml);
}, },
/** /**
Gets the ID of the assessment Gets the ID of the assessment
Returns: Returns:
string (CSS ID of the Element object) string (CSS ID of the Element object)
**/ **/
getID: function() { getID: function() {
return $(this.element).attr('id'); return $(this.element).attr('id');
}, },
validate: function() { return true; }, validate: function() { return true; },
validationErrors: function() { return []; }, validationErrors: function() { return []; },
clearValidationErrors: function() {}, clearValidationErrors: function() {}
}; };
\ No newline at end of file
/** /**
Utilities for reading / writing fields. Utilities for reading / writing fields.
**/ **/
OpenAssessment.Fields = { OpenAssessment.Fields = {
stringField: function(sel, value) { stringField: function(sel, value) {
if (value !== undefined) { sel.val(value); } if (value !== undefined) { sel.val(value); }
...@@ -10,21 +10,20 @@ OpenAssessment.Fields = { ...@@ -10,21 +10,20 @@ OpenAssessment.Fields = {
booleanField: function(sel, value) { booleanField: function(sel, value) {
if (value !== undefined) { sel.prop("checked", value); } if (value !== undefined) { sel.prop("checked", value); }
return sel.prop("checked"); return sel.prop("checked");
}, }
}; };
/** /**
Integer input. Integer input.
Args: Args:
inputSel (JQuery selector or DOM element): The input field. inputSel (JQuery selector or DOM element): The input field.
Keyword args: Keyword args:
min (int): The minimum value allowed in the input. min (int): The minimum value allowed in the input.
max (int): The maximum value allowed in the input. max (int): The maximum value allowed in the input.
**/ **/
OpenAssessment.IntField = function(inputSel, restrictions) { OpenAssessment.IntField = function(inputSel, restrictions) {
this.max = restrictions.max; this.max = restrictions.max;
this.min = restrictions.min; this.min = restrictions.min;
...@@ -34,39 +33,39 @@ OpenAssessment.IntField = function(inputSel, restrictions) { ...@@ -34,39 +33,39 @@ OpenAssessment.IntField = function(inputSel, restrictions) {
OpenAssessment.IntField.prototype = { OpenAssessment.IntField.prototype = {
/** /**
Retrieve the integer value from the input. Retrieve the integer value from the input.
Decimal values will be truncated, and non-numeric Decimal values will be truncated, and non-numeric
values will become NaN. values will become NaN.
Returns: Returns:
integer or NaN integer or NaN
**/ **/
get: function() { get: function() {
return parseInt(this.input.val().trim(), 10); return parseInt(this.input.val().trim(), 10);
}, },
/** /**
Set the input value. Set the input value.
Args: Args:
val (int or string) val (int or string)
**/ **/
set: function(val) { set: function(val) {
this.input.val(val); this.input.val(val);
}, },
/** /**
Mark validation errors if the field does not satisfy the restrictions. Mark validation errors if the field does not satisfy the restrictions.
Fractional values are not considered valid integers. Fractional values are not considered valid integers.
This will trim whitespace from the field, so " 34 " would be considered This will trim whitespace from the field, so " 34 " would be considered
a valid input. a valid input.
Returns: Returns:
Boolean indicating whether the field's value is valid. Boolean indicating whether the field's value is valid.
**/ **/
validate: function() { validate: function() {
var value = this.get(); var value = this.get();
var isValid = !isNaN(value) && value >= this.min && value <= this.max; var isValid = !isNaN(value) && value >= this.min && value <= this.max;
...@@ -83,41 +82,40 @@ OpenAssessment.IntField.prototype = { ...@@ -83,41 +82,40 @@ OpenAssessment.IntField.prototype = {
}, },
/** /**
Clear any validation errors from the UI. Clear any validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
this.input.removeClass("openassessment_highlighted_field"); this.input.removeClass("openassessment_highlighted_field");
}, },
/** /**
Return a list of validation errors currently displayed Return a list of validation errors currently displayed
in the UI. Mainly useful for testing. in the UI. Mainly useful for testing.
Returns: Returns:
list of strings list of strings
**/ **/
validationErrors: function() { validationErrors: function() {
var hasError = this.input.hasClass("openassessment_highlighted_field"); var hasError = this.input.hasClass("openassessment_highlighted_field");
return hasError ? ["Int field is invalid"] : []; return hasError ? ["Int field is invalid"] : [];
}, }
}; };
/** /**
Show and hide elements based on a checkbox. Show and hide elements based on a checkbox.
Args: Args:
checkboxSel (JQuery selector): The checkbox used to toggle whether sections checkboxSel (JQuery selector): The checkbox used to toggle whether sections
are shown or hidden. are shown or hidden.
shownSel (JQuery selector): The section to show when the checkbox is checked. shownSel (JQuery selector): The section to show when the checkbox is checked.
hiddenSel (JQuery selector): The section to show when the checkbox is unchecked. hiddenSel (JQuery selector): The section to show when the checkbox is unchecked.
notifier (OpenAssessment.Notifier): Receives notifications when the checkbox state changes. notifier (OpenAssessment.Notifier): Receives notifications when the checkbox state changes.
Sends the following notifications: Sends the following notifications:
* toggleOn * toggleOn
* toggleOff * toggleOff
**/ **/
OpenAssessment.ToggleControl = function(checkboxSel, shownSel, hiddenSel, notifier) { OpenAssessment.ToggleControl = function(checkboxSel, shownSel, hiddenSel, notifier) {
this.checkbox = checkboxSel; this.checkbox = checkboxSel;
this.shownSection = shownSel; this.shownSection = shownSel;
...@@ -127,15 +125,15 @@ OpenAssessment.ToggleControl = function(checkboxSel, shownSel, hiddenSel, notifi ...@@ -127,15 +125,15 @@ OpenAssessment.ToggleControl = function(checkboxSel, shownSel, hiddenSel, notifi
OpenAssessment.ToggleControl.prototype = { OpenAssessment.ToggleControl.prototype = {
/** /**
Install the event handler for the checkbox, Install the event handler for the checkbox,
passing in the toggle control object as the event data. passing in the toggle control object as the event data.
Args: Args:
checkboxSelector (string): The CSS selector string for the checkbox. checkboxSelector (string): The CSS selector string for the checkbox.
Returns: Returns:
OpenAssessment.ToggleControl OpenAssessment.ToggleControl
**/ **/
install: function() { install: function() {
this.checkbox.change( this.checkbox.change(
this, function(event) { this, function(event) {
...@@ -164,16 +162,15 @@ OpenAssessment.ToggleControl.prototype = { ...@@ -164,16 +162,15 @@ OpenAssessment.ToggleControl.prototype = {
} }
}; };
/** /**
Date and time input fields. Date and time input fields.
Args: Args:
element (DOM element): The parent element of the control inputs. element (DOM element): The parent element of the control inputs.
datePicker (string): The CSS selector for the date input field. datePicker (string): The CSS selector for the date input field.
timePicker (string): The CSS selector for the time input field. timePicker (string): The CSS selector for the time input field.
**/ **/
OpenAssessment.DatetimeControl = function(element, datePicker, timePicker) { OpenAssessment.DatetimeControl = function(element, datePicker, timePicker) {
this.element = element; this.element = element;
this.datePicker = datePicker; this.datePicker = datePicker;
...@@ -182,15 +179,15 @@ OpenAssessment.DatetimeControl = function(element, datePicker, timePicker) { ...@@ -182,15 +179,15 @@ OpenAssessment.DatetimeControl = function(element, datePicker, timePicker) {
OpenAssessment.DatetimeControl.prototype = { OpenAssessment.DatetimeControl.prototype = {
/** /**
Configure the date and time picker inputs. Configure the date and time picker inputs.
Returns: Returns:
OpenAssessment.DatetimeControl OpenAssessment.DatetimeControl
**/ **/
install: function() { install: function() {
var dateString = $(this.datePicker, this.element).val(); var dateString = $(this.datePicker, this.element).val();
$(this.datePicker, this.element).datepicker({ showButtonPanel: true }) $(this.datePicker, this.element).datepicker({showButtonPanel: true})
.datepicker("option", "dateFormat", "yy-mm-dd") .datepicker("option", "dateFormat", "yy-mm-dd")
.datepicker("setDate", dateString); .datepicker("setDate", dateString);
$(this.timePicker, this.element).timepicker({ $(this.timePicker, this.element).timepicker({
...@@ -201,16 +198,16 @@ OpenAssessment.DatetimeControl.prototype = { ...@@ -201,16 +198,16 @@ OpenAssessment.DatetimeControl.prototype = {
}, },
/** /**
Get or set the date and time. Get or set the date and time.
Args: Args:
dateString (string, optional): If provided, set the date (YYYY-MM-DD). dateString (string, optional): If provided, set the date (YYYY-MM-DD).
timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock). timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).
Returns: Returns:
ISO-formatted datetime string. ISO-formatted datetime string.
**/ **/
datetime: function(dateString, timeString) { datetime: function(dateString, timeString) {
var datePickerSel = $(this.datePicker, this.element); var datePickerSel = $(this.datePicker, this.element);
var timePickerSel = $(this.timePicker, this.element); var timePickerSel = $(this.timePicker, this.element);
...@@ -220,12 +217,12 @@ OpenAssessment.DatetimeControl.prototype = { ...@@ -220,12 +217,12 @@ OpenAssessment.DatetimeControl.prototype = {
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the fields are valid. Boolean indicating whether the fields are valid.
**/ **/
validate: function() { validate: function() {
var dateString = $(this.datePicker, this.element).val(); var dateString = $(this.datePicker, this.element).val();
var timeString = $(this.timePicker, this.element).val(); var timeString = $(this.timePicker, this.element).val();
...@@ -247,7 +244,7 @@ OpenAssessment.DatetimeControl.prototype = { ...@@ -247,7 +244,7 @@ OpenAssessment.DatetimeControl.prototype = {
//time validation //time validation
var matches = timeString.match(/^\d{2}:\d{2}$/g); var matches = timeString.match(/^\d{2}:\d{2}$/g);
var isTimeValid = (matches !== null); var isTimeValid = (matches !== null);
if(!isTimeValid) { if (!isTimeValid) {
$(this.timePicker, this.element).addClass("openassessment_highlighted_field"); $(this.timePicker, this.element).addClass("openassessment_highlighted_field");
} }
...@@ -255,21 +252,21 @@ OpenAssessment.DatetimeControl.prototype = { ...@@ -255,21 +252,21 @@ OpenAssessment.DatetimeControl.prototype = {
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
$(this.datePicker, this.element).removeClass("openassessment_highlighted_field"); $(this.datePicker, this.element).removeClass("openassessment_highlighted_field");
$(this.timePicker, this.element).removeClass("openassessment_highlighted_field"); $(this.timePicker, this.element).removeClass("openassessment_highlighted_field");
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
var dateHasError = $(this.datePicker, this.element).hasClass("openassessment_highlighted_field"); var dateHasError = $(this.datePicker, this.element).hasClass("openassessment_highlighted_field");
...@@ -279,24 +276,23 @@ OpenAssessment.DatetimeControl.prototype = { ...@@ -279,24 +276,23 @@ OpenAssessment.DatetimeControl.prototype = {
if (timeHasError) { errors.push("Time is invalid"); } if (timeHasError) { errors.push("Time is invalid"); }
return errors; return errors;
}, }
}; };
/** /**
Show and hide elements based on select options. Show and hide elements based on select options.
Args: Args:
selectSel (JQuery selector): The select used to toggle whether sections selectSel (JQuery selector): The select used to toggle whether sections
are shown or hidden. are shown or hidden.
mapping (Object): A mapping object that is used to specify the relationship mapping (Object): A mapping object that is used to specify the relationship
between option and section. e.g. between option and section. e.g.
{ {
option1: selector1, option1: selector1,
option2: selector2, option2: selector2,
} }
When an option is selected, the section is shown and all other sections will be hidden. When an option is selected, the section is shown and all other sections will be hidden.
notifier (OpenAssessment.Notifier): Receives notifications when the select state changes. notifier (OpenAssessment.Notifier): Receives notifications when the select state changes.
Sends the following notifications: Sends the following notifications:
* selectionChanged * selectionChanged
...@@ -343,9 +339,9 @@ OpenAssessment.SelectControl.prototype = { ...@@ -343,9 +339,9 @@ OpenAssessment.SelectControl.prototype = {
This is similar to string field but allow you to pass in a custom validation function to validate the input field. This is similar to string field but allow you to pass in a custom validation function to validate the input field.
Args: Args:
inputSel (JQuery selector or DOM element): The input field. inputSel (JQuery selector or DOM element): The input field.
validator (callable): The callback for custom validation function. The function should accept validator (callable): The callback for custom validation function. The function should accept
one parameter for the value of the input and returns an array of errors strings. If not error, return []. one parameter for the value of the input and returns an array of errors strings. If not error, return [].
*/ */
OpenAssessment.InputControl = function(inputSel, validator) { OpenAssessment.InputControl = function(inputSel, validator) {
this.input = $(inputSel); this.input = $(inputSel);
...@@ -359,7 +355,7 @@ OpenAssessment.InputControl.prototype = { ...@@ -359,7 +355,7 @@ OpenAssessment.InputControl.prototype = {
Retrieve the string value from the input. Retrieve the string value from the input.
Returns: Returns:
string string
**/ **/
get: function() { get: function() {
return this.input.val(); return this.input.val();
...@@ -369,7 +365,7 @@ OpenAssessment.InputControl.prototype = { ...@@ -369,7 +365,7 @@ OpenAssessment.InputControl.prototype = {
Set the input value. Set the input value.
Args: Args:
val (string) val (string)
**/ **/
set: function(val) { set: function(val) {
...@@ -380,7 +376,7 @@ OpenAssessment.InputControl.prototype = { ...@@ -380,7 +376,7 @@ OpenAssessment.InputControl.prototype = {
Mark validation errors if the field does not pass the validation callback function. Mark validation errors if the field does not pass the validation callback function.
Returns: Returns:
Boolean indicating whether the field's value is valid. Boolean indicating whether the field's value is valid.
**/ **/
validate: function() { validate: function() {
...@@ -407,7 +403,7 @@ OpenAssessment.InputControl.prototype = { ...@@ -407,7 +403,7 @@ OpenAssessment.InputControl.prototype = {
in the UI. in the UI.
Returns: Returns:
list of strings that contain error messages list of strings that contain error messages
**/ **/
validationErrors: function() { validationErrors: function() {
......
/** /**
Dynamically update student training examples based on Dynamically update student training examples based on
changes to the prompts or the rubric. changes to the prompts or the rubric.
**/ **/
OpenAssessment.StudentTrainingListener = function() { OpenAssessment.StudentTrainingListener = function() {
this.element = $('#oa_student_training_editor'); this.element = $('#oa_student_training_editor');
this.alert = new OpenAssessment.ValidationAlert(); this.alert = new OpenAssessment.ValidationAlert();
...@@ -10,7 +10,7 @@ OpenAssessment.StudentTrainingListener = function() { ...@@ -10,7 +10,7 @@ OpenAssessment.StudentTrainingListener = function() {
OpenAssessment.StudentTrainingListener.prototype = { OpenAssessment.StudentTrainingListener.prototype = {
/** /**
Add a answer part in the training examples when a prompt is added. Add a answer part in the training examples when a prompt is added.
*/ */
promptAdd: function() { promptAdd: function() {
var view = this.element; var view = this.element;
...@@ -23,7 +23,7 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -23,7 +23,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
}, },
/** /**
Remove the answer part in the training examples when a prompt is removed. Remove the answer part in the training examples when a prompt is removed.
*/ */
promptRemove: function(data) { promptRemove: function(data) {
var view = this.element; var view = this.element;
...@@ -35,11 +35,11 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -35,11 +35,11 @@ OpenAssessment.StudentTrainingListener.prototype = {
been updated. been updated.
Args: Args:
criterionName (str): The name of the criterion that contains the updated criterionName (str): The name of the criterion that contains the updated
option. option.
name (str): The name of the option. name (str): The name of the option.
label (str): The label for the option. label (str): The label for the option.
points (int): The point value for the option. points (int): The point value for the option.
*/ */
optionUpdated: function(data) { optionUpdated: function(data) {
this._optionSel(data.criterionName).each( this._optionSel(data.criterionName).each(
...@@ -63,11 +63,11 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -63,11 +63,11 @@ OpenAssessment.StudentTrainingListener.prototype = {
HTML. This will be resolved server-side. HTML. This will be resolved server-side.
Args: Args:
criterionName (str): The name of the criterion that will have an criterionName (str): The name of the criterion that will have an
additional option. additional option.
name (str): The name of the new option. name (str): The name of the new option.
label (str): The new option label. label (str): The new option label.
points (int): The point value of the new option. points (int): The point value of the new option.
*/ */
optionAdd: function(data) { optionAdd: function(data) {
// First, check to see if the criterion exists on the training examples // First, check to see if the criterion exists on the training examples
...@@ -93,10 +93,9 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -93,10 +93,9 @@ OpenAssessment.StudentTrainingListener.prototype = {
}); });
if (criterionAdded) { if (criterionAdded) {
/* jshint maxlen:300 */
this.displayAlertMsg( this.displayAlertMsg(
gettext("Criterion Added"), gettext("Criterion Added"),
gettext("You have added a criterion. You will need to select an option for the criterion in the Learner Training step. To do this, click the Settings tab.") gettext("You have added a criterion. You will need to select an option for the criterion in the Learner Training step. To do this, click the Settings tab.") // jscs:ignore maximumLineLength
); );
} }
}, },
...@@ -111,9 +110,9 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -111,9 +110,9 @@ OpenAssessment.StudentTrainingListener.prototype = {
invoked. invoked.
Args: Args:
criterionName (str): The name of the criterion where the option is criterionName (str): The name of the criterion where the option is
being removed. being removed.
name (str): The option being removed. name (str): The option being removed.
*/ */
optionRemove: function(data) { optionRemove: function(data) {
...@@ -123,10 +122,10 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -123,10 +122,10 @@ OpenAssessment.StudentTrainingListener.prototype = {
var criterionOption = this; var criterionOption = this;
if ($(criterionOption).val() === data.name.toString()) { if ($(criterionOption).val() === data.name.toString()) {
$(criterionOption).val("") $(criterionOption).val("")
.addClass("openassessment_highlighted_field") .addClass("openassessment_highlighted_field")
.click(function() { .click(function() {
$(criterionOption).removeClass("openassessment_highlighted_field"); $(criterionOption).removeClass("openassessment_highlighted_field");
}); });
invalidated = true; invalidated = true;
} }
...@@ -141,10 +140,9 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -141,10 +140,9 @@ OpenAssessment.StudentTrainingListener.prototype = {
}); });
if (invalidated) { if (invalidated) {
/* jshint maxlen:300 */
this.displayAlertMsg( this.displayAlertMsg(
gettext("Option Deleted"), gettext("Option Deleted"),
gettext("You have deleted an option. That option has been removed from its criterion in the sample responses in the Learner Training step. You might have to select a new option for the criterion.") gettext("You have deleted an option. That option has been removed from its criterion in the sample responses in the Learner Training step. You might have to select a new option for the criterion.") // jscs:ignore maximumLineLength
); );
} }
}, },
...@@ -163,7 +161,7 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -163,7 +161,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
notified. notified.
Args: Args:
criterionName (str): The criterion where all options have been removed. criterionName (str): The criterion where all options have been removed.
*/ */
removeAllOptions: function(data) { removeAllOptions: function(data) {
...@@ -177,10 +175,9 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -177,10 +175,9 @@ OpenAssessment.StudentTrainingListener.prototype = {
}); });
if (changed) { if (changed) {
/* jshint maxlen:300 */
this.displayAlertMsg( this.displayAlertMsg(
gettext("Option Deleted"), gettext("Option Deleted"),
gettext("You have deleted all the options for this criterion. The criterion has been removed from the sample responses in the Learner Training step.") gettext("You have deleted all the options for this criterion. The criterion has been removed from the sample responses in the Learner Training step.") // jscs:ignore maximumLineLength
); );
} }
}, },
...@@ -191,7 +188,7 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -191,7 +188,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
to reflect this change. to reflect this change.
Args: Args:
criterionName (str): The name of the criterion removed. criterionName (str): The name of the criterion removed.
*/ */
criterionRemove: function(data) { criterionRemove: function(data) {
...@@ -199,16 +196,15 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -199,16 +196,15 @@ OpenAssessment.StudentTrainingListener.prototype = {
var sel = '.openassessment_training_example_criterion[data-criterion="' + data.criterionName + '"]'; var sel = '.openassessment_training_example_criterion[data-criterion="' + data.criterionName + '"]';
$(sel, this.element).each( $(sel, this.element).each(
function() { function() {
$(this).remove(); $(this).remove();
changed = true; changed = true;
} }
); );
if (changed) { if (changed) {
/* jshint maxlen:300 */
this.displayAlertMsg( this.displayAlertMsg(
gettext("Criterion Deleted"), gettext("Criterion Deleted"),
gettext("You have deleted a criterion. The criterion has been removed from the example responses in the Learner Training step.") gettext("You have deleted a criterion. The criterion has been removed from the example responses in the Learner Training step.") // jscs:ignore maximumLineLength
); );
} }
}, },
...@@ -218,14 +214,14 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -218,14 +214,14 @@ OpenAssessment.StudentTrainingListener.prototype = {
at least one training example, and that student training is enabled. at least one training example, and that student training is enabled.
Args: Args:
title (str): Title of the alert message. title (str): Title of the alert message.
msg (str): Message body for the alert. msg (str): Message body for the alert.
*/ */
displayAlertMsg: function(title, msg) { displayAlertMsg: function(title, msg) {
if ($("#include_student_training", this.element).is(":checked") && if ($("#include_student_training", this.element).is(":checked") &&
// Check for at least more than one example, to exclude the template // Check for at least more than one example, to exclude the template
$(".openassessment_training_example", this.element).length > 1) { $(".openassessment_training_example", this.element).length > 1) {
this.alert.setMessage(title, msg).show(); this.alert.setMessage(title, msg).show();
} }
}, },
...@@ -235,8 +231,8 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -235,8 +231,8 @@ OpenAssessment.StudentTrainingListener.prototype = {
has changed in the rubric. has changed in the rubric.
Args: Args:
criterionName (str): Name of the criterion criterionName (str): Name of the criterion
criterionLabel (str): New label to replace on the training examples. criterionLabel (str): New label to replace on the training examples.
*/ */
criterionUpdated: function(data) { criterionUpdated: function(data) {
var sel = '.openassessment_training_example_criterion[data-criterion="' + data.criterionName + '"]'; var sel = '.openassessment_training_example_criterion[data-criterion="' + data.criterionName + '"]';
...@@ -255,8 +251,8 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -255,8 +251,8 @@ OpenAssessment.StudentTrainingListener.prototype = {
examples. examples.
Args: Args:
criterionName (str): The name of the criterion being added. criterionName (str): The name of the criterion being added.
label (str): The label for the new criterion. label (str): The label for the new criterion.
*/ */
criterionAdd: function(data) { criterionAdd: function(data) {
var view = this.element; var view = this.element;
...@@ -275,23 +271,23 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -275,23 +271,23 @@ OpenAssessment.StudentTrainingListener.prototype = {
}, },
/** /**
Retrieve the available criteria labels for training examples. Retrieve the available criteria labels for training examples.
This is mainly useful for testing. This is mainly useful for testing.
The returned array will always contain an extra example The returned array will always contain an extra example
for the client-side template for new examples. for the client-side template for new examples.
Returns: Returns:
Array of object literals mapping criteria names to labels. Array of object literals mapping criteria names to labels.
Example usage: Example usage:
>>> listener.examplesCriteriaLabels(); >>> listener.examplesCriteriaLabels();
>>> [ >>> [
>>> { criterion_1: "abcd", criterion_2: "xyz" }, >>> { criterion_1: "abcd", criterion_2: "xyz" },
>>> { criterion_1: "abcd", criterion_2: "xyz" } >>> { criterion_1: "abcd", criterion_2: "xyz" }
>>> ] >>> ]
**/ **/
examplesCriteriaLabels: function() { examplesCriteriaLabels: function() {
var examples = []; var examples = [];
$(".openassessment_training_example_criteria_selections", this.element).each( $(".openassessment_training_example_criteria_selections", this.element).each(
...@@ -312,34 +308,34 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -312,34 +308,34 @@ OpenAssessment.StudentTrainingListener.prototype = {
}, },
/** /**
Retrieve the available option labels for training examples. Retrieve the available option labels for training examples.
This is mainly useful for testing. This is mainly useful for testing.
The returned array will always contain an extra example The returned array will always contain an extra example
for the client-side template for new examples. for the client-side template for new examples.
Returns: Returns:
Array of object literals Array of object literals
Example usage: Example usage:
>>> listener.examplesOptionsLabels(); >>> listener.examplesOptionsLabels();
>>> [ >>> [
>>> { >>> {
>>> criterion_1: { >>> criterion_1: {
>>> "": "Not Scored", >>> "": "Not Scored",
>>> option_1: "First Option - 1 points", >>> option_1: "First Option - 1 points",
>>> option_2: "Second Option - 2 points", >>> option_2: "Second Option - 2 points",
>>> } >>> }
>>> }, >>> },
>>> { >>> {
>>> criterion_1: { >>> criterion_1: {
>>> "": "Not Scored", >>> "": "Not Scored",
>>> option_1: "First Option - 1 points", >>> option_1: "First Option - 1 points",
>>> option_2: "Second Option - 2 points", >>> option_2: "Second Option - 2 points",
>>> } >>> }
>>> } >>> }
>>> ] >>> ]
**/ **/
examplesOptionsLabels: function() { examplesOptionsLabels: function() {
var examples = []; var examples = [];
$(".openassessment_training_example_criteria_selections", this.element).each( $(".openassessment_training_example_criteria_selections", this.element).each(
...@@ -365,12 +361,11 @@ OpenAssessment.StudentTrainingListener.prototype = { ...@@ -365,12 +361,11 @@ OpenAssessment.StudentTrainingListener.prototype = {
} }
}; };
/** /**
Show a warning when a user disables an assessment, Show a warning when a user disables an assessment,
since any data in the disabled section won't be persisted since any data in the disabled section won't be persisted
on save. on save.
**/ **/
OpenAssessment.AssessmentToggleListener = function() { OpenAssessment.AssessmentToggleListener = function() {
this.alert = new OpenAssessment.ValidationAlert(); this.alert = new OpenAssessment.ValidationAlert();
}; };
......
...@@ -44,4 +44,4 @@ OpenAssessment.Notifier.prototype = { ...@@ -44,4 +44,4 @@ OpenAssessment.Notifier.prototype = {
} }
} }
} }
}; };
\ No newline at end of file
/** /**
Editing interface for the prompts. Editing interface for the prompts.
Args: Args:
element (DOM element): The DOM element representing this view. element (DOM element): The DOM element representing this view.
Returns: Returns:
OpenAssessment.EditPromptsView OpenAssessment.EditPromptsView
**/ **/
OpenAssessment.EditPromptsView = function(element, notifier) { OpenAssessment.EditPromptsView = function(element, notifier) {
this.element = element; this.element = element;
this.editorElement = $(this.element).closest("#openassessment-editor"); this.editorElement = $(this.element).closest("#openassessment-editor");
...@@ -27,36 +27,35 @@ OpenAssessment.EditPromptsView = function(element, notifier) { ...@@ -27,36 +27,35 @@ OpenAssessment.EditPromptsView = function(element, notifier) {
this.promptsContainer.addEventListeners(); this.promptsContainer.addEventListeners();
}; };
OpenAssessment.EditPromptsView.prototype = { OpenAssessment.EditPromptsView.prototype = {
/** /**
Construct a list of prompts definitions from the editor UI. Construct a list of prompts definitions from the editor UI.
Returns: Returns:
list of prompt objects list of prompt objects
Example usage: Example usage:
>>> editPromptsView.promptsDefinition(); >>> editPromptsView.promptsDefinition();
[ [
{ {
uuid: "cfvgbh657", uuid: "cfvgbh657",
description: "Description", description: "Description",
order_num: 0, order_num: 0,
}, },
... ...
] ]
**/ **/
promptsDefinition: function() { promptsDefinition: function() {
var prompts = this.promptsContainer.getItemValues(); var prompts = this.promptsContainer.getItemValues();
return prompts; return prompts;
}, },
/** /**
Add a new prompt. Add a new prompt.
Uses a client-side template to create the new prompt. Uses a client-side template to create the new prompt.
**/ **/
addPrompt: function() { addPrompt: function() {
if (this.addRemoveEnabled) { if (this.addRemoveEnabled) {
this.promptsContainer.add(); this.promptsContainer.add();
...@@ -64,11 +63,11 @@ OpenAssessment.EditPromptsView.prototype = { ...@@ -64,11 +63,11 @@ OpenAssessment.EditPromptsView.prototype = {
}, },
/** /**
Remove a prompt. Remove a prompt.
Args: Args:
item (OpenAssessment.RubricCriterion): The criterion item to remove. item (OpenAssessment.RubricCriterion): The criterion item to remove.
**/ **/
removePrompt: function(item) { removePrompt: function(item) {
if (this.addRemoveEnabled) { if (this.addRemoveEnabled) {
this.promptsContainer.remove(item); this.promptsContainer.remove(item);
...@@ -76,56 +75,56 @@ OpenAssessment.EditPromptsView.prototype = { ...@@ -76,56 +75,56 @@ OpenAssessment.EditPromptsView.prototype = {
}, },
/** /**
Retrieve all prompts. Retrieve all prompts.
Returns: Returns:
Array of OpenAssessment.Prompt objects. Array of OpenAssessment.Prompt objects.
**/ **/
getAllPrompts: function() { getAllPrompts: function() {
return this.promptsContainer.getAllItems(); return this.promptsContainer.getAllItems();
}, },
/** /**
Retrieve a prompt item from the prompts. Retrieve a prompt item from the prompts.
Args: Args:
index (int): The index of the prompt, starting from 0. index (int): The index of the prompt, starting from 0.
Returns: Returns:
OpenAssessment.Prompt or null OpenAssessment.Prompt or null
**/ **/
getPromptItem: function(index) { getPromptItem: function(index) {
return this.promptsContainer.getItem(index); return this.promptsContainer.getItem(index);
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the view is valid. Boolean indicating whether the view is valid.
**/ **/
validate: function() { validate: function() {
return true; return true;
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
return errors; return errors;
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() {} clearValidationErrors: function() {}
}; };
\ No newline at end of file
/** /**
Interface for editing rubric definitions. Interface for editing rubric definitions.
Args: Args:
element (DOM element): The DOM element representing the rubric. element (DOM element): The DOM element representing the rubric.
notifier (OpenAssessment.Notifier): Used to notify other views about updates to the rubric. notifier (OpenAssessment.Notifier): Used to notify other views about updates to the rubric.
This view fires the following notification events: This view fires the following notification events:
* optionAdd: An option was added to the rubric. * optionAdd: An option was added to the rubric.
* optionRemove: An option was removed from the rubric. * optionRemove: An option was removed from the rubric.
* optionUpdated: An option's label and/or points were updated in the rubric. * optionUpdated: An option's label and/or points were updated in the rubric.
* criterionRemove: A criterion was removed from the rubric. * criterionRemove: A criterion was removed from the rubric.
* criterionUpdated: A criterion's label was updated in the rubric. * criterionUpdated: A criterion's label was updated in the rubric.
**/ **/
OpenAssessment.EditRubricView = function(element, notifier) { OpenAssessment.EditRubricView = function(element, notifier) {
this.element = element; this.element = element;
this.criterionAddButton = $('#openassessment_rubric_add_criterion', this.element); this.criterionAddButton = $('#openassessment_rubric_add_criterion', this.element);
...@@ -32,43 +32,43 @@ OpenAssessment.EditRubricView = function(element, notifier) { ...@@ -32,43 +32,43 @@ OpenAssessment.EditRubricView = function(element, notifier) {
OpenAssessment.EditRubricView.prototype = { OpenAssessment.EditRubricView.prototype = {
/** /**
Construct a list of criteria definitions from the editor UI. Construct a list of criteria definitions from the editor UI.
Returns: Returns:
list of criteria objects list of criteria objects
Example usage: Example usage:
>>> editRubricView.criteriaDefinition(); >>> editRubricView.criteriaDefinition();
[ [
{ {
name: "Criterion", name: "Criterion",
prompt: "Prompt", prompt: "Prompt",
order_num: 0, order_num: 0,
feedback: "disabled", feedback: "disabled",
options: [ options: [
{ {
order_num: 0, order_num: 0,
points: 1, points: 1,
name: "Good", name: "Good",
explanation: "Explanation" explanation: "Explanation"
}, },
... ...
] ]
}, },
... ...
] ]
**/ **/
criteriaDefinition: function() { criteriaDefinition: function() {
var criteria = this.criteriaContainer.getItemValues(); var criteria = this.criteriaContainer.getItemValues();
// Add order_num fields for criteria and options // Add order_num fields for criteria and options
for (var criterion_idx = 0; criterion_idx < criteria.length; criterion_idx++) { for (var criterionIndex = 0; criterionIndex < criteria.length; criterionIndex++) {
var criterion = criteria[criterion_idx]; var criterion = criteria[criterionIndex];
criterion.order_num = criterion_idx; criterion.order_num = criterionIndex;
for (var option_idx = 0; option_idx < criterion.options.length; option_idx++) { for (var optionIndex = 0; optionIndex < criterion.options.length; optionIndex++) {
var option = criterion.options[option_idx]; var option = criterion.options[optionIndex];
option.order_num = option_idx; option.order_num = optionIndex;
} }
} }
...@@ -76,156 +76,156 @@ OpenAssessment.EditRubricView.prototype = { ...@@ -76,156 +76,156 @@ OpenAssessment.EditRubricView.prototype = {
}, },
/** /**
Get or set the feedback prompt in the editor. Get or set the feedback prompt in the editor.
This is the prompt shown to students when giving "overall" feedback This is the prompt shown to students when giving "overall" feedback
on a submission. on a submission.
Args: Args:
text (string, optional): If provided, set the feedback prompt to this value. text (string, optional): If provided, set the feedback prompt to this value.
Returns: Returns:
string string
**/ **/
feedbackPrompt: function(text) { feedbackPrompt: function(text) {
var sel = $("#openassessment_rubric_feedback", this.element); var sel = $("#openassessment_rubric_feedback", this.element);
return OpenAssessment.Fields.stringField(sel, text); return OpenAssessment.Fields.stringField(sel, text);
}, },
/** /**
Get or set the default feedback response text in the editor. Get or set the default feedback response text in the editor.
The text is used as a student's default response to the feedback The text is used as a student's default response to the feedback
prompt. prompt.
Args: Args:
text (string, option): If provided, sets the default text to this value. text (string, option): If provided, sets the default text to this value.
Returns: Returns:
string string
**/ **/
feedback_default_text: function(text) { feedback_default_text: function(text) {
var sel = $("#openassessment_rubric_feedback_default_text", this.element); var sel = $("#openassessment_rubric_feedback_default_text", this.element);
return OpenAssessment.Fields.stringField(sel, text); return OpenAssessment.Fields.stringField(sel, text);
}, },
/** /**
Add a new criterion to the rubric. Add a new criterion to the rubric.
Uses a client-side template to create the new criterion. Uses a client-side template to create the new criterion.
**/ **/
addCriterion: function() { addCriterion: function() {
this.criteriaContainer.add(); this.criteriaContainer.add();
}, },
/** /**
Remove a criterion from the rubric. Remove a criterion from the rubric.
Args: Args:
item (OpenAssessment.RubricCriterion): The criterion item to remove. item (OpenAssessment.RubricCriterion): The criterion item to remove.
**/ **/
removeCriterion: function(item) { removeCriterion: function(item) {
this.criteriaContainer.remove(item); this.criteriaContainer.remove(item);
}, },
/** /**
Retrieve all criteria from the rubric. Retrieve all criteria from the rubric.
Returns: Returns:
Array of OpenAssessment.RubricCriterion objects. Array of OpenAssessment.RubricCriterion objects.
**/ **/
getAllCriteria: function() { getAllCriteria: function() {
return this.criteriaContainer.getAllItems(); return this.criteriaContainer.getAllItems();
}, },
/** /**
Retrieve a criterion item from the rubric. Retrieve a criterion item from the rubric.
Args: Args:
index (int): The index of the criterion, starting from 0. index (int): The index of the criterion, starting from 0.
Returns: Returns:
OpenAssessment.RubricCriterion or null OpenAssessment.RubricCriterion or null
**/ **/
getCriterionItem: function(index) { getCriterionItem: function(index) {
return this.criteriaContainer.getItem(index); return this.criteriaContainer.getItem(index);
}, },
/** /**
Add a new option to the rubric. Add a new option to the rubric.
Args: Args:
criterionIndex (int): The index of the criterion to which criterionIndex (int): The index of the criterion to which
the option will be added (starts from 0). the option will be added (starts from 0).
**/ **/
addOption: function(criterionIndex) { addOption: function(criterionIndex) {
var criterionItem = this.getCriterionItem(criterionIndex); var criterionItem = this.getCriterionItem(criterionIndex);
criterionItem.optionContainer.add(); criterionItem.optionContainer.add();
}, },
/** /**
Remove an option from the rubric. Remove an option from the rubric.
Args: Args:
criterionIndex (int): The index of the criterion, starting from 0. criterionIndex (int): The index of the criterion, starting from 0.
item (OpenAssessment.RubricOption): The option item to remove. item (OpenAssessment.RubricOption): The option item to remove.
**/ **/
removeOption: function(criterionIndex, item) { removeOption: function(criterionIndex, item) {
var criterionItem = this.getCriterionItem(criterionIndex); var criterionItem = this.getCriterionItem(criterionIndex);
criterionItem.optionContainer.remove(item); criterionItem.optionContainer.remove(item);
}, },
/** /**
Retrieve all options for a particular criterion. Retrieve all options for a particular criterion.
Args: Args:
criterionIndex (int): The index of the criterion, starting from 0. criterionIndex (int): The index of the criterion, starting from 0.
Returns: Returns:
Array of OpenAssessment.RubricOption Array of OpenAssessment.RubricOption
**/ **/
getAllOptions: function(criterionIndex) { getAllOptions: function(criterionIndex) {
var criterionItem = this.getCriterionItem(criterionIndex); var criterionItem = this.getCriterionItem(criterionIndex);
return criterionItem.optionContainer.getAllItems(); return criterionItem.optionContainer.getAllItems();
}, },
/** /**
Retrieve a particular option from the rubric. Retrieve a particular option from the rubric.
Args: Args:
criterionIndex (int): The index of the criterion, starting from 0. criterionIndex (int): The index of the criterion, starting from 0.
optionIndex (int): The index of the option within the criterion, optionIndex (int): The index of the option within the criterion,
starting from 0. starting from 0.
Returns: Returns:
OpenAssessment.RubricOption OpenAssessment.RubricOption
**/ **/
getOptionItem: function(criterionIndex, optionIndex) { getOptionItem: function(criterionIndex, optionIndex) {
var criterionItem = this.getCriterionItem(criterionIndex); var criterionItem = this.getCriterionItem(criterionIndex);
return criterionItem.optionContainer.getItem(optionIndex); return criterionItem.optionContainer.getItem(optionIndex);
}, },
/** /**
Mark validation errors. Mark validation errors.
Returns: Returns:
Boolean indicating whether the view is valid. Boolean indicating whether the view is valid.
**/ **/
validate: function() { validate: function() {
var criteria = this.getAllCriteria(); var criteria = this.getAllCriteria();
var isValid = criteria.length > 0; var isValid = criteria.length > 0;
if (!isValid) { if (!isValid) {
this.criterionAddButton this.criterionAddButton
.addClass("openassessment_highlighted_field") .addClass("openassessment_highlighted_field")
.click( function() { .click(function() {
$(this).removeClass("openassessment_highlighted_field"); $(this).removeClass("openassessment_highlighted_field");
} }
); );
} }
$.each(criteria, function() { $.each(criteria, function() {
...@@ -235,14 +235,14 @@ OpenAssessment.EditRubricView.prototype = { ...@@ -235,14 +235,14 @@ OpenAssessment.EditRubricView.prototype = {
return isValid; return isValid;
}, },
/** /**
Return a list of validation errors visible in the UI. Return a list of validation errors visible in the UI.
Mainly useful for testing. Mainly useful for testing.
Returns: Returns:
list of string list of string
**/ **/
validationErrors: function() { validationErrors: function() {
var errors = []; var errors = [];
...@@ -259,8 +259,8 @@ OpenAssessment.EditRubricView.prototype = { ...@@ -259,8 +259,8 @@ OpenAssessment.EditRubricView.prototype = {
}, },
/** /**
Clear all validation errors from the UI. Clear all validation errors from the UI.
**/ **/
clearValidationErrors: function() { clearValidationErrors: function() {
this.criterionAddButton.removeClass("openassessment_highlighted_field"); this.criterionAddButton.removeClass("openassessment_highlighted_field");
......
...@@ -38,7 +38,7 @@ OpenAssessment.EditSettingsView = function(element, assessmentViews, data) { ...@@ -38,7 +38,7 @@ OpenAssessment.EditSettingsView = function(element, assessmentViews, data) {
this.leaderboardIntField = new OpenAssessment.IntField( this.leaderboardIntField = new OpenAssessment.IntField(
$("#openassessment_leaderboard_editor", this.element), $("#openassessment_leaderboard_editor", this.element),
{ min: 0, max: 100 } {min: 0, max: 100}
); );
this.fileTypeWhiteListInputField = new OpenAssessment.InputControl( this.fileTypeWhiteListInputField = new OpenAssessment.InputControl(
...@@ -67,13 +67,12 @@ OpenAssessment.EditSettingsView = function(element, assessmentViews, data) { ...@@ -67,13 +67,12 @@ OpenAssessment.EditSettingsView = function(element, assessmentViews, data) {
this.initializeSortableAssessments(); this.initializeSortableAssessments();
}; };
OpenAssessment.EditSettingsView.prototype = { OpenAssessment.EditSettingsView.prototype = {
/** /**
Installs click listeners which initialize drag and drop functionality for assessment modules. Installs click listeners which initialize drag and drop functionality for assessment modules.
**/ **/
initializeSortableAssessments: function () { initializeSortableAssessments: function() {
var view = this; var view = this;
// Initialize Drag and Drop of Assessment Modules // Initialize Drag and Drop of Assessment Modules
$('#openassessment_assessment_module_settings_editors', view.element).sortable({ $('#openassessment_assessment_module_settings_editors', view.element).sortable({
...@@ -255,7 +254,7 @@ OpenAssessment.EditSettingsView.prototype = { ...@@ -255,7 +254,7 @@ OpenAssessment.EditSettingsView.prototype = {
// Find all assessment modules within our element in the DOM, // Find all assessment modules within our element in the DOM,
// and append their definitions to the description // and append their definitions to the description
$('.openassessment_assessment_module_settings_editor', this.assessmentsElement).each( $('.openassessment_assessment_module_settings_editor', this.assessmentsElement).each(
function () { function() {
var asmntView = view.assessmentViews[$(this).attr('id')]; var asmntView = view.assessmentViews[$(this).attr('id')];
if (asmntView.isEnabled()) { if (asmntView.isEnabled()) {
var description = asmntView.description(); var description = asmntView.description();
...@@ -280,7 +279,7 @@ OpenAssessment.EditSettingsView.prototype = { ...@@ -280,7 +279,7 @@ OpenAssessment.EditSettingsView.prototype = {
var editorAssessments = []; var editorAssessments = [];
var view = this; var view = this;
$('.openassessment_assessment_module_settings_editor', this.assessmentsElement).each( $('.openassessment_assessment_module_settings_editor', this.assessmentsElement).each(
function () { function() {
var asmntView = view.assessmentViews[$(this).attr('id')]; var asmntView = view.assessmentViews[$(this).attr('id')];
editorAssessments.push(asmntView.name); editorAssessments.push(asmntView.name);
} }
......
...@@ -48,7 +48,7 @@ OpenAssessment.ValidationAlert.prototype = { ...@@ -48,7 +48,7 @@ OpenAssessment.ValidationAlert.prototype = {
'border-top-left-radius': '3px' 'border-top-left-radius': '3px'
}; };
$('.oa_editor_content_wrapper', this.editorElement).each( function () { $('.oa_editor_content_wrapper', this.editorElement).each(function() {
$(this).css(styles); $(this).css(styles);
}); });
...@@ -61,12 +61,12 @@ OpenAssessment.ValidationAlert.prototype = { ...@@ -61,12 +61,12 @@ OpenAssessment.ValidationAlert.prototype = {
Returns: Returns:
OpenAssessment.ValidationAlert OpenAssessment.ValidationAlert
*/ */
show : function() { show: function() {
var view = this; var view = this;
if (this.isVisible()){ if (this.isVisible()) {
$(this.element).animate( $(this.element).animate(
{'background-color': view.ALERT_YELLOW}, 300, 'swing', function () { {'background-color': view.ALERT_YELLOW}, 300, 'swing', function() {
$(this).animate({'background-color': view.DARK_GREY}, 700, 'swing'); $(this).animate({'background-color': view.DARK_GREY}, 700, 'swing');
} }
); );
...@@ -84,7 +84,7 @@ OpenAssessment.ValidationAlert.prototype = { ...@@ -84,7 +84,7 @@ OpenAssessment.ValidationAlert.prototype = {
'border-top-left-radius': '0px' 'border-top-left-radius': '0px'
}; };
$('.oa_editor_content_wrapper', this.editorElement).each(function () { $('.oa_editor_content_wrapper', this.editorElement).each(function() {
$(this).css(styles); $(this).css(styles);
}); });
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
"phantomjs": "^1.9.11", "phantomjs": "^1.9.11",
"sinon": "^1.10.3", "sinon": "^1.10.3",
"uglify-js": "2.3.6", "uglify-js": "2.3.6",
"jshint": "2.8.0" "jshint": "2.8.0",
"jscs": "2.6.0"
}, },
"scripts": { "scripts": {
"test": "./node_modules/karma/bin/karma start --reporters spec,coverage" "test": "./node_modules/karma/bin/karma start --reporters spec,coverage"
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
git+https://github.com/edx/XBlock.git@xblock-0.4.1#egg=XBlock==0.4.1 git+https://github.com/edx/XBlock.git@xblock-0.4.1#egg=XBlock==0.4.1
# edx-submissions # edx-submissions
git+https://github.com/edx/edx-submissions.git@0.1.2#egg=edx-submissions==0.1.2 git+https://github.com/edx/edx-submissions.git@0.1.3#egg=edx-submissions==0.1.3
# Third Party Requirements # Third Party Requirements
boto>=2.32.1,<3.0.0 boto>=2.32.1,<3.0.0
......
-r base.txt -r base.txt
-r test-acceptance.txt -r test-acceptance.txt
coverage==3.7.1 coverage==4.0.2
django-nose==1.4.1 django-nose==1.4.1
mock==1.0.1 mock==1.0.1
moto==0.2.22 moto==0.3.1
pep8==1.5.7 pep8==1.6.2
pylint<1.0 pylint<1.0
git+https://github.com/edx/django-pyfs.git@1.0.3#egg=django-pyfs==1.0.3 git+https://github.com/edx/django-pyfs.git@1.0.3#egg=django-pyfs==1.0.3
......
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