Commit 2232813d by Will Daly

Add tests for dynamic update of student training examples based on rubric changes.

Use dependency injection for event notification; moved some classes around.
Move the container JS classes into the Studio minified JS.
Fix a bug that broke student training updates in Firefox and PhantomJS.
Move fixture path installation into a common file shared by all tests.

Add tests that verify the correct notifications
are sent by the rubric view.
parent a05d51fd
......@@ -27,6 +27,7 @@ module.exports = function(config) {
'src/*.js',
'src/lms/*.js',
'src/studio/*.js',
'spec/test_shared.js',
'spec/*.js',
'spec/lms/*.js',
'spec/studio/*.js',
......
......@@ -391,7 +391,7 @@
"submission_due": "2014-10-1T10:00:00",
"criteria": [
{
"name": "52bfbd0eb3044212b809564866e77079",
"name": "criterion_1",
"label": "Criterion with two options",
"prompt": "Prompt for criterion with two options",
"order_num": 0,
......@@ -400,14 +400,14 @@
{
"order_num": 0,
"points": 1,
"name": "85bbbecbb6a343f8a2146cde0e609ad0",
"name": "option_1",
"label": "Fair",
"explanation": "Fair explanation"
},
{
"order_num": 1,
"points": 2,
"name": "5936d5b9e281403ca123964055d4719a",
"name": "option_2",
"label": "Good",
"explanation": "Good explanation"
}
......@@ -415,7 +415,7 @@
"points_possible": 2
},
{
"name": "d96bb68a69ee4ccb8f86c753b6924f75",
"name": "criterion_2",
"label": "Criterion with no options",
"prompt": "Prompt for criterion with no options",
"order_num": 0,
......@@ -424,7 +424,7 @@
"points_possible": 0
},
{
"name": "2ca052403b06424da714f7a80dfb954d",
"name": "criterion_3",
"label": "Criterion with optional feedback",
"prompt": "Prompt for criterion with optional feedback",
"order_num": 2,
......@@ -433,7 +433,7 @@
{
"order_num": 0,
"points": 2,
"name": "d7445661a89b4b339b9788cb7225a603",
"name": "option_1",
"label": "Good",
"explanation": "Good explanation"
}
......@@ -462,6 +462,148 @@
"output": "oa_edit.html"
},
{
"template": "openassessmentblock/edit/oa_edit.html",
"context": {
"prompt": "Test prompt",
"title": "Test title",
"submission_due": "2014-10-1T10:00:00",
"criteria": [
{
"name": "criterion_with_two_options",
"label": "Criterion with two options",
"prompt": "Criterion with two options prompt",
"order_num": 0,
"feedback": "disabled",
"options": [
{
"order_num": 0,
"points": 1,
"name": "option_1",
"label": "Fair",
"explanation": "Fair explanation"
},
{
"order_num": 1,
"points": 2,
"name": "option_2",
"label": "Good",
"explanation": "Good explanation"
}
],
"points_possible": 2
},
{
"name": "criterion_no_options",
"label": "Criterion with no options",
"prompt": "Criterion with no options prompt",
"order_num": 0,
"options": [],
"feedback": "required",
"points_possible": 0
}
],
"assessments": {
"training": {
"examples": [
{
"answer": "Test answer",
"criteria": [
{
"name": "criterion_with_two_options",
"label": "Criterion with two options",
"prompt": "Criterion with two options prompt",
"order_num": 0,
"feedback": "disabled",
"options": [
{
"order_num": 0,
"points": 1,
"name": "option_1",
"label": "Fair",
"explanation": "Fair explanation"
},
{
"order_num": 1,
"points": 2,
"name": "option_2",
"label": "Good",
"explanation": "Good explanation"
}
],
"points_possible": 2,
"option_selected": "option_1"
},
{
"name": "criterion_no_options",
"label": "Criterion with no options",
"prompt": "Criterion with no options prompt",
"order_num": 0,
"options": [],
"feedback": "required",
"points_possible": 0,
"option_selected": ""
}
]
}
],
"template": {
"answer": "",
"criteria": [
{
"name": "criterion_with_two_options",
"label": "Criterion with two options",
"prompt": "Criterion with two options prompt",
"order_num": 0,
"feedback": "disabled",
"options": [
{
"order_num": 0,
"points": 1,
"name": "option_1",
"label": "Fair",
"explanation": "Fair explanation"
},
{
"order_num": 1,
"points": 2,
"name": "option_2",
"label": "Good",
"explanation": "Good explanation"
}
],
"points_possible": 2,
"option_selected": ""
},
{
"name": "criterion_no_options",
"label": "Criterion with no options",
"prompt": "Criterion with no options prompt",
"order_num": 0,
"options": [],
"feedback": "required",
"points_possible": 0,
"option_selected": ""
}
]
}
},
"peer_assessment": {
"start": "",
"due": "",
"must_grade": 5,
"must_be_graded_by": 3
}
},
"editor_assessments_order": [
"student_training",
"peer_assessment",
"self_assessment",
"example_based_assessment"
]
},
"output": "oa_edit_student_training.html"
},
{
"template": "openassessmentblock/staff_debug/staff_debug.html",
"context": {
"status_counts": {
......
if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.FileUploader=function(){this.upload=function(url,data,contentType){return $.Deferred(function(defer){$.ajax({url:url,type:"PUT",data:data,async:false,processData:false,contentType:contentType}).done(function(data,textStatus,jqXHR){defer.resolve()}).fail(function(data,textStatus,jqXHR){defer.rejectWith(this,[textStatus])})}).promise()}};if(typeof OpenAssessment.Server=="undefined"||!OpenAssessment.Server){OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX",gettext("This response could not be submitted.")])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},scheduleTraining:function(){var url=this.url("schedule_training");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},rescheduleUnfinishedTasks:function(){var url=this.url("reschedule_unfinished_tasks");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("One or more rescheduling tasks failed.")])})})},updateEditorContext:function(kwargs){var url=this.url("update_editor_context");var payload=JSON.stringify({prompt:kwargs.prompt,feedback_prompt:kwargs.feedbackPrompt,title:kwargs.title,submission_start:kwargs.submissionStart,submission_due:kwargs.submissionDue,criteria:kwargs.criteria,assessments:kwargs.assessments,editor_assessments_order:kwargs.editorAssessmentsOrder,allow_file_upload:kwargs.imageSubmissionEnabled});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This problem could not be saved.")])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("The server could not be contacted.")])})}).promise()},getUploadUrl:function(contentType){var url=this.url("upload_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({contentType:contentType})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve upload url.")])})}).promise()},getDownloadUrl:function(){var url=this.url("download_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve download url.")])})}).promise()}}}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.BaseView=function(runtime,element,server){this.runtime=runtime;this.element=element;this.server=server;this.fileUploader=new OpenAssessment.FileUploader;this.responseView=new OpenAssessment.ResponseView(this.element,this.server,this.fileUploader,this);this.trainingView=new OpenAssessment.StudentTrainingView(this.element,this.server,this);this.selfView=new OpenAssessment.SelfView(this.element,this.server,this);this.peerView=new OpenAssessment.PeerView(this.element,this.server,this);this.gradeView=new OpenAssessment.GradeView(this.element,this.server,this);this.messageView=new OpenAssessment.MessageView(this.element,this.server,this);this.staffInfoView=new OpenAssessment.StaffInfoView(this.element,this.server,this)};OpenAssessment.BaseView.prototype={scrollToTop:function(){if($.scrollTo instanceof Function){$(window).scrollTo($("#openassessment__steps"),800,{offset:-50})}},setUpCollapseExpand:function(parentSel){parentSel.find(".ui-toggle-visibility__control").click(function(eventData){var sel=$(eventData.target).closest(".ui-toggle-visibility");sel.toggleClass("is--collapsed")})},load:function(){this.responseView.load();this.loadAssessmentModules();this.staffInfoView.load()},loadAssessmentModules:function(){this.trainingView.load();this.peerView.load();this.selfView.load();this.gradeView.load()},loadMessageView:function(){this.messageView.load()},toggleActionError:function(type,msg){var element=this.element;var container=null;if(type=="save"){container=".response__submission__actions"}else if(type=="submit"||type=="peer"||type=="self"||type=="student-training"){container=".step__actions"}else if(type=="feedback_assess"){container=".submission__feedback__actions"}else if(type=="upload"){container="#upload__error"}if(container===null){if(msg!==null){console.log(msg)}}else{var msgHtml=msg===null?"":msg;$(container+" .message__content",element).html("<p>"+msgHtml+"</p>");$(container,element).toggleClass("has--error",msg!==null)}},showLoadError:function(step){var container="#openassessment__"+step;$(container).toggleClass("has--error",true);$(container+" .step__status__value i").removeClass().addClass("ico icon-warning-sign");$(container+" .step__status__value .copy").html(gettext("Unable to Load"))}};function OpenAssessmentBlock(runtime,element){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.BaseView(runtime,element,server);view.load()}OpenAssessment.Container=function(containerItem,kwargs){this.containerItem=containerItem;this.containerElement=kwargs.containerElement;this.templateElement=kwargs.templateElement;this.addButtonElement=kwargs.addButtonElement;this.removeButtonClass=kwargs.removeButtonClass;this.containerItemClass=kwargs.containerItemClass;$(this.addButtonElement).click($.proxy(this.add,this));var container=this;$("."+this.removeButtonClass,this.containerElement).click(function(eventData){var item=new container.containerItem(eventData.target);container.remove(item)});$("."+this.containerItemClass,this.containerElement).each(function(index,element){new container.containerItem(element)})};OpenAssessment.Container.prototype={add:function(){$(this.templateElement).children().first().clone().removeAttr("id").toggleClass("is--hidden",false).toggleClass(this.containerItemClass,true).appendTo($(this.containerElement));var container=this;var containerItem=$("."+this.containerItemClass,this.containerElement).last();containerItem.find("."+this.removeButtonClass).click(function(eventData){var containerItem=new container.containerItem(eventData.target);container.remove(containerItem)});var handlerItem=new this.containerItem(containerItem);handlerItem.addHandler()},remove:function(item){var itemElement=$(item.element).closest("."+this.containerItemClass);var containerItem=new this.containerItem(itemElement);containerItem.removeHandler();itemElement.remove()},getItemValues:function(){var values=[];var container=this;$("."+this.containerItemClass,this.containerElement).each(function(index,element){var containerItem=new container.containerItem(element);var fieldValues=containerItem.getFieldValues();values.push(fieldValues)});return values},getItem:function(index){var element=$("."+this.containerItemClass,this.containerElement).get(index);return element!==undefined?new this.containerItem(element):null},getAllItems:function(){var container=this;return $("."+this.containerItemClass,this.containerElement).map(function(){return new container.containerItem(this)})}};OpenAssessment.ItemUtilities={createUniqueName:function(selector,nameAttribute){var index=0;while(index<=selector.length){if(selector.parent().find("*["+nameAttribute+"='"+index+"']").length==0){return index.toString()}index++}return null}};OpenAssessment.RubricOption=function(element){this.element=element;this.modificationHandler=new OpenAssessment.RubricEventHandler;$(this.element).focusout($.proxy(this.updateHandler,this))};OpenAssessment.RubricOption.prototype={getFieldValues:function(){var fields={label:OpenAssessment.Fields.stringField($(".openassessment_criterion_option_label",this.element)),points:OpenAssessment.Fields.intField($(".openassessment_criterion_option_points",this.element)),explanation:OpenAssessment.Fields.stringField($(".openassessment_criterion_option_explanation",this.element))};var nameString=OpenAssessment.Fields.stringField($(".openassessment_criterion_option_name",this.element));if(nameString!==""){fields.name=nameString}return fields},addHandler:function(){var criterionElement=$(this.element).closest(".openassessment_criterion");var criterionName=$(criterionElement).data("criterion");var criterionLabel=$(".openassessment_criterion_label",criterionElement).val();var options=$(".openassessment_criterion_option",this.element.parent());var name=OpenAssessment.ItemUtilities.createUniqueName(options,"data-option");$(this.element).attr("data-criterion",criterionName).attr("data-option",name);$(".openassessment_criterion_option_name",this.element).attr("value",name);var fields=this.getFieldValues();this.modificationHandler.notificationFired("optionAdd",{criterionName:criterionName,criterionLabel:criterionLabel,name:name,label:fields.label,points:fields.points})},removeHandler:function(){var criterionName=$(this.element).data("criterion");var optionName=$(this.element).data("option");this.modificationHandler.notificationFired("optionRemove",{criterionName:criterionName,name:optionName})},updateHandler:function(){var fields=this.getFieldValues();var criterionName=$(this.element).data("criterion");var optionName=$(this.element).data("option");var optionLabel=fields.label;var optionPoints=fields.points;this.modificationHandler.notificationFired("optionUpdated",{criterionName:criterionName,name:optionName,label:optionLabel,points:optionPoints})}};OpenAssessment.RubricCriterion=function(element){this.element=element;this.modificationHandler=new OpenAssessment.RubricEventHandler;this.optionContainer=new OpenAssessment.Container(OpenAssessment.RubricOption,{containerElement:$(".openassessment_criterion_option_list",this.element).get(0),templateElement:$("#openassessment_option_template").get(0),addButtonElement:$(".openassessment_criterion_add_option",this.element).get(0),removeButtonClass:"openassessment_criterion_option_remove_button",containerItemClass:"openassessment_criterion_option"});$(this.element).focusout($.proxy(this.updateHandler,this))};OpenAssessment.RubricCriterion.prototype={getFieldValues:function(){var fields={label:OpenAssessment.Fields.stringField($(".openassessment_criterion_label",this.element)),prompt:OpenAssessment.Fields.stringField($(".openassessment_criterion_prompt",this.element)),feedback:OpenAssessment.Fields.stringField($(".openassessment_criterion_feedback",this.element)),options:this.optionContainer.getItemValues()};var nameString=OpenAssessment.Fields.stringField($(".openassessment_criterion_name",this.element));if(nameString!==""){fields.name=nameString}return fields},addOption:function(){this.optionContainer.add()},addHandler:function(){var criteria=$(".openassessment_criterion",this.element.parent());var name=OpenAssessment.ItemUtilities.createUniqueName(criteria,"data-criterion");$(this.element).attr("data-criterion",name);$(".openassessment_criterion_name",this.element).attr("value",name)},removeHandler:function(){var criterionName=$(this.element).data("criterion");this.modificationHandler.notificationFired("criterionRemove",{criterionName:criterionName})},updateHandler:function(){var fields=this.getFieldValues();var criterionName=fields.name;var criterionLabel=fields.label;this.modificationHandler.notificationFired("criterionUpdated",{criterionName:criterionName,criterionLabel:criterionLabel})}};OpenAssessment.TrainingExample=function(element){this.element=element};OpenAssessment.TrainingExample.prototype={getFieldValues:function(){var optionsSelected=[];$(".openassessment_training_example_criterion_option",this.element).each(function(){optionsSelected.push({criterion:$(this).data("criterion"),option:$(this).prop("value")})});return{answer:$(".openassessment_training_example_essay",this.element).first().prop("value"),options_selected:optionsSelected}},addHandler:function(){},removeHandler:function(){},updateHandler:function(){}};OpenAssessment.GradeView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.GradeView.prototype={load:function(){var view=this;var baseView=this.baseView;this.server.render("grade").done(function(html){$("#openassessment__grade",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){baseView.showLoadError("grade",errMsg)})},installHandlers:function(){var sel=$("#openassessment__grade",this.element);this.baseView.setUpCollapseExpand(sel);var view=this;sel.find("#feedback__submit").click(function(eventObject){eventObject.preventDefault();view.submitFeedbackOnAssessment()})},feedbackText:function(text){if(typeof text==="undefined"){return $("#feedback__remarks__value",this.element).val()}else{$("#feedback__remarks__value",this.element).val(text)}},feedbackOptions:function(options){var view=this;if(typeof options==="undefined"){return $.map($(".feedback__overall__value:checked",view.element),function(element,index){return $(element).val()})}else{$(".feedback__overall__value",this.element).prop("checked",false);$.each(options,function(index,opt){$("#feedback__overall__value--"+opt,view.element).prop("checked",true)})}},setHidden:function(sel,hidden){sel.toggleClass("is--hidden",hidden);sel.attr("aria-hidden",hidden?"true":"false")},isHidden:function(sel){return sel.hasClass("is--hidden")&&sel.attr("aria-hidden")=="true"},feedbackState:function(newState){var containerSel=$(".submission__feedback__content",this.element);var instructionsSel=containerSel.find(".submission__feedback__instructions");var fieldsSel=containerSel.find(".submission__feedback__fields");var actionsSel=containerSel.find(".submission__feedback__actions");var transitionSel=containerSel.find(".transition__status");var messageSel=containerSel.find(".message--complete");if(typeof newState==="undefined"){var isSubmitting=containerSel.hasClass("is--transitioning")&&containerSel.hasClass("is--submitting")&&!this.isHidden(transitionSel)&&this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var hasSubmitted=containerSel.hasClass("is--submitted")&&this.isHidden(transitionSel)&&!this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var isOpen=!containerSel.hasClass("is--submitted")&&!containerSel.hasClass("is--transitioning")&&!containerSel.hasClass("is--submitting")&&this.isHidden(transitionSel)&&this.isHidden(messageSel)&&!this.isHidden(instructionsSel)&&!this.isHidden(fieldsSel)&&!this.isHidden(actionsSel);if(isOpen){return"open"}else if(isSubmitting){return"submitting"}else if(hasSubmitted){return"submitted"}else{throw"Invalid feedback state"}}else{if(newState=="open"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,false);this.setHidden(fieldsSel,false);this.setHidden(actionsSel,false);this.setHidden(transitionSel,true);this.setHidden(messageSel,true)}else if(newState=="submitting"){containerSel.toggleClass("is--transitioning",true);containerSel.toggleClass("is--submitting",true);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,false);this.setHidden(messageSel,true)}else if(newState=="submitted"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",true);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,true);this.setHidden(messageSel,false)}}},submitFeedbackOnAssessment:function(){var view=this;var baseView=this.baseView;$("#feedback__submit",this.element).toggleClass("is--disabled",true);view.feedbackState("submitting");this.server.submitFeedbackOnAssessment(this.feedbackText(),this.feedbackOptions()).done(function(){view.feedbackState("submitted")}).fail(function(errMsg){baseView.toggleActionError("feedback_assess",errMsg)})}};OpenAssessment.MessageView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.MessageView.prototype={load:function(){var view=this;var baseView=this.baseView;this.server.render("message").done(function(html){$("#openassessment__message",view.element).replaceWith(html)}).fail(function(errMsg){baseView.showLoadError("message",errMsg)})}};OpenAssessment.PeerView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.PeerView.prototype={load:function(){var view=this;this.server.render("peer_assessment").done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(false)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment")});view.baseView.loadMessageView()},loadContinuedAssessment:function(){var view=this;view.continueAssessmentEnabled(false);this.server.renderContinuedPeer().done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(true)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment");view.continueAssessmentEnabled(true)})},continueAssessmentEnabled:function(enabled){var button=$("#peer-assessment__continue__grading",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},installHandlers:function(isContinuedAssessment){var sel=$("#openassessment__peer-assessment",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#peer-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(view.peerSubmitEnabled,view))}sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();if(!isContinuedAssessment){view.peerAssess()}else{view.continuedPeerAssess()}});sel.find("#peer-assessment__continue__grading").click(function(eventObject){eventObject.preventDefault();view.loadContinuedAssessment()})},peerSubmitEnabled:function(enabled){var button=$("#peer-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},peerAssess:function(){var view=this;var baseView=view.baseView;this.peerAssessRequest(function(){view.load();baseView.loadAssessmentModules();baseView.scrollToTop()})},continuedPeerAssess:function(){var view=this;var gradeView=this.baseView.gradeView;var baseView=view.baseView;view.peerAssessRequest(function(){view.loadContinuedAssessment();gradeView.load();baseView.scrollToTop()})},peerAssessRequest:function(successFunction){var view=this;view.baseView.toggleActionError("peer",null);view.peerSubmitEnabled(false);this.server.peerAssess(this.rubric.optionsSelected(),this.rubric.criterionFeedback(),this.overallFeedback()).done(successFunction).fail(function(errMsg){view.baseView.toggleActionError("peer",errMsg);view.peerSubmitEnabled(true)})},overallFeedback:function(overallFeedback){var selector="#assessment__rubric__question--feedback__value";if(typeof overallFeedback==="undefined"){return $(selector,this.element).val()}else{$(selector,this.element).val(overallFeedback)}}};OpenAssessment.ResponseView=function(element,server,fileUploader,baseView){this.element=element;this.server=server;this.fileUploader=fileUploader;this.baseView=baseView;this.savedResponse="";this.files=null;this.imageType=null;this.lastChangeTime=Date.now();this.errorOnLastSave=false;this.autoSaveTimerId=null};OpenAssessment.ResponseView.prototype={AUTO_SAVE_POLL_INTERVAL:2e3,AUTO_SAVE_WAIT:3e4,MAX_FILE_SIZE:5242880,load:function(){var view=this;this.server.render("submission").done(function(html){$("#openassessment__response",view.element).replaceWith(html);view.installHandlers();view.setAutoSaveEnabled(true)}).fail(function(errMsg){view.baseView.showLoadError("response")})},installHandlers:function(){var sel=$("#openassessment__response",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);this.savedResponse=this.response();var handleChange=function(eventData){view.handleResponseChanged()};sel.find("#submission__answer__value").on("change keyup drop paste",handleChange);var handlePrepareUpload=function(eventData){view.prepareUpload(eventData.target.files)};sel.find("input[type=file]").on("change",handlePrepareUpload);sel.find("#step--response__submit").click(function(eventObject){eventObject.preventDefault();view.submit()});sel.find("#submission__save").click(function(eventObject){eventObject.preventDefault();view.save()});sel.find("#file__upload").click(function(eventObject){eventObject.preventDefault();view.fileUpload()})},setAutoSaveEnabled:function(enabled){if(enabled){if(this.autoSaveTimerId===null){this.autoSaveTimerId=setInterval($.proxy(this.autoSave,this),this.AUTO_SAVE_POLL_INTERVAL)}}else{if(this.autoSaveTimerId!==null){clearInterval(this.autoSaveTimerId)}}},submitEnabled:function(enabled){var sel=$("#step--response__submit",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveEnabled:function(enabled){var sel=$("#submission__save",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveStatus:function(msg){var sel=$("#response__save_status h3",this.element);if(typeof msg==="undefined"){return sel.text()}else{var label=gettext("Status of Your Response");sel.html('<span class="sr">'+label+":"+"</span>\n"+msg)}},unsavedWarningEnabled:function(enabled){if(typeof enabled==="undefined"){return window.onbeforeunload!==null}else{if(enabled){window.onbeforeunload=function(){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{window.onbeforeunload=null}}},response:function(text){var sel=$("#submission__answer__value",this.element);if(typeof text==="undefined"){return sel.val()}else{sel.val(text)}},responseChanged:function(){var currentResponse=$.trim(this.response());var savedResponse=$.trim(this.savedResponse);return savedResponse!==currentResponse},autoSave:function(){var timeSinceLastChange=Date.now()-this.lastChangeTime;if(this.responseChanged()&&timeSinceLastChange>this.AUTO_SAVE_WAIT&&!this.errorOnLastSave){this.save()}},handleResponseChanged:function(){var isBlank=$.trim(this.response())!=="";this.submitEnabled(isBlank);if(this.responseChanged()){this.saveEnabled(isBlank);this.saveStatus(gettext("This response has not been saved."));this.unsavedWarningEnabled(true)}this.lastChangeTime=Date.now()},save:function(){this.errorOnLastSave=false;this.saveStatus(gettext("Saving..."));this.baseView.toggleActionError("save",null);this.unsavedWarningEnabled(false);var view=this;var savedResponse=this.response();this.server.save(savedResponse).done(function(){view.savedResponse=savedResponse;var currentResponse=view.response();view.submitEnabled(currentResponse!=="");if(currentResponse==savedResponse){view.saveEnabled(false);view.saveStatus(gettext("This response has been saved but not submitted."))}}).fail(function(errMsg){view.saveStatus(gettext("Error"));view.baseView.toggleActionError("save",errMsg);view.errorOnLastSave=true})},submit:function(){this.submitEnabled(false);var view=this;var baseView=this.baseView;this.confirmSubmission().pipe(function(){var submission=$("#submission__answer__value",view.element).val();baseView.toggleActionError("response",null);return view.server.submit(submission)}).done($.proxy(view.moveToNextStep,view)).fail(function(errCode,errMsg){if(errCode=="ENOMULTI"){view.moveToNextStep()}else{if(errMsg){baseView.toggleActionError("submit",errMsg)}view.submitEnabled(true)}})},moveToNextStep:function(){this.load();this.baseView.loadAssessmentModules();this.unsavedWarningEnabled(false)},confirmSubmission:function(){var msg="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.";return $.Deferred(function(defer){if(confirm(msg)){defer.resolve()}else{defer.reject()}})},prepareUpload:function(files){this.files=null;this.imageType=files[0].type;if(files[0].size>this.MAX_FILE_SIZE){this.baseView.toggleActionError("upload",gettext("File size must be 5MB or less."))}else if(this.imageType.substring(0,6)!="image/"){this.baseView.toggleActionError("upload",gettext("File must be an image."))}else{this.baseView.toggleActionError("upload",null);this.files=files}$("#file__upload").toggleClass("is--disabled",this.files===null)},fileUpload:function(){var view=this;var fileUpload=$("#file__upload");fileUpload.addClass("is--disabled");var handleError=function(errMsg){view.baseView.toggleActionError("upload",errMsg);fileUpload.removeClass("is--disabled")};this.server.getUploadUrl(view.imageType).done(function(url){var image=view.files[0];view.fileUploader.upload(url,image,view.imageType).done(function(){view.imageUrl();view.baseView.toggleActionError("upload",null)}).fail(handleError)}).fail(handleError)},imageUrl:function(){var view=this;var image=$("#submission__answer__image",view.element);view.server.getDownloadUrl().done(function(url){image.attr("src",url);return url})}};OpenAssessment.Rubric=function(element){this.element=element};OpenAssessment.Rubric.prototype={criterionFeedback:function(criterionFeedback){var selector="textarea.answer__value";var feedback={};$(selector,this.element).each(function(index,sel){if(typeof criterionFeedback!=="undefined"){$(sel).val(criterionFeedback[sel.name]);feedback[sel.name]=criterionFeedback[sel.name]}else{feedback[sel.name]=$(sel).val()}});return feedback},optionsSelected:function(optionsSelected){var selector="input[type=radio]";if(typeof optionsSelected==="undefined"){var options={};$(selector+":checked",this.element).each(function(index,sel){options[sel.name]=sel.value});return options}else{$(selector,this.element).prop("checked",false);$(selector,this.element).each(function(index,sel){if(optionsSelected.hasOwnProperty(sel.name)){if(sel.value==optionsSelected[sel.name]){$(sel).prop("checked",true)}}})}},canSubmitCallback:function(callback){var rubric=this;callback(rubric.canSubmit());$(this.element).on("change keyup drop paste",function(){callback(rubric.canSubmit())})},canSubmit:function(){var numChecked=$("input[type=radio]:checked",this.element).length;var numAvailable=$(".field--radio.assessment__rubric__question.has--options",this.element).length;var completedRequiredComments=true;$("textarea[required]",this.element).each(function(){var trimmedText=$.trim($(this).val());if(trimmedText===""){completedRequiredComments=false}});return numChecked==numAvailable&&completedRequiredComments},showCorrections:function(corrections){var selector="input[type=radio]";var hasErrors=false;$(selector,this.element).each(function(index,sel){var listItem=$(sel).parents(".assessment__rubric__question");if(corrections.hasOwnProperty(sel.name)){hasErrors=true;listItem.find(".message--incorrect").removeClass("is--hidden");listItem.find(".message--correct").addClass("is--hidden")}else{listItem.find(".message--correct").removeClass("is--hidden");
listItem.find(".message--incorrect").addClass("is--hidden")}});return hasErrors}};OpenAssessment.SelfView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.SelfView.prototype={load:function(){var view=this;this.server.render("self_assessment").done(function(html){$("#openassessment__self-assessment",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.showLoadError("self-assessment")})},installHandlers:function(){var view=this;var sel=$("#openassessment__self-assessment",view.element);this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#self-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.selfSubmitEnabled,this))}sel.find("#self-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.selfAssess()})},selfSubmitEnabled:function(enabled){var button=$("#self-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},selfAssess:function(){var view=this;var baseView=this.baseView;baseView.toggleActionError("self",null);view.selfSubmitEnabled(false);var options=this.rubric.optionsSelected();this.server.selfAssess(options).done(function(){baseView.loadAssessmentModules();baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("self",errMsg);view.selfSubmitEnabled(true)})}};OpenAssessment.StaffInfoView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.StaffInfoView.prototype={load:function(){var view=this;if($("#openassessment__staff-info",view.element).length>0){this.server.render("staff_info").done(function(html){$("#openassessment__staff-info",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("staff_info")})}},loadStudentInfo:function(){var view=this;var sel=$("#openassessment__staff-info",this.element);var student_id=sel.find("#openassessment__student_id").val();this.server.studentInfo(student_id).done(function(html){$("#openassessment__student-info",view.element).replaceWith(html)}).fail(function(errMsg){view.showLoadError("student_info")})},installHandlers:function(){var sel=$("#openassessment__staff-info",this.element);var view=this;if(sel.length<=0){return}this.baseView.setUpCollapseExpand(sel,function(){});sel.find("#openassessment_student_info_form").submit(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()});sel.find("#submit_student_id").click(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()});sel.find("#schedule_training").click(function(eventObject){eventObject.preventDefault();view.scheduleTraining()});sel.find("#reschedule_unfinished_tasks").click(function(eventObject){eventObject.preventDefault();view.rescheduleUnfinishedTasks()})},scheduleTraining:function(){var view=this;this.server.scheduleTraining().done(function(msg){$("#schedule_training_message",this.element).text(msg)}).fail(function(errMsg){$("#schedule_training_message",this.element).text(errMsg)})},rescheduleUnfinishedTasks:function(){var view=this;this.server.rescheduleUnfinishedTasks().done(function(msg){$("#reschedule_unfinished_tasks_message",this.element).text(msg)}).fail(function(errMsg){$("#reschedule_unfinished_tasks_message",this.element).text(errMsg)})}};OpenAssessment.StudentTrainingView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.StudentTrainingView.prototype={load:function(){var view=this;this.server.render("student_training").done(function(html){$("#openassessment__student-training",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("student-training")})},installHandlers:function(){var sel=$("#openassessment__student-training",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#student-training--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.assessButtonEnabled,this))}sel.find("#student-training--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.assess()})},assess:function(){this.assessButtonEnabled(false);var options={};if(this.rubric!==null){options=this.rubric.optionsSelected()}var view=this;var baseView=this.baseView;this.server.trainingAssess(options).done(function(corrections){var incorrect=$("#openassessment__student-training--incorrect",this.element);var instructions=$("#openassessment__student-training--instructions",this.element);if(!view.rubric.showCorrections(corrections)){view.load();baseView.loadAssessmentModules();incorrect.addClass("is--hidden");instructions.removeClass("is--hidden")}else{instructions.addClass("is--hidden");incorrect.removeClass("is--hidden")}baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("student-training",errMsg);view.assessButtonEnabled(true)})},assessButtonEnabled:function(isEnabled){var button=$("#student-training--001__assessment__submit",this.element);if(typeof isEnabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!isEnabled)}}};
\ No newline at end of file
if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}if(typeof OpenAssessment.Server=="undefined"||!OpenAssessment.Server){OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX",gettext("This response could not be submitted.")])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},scheduleTraining:function(){var url=this.url("schedule_training");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},rescheduleUnfinishedTasks:function(){var url=this.url("reschedule_unfinished_tasks");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("One or more rescheduling tasks failed.")])})})},updateEditorContext:function(kwargs){var url=this.url("update_editor_context");var payload=JSON.stringify({prompt:kwargs.prompt,feedback_prompt:kwargs.feedbackPrompt,title:kwargs.title,submission_start:kwargs.submissionStart,submission_due:kwargs.submissionDue,criteria:kwargs.criteria,assessments:kwargs.assessments,editor_assessments_order:kwargs.editorAssessmentsOrder,allow_file_upload:kwargs.imageSubmissionEnabled});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This problem could not be saved.")])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("The server could not be contacted.")])})}).promise()},getUploadUrl:function(contentType){var url=this.url("upload_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({contentType:contentType})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve upload url.")])})}).promise()},getDownloadUrl:function(){var url=this.url("download_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve download url.")])})}).promise()}}}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.BaseView=function(runtime,element,server){this.runtime=runtime;this.element=element;this.server=server;this.fileUploader=new OpenAssessment.FileUploader;this.responseView=new OpenAssessment.ResponseView(this.element,this.server,this.fileUploader,this);this.trainingView=new OpenAssessment.StudentTrainingView(this.element,this.server,this);this.selfView=new OpenAssessment.SelfView(this.element,this.server,this);this.peerView=new OpenAssessment.PeerView(this.element,this.server,this);this.gradeView=new OpenAssessment.GradeView(this.element,this.server,this);this.messageView=new OpenAssessment.MessageView(this.element,this.server,this);this.staffInfoView=new OpenAssessment.StaffInfoView(this.element,this.server,this)};OpenAssessment.BaseView.prototype={scrollToTop:function(){if($.scrollTo instanceof Function){$(window).scrollTo($("#openassessment__steps"),800,{offset:-50})}},setUpCollapseExpand:function(parentSel){parentSel.find(".ui-toggle-visibility__control").click(function(eventData){var sel=$(eventData.target).closest(".ui-toggle-visibility");sel.toggleClass("is--collapsed")})},load:function(){this.responseView.load();this.loadAssessmentModules();this.staffInfoView.load()},loadAssessmentModules:function(){this.trainingView.load();this.peerView.load();this.selfView.load();this.gradeView.load()},loadMessageView:function(){this.messageView.load()},toggleActionError:function(type,msg){var element=this.element;var container=null;if(type=="save"){container=".response__submission__actions"}else if(type=="submit"||type=="peer"||type=="self"||type=="student-training"){container=".step__actions"}else if(type=="feedback_assess"){container=".submission__feedback__actions"}else if(type=="upload"){container="#upload__error"}if(container===null){if(msg!==null){console.log(msg)}}else{var msgHtml=msg===null?"":msg;$(container+" .message__content",element).html("<p>"+msgHtml+"</p>");$(container,element).toggleClass("has--error",msg!==null)}},showLoadError:function(step){var container="#openassessment__"+step;$(container).toggleClass("has--error",true);$(container+" .step__status__value i").removeClass().addClass("ico icon-warning-sign");$(container+" .step__status__value .copy").html(gettext("Unable to Load"))}};function OpenAssessmentBlock(runtime,element){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.BaseView(runtime,element,server);view.load()}OpenAssessment.FileUploader=function(){this.upload=function(url,data,contentType){return $.Deferred(function(defer){$.ajax({url:url,type:"PUT",data:data,async:false,processData:false,contentType:contentType}).done(function(data,textStatus,jqXHR){defer.resolve()}).fail(function(data,textStatus,jqXHR){defer.rejectWith(this,[textStatus])})}).promise()}};OpenAssessment.GradeView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.GradeView.prototype={load:function(){var view=this;var baseView=this.baseView;this.server.render("grade").done(function(html){$("#openassessment__grade",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){baseView.showLoadError("grade",errMsg)})},installHandlers:function(){var sel=$("#openassessment__grade",this.element);this.baseView.setUpCollapseExpand(sel);var view=this;sel.find("#feedback__submit").click(function(eventObject){eventObject.preventDefault();view.submitFeedbackOnAssessment()})},feedbackText:function(text){if(typeof text==="undefined"){return $("#feedback__remarks__value",this.element).val()}else{$("#feedback__remarks__value",this.element).val(text)}},feedbackOptions:function(options){var view=this;if(typeof options==="undefined"){return $.map($(".feedback__overall__value:checked",view.element),function(element,index){return $(element).val()})}else{$(".feedback__overall__value",this.element).prop("checked",false);$.each(options,function(index,opt){$("#feedback__overall__value--"+opt,view.element).prop("checked",true)})}},setHidden:function(sel,hidden){sel.toggleClass("is--hidden",hidden);sel.attr("aria-hidden",hidden?"true":"false")},isHidden:function(sel){return sel.hasClass("is--hidden")&&sel.attr("aria-hidden")=="true"},feedbackState:function(newState){var containerSel=$(".submission__feedback__content",this.element);var instructionsSel=containerSel.find(".submission__feedback__instructions");var fieldsSel=containerSel.find(".submission__feedback__fields");var actionsSel=containerSel.find(".submission__feedback__actions");var transitionSel=containerSel.find(".transition__status");var messageSel=containerSel.find(".message--complete");if(typeof newState==="undefined"){var isSubmitting=containerSel.hasClass("is--transitioning")&&containerSel.hasClass("is--submitting")&&!this.isHidden(transitionSel)&&this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var hasSubmitted=containerSel.hasClass("is--submitted")&&this.isHidden(transitionSel)&&!this.isHidden(messageSel)&&this.isHidden(instructionsSel)&&this.isHidden(fieldsSel)&&this.isHidden(actionsSel);var isOpen=!containerSel.hasClass("is--submitted")&&!containerSel.hasClass("is--transitioning")&&!containerSel.hasClass("is--submitting")&&this.isHidden(transitionSel)&&this.isHidden(messageSel)&&!this.isHidden(instructionsSel)&&!this.isHidden(fieldsSel)&&!this.isHidden(actionsSel);if(isOpen){return"open"}else if(isSubmitting){return"submitting"}else if(hasSubmitted){return"submitted"}else{throw"Invalid feedback state"}}else{if(newState=="open"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,false);this.setHidden(fieldsSel,false);this.setHidden(actionsSel,false);this.setHidden(transitionSel,true);this.setHidden(messageSel,true)}else if(newState=="submitting"){containerSel.toggleClass("is--transitioning",true);containerSel.toggleClass("is--submitting",true);containerSel.toggleClass("is--submitted",false);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,false);this.setHidden(messageSel,true)}else if(newState=="submitted"){containerSel.toggleClass("is--transitioning",false);containerSel.toggleClass("is--submitting",false);containerSel.toggleClass("is--submitted",true);this.setHidden(instructionsSel,true);this.setHidden(fieldsSel,true);this.setHidden(actionsSel,true);this.setHidden(transitionSel,true);this.setHidden(messageSel,false)}}},submitFeedbackOnAssessment:function(){var view=this;var baseView=this.baseView;$("#feedback__submit",this.element).toggleClass("is--disabled",true);view.feedbackState("submitting");this.server.submitFeedbackOnAssessment(this.feedbackText(),this.feedbackOptions()).done(function(){view.feedbackState("submitted")}).fail(function(errMsg){baseView.toggleActionError("feedback_assess",errMsg)})}};OpenAssessment.MessageView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.MessageView.prototype={load:function(){var view=this;var baseView=this.baseView;this.server.render("message").done(function(html){$("#openassessment__message",view.element).replaceWith(html)}).fail(function(errMsg){baseView.showLoadError("message",errMsg)})}};OpenAssessment.PeerView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.PeerView.prototype={load:function(){var view=this;this.server.render("peer_assessment").done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(false)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment")});view.baseView.loadMessageView()},loadContinuedAssessment:function(){var view=this;view.continueAssessmentEnabled(false);this.server.renderContinuedPeer().done(function(html){$("#openassessment__peer-assessment",view.element).replaceWith(html);view.installHandlers(true)}).fail(function(errMsg){view.baseView.showLoadError("peer-assessment");view.continueAssessmentEnabled(true)})},continueAssessmentEnabled:function(enabled){var button=$("#peer-assessment__continue__grading",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},installHandlers:function(isContinuedAssessment){var sel=$("#openassessment__peer-assessment",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#peer-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(view.peerSubmitEnabled,view))}sel.find("#peer-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();if(!isContinuedAssessment){view.peerAssess()}else{view.continuedPeerAssess()}});sel.find("#peer-assessment__continue__grading").click(function(eventObject){eventObject.preventDefault();view.loadContinuedAssessment()})},peerSubmitEnabled:function(enabled){var button=$("#peer-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},peerAssess:function(){var view=this;var baseView=view.baseView;this.peerAssessRequest(function(){view.load();baseView.loadAssessmentModules();baseView.scrollToTop()})},continuedPeerAssess:function(){var view=this;var gradeView=this.baseView.gradeView;var baseView=view.baseView;view.peerAssessRequest(function(){view.loadContinuedAssessment();gradeView.load();baseView.scrollToTop()})},peerAssessRequest:function(successFunction){var view=this;view.baseView.toggleActionError("peer",null);view.peerSubmitEnabled(false);this.server.peerAssess(this.rubric.optionsSelected(),this.rubric.criterionFeedback(),this.overallFeedback()).done(successFunction).fail(function(errMsg){view.baseView.toggleActionError("peer",errMsg);view.peerSubmitEnabled(true)})},overallFeedback:function(overallFeedback){var selector="#assessment__rubric__question--feedback__value";if(typeof overallFeedback==="undefined"){return $(selector,this.element).val()}else{$(selector,this.element).val(overallFeedback)}}};OpenAssessment.ResponseView=function(element,server,fileUploader,baseView){this.element=element;this.server=server;this.fileUploader=fileUploader;this.baseView=baseView;this.savedResponse="";this.files=null;this.imageType=null;this.lastChangeTime=Date.now();this.errorOnLastSave=false;this.autoSaveTimerId=null};OpenAssessment.ResponseView.prototype={AUTO_SAVE_POLL_INTERVAL:2e3,AUTO_SAVE_WAIT:3e4,MAX_FILE_SIZE:5242880,load:function(){var view=this;this.server.render("submission").done(function(html){$("#openassessment__response",view.element).replaceWith(html);view.installHandlers();view.setAutoSaveEnabled(true)}).fail(function(errMsg){view.baseView.showLoadError("response")})},installHandlers:function(){var sel=$("#openassessment__response",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);this.savedResponse=this.response();var handleChange=function(eventData){view.handleResponseChanged()};sel.find("#submission__answer__value").on("change keyup drop paste",handleChange);var handlePrepareUpload=function(eventData){view.prepareUpload(eventData.target.files)};sel.find("input[type=file]").on("change",handlePrepareUpload);sel.find("#step--response__submit").click(function(eventObject){eventObject.preventDefault();view.submit()});sel.find("#submission__save").click(function(eventObject){eventObject.preventDefault();view.save()});sel.find("#file__upload").click(function(eventObject){eventObject.preventDefault();view.fileUpload()})},setAutoSaveEnabled:function(enabled){if(enabled){if(this.autoSaveTimerId===null){this.autoSaveTimerId=setInterval($.proxy(this.autoSave,this),this.AUTO_SAVE_POLL_INTERVAL)}}else{if(this.autoSaveTimerId!==null){clearInterval(this.autoSaveTimerId)}}},submitEnabled:function(enabled){var sel=$("#step--response__submit",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveEnabled:function(enabled){var sel=$("#submission__save",this.element);if(typeof enabled==="undefined"){return!sel.hasClass("is--disabled")}else{sel.toggleClass("is--disabled",!enabled)}},saveStatus:function(msg){var sel=$("#response__save_status h3",this.element);if(typeof msg==="undefined"){return sel.text()}else{var label=gettext("Status of Your Response");sel.html('<span class="sr">'+label+":"+"</span>\n"+msg)}},unsavedWarningEnabled:function(enabled){if(typeof enabled==="undefined"){return window.onbeforeunload!==null}else{if(enabled){window.onbeforeunload=function(){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{window.onbeforeunload=null}}},response:function(text){var sel=$("#submission__answer__value",this.element);if(typeof text==="undefined"){return sel.val()}else{sel.val(text)}},responseChanged:function(){var currentResponse=$.trim(this.response());var savedResponse=$.trim(this.savedResponse);return savedResponse!==currentResponse},autoSave:function(){var timeSinceLastChange=Date.now()-this.lastChangeTime;if(this.responseChanged()&&timeSinceLastChange>this.AUTO_SAVE_WAIT&&!this.errorOnLastSave){this.save()}},handleResponseChanged:function(){var isBlank=$.trim(this.response())!=="";this.submitEnabled(isBlank);if(this.responseChanged()){this.saveEnabled(isBlank);this.saveStatus(gettext("This response has not been saved."));this.unsavedWarningEnabled(true)}this.lastChangeTime=Date.now()},save:function(){this.errorOnLastSave=false;this.saveStatus(gettext("Saving..."));this.baseView.toggleActionError("save",null);this.unsavedWarningEnabled(false);var view=this;var savedResponse=this.response();this.server.save(savedResponse).done(function(){view.savedResponse=savedResponse;var currentResponse=view.response();view.submitEnabled(currentResponse!=="");if(currentResponse==savedResponse){view.saveEnabled(false);view.saveStatus(gettext("This response has been saved but not submitted."))}}).fail(function(errMsg){view.saveStatus(gettext("Error"));view.baseView.toggleActionError("save",errMsg);view.errorOnLastSave=true})},submit:function(){this.submitEnabled(false);var view=this;var baseView=this.baseView;this.confirmSubmission().pipe(function(){var submission=$("#submission__answer__value",view.element).val();baseView.toggleActionError("response",null);return view.server.submit(submission)}).done($.proxy(view.moveToNextStep,view)).fail(function(errCode,errMsg){if(errCode=="ENOMULTI"){view.moveToNextStep()}else{if(errMsg){baseView.toggleActionError("submit",errMsg)}view.submitEnabled(true)}})},moveToNextStep:function(){this.load();this.baseView.loadAssessmentModules();this.unsavedWarningEnabled(false)},confirmSubmission:function(){var msg="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.";return $.Deferred(function(defer){if(confirm(msg)){defer.resolve()}else{defer.reject()}})},prepareUpload:function(files){this.files=null;this.imageType=files[0].type;if(files[0].size>this.MAX_FILE_SIZE){this.baseView.toggleActionError("upload",gettext("File size must be 5MB or less."))}else if(this.imageType.substring(0,6)!="image/"){this.baseView.toggleActionError("upload",gettext("File must be an image."))}else{this.baseView.toggleActionError("upload",null);this.files=files}$("#file__upload").toggleClass("is--disabled",this.files===null)},fileUpload:function(){var view=this;var fileUpload=$("#file__upload");fileUpload.addClass("is--disabled");var handleError=function(errMsg){view.baseView.toggleActionError("upload",errMsg);fileUpload.removeClass("is--disabled")};this.server.getUploadUrl(view.imageType).done(function(url){var image=view.files[0];view.fileUploader.upload(url,image,view.imageType).done(function(){view.imageUrl();view.baseView.toggleActionError("upload",null)}).fail(handleError)}).fail(handleError)},imageUrl:function(){var view=this;var image=$("#submission__answer__image",view.element);view.server.getDownloadUrl().done(function(url){image.attr("src",url);return url})}};OpenAssessment.Rubric=function(element){this.element=element};OpenAssessment.Rubric.prototype={criterionFeedback:function(criterionFeedback){var selector="textarea.answer__value";var feedback={};$(selector,this.element).each(function(index,sel){if(typeof criterionFeedback!=="undefined"){$(sel).val(criterionFeedback[sel.name]);feedback[sel.name]=criterionFeedback[sel.name]}else{feedback[sel.name]=$(sel).val()}});return feedback},optionsSelected:function(optionsSelected){var selector="input[type=radio]";if(typeof optionsSelected==="undefined"){var options={};$(selector+":checked",this.element).each(function(index,sel){options[sel.name]=sel.value});return options}else{$(selector,this.element).prop("checked",false);$(selector,this.element).each(function(index,sel){if(optionsSelected.hasOwnProperty(sel.name)){if(sel.value==optionsSelected[sel.name]){$(sel).prop("checked",true)}}})}},canSubmitCallback:function(callback){var rubric=this;callback(rubric.canSubmit());$(this.element).on("change keyup drop paste",function(){callback(rubric.canSubmit())})},canSubmit:function(){var numChecked=$("input[type=radio]:checked",this.element).length;var numAvailable=$(".field--radio.assessment__rubric__question.has--options",this.element).length;var completedRequiredComments=true;$("textarea[required]",this.element).each(function(){var trimmedText=$.trim($(this).val());if(trimmedText===""){completedRequiredComments=false}});return numChecked==numAvailable&&completedRequiredComments},showCorrections:function(corrections){var selector="input[type=radio]";var hasErrors=false;$(selector,this.element).each(function(index,sel){var listItem=$(sel).parents(".assessment__rubric__question");if(corrections.hasOwnProperty(sel.name)){hasErrors=true;listItem.find(".message--incorrect").removeClass("is--hidden");listItem.find(".message--correct").addClass("is--hidden")}else{listItem.find(".message--correct").removeClass("is--hidden");listItem.find(".message--incorrect").addClass("is--hidden")}});return hasErrors}};OpenAssessment.SelfView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.SelfView.prototype={load:function(){var view=this;this.server.render("self_assessment").done(function(html){$("#openassessment__self-assessment",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.showLoadError("self-assessment")})},installHandlers:function(){var view=this;var sel=$("#openassessment__self-assessment",view.element);this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#self-assessment--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.selfSubmitEnabled,this))}sel.find("#self-assessment--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.selfAssess()})},selfSubmitEnabled:function(enabled){var button=$("#self-assessment--001__assessment__submit",this.element);if(typeof enabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!enabled)}},selfAssess:function(){var view=this;var baseView=this.baseView;baseView.toggleActionError("self",null);view.selfSubmitEnabled(false);var options=this.rubric.optionsSelected();this.server.selfAssess(options).done(function(){baseView.loadAssessmentModules();baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("self",errMsg);view.selfSubmitEnabled(true)})}};OpenAssessment.StaffInfoView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView};OpenAssessment.StaffInfoView.prototype={load:function(){var view=this;if($("#openassessment__staff-info",view.element).length>0){this.server.render("staff_info").done(function(html){$("#openassessment__staff-info",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("staff_info")})}},loadStudentInfo:function(){var view=this;var sel=$("#openassessment__staff-info",this.element);var student_id=sel.find("#openassessment__student_id").val();this.server.studentInfo(student_id).done(function(html){$("#openassessment__student-info",view.element).replaceWith(html)}).fail(function(errMsg){view.showLoadError("student_info")})},installHandlers:function(){var sel=$("#openassessment__staff-info",this.element);var view=this;if(sel.length<=0){return}this.baseView.setUpCollapseExpand(sel,function(){});sel.find("#openassessment_student_info_form").submit(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()});sel.find("#submit_student_id").click(function(eventObject){eventObject.preventDefault();view.loadStudentInfo()});sel.find("#schedule_training").click(function(eventObject){eventObject.preventDefault();view.scheduleTraining()});sel.find("#reschedule_unfinished_tasks").click(function(eventObject){eventObject.preventDefault();view.rescheduleUnfinishedTasks()})},scheduleTraining:function(){var view=this;this.server.scheduleTraining().done(function(msg){$("#schedule_training_message",this.element).text(msg)}).fail(function(errMsg){$("#schedule_training_message",this.element).text(errMsg)})},rescheduleUnfinishedTasks:function(){var view=this;this.server.rescheduleUnfinishedTasks().done(function(msg){$("#reschedule_unfinished_tasks_message",this.element).text(msg)}).fail(function(errMsg){$("#reschedule_unfinished_tasks_message",this.element).text(errMsg)})}};OpenAssessment.StudentTrainingView=function(element,server,baseView){this.element=element;this.server=server;this.baseView=baseView;this.rubric=null};OpenAssessment.StudentTrainingView.prototype={load:function(){var view=this;this.server.render("student_training").done(function(html){$("#openassessment__student-training",view.element).replaceWith(html);view.installHandlers()}).fail(function(errMsg){view.baseView.showLoadError("student-training")})},installHandlers:function(){var sel=$("#openassessment__student-training",this.element);var view=this;this.baseView.setUpCollapseExpand(sel);var rubricSelector=$("#student-training--001__assessment",this.element);if(rubricSelector.size()>0){var rubricElement=rubricSelector.get(0);this.rubric=new OpenAssessment.Rubric(rubricElement)}if(this.rubric!==null){this.rubric.canSubmitCallback($.proxy(this.assessButtonEnabled,this))}sel.find("#student-training--001__assessment__submit").click(function(eventObject){eventObject.preventDefault();view.assess()})},assess:function(){this.assessButtonEnabled(false);var options={};if(this.rubric!==null){options=this.rubric.optionsSelected()}var view=this;var baseView=this.baseView;this.server.trainingAssess(options).done(function(corrections){var incorrect=$("#openassessment__student-training--incorrect",this.element);var instructions=$("#openassessment__student-training--instructions",this.element);if(!view.rubric.showCorrections(corrections)){view.load();baseView.loadAssessmentModules();incorrect.addClass("is--hidden");instructions.removeClass("is--hidden")}else{instructions.addClass("is--hidden");incorrect.removeClass("is--hidden")}baseView.scrollToTop()}).fail(function(errMsg){baseView.toggleActionError("student-training",errMsg);view.assessButtonEnabled(true)})},assessButtonEnabled:function(isEnabled){var button=$("#student-training--001__assessment__submit",this.element);if(typeof isEnabled==="undefined"){return!button.hasClass("is--disabled")}else{button.toggleClass("is--disabled",!isEnabled)}}};
\ No newline at end of file
if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.FileUploader=function(){this.upload=function(url,data,contentType){return $.Deferred(function(defer){$.ajax({url:url,type:"PUT",data:data,async:false,processData:false,contentType:contentType}).done(function(data,textStatus,jqXHR){defer.resolve()}).fail(function(data,textStatus,jqXHR){defer.rejectWith(this,[textStatus])})}).promise()}};if(typeof OpenAssessment.Server=="undefined"||!OpenAssessment.Server){OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX",gettext("This response could not be submitted.")])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},scheduleTraining:function(){var url=this.url("schedule_training");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},rescheduleUnfinishedTasks:function(){var url=this.url("reschedule_unfinished_tasks");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("One or more rescheduling tasks failed.")])})})},updateEditorContext:function(kwargs){var url=this.url("update_editor_context");var payload=JSON.stringify({prompt:kwargs.prompt,feedback_prompt:kwargs.feedbackPrompt,title:kwargs.title,submission_start:kwargs.submissionStart,submission_due:kwargs.submissionDue,criteria:kwargs.criteria,assessments:kwargs.assessments,editor_assessments_order:kwargs.editorAssessmentsOrder,allow_file_upload:kwargs.imageSubmissionEnabled});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This problem could not be saved.")])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("The server could not be contacted.")])})}).promise()},getUploadUrl:function(contentType){var url=this.url("upload_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({contentType:contentType})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve upload url.")])})}).promise()},getDownloadUrl:function(){var url=this.url("download_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve download url.")])})}).promise()}}}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.StudioView=function(runtime,element,server){this.element=element;this.runtime=runtime;this.server=server;this.fixModalHeight();this.initializeTabs();this.promptView=new OpenAssessment.EditPromptView($("#oa_prompt_editor_wrapper",this.element).get(0));var studentTrainingView=new OpenAssessment.EditStudentTrainingView($("#oa_student_training_editor",this.element).get(0));var peerAssessmentView=new OpenAssessment.EditPeerAssessmentView($("#oa_peer_assessment_editor",this.element).get(0));var selfAssessmentView=new OpenAssessment.EditSelfAssessmentView($("#oa_self_assessment_editor",this.element).get(0));var exampleBasedAssessmentView=new OpenAssessment.EditExampleBasedAssessmentView($("#oa_ai_assessment_editor",this.element).get(0));var assessmentLookupDictionary={};assessmentLookupDictionary[studentTrainingView.getID()]=studentTrainingView;assessmentLookupDictionary[peerAssessmentView.getID()]=peerAssessmentView;assessmentLookupDictionary[selfAssessmentView.getID()]=selfAssessmentView;assessmentLookupDictionary[exampleBasedAssessmentView.getID()]=exampleBasedAssessmentView;this.settingsView=new OpenAssessment.EditSettingsView($("#oa_basic_settings_editor",this.element).get(0),assessmentLookupDictionary);this.rubricView=new OpenAssessment.EditRubricView($("#oa_rubric_editor_wrapper",this.element).get(0));$(".openassessment_save_button",this.element).click($.proxy(this.save,this));$(".openassessment_cancel_button",this.element).click($.proxy(this.cancel,this))};OpenAssessment.StudioView.prototype={fixModalHeight:function(){$(this.element).addClass("openassessment_full_height").parentsUntil(".modal-window").addClass("openassessment_full_height");$(this.element).closest(".modal-window").addClass("openassessment_modal_window")},initializeTabs:function(){if(typeof OpenAssessment.lastOpenEditingTab==="undefined"){OpenAssessment.lastOpenEditingTab=2}$(".openassessment_editor_content_and_tabs",this.element).tabs({active:OpenAssessment.lastOpenEditingTab})},saveTabState:function(){var tabElement=$(".openassessment_editor_content_and_tabs",this.element);OpenAssessment.lastOpenEditingTab=tabElement.tabs("option","active")},save:function(){var view=this;this.saveTabState();this.server.checkReleased().done(function(isReleased){if(isReleased){view.confirmPostReleaseUpdate($.proxy(view.updateEditorContext,view))}else{view.updateEditorContext()}}).fail(function(errMsg){view.showError(errMsg)})},confirmPostReleaseUpdate:function(onConfirm){var msg=gettext("This problem has already been released. Any changes will apply only to future assessments.");if(confirm(msg)){onConfirm()}},updateEditorContext:function(){this.runtime.notify("save",{state:"start"});var view=this;this.server.updateEditorContext({prompt:view.promptView.promptText(),feedbackPrompt:view.rubricView.feedbackPrompt(),criteria:view.rubricView.criteriaDefinition(),title:view.settingsView.displayName(),submissionStart:view.settingsView.submissionStart(),submissionDue:view.settingsView.submissionDue(),assessments:view.settingsView.assessmentsDescription(),imageSubmissionEnabled:view.settingsView.imageSubmissionEnabled(),editorAssessmentsOrder:view.settingsView.editorAssessmentsOrder()}).done(function(){view.runtime.notify("save",{state:"end"})}).fail(function(msg){view.showError(msg)})},cancel:function(){this.saveTabState();this.runtime.notify("cancel",{})},showError:function(errorMsg){this.runtime.notify("error",{msg:errorMsg})}};function OpenAssessmentEditor(runtime,element){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.StudioView(runtime,element,server)}OpenAssessment.EditPeerAssessmentView=function(element){this.element=element;this.name="peer-assessment";new OpenAssessment.ToggleControl(this.element,"#peer_assessment_description_closed","#peer_assessment_settings_editor").install("#include_peer_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_start_date","#peer_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_due_date","#peer_assessment_due_time").install()};OpenAssessment.EditPeerAssessmentView.prototype={description:function(){return{must_grade:this.mustGradeNum(),must_be_graded_by:this.mustBeGradedByNum(),start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_peer_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},mustGradeNum:function(num){var sel=$("#peer_assessment_must_grade",this.element);return OpenAssessment.Fields.intField(sel,num)},mustBeGradedByNum:function(num){var sel=$("#peer_assessment_graded_by",this.element);return OpenAssessment.Fields.intField(sel,num)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditSelfAssessmentView=function(element){this.element=element;this.name="self-assessment";new OpenAssessment.ToggleControl(this.element,"#self_assessment_description_closed","#self_assessment_settings_editor").install("#include_self_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_start_date","#self_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_due_date","#self_assessment_due_time").install()};OpenAssessment.EditSelfAssessmentView.prototype={description:function(){return{start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_self_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditStudentTrainingView=function(element){this.element=element;this.name="student-training";new OpenAssessment.ToggleControl(this.element,"#student_training_description_closed","#student_training_settings_editor").install("#include_student_training");this.exampleContainer=new OpenAssessment.Container(OpenAssessment.TrainingExample,{containerElement:$("#openassessment_training_example_list",this.element).get(0),templateElement:$("#openassessment_training_example_template",this.element).get(0),addButtonElement:$(".openassessment_add_training_example",this.element).get(0),removeButtonClass:"openassessment_training_example_remove",containerItemClass:"openassessment_training_example"})};OpenAssessment.EditStudentTrainingView.prototype={description:function(){return{examples:this.exampleContainer.getItemValues()}},isEnabled:function(isEnabled){var sel=$("#include_student_training",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},exampleDefinitions:function(xml){var sel=$("#student_training_examples",this.element);return OpenAssessment.Fields.stringField(sel,xml)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditExampleBasedAssessmentView=function(element){this.element=element;this.name="example-based-assessment";new OpenAssessment.ToggleControl(this.element,"#ai_assessment_description_closed","#ai_assessment_settings_editor").install("#include_ai_assessment")};OpenAssessment.EditExampleBasedAssessmentView.prototype={description:function(){return{examples_xml:this.exampleDefinitions()}},isEnabled:function(isEnabled){var sel=$("#include_ai_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},exampleDefinitions:function(xml){var sel=$("#ai_training_examples",this.element);return OpenAssessment.Fields.stringField(sel,xml)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.Fields={stringField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return sel.val()},intField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return parseInt(sel.val(),10)},booleanField:function(sel,value){if(typeof value!=="undefined"){sel.prop("checked",value)}return sel.prop("checked")}};OpenAssessment.ToggleControl=function(element,hiddenSelector,shownSelector){this.element=element;this.hiddenSelector=hiddenSelector;this.shownSelector=shownSelector};OpenAssessment.ToggleControl.prototype={install:function(checkboxSelector){$(checkboxSelector,this.element).change(this,function(event){var control=event.data;if(this.checked){control.show()}else{control.hide()}});return this},show:function(){$(this.hiddenSelector,this.element).addClass("is--hidden");$(this.shownSelector,this.element).removeClass("is--hidden")},hide:function(){$(this.hiddenSelector,this.element).removeClass("is--hidden");$(this.shownSelector,this.element).addClass("is--hidden")}};OpenAssessment.DatetimeControl=function(element,datePicker,timePicker){this.element=element;this.datePicker=datePicker;this.timePicker=timePicker};OpenAssessment.DatetimeControl.prototype={install:function(){var dateString=$(this.datePicker,this.element).val();$(this.datePicker,this.element).datepicker({showButtonPanel:true}).datepicker("option","dateFormat","yy-mm-dd").datepicker("setDate",dateString);$(this.timePicker,this.element).timepicker({timeFormat:"H:i",step:60});return this},datetime:function(dateString,timeString){var datePickerSel=$(this.datePicker,this.element);var timePickerSel=$(this.timePicker,this.element);if(typeof dateString!=="undefined"){datePickerSel.datepicker("setDate",dateString)}if(typeof timeString!=="undefined"){timePickerSel.val(timeString)}if(datePickerSel.val()===""&&timePickerSel.val()===""){return null}return datePickerSel.val()+"T"+timePickerSel.val()}};OpenAssessment.EditPromptView=function(element){this.element=element};OpenAssessment.EditPromptView.prototype={promptText:function(text){var sel=$("#openassessment_prompt_editor",this.element);return OpenAssessment.Fields.stringField(sel,text)}};OpenAssessment.EditRubricView=function(element){this.element=element;this.criteriaContainer=new OpenAssessment.Container(OpenAssessment.RubricCriterion,{containerElement:$("#openassessment_criterion_list",this.element).get(0),templateElement:$("#openassessment_criterion_template",this.element).get(0),addButtonElement:$("#openassessment_rubric_add_criterion",this.element).get(0),removeButtonClass:"openassessment_criterion_remove_button",containerItemClass:"openassessment_criterion"});this.alert=new OpenAssessment.ValidationAlert($("#openassessment_rubric_validation_alert",this.element))};OpenAssessment.EditRubricView.prototype={criteriaDefinition:function(){var criteria=this.criteriaContainer.getItemValues();for(var criterion_idx=0;criterion_idx<criteria.length;criterion_idx++){var criterion=criteria[criterion_idx];criterion.order_num=criterion_idx;for(var option_idx=0;option_idx<criterion.options.length;option_idx++){var option=criterion.options[option_idx];option.order_num=option_idx}}return criteria},feedbackPrompt:function(text){var sel=$("#openassessment_rubric_feedback",this.element);return OpenAssessment.Fields.stringField(sel,text)},removeAllCriteria:function(){var items=this.criteriaContainer.getAllItems();var view=this;$.each(items,function(){view.criteriaContainer.remove(this)})},addCriterion:function(){this.criteriaContainer.add()},getCriterionItem:function(index){return this.criteriaContainer.getItem(index)}};OpenAssessment.ValidationAlert=function(element){this.element=element;this.title=$(".openassessment_alert_title",this.element);this.message=$(".openassessment_alert_message",this.element)};OpenAssessment.ValidationAlert.prototype={hide:function(){this.element.addClass("is--hidden")},show:function(){this.element.removeClass("is--hidden")},setMessage:function(newTitle,newMessage){this.title.text(newTitle);this.message.text(newMessage)}};OpenAssessment.EditSettingsView=function(element,assessmentViews){this.settingsElement=element;this.assessmentsElement=$(element).siblings("#openassessment_assessment_module_settings_editors").get(0);this.assessmentViews=assessmentViews;this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_start_date","#openassessment_submission_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_due_date","#openassessment_submission_due_time").install();this.initializeSortableAssessments()};OpenAssessment.EditSettingsView.prototype={initializeSortableAssessments:function(){var view=this;$("#openassessment_assessment_module_settings_editors",view.element).sortable({start:function(event,ui){$(".openassessment_assessment_module_editor",view.element).hide();var targetHeight="auto";ui.placeholder.height(targetHeight);ui.helper.height(targetHeight);$("#openassessment_assessment_module_settings_editors",view.element).sortable("refresh").sortable("refreshPositions")},stop:function(event,ui){$(".openassessment_assessment_module_editor",view.element).show()},snap:true,axis:"y",handle:".drag-handle",cursorAt:{top:20}});$("#openassessment_assessment_module_settings_editors .drag-handle",view.element).disableSelection()},displayName:function(name){var sel=$("#openassessment_title_editor",this.settingsElement);return OpenAssessment.Fields.stringField(sel,name)},submissionStart:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},submissionDue:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},imageSubmissionEnabled:function(isEnabled){var sel=$("#openassessment_submission_image_editor",this.settingsElement);if(typeof isEnabled!=="undefined"){if(isEnabled){sel.val(1)}else{sel.val(0)}}return sel.val()==1},assessmentsDescription:function(){var assessmentDescList=[];var view=this;$(".openassessment_assessment_module_settings_editor",this.assessmentsElement).each(function(){var asmntView=view.assessmentViews[$(this).attr("id")];if(asmntView.isEnabled()){var description=asmntView.description();description["name"]=asmntView.name;assessmentDescList.push(description)}});return assessmentDescList},editorAssessmentsOrder:function(){var editorAssessments=[];var view=this;$(".openassessment_assessment_module_settings_editor",this.assessmentsElement).each(function(){var asmntView=view.assessmentViews[$(this).attr("id")];editorAssessments.push(asmntView.name)});return editorAssessments}};OpenAssessment.RubricEventHandler=function(){this.listeners=[new OpenAssessment.StudentTrainingListener]};OpenAssessment.RubricEventHandler.prototype={notificationFired:function(name,data){for(var i=0;i<this.listeners.length;i++){if(typeof this.listeners[i][name]==="function"){this.listeners[i][name](data)}}}};OpenAssessment.StudentTrainingListener=function(){this.element=$("#oa_student_training_editor");this.alert=new OpenAssessment.ValidationAlert($("#openassessment_rubric_validation_alert"))};OpenAssessment.StudentTrainingListener.prototype={generateOptionString:function(name,points){return name+" - "+points+gettext(" points")},optionUpdated:function(data){var view=this;$('.openassessment_training_example_criterion[data-criterion="'+data.criterionName+'"',this.element).each(function(){var criterion=this;var option=$("option[value='"+data.name+"'",criterion);$(option).text(view.generateOptionString(data.label,data.points))})},optionAdd:function(data){var options=$('.openassessment_training_example_criterion_option[data-criterion="'+data.criterionName+'"]');var view=this;var criterionAdded=false;var examplesUpdated=false;if(options.length==0){this.criterionAdd(data);criterionAdded=true}$(".openassessment_training_example_criterion_option",this.element).each(function(){if($(this).data("criterion")===data.criterionName){var criterion=this;$(criterion).append($("<option></option>").attr("value",data.name).text(view.generateOptionString(data.label,data.points)));examplesUpdated=true}});if(criterionAdded&&examplesUpdated){this.displayAlertMsg(gettext("Criterion Addition requires Training Example Updates"),gettext("Because you added a criterion, student training examples "+"will have to be updated."))}},optionRemove:function(data){var validator=this;var changed=false;$(".openassessment_training_example_criterion_option",this.element).each(function(){var criterionOption=this;if($(criterionOption).data("criterion")===data.criterionName){if($(criterionOption).val()==data.name){$(criterionOption).val("");$(criterionOption).addClass("openassessment_highlighted_field");$(criterionOption).click(function(){$(criterionOption).removeClass("openassessment_highlighted_field")});changed=true}$("option[value='"+data.name+"'",criterionOption).remove();if($("option",criterionOption).length==1){validator.removeAllOptions(data);return}}});if(changed){this.displayAlertMsg(gettext("Option Deletion Led to Invalidation"),gettext("Because you deleted an option, some student training "+"examples had to be reset."))}},removeAllOptions:function(data){var changed=false;$(".openassessment_training_example_criterion",this.element).each(function(){var criterion=this;if($(criterion).data("criterion")==data.criterionName){$(criterion).remove();changed=true}});if(changed){this.displayAlertMsg(gettext("Option Deletion Led to Invalidation"),gettext("The deletion of the last criterion option caused the "+"criterion to be removed in the student training examples."))}},criterionRemove:function(data){var changed=false;$('.openassessment_training_example_criterion[data-criterion="'+data.criterionName+'"',this.element).each(function(){$(this).remove();changed=true});if(changed){this.displayAlertMsg(gettext("Criterion Deletion Led to Invalidation"),gettext("Because you deleted a criterion, there were student "+"training examples where the criterion had to be removed."))}},displayAlertMsg:function(title,msg){this.alert.setMessage(title,msg);this.alert.show()},criterionUpdated:function(data){$('.openassessment_training_example_criterion[data-criterion="'+data.criterionName+'"',this.element).each(function(){$(".openassessment_training_example_criterion_name_wrapper",this).text(data.criterionLabel)})},criterionAdd:function(data){var view=this.element;var criterion=$("#openassessment_training_example_criterion_template").children().first().clone().removeAttr("id").attr("data-criterion",data.criterionName).toggleClass("is--hidden",false).appendTo(".openassessment_training_example_criteria_selections",view);criterion.find(".openassessment_training_example_criterion_option").attr("data-criterion",data.criterionName);criterion.find(".openassessment_training_example_criterion_name_wrapper").text(data.label)}};
\ No newline at end of file
if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}if(typeof OpenAssessment.Server=="undefined"||!OpenAssessment.Server){OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX",gettext("This response could not be submitted.")])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},scheduleTraining:function(){var url=this.url("schedule_training");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},rescheduleUnfinishedTasks:function(){var url=this.url("reschedule_unfinished_tasks");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("One or more rescheduling tasks failed.")])})})},updateEditorContext:function(kwargs){var url=this.url("update_editor_context");var payload=JSON.stringify({prompt:kwargs.prompt,feedback_prompt:kwargs.feedbackPrompt,title:kwargs.title,submission_start:kwargs.submissionStart,submission_due:kwargs.submissionDue,criteria:kwargs.criteria,assessments:kwargs.assessments,editor_assessments_order:kwargs.editorAssessmentsOrder,allow_file_upload:kwargs.imageSubmissionEnabled});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This problem could not be saved.")])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("The server could not be contacted.")])})}).promise()},getUploadUrl:function(contentType){var url=this.url("upload_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({contentType:contentType})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve upload url.")])})}).promise()},getDownloadUrl:function(){var url=this.url("download_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve download url.")])})}).promise()}}}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.Container=function(containerItem,kwargs){this.containerElement=kwargs.containerElement;this.templateElement=kwargs.templateElement;this.addButtonElement=kwargs.addButtonElement;this.removeButtonClass=kwargs.removeButtonClass;this.containerItemClass=kwargs.containerItemClass;this.notifier=kwargs.notifier;var container=this;this.createContainerItem=function(element){return new containerItem(element,container.notifier)};$(this.addButtonElement).click($.proxy(this.add,this));$("."+this.removeButtonClass,this.containerElement).click(function(eventData){var item=container.createContainerItem(eventData.target);container.remove(item)});$("."+this.containerItemClass,this.containerElement).each(function(index,element){container.createContainerItem(element)})};OpenAssessment.Container.prototype={add:function(){$(this.templateElement).children().first().clone().removeAttr("id").toggleClass("is--hidden",false).toggleClass(this.containerItemClass,true).appendTo($(this.containerElement));var container=this;var containerItem=$("."+this.containerItemClass,this.containerElement).last();containerItem.find("."+this.removeButtonClass).click(function(eventData){var containerItem=container.createContainerItem(eventData.target);container.remove(containerItem)});var handlerItem=container.createContainerItem(containerItem);handlerItem.addHandler()},remove:function(item){var itemElement=$(item.element).closest("."+this.containerItemClass);var containerItem=this.createContainerItem(itemElement);containerItem.removeHandler();itemElement.remove()},getItemValues:function(){var values=[];var container=this;$("."+this.containerItemClass,this.containerElement).each(function(index,element){var containerItem=container.createContainerItem(element);var fieldValues=containerItem.getFieldValues();values.push(fieldValues)});return values},getItem:function(index){var element=$("."+this.containerItemClass,this.containerElement).get(index);return element!==undefined?this.createContainerItem(element):null},getAllItems:function(){var container=this;return $("."+this.containerItemClass,this.containerElement).map(function(){return container.createContainerItem(this)})}};OpenAssessment.ItemUtilities={createUniqueName:function(selector,nameAttribute){var index=0;while(index<=selector.length){if(selector.parent().find("*["+nameAttribute+"='"+index+"']").length===0){return index.toString()}index++}return null}};OpenAssessment.RubricOption=function(element,notifier){this.element=element;this.notifier=notifier;$(this.element).focusout($.proxy(this.updateHandler,this))};OpenAssessment.RubricOption.prototype={getFieldValues:function(){var fields={label:OpenAssessment.Fields.stringField($(".openassessment_criterion_option_label",this.element)),points:OpenAssessment.Fields.intField($(".openassessment_criterion_option_points",this.element)),explanation:OpenAssessment.Fields.stringField($(".openassessment_criterion_option_explanation",this.element))};var nameString=OpenAssessment.Fields.stringField($(".openassessment_criterion_option_name",this.element));if(nameString!==""){fields.name=nameString}return fields},addHandler:function(){var criterionElement=$(this.element).closest(".openassessment_criterion");var criterionName=$(criterionElement).data("criterion");var criterionLabel=$(".openassessment_criterion_label",criterionElement).val();var options=$(".openassessment_criterion_option",this.element.parent());var name=OpenAssessment.ItemUtilities.createUniqueName(options,"data-option");$(this.element).attr("data-criterion",criterionName).attr("data-option",name);$(".openassessment_criterion_option_name",this.element).attr("value",name);var fields=this.getFieldValues();this.notifier.notificationFired("optionAdd",{criterionName:criterionName,criterionLabel:criterionLabel,name:name,label:fields.label,points:fields.points})},removeHandler:function(){var criterionName=$(this.element).data("criterion");var optionName=$(this.element).data("option");this.notifier.notificationFired("optionRemove",{criterionName:criterionName,name:optionName})},updateHandler:function(){var fields=this.getFieldValues();var criterionName=$(this.element).data("criterion");var optionName=$(this.element).data("option");var optionLabel=fields.label;var optionPoints=fields.points;this.notifier.notificationFired("optionUpdated",{criterionName:criterionName,name:optionName,label:optionLabel,points:optionPoints})}};OpenAssessment.RubricCriterion=function(element,notifier){this.element=element;this.notifier=notifier;this.optionContainer=new OpenAssessment.Container(OpenAssessment.RubricOption,{containerElement:$(".openassessment_criterion_option_list",this.element).get(0),templateElement:$("#openassessment_option_template").get(0),addButtonElement:$(".openassessment_criterion_add_option",this.element).get(0),removeButtonClass:"openassessment_criterion_option_remove_button",containerItemClass:"openassessment_criterion_option",notifier:this.notifier});$(this.element).focusout($.proxy(this.updateHandler,this))};OpenAssessment.RubricCriterion.prototype={getFieldValues:function(){var fields={label:OpenAssessment.Fields.stringField($(".openassessment_criterion_label",this.element)),prompt:OpenAssessment.Fields.stringField($(".openassessment_criterion_prompt",this.element)),feedback:OpenAssessment.Fields.stringField($(".openassessment_criterion_feedback",this.element)),options:this.optionContainer.getItemValues()};var nameString=OpenAssessment.Fields.stringField($(".openassessment_criterion_name",this.element));if(nameString!==""){fields.name=nameString}return fields},addOption:function(){this.optionContainer.add()},addHandler:function(){var criteria=$(".openassessment_criterion",this.element.parent());var name=OpenAssessment.ItemUtilities.createUniqueName(criteria,"data-criterion");$(this.element).attr("data-criterion",name);$(".openassessment_criterion_name",this.element).attr("value",name)},removeHandler:function(){var criterionName=$(this.element).data("criterion");this.notifier.notificationFired("criterionRemove",{criterionName:criterionName})},updateHandler:function(){var fields=this.getFieldValues();var criterionName=fields.name;var criterionLabel=fields.label;this.notifier.notificationFired("criterionUpdated",{criterionName:criterionName,criterionLabel:criterionLabel})}};OpenAssessment.TrainingExample=function(element){this.element=element};OpenAssessment.TrainingExample.prototype={getFieldValues:function(){var optionsSelected=[];$(".openassessment_training_example_criterion_option",this.element).each(function(){optionsSelected.push({criterion:$(this).data("criterion"),option:$(this).prop("value")})});return{answer:$(".openassessment_training_example_essay",this.element).first().prop("value"),options_selected:optionsSelected}},addHandler:function(){},removeHandler:function(){},updateHandler:function(){}};OpenAssessment.StudioView=function(runtime,element,server){this.element=element;this.runtime=runtime;this.server=server;this.fixModalHeight();this.initializeTabs();this.promptView=new OpenAssessment.EditPromptView($("#oa_prompt_editor_wrapper",this.element).get(0));var studentTrainingView=new OpenAssessment.EditStudentTrainingView($("#oa_student_training_editor",this.element).get(0));var peerAssessmentView=new OpenAssessment.EditPeerAssessmentView($("#oa_peer_assessment_editor",this.element).get(0));var selfAssessmentView=new OpenAssessment.EditSelfAssessmentView($("#oa_self_assessment_editor",this.element).get(0));var exampleBasedAssessmentView=new OpenAssessment.EditExampleBasedAssessmentView($("#oa_ai_assessment_editor",this.element).get(0));var assessmentLookupDictionary={};assessmentLookupDictionary[studentTrainingView.getID()]=studentTrainingView;assessmentLookupDictionary[peerAssessmentView.getID()]=peerAssessmentView;assessmentLookupDictionary[selfAssessmentView.getID()]=selfAssessmentView;assessmentLookupDictionary[exampleBasedAssessmentView.getID()]=exampleBasedAssessmentView;this.settingsView=new OpenAssessment.EditSettingsView($("#oa_basic_settings_editor",this.element).get(0),assessmentLookupDictionary);this.rubricView=new OpenAssessment.EditRubricView($("#oa_rubric_editor_wrapper",this.element).get(0),new OpenAssessment.Notifier([new OpenAssessment.StudentTrainingListener]));$(".openassessment_save_button",this.element).click($.proxy(this.save,this));$(".openassessment_cancel_button",this.element).click($.proxy(this.cancel,this))};OpenAssessment.StudioView.prototype={fixModalHeight:function(){$(this.element).addClass("openassessment_full_height").parentsUntil(".modal-window").addClass("openassessment_full_height");$(this.element).closest(".modal-window").addClass("openassessment_modal_window")},initializeTabs:function(){if(typeof OpenAssessment.lastOpenEditingTab==="undefined"){OpenAssessment.lastOpenEditingTab=2}$(".openassessment_editor_content_and_tabs",this.element).tabs({active:OpenAssessment.lastOpenEditingTab})},saveTabState:function(){var tabElement=$(".openassessment_editor_content_and_tabs",this.element);OpenAssessment.lastOpenEditingTab=tabElement.tabs("option","active")},save:function(){var view=this;this.saveTabState();this.server.checkReleased().done(function(isReleased){if(isReleased){view.confirmPostReleaseUpdate($.proxy(view.updateEditorContext,view))}else{view.updateEditorContext()}}).fail(function(errMsg){view.showError(errMsg)})},confirmPostReleaseUpdate:function(onConfirm){var msg=gettext("This problem has already been released. Any changes will apply only to future assessments.");if(confirm(msg)){onConfirm()}},updateEditorContext:function(){this.runtime.notify("save",{state:"start"});var view=this;this.server.updateEditorContext({prompt:view.promptView.promptText(),feedbackPrompt:view.rubricView.feedbackPrompt(),criteria:view.rubricView.criteriaDefinition(),title:view.settingsView.displayName(),submissionStart:view.settingsView.submissionStart(),submissionDue:view.settingsView.submissionDue(),assessments:view.settingsView.assessmentsDescription(),imageSubmissionEnabled:view.settingsView.imageSubmissionEnabled(),editorAssessmentsOrder:view.settingsView.editorAssessmentsOrder()}).done(function(){view.runtime.notify("save",{state:"end"})}).fail(function(msg){view.showError(msg)})},cancel:function(){this.saveTabState();this.runtime.notify("cancel",{})},showError:function(errorMsg){this.runtime.notify("error",{msg:errorMsg})}};function OpenAssessmentEditor(runtime,element){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.StudioView(runtime,element,server)}OpenAssessment.EditPeerAssessmentView=function(element){this.element=element;this.name="peer-assessment";new OpenAssessment.ToggleControl(this.element,"#peer_assessment_description_closed","#peer_assessment_settings_editor").install("#include_peer_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_start_date","#peer_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_due_date","#peer_assessment_due_time").install()};OpenAssessment.EditPeerAssessmentView.prototype={description:function(){return{must_grade:this.mustGradeNum(),must_be_graded_by:this.mustBeGradedByNum(),start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_peer_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},mustGradeNum:function(num){var sel=$("#peer_assessment_must_grade",this.element);return OpenAssessment.Fields.intField(sel,num)},mustBeGradedByNum:function(num){var sel=$("#peer_assessment_graded_by",this.element);return OpenAssessment.Fields.intField(sel,num)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditSelfAssessmentView=function(element){this.element=element;this.name="self-assessment";new OpenAssessment.ToggleControl(this.element,"#self_assessment_description_closed","#self_assessment_settings_editor").install("#include_self_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_start_date","#self_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_due_date","#self_assessment_due_time").install()};OpenAssessment.EditSelfAssessmentView.prototype={description:function(){return{start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_self_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditStudentTrainingView=function(element){this.element=element;this.name="student-training";new OpenAssessment.ToggleControl(this.element,"#student_training_description_closed","#student_training_settings_editor").install("#include_student_training");this.exampleContainer=new OpenAssessment.Container(OpenAssessment.TrainingExample,{containerElement:$("#openassessment_training_example_list",this.element).get(0),templateElement:$("#openassessment_training_example_template",this.element).get(0),addButtonElement:$(".openassessment_add_training_example",this.element).get(0),removeButtonClass:"openassessment_training_example_remove",containerItemClass:"openassessment_training_example"})};OpenAssessment.EditStudentTrainingView.prototype={description:function(){return{examples:this.exampleContainer.getItemValues()}},isEnabled:function(isEnabled){var sel=$("#include_student_training",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditExampleBasedAssessmentView=function(element){this.element=element;this.name="example-based-assessment";new OpenAssessment.ToggleControl(this.element,"#ai_assessment_description_closed","#ai_assessment_settings_editor").install("#include_ai_assessment")};OpenAssessment.EditExampleBasedAssessmentView.prototype={description:function(){return{examples_xml:this.exampleDefinitions()}},isEnabled:function(isEnabled){var sel=$("#include_ai_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},exampleDefinitions:function(xml){var sel=$("#ai_training_examples",this.element);return OpenAssessment.Fields.stringField(sel,xml)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.Fields={stringField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return sel.val()},intField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return parseInt(sel.val(),10)},booleanField:function(sel,value){if(typeof value!=="undefined"){sel.prop("checked",value)}return sel.prop("checked")}};OpenAssessment.ToggleControl=function(element,hiddenSelector,shownSelector){this.element=element;this.hiddenSelector=hiddenSelector;this.shownSelector=shownSelector};OpenAssessment.ToggleControl.prototype={install:function(checkboxSelector){$(checkboxSelector,this.element).change(this,function(event){var control=event.data;if(this.checked){control.show()}else{control.hide()}});return this},show:function(){$(this.hiddenSelector,this.element).addClass("is--hidden");$(this.shownSelector,this.element).removeClass("is--hidden")},hide:function(){$(this.hiddenSelector,this.element).removeClass("is--hidden");$(this.shownSelector,this.element).addClass("is--hidden")}};OpenAssessment.DatetimeControl=function(element,datePicker,timePicker){this.element=element;this.datePicker=datePicker;this.timePicker=timePicker};OpenAssessment.DatetimeControl.prototype={install:function(){var dateString=$(this.datePicker,this.element).val();$(this.datePicker,this.element).datepicker({showButtonPanel:true}).datepicker("option","dateFormat","yy-mm-dd").datepicker("setDate",dateString);$(this.timePicker,this.element).timepicker({timeFormat:"H:i",step:60});return this},datetime:function(dateString,timeString){var datePickerSel=$(this.datePicker,this.element);var timePickerSel=$(this.timePicker,this.element);if(typeof dateString!=="undefined"){datePickerSel.datepicker("setDate",dateString)}if(typeof timeString!=="undefined"){timePickerSel.val(timeString)}if(datePickerSel.val()===""&&timePickerSel.val()===""){return null}return datePickerSel.val()+"T"+timePickerSel.val()}};OpenAssessment.StudentTrainingListener=function(){this.element=$("#oa_student_training_editor");this.alert=new OpenAssessment.ValidationAlert($("#openassessment_rubric_validation_alert"))};OpenAssessment.StudentTrainingListener.prototype={optionUpdated:function(data){var view=this;var sel='.openassessment_training_example_criterion[data-criterion="'+data.criterionName+'"]';$(sel,this.element).each(function(){var criterion=this;var option=$('option[value="'+data.name+'"]',criterion);$(option).text(view._generateOptionString(data.label,data.points))})},optionAdd:function(data){var options=$('.openassessment_training_example_criterion_option[data-criterion="'+data.criterionName+'"]');var view=this;var criterionAdded=false;var examplesUpdated=false;if(options.length===0){this.criterionAdd(data);criterionAdded=true}$(".openassessment_training_example_criterion_option",this.element).each(function(){if($(this).data("criterion")===data.criterionName){var criterion=this;$(criterion).append($("<option></option>").attr("value",data.name).text(view._generateOptionString(data.label,data.points)));examplesUpdated=true}});if(criterionAdded&&examplesUpdated){this.displayAlertMsg(gettext("Criterion Addition requires Training Example Updates"),gettext("Because you added a criterion, student training examples will have to be updated."))}},optionRemove:function(data){var handler=this;var changed=false;$(".openassessment_training_example_criterion_option",this.element).each(function(){var criterionOption=this;if($(criterionOption).data("criterion")===data.criterionName){if($(criterionOption).val()==data.name){$(criterionOption).val("");$(criterionOption).addClass("openassessment_highlighted_field");$(criterionOption).click(function(){$(criterionOption).removeClass("openassessment_highlighted_field")});changed=true}$('option[value="'+data.name+'"]',criterionOption).remove();if($("option",criterionOption).length==1){handler.removeAllOptions(data);return}}});if(changed){this.displayAlertMsg(gettext("Option Deletion Led to Invalidation"),gettext("Because you deleted an option, some student training examples had to be reset."))}},removeAllOptions:function(data){var changed=false;$(".openassessment_training_example_criterion",this.element).each(function(){var criterion=this;if($(criterion).data("criterion")==data.criterionName){$(criterion).remove();changed=true}});if(changed){this.displayAlertMsg(gettext("Option Deletion Led to Invalidation"),gettext("The deletion of the last criterion option caused the criterion to be removed in the student training examples."))}},criterionRemove:function(data){var changed=false;var sel='.openassessment_training_example_criterion[data-criterion="'+data.criterionName+'"]';$(sel,this.element).each(function(){$(this).remove();changed=true});if(changed){this.displayAlertMsg(gettext("Criterion Deletion Led to Invalidation"),gettext("Because you deleted a criterion, there were student training examples where the criterion had to be removed."))}},displayAlertMsg:function(title,msg){this.alert.setMessage(title,msg);this.alert.show()},criterionUpdated:function(data){var sel='.openassessment_training_example_criterion[data-criterion="'+data.criterionName+'"]';$(sel,this.element).each(function(){$(".openassessment_training_example_criterion_name_wrapper",this).text(data.criterionLabel)})},criterionAdd:function(data){var view=this.element;var criterion=$("#openassessment_training_example_criterion_template").children().first().clone().removeAttr("id").attr("data-criterion",data.criterionName).toggleClass("is--hidden",false).appendTo(".openassessment_training_example_criteria_selections",view);criterion.find(".openassessment_training_example_criterion_option").attr("data-criterion",data.criterionName);criterion.find(".openassessment_training_example_criterion_name_wrapper").text(data.label)},examplesCriteriaLabels:function(){var examples=[];$(".openassessment_training_example_criteria_selections",this.element).each(function(){var exampleDescription={};$(".openassessment_training_example_criterion",this).each(function(){var criterionName=$(this).data("criterion");var criterionLabel=$(".openassessment_training_example_criterion_name_wrapper",this).text().trim();exampleDescription[criterionName]=criterionLabel});examples.push(exampleDescription)});return examples},examplesOptionsLabels:function(){var examples=[];$(".openassessment_training_example_criteria_selections",this.element).each(function(){var exampleDescription={};$(".openassessment_training_example_criterion_option",this).each(function(){var criterionName=$(this).data("criterion");exampleDescription[criterionName]={};$("option",this).each(function(){var optionName=$(this).val();var optionLabel=$(this).text().trim();exampleDescription[criterionName][optionName]=optionLabel})});examples.push(exampleDescription)});return examples},_generateOptionString:function(name,points){return name+" - "+points+gettext(" points")}};OpenAssessment.Notifier=function(listeners){this.listeners=listeners};OpenAssessment.Notifier.prototype={notificationFired:function(name,data){for(var i=0;i<this.listeners.length;i++){if(typeof this.listeners[i][name]==="function"){this.listeners[i][name](data)}}}};OpenAssessment.EditPromptView=function(element){this.element=element};OpenAssessment.EditPromptView.prototype={promptText:function(text){var sel=$("#openassessment_prompt_editor",this.element);return OpenAssessment.Fields.stringField(sel,text)}};OpenAssessment.EditRubricView=function(element,notifier){this.element=element;this.criteriaContainer=new OpenAssessment.Container(OpenAssessment.RubricCriterion,{containerElement:$("#openassessment_criterion_list",this.element).get(0),templateElement:$("#openassessment_criterion_template",this.element).get(0),addButtonElement:$("#openassessment_rubric_add_criterion",this.element).get(0),removeButtonClass:"openassessment_criterion_remove_button",containerItemClass:"openassessment_criterion",notifier:notifier});this.alert=new OpenAssessment.ValidationAlert($("#openassessment_rubric_validation_alert",this.element))};OpenAssessment.EditRubricView.prototype={criteriaDefinition:function(){var criteria=this.criteriaContainer.getItemValues();for(var criterion_idx=0;criterion_idx<criteria.length;criterion_idx++){var criterion=criteria[criterion_idx];criterion.order_num=criterion_idx;for(var option_idx=0;option_idx<criterion.options.length;option_idx++){var option=criterion.options[option_idx];option.order_num=option_idx}}return criteria},feedbackPrompt:function(text){var sel=$("#openassessment_rubric_feedback",this.element);return OpenAssessment.Fields.stringField(sel,text)},addCriterion:function(){this.criteriaContainer.add()},removeCriterion:function(item){this.criteriaContainer.remove(item)},getAllCriteria:function(){return this.criteriaContainer.getAllItems()},getCriterionItem:function(index){return this.criteriaContainer.getItem(index)},addOption:function(criterionIndex){var criterionItem=this.getCriterionItem(criterionIndex);criterionItem.optionContainer.add()},removeOption:function(criterionIndex,item){var criterionItem=this.getCriterionItem(criterionIndex);criterionItem.optionContainer.remove(item)},getAllOptions:function(criterionIndex){var criterionItem=this.getCriterionItem(criterionIndex);return criterionItem.optionContainer.getAllItems()},getOptionItem:function(criterionIndex,optionIndex){var criterionItem=this.getCriterionItem(criterionIndex);return criterionItem.optionContainer.getItem(optionIndex)}};OpenAssessment.EditSettingsView=function(element,assessmentViews){this.settingsElement=element;this.assessmentsElement=$(element).siblings("#openassessment_assessment_module_settings_editors").get(0);this.assessmentViews=assessmentViews;this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_start_date","#openassessment_submission_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_due_date","#openassessment_submission_due_time").install();this.initializeSortableAssessments()};OpenAssessment.EditSettingsView.prototype={initializeSortableAssessments:function(){var view=this;$("#openassessment_assessment_module_settings_editors",view.element).sortable({start:function(event,ui){$(".openassessment_assessment_module_editor",view.element).hide();var targetHeight="auto";ui.placeholder.height(targetHeight);ui.helper.height(targetHeight);$("#openassessment_assessment_module_settings_editors",view.element).sortable("refresh").sortable("refreshPositions")
},stop:function(event,ui){$(".openassessment_assessment_module_editor",view.element).show()},snap:true,axis:"y",handle:".drag-handle",cursorAt:{top:20}});$("#openassessment_assessment_module_settings_editors .drag-handle",view.element).disableSelection()},displayName:function(name){var sel=$("#openassessment_title_editor",this.settingsElement);return OpenAssessment.Fields.stringField(sel,name)},submissionStart:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},submissionDue:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},imageSubmissionEnabled:function(isEnabled){var sel=$("#openassessment_submission_image_editor",this.settingsElement);if(typeof isEnabled!=="undefined"){if(isEnabled){sel.val(1)}else{sel.val(0)}}return sel.val()==1},assessmentsDescription:function(){var assessmentDescList=[];var view=this;$(".openassessment_assessment_module_settings_editor",this.assessmentsElement).each(function(){var asmntView=view.assessmentViews[$(this).attr("id")];if(asmntView.isEnabled()){var description=asmntView.description();description["name"]=asmntView.name;assessmentDescList.push(description)}});return assessmentDescList},editorAssessmentsOrder:function(){var editorAssessments=[];var view=this;$(".openassessment_assessment_module_settings_editor",this.assessmentsElement).each(function(){var asmntView=view.assessmentViews[$(this).attr("id")];editorAssessments.push(asmntView.name)});return editorAssessments}};OpenAssessment.ValidationAlert=function(element){this.element=element;this.title=$(".openassessment_alert_title",this.element);this.message=$(".openassessment_alert_message",this.element)};OpenAssessment.ValidationAlert.prototype={hide:function(){this.element.addClass("is--hidden")},show:function(){this.element.removeClass("is--hidden")},setMessage:function(newTitle,newMessage){this.title.text(newTitle);this.message.text(newMessage)},isVisible:function(){return!this.element.hasClass("is--hidden")},getTitle:function(){return this.title.text()},getMessage:function(){return this.message.text()}};
\ No newline at end of file
......@@ -56,7 +56,6 @@ describe("OpenAssessment.BaseView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_base.html');
// Create a new stub server
......
......@@ -42,7 +42,6 @@ describe("OpenAssessment.GradeView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_grade_complete.html');
// Create the stub server
......
......@@ -44,7 +44,6 @@ describe("OpenAssessment.PeerView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_peer_assessment.html');
// Create a new stub server
......
......@@ -97,7 +97,6 @@ describe("OpenAssessment.ResponseView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_response.html');
// Create stub objects
......
......@@ -39,7 +39,6 @@ describe("OpenAssessment.SelfView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_self_assessment.html');
// Create a new stub server
......
......@@ -69,9 +69,6 @@ describe("OpenAssessment.StaffInfoView", function() {
};
beforeEach(function() {
// Configure the Jasmine fixtures path
jasmine.getFixtures().fixturesPath = 'base/fixtures';
// Create a new stub server
server = new StubServer();
......
......@@ -45,7 +45,6 @@ describe("OpenAssessment.StudentTrainingView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_student_training.html');
// Create a new stub server
......
......@@ -7,7 +7,6 @@ describe("OpenAssessment.Rubric", function() {
var rubric = null;
beforeEach(function() {
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_rubric.html');
var el = $("#peer-assessment--001__assessment").get(0);
......
......@@ -52,28 +52,28 @@ describe("OpenAssessment.StudioView", function() {
{
order_num: 0,
label: "Criterion with two options",
name: "52bfbd0eb3044212b809564866e77079",
name: "criterion_1",
prompt: "Prompt for criterion with two options",
feedback: "disabled",
options: [
{
order_num: 0,
points: 1,
name: "85bbbecbb6a343f8a2146cde0e609ad0",
name: "option_1",
label: "Fair",
explanation: "Fair explanation"
},
{
order_num: 1,
points: 2,
name: "5936d5b9e281403ca123964055d4719a",
name: "option_2",
label: "Good",
explanation: "Good explanation"
}
]
},
{
name: "d96bb68a69ee4ccb8f86c753b6924f75",
name: "criterion_2",
label: "Criterion with no options",
prompt: "Prompt for criterion with no options",
order_num: 1,
......@@ -81,7 +81,7 @@ describe("OpenAssessment.StudioView", function() {
feedback: "required",
},
{
name: "2ca052403b06424da714f7a80dfb954d",
name: "criterion_3",
label: "Criterion with optional feedback",
prompt: "Prompt for criterion with optional feedback",
order_num: 2,
......@@ -90,7 +90,7 @@ describe("OpenAssessment.StudioView", function() {
{
order_num: 0,
points: 2,
name: "d7445661a89b4b339b9788cb7225a603",
name: "option_1",
label: "Good",
explanation: "Good explanation"
}
......@@ -121,7 +121,6 @@ describe("OpenAssessment.StudioView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_edit.html');
// Create the stub server
......@@ -190,7 +189,7 @@ describe("OpenAssessment.StudioView", function() {
expect(runtime.notify).toHaveBeenCalledWith('cancel', {});
});
it("displays an error when server reports an update XML error", function() {
it("displays an error when server reports an error", function() {
server.updateError = true;
view.save();
expect(runtime.notify).toHaveBeenCalledWith('error', {msg: 'Test error'});
......
......@@ -18,7 +18,6 @@ describe("OpenAssessment edit assessment views", function() {
};
beforeEach(function() {
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_edit.html');
});
......@@ -126,4 +125,4 @@ describe("OpenAssessment edit assessment views", function() {
it("Enables and disables", function() { testEnableAndDisable(view); });
it("Loads a description", function() { testLoadXMLExamples(view); });
});
});
\ No newline at end of file
});
/**
Tests for the student training listener,
which dynamically updates student training examples
based on rubric changes.
**/
describe("OpenAssessment.StudentTrainingListener", function() {
var listener = null;
/**
Check that all student training examples have the expected
criteria or option labels.
Args:
actual (array): A list of example criteria or option labels
(object literals) retrieved from the DOM.
expected (object literal): The expected value for each example.
numExamples (int, optional): The number of student training examples
(defaults to 1).
**/
var assertExampleLabels = function(actual, expected, numExamples) {
// The most common case is one example, so use that as a default.
if (typeof(numExamples) == "undefined") {
numExamples = 1;
}
// Add one to the number of examples to include the client-side template.
expect(actual.length).toEqual(numExamples + 1);
// Verify that each example matches what we expect.
// Since there is only one rubric for the problem,
// the training examples should always match that rubric.
for (var index in actual) {
for (var criterionName in expected) {
expect(actual[index][criterionName]).toEqual(expected[criterionName]);
}
}
};
beforeEach(function() {
loadFixtures('oa_edit_student_training.html');
listener = new OpenAssessment.StudentTrainingListener();
});
it("updates the label of an option", function() {
// Initial state, set by the fixture
assertExampleLabels(
listener.examplesOptionsLabels(),
{
criterion_with_two_options: {
"": "Not Scored",
option_1: "Fair - 1 points",
option_2: "Good - 2 points"
}
}
);
// Update the option label and points,
listener.optionUpdated({
criterionName: "criterion_with_two_options",
name: "option_1",
label: "This is a new label!",
points: 42
});
// Verify the new state
assertExampleLabels(
listener.examplesOptionsLabels(),
{
criterion_with_two_options: {
"": "Not Scored",
option_1: "This is a new label! - 42 points",
option_2: "Good - 2 points"
}
}
);
});
it("removes an option and displays an alert", function() {
// Initial state, set by the fixture
assertExampleLabels(
listener.examplesOptionsLabels(),
{
criterion_with_two_options: {
"": "Not Scored",
option_1: "Fair - 1 points",
option_2: "Good - 2 points"
}
}
);
expect(listener.alert.isVisible()).toBe(false);
// Remove an option
listener.optionRemove({
criterionName: "criterion_with_two_options",
name: "option_1"
});
// Verify the new state
assertExampleLabels(
listener.examplesOptionsLabels(),
{
criterion_with_two_options: {
"": "Not Scored",
option_2: "Good - 2 points"
}
}
);
// The alert should be displayed
expect(listener.alert.isVisible()).toBe(true);
});
it("removes a criterion if the criterion has no options", function() {
// Initial state, set by the fixture
assertExampleLabels(
listener.examplesCriteriaLabels(),
{ criterion_with_two_options: "Criterion with two options" }
);
expect(listener.alert.isVisible()).toBe(false);
// Remove all options for the criterion
listener.removeAllOptions({
criterionName: "criterion_with_two_options"
});
// Since the criterion has no options, it should no longer
// be available in student training
assertExampleLabels(listener.examplesCriteriaLabels(), {}, 1);
// The alert should be displayed
expect(listener.alert.isVisible()).toBe(true);
});
it("updates the label of a criterion", function() {
// Initial state, set by the fixture
assertExampleLabels(
listener.examplesCriteriaLabels(),
{ criterion_with_two_options: "Criterion with two options" }
);
// Update a label
listener.criterionUpdated({
criterionName: "criterion_with_two_options",
criterionLabel: "This is a new label!",
});
// Verify the new state
assertExampleLabels(
listener.examplesCriteriaLabels(),
{ criterion_with_two_options: "This is a new label!" }
);
});
it("adds a criterion and options", function() {
// Initial state, set by the fixture
assertExampleLabels(
listener.examplesCriteriaLabels(),
{ criterion_with_two_options: "Criterion with two options" }
);
// Add the criterion, which has no options
listener.criterionAdd({
criterionName: "new_criterion",
label: "This is a new criterion!"
});
// Since the criterion has no options, it should not
// be displayed.
assertExampleLabels(
listener.examplesCriteriaLabels(),
{ criterion_with_two_options: "Criterion with two options" }
);
// Add an option to the criterion
listener.optionAdd({
criterionName: "new_criterion",
name: "new_option",
label: "This is a new option!",
points: 56
});
// Now the criterion should be visible in student training
assertExampleLabels(
listener.examplesCriteriaLabels(),
{
criterion_with_two_options: "Criterion with two options",
new_criterion: "This is a new criterion!"
}
);
assertExampleLabels(
listener.examplesOptionsLabels(),
{
criterion_with_two_options: {
"": "Not Scored",
option_1: "Fair - 1 points",
option_2: "Good - 2 points",
},
new_criterion: {
"": "Not Scored",
new_option: "This is a new option! - 56 points"
}
}
);
// Add another option to the criterion
listener.optionAdd({
criterionName: "new_criterion",
name: "yet_another_option",
label: "This is yet another option!",
points: 27
});
assertExampleLabels(
listener.examplesOptionsLabels(),
{
criterion_with_two_options: {
"": "Not Scored",
option_1: "Fair - 1 points",
option_2: "Good - 2 points",
},
new_criterion: {
"": "Not Scored",
new_option: "This is a new option! - 56 points",
yet_another_option: "This is yet another option! - 27 points"
}
}
);
});
it("removes a criterion and displays an alert", function() {
// Initial state, set by the fixture
assertExampleLabels(
listener.examplesCriteriaLabels(),
{ criterion_with_two_options: "Criterion with two options" }
);
expect(listener.alert.isVisible()).toBe(false);
// Remove the criterion
listener.criterionRemove({
criterionName: "criterion_with_two_options"
});
// The criterion should no longer be displayed
assertExampleLabels(listener.examplesCriteriaLabels(), {}, 1);
// The alert should be displayed
expect(listener.alert.isVisible()).toBe(true);
});
});
describe("OpenAssessment.Notifier", function() {
var notifier = null;
var listeners = [];
var StubListener = function() {
this.receivedData = null;
this.testNotification = function(data) {
this.receivedData = data;
};
};
beforeEach(function() {
listeners = [ new StubListener(), new StubListener() ];
notifier = new OpenAssessment.Notifier(listeners);
});
it("notifies listeners when a notification fires", function() {
// Fire a notification that the listeners don't respond to
notifier.notificationFired("ignore this!", {});
expect(listeners[0].receivedData).toBe(null);
expect(listeners[1].receivedData).toBe(null);
// Fire a notification that the listeners care about
var testData = { foo: "bar" };
notifier.notificationFired("testNotification", testData);
// Check that the listeners were notified
expect(listeners[0].receivedData).toBe(testData);
expect(listeners[1].receivedData).toBe(testData);
});
});
......@@ -8,7 +8,6 @@ describe("OpenAssessment.EditPromptView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_edit.html');
// Create the view
......@@ -22,4 +21,4 @@ describe("OpenAssessment.EditPromptView", function() {
view.promptText("This is a test prompt!");
expect(view.promptText()).toEqual("This is a test prompt!");
});
});
\ No newline at end of file
});
......@@ -3,13 +3,25 @@ Tests for the rubric editing view.
**/
describe("OpenAssessment.EditRubricView", function() {
// Use a stub notifier implementation that simply stores
// the notifications it receives.
var notifier = null;
var StubNotifier = function() {
this.notifications = [];
this.notificationFired = function(name, data) {
this.notifications.push({
name: name,
data: data
});
};
};
var view = null;
beforeEach(function() {
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_edit.html');
var el = $("#oa_rubric_editor_wrapper").get(0);
view = new OpenAssessment.EditRubricView(el);
notifier = new StubNotifier();
view = new OpenAssessment.EditRubricView(el, notifier);
});
it("reads a criteria definition from the editor", function() {
......@@ -20,7 +32,7 @@ describe("OpenAssessment.EditRubricView", function() {
// Criterion with two options, feedback disabled
expect(criteria[0]).toEqual({
name: "52bfbd0eb3044212b809564866e77079",
name: "criterion_1",
label: "Criterion with two options",
prompt: "Prompt for criterion with two options",
order_num: 0,
......@@ -29,14 +41,14 @@ describe("OpenAssessment.EditRubricView", function() {
{
order_num: 0,
points: 1,
name: "85bbbecbb6a343f8a2146cde0e609ad0",
name: "option_1",
label: "Fair",
explanation: "Fair explanation"
},
{
order_num: 1,
points: 2,
name: "5936d5b9e281403ca123964055d4719a",
name: "option_2",
label: "Good",
explanation: "Good explanation"
}
......@@ -45,7 +57,7 @@ describe("OpenAssessment.EditRubricView", function() {
// Criterion with no options, feedback required
expect(criteria[1]).toEqual({
name: "d96bb68a69ee4ccb8f86c753b6924f75",
name: "criterion_2",
label: "Criterion with no options",
prompt: "Prompt for criterion with no options",
order_num: 1,
......@@ -55,7 +67,7 @@ describe("OpenAssessment.EditRubricView", function() {
// Criterion with one option, feeback optional
expect(criteria[2]).toEqual({
name: "2ca052403b06424da714f7a80dfb954d",
name: "criterion_3",
label: "Criterion with optional feedback",
prompt: "Prompt for criterion with optional feedback",
order_num: 2,
......@@ -64,7 +76,7 @@ describe("OpenAssessment.EditRubricView", function() {
{
order_num: 0,
points: 2,
name: "d7445661a89b4b339b9788cb7225a603",
name: "option_1",
label: "Good",
explanation: "Good explanation"
}
......@@ -75,14 +87,13 @@ describe("OpenAssessment.EditRubricView", function() {
it("creates new criteria and options", function() {
// Delete all existing criteria from the rubric
// Then add new criteria (created from a client-side template)
view.removeAllCriteria();
$.each(view.getAllCriteria(), function() { view.removeCriterion(this); });
view.addCriterion();
view.addCriterion();
// Add an option to the second criterion
view.getCriterionItem(1).addOption();
view.addOption(1);
// Check the definition
// Since no criteria/option names are set, leave them out of the description.
// This will cause the server to assign them unique names.
var criteria = view.criteriaDefinition();
......@@ -124,4 +135,77 @@ describe("OpenAssessment.EditRubricView", function() {
expect(view.feedbackPrompt()).toEqual(prompt);
});
});
\ No newline at end of file
it("fires a notification when an option is added", function() {
view.addOption();
expect(notifier.notifications).toContain({
name: "optionAdd",
data: {
criterionName: 'criterion_1',
criterionLabel: 'Criterion with two options',
name:'0',
label: '',
points : 1
}
});
// Add a second option and ensure that it is given a unique name
view.addOption();
expect(notifier.notifications).toContain({
name: "optionAdd",
data: {
criterionName: 'criterion_1',
criterionLabel: 'Criterion with two options',
name:'1',
label: '',
points : 1
}
});
});
it("fires a notification when an option is removed", function() {
view.removeOption(0, view.getOptionItem(0, 0));
expect(notifier.notifications).toContain({
name: "optionRemove",
data: {
criterionName: 'criterion_1',
name: 'option_1'
}
});
});
it("fires a notification when an option's label or points are updated", function() {
// Simulate what happens when the options label or points are updated
view.getOptionItem(0, 0).updateHandler();
expect(notifier.notifications).toContain({
name: "optionUpdated",
data: {
criterionName: 'criterion_1',
name: 'option_1',
label: 'Fair',
points: 1
}
});
});
it("fires a notification when a criterion's label is updated", function() {
// Simulate what happens when a criterion label is updated
view.getCriterionItem(0).updateHandler();
expect(notifier.notifications).toContain({
name: "criterionUpdated",
data: {
criterionName: 'criterion_1',
criterionLabel: 'Criterion with two options'
}
});
});
it("fires a notification when a criterion is removed", function() {
view.criteriaContainer.remove(view.getCriterionItem(0));
expect(notifier.notifications).toContain({
name: "criterionRemove",
data: {criterionName : 'criterion_1'}
});
});
});
......@@ -22,7 +22,6 @@ describe("OpenAssessment.EditSettingsView", function() {
beforeEach(function() {
// Load the DOM fixture
jasmine.getFixtures().fixturesPath = 'base/fixtures';
loadFixtures('oa_edit.html');
// Create the stub assessment views
......
describe("OpenAssessment.ValidationAlert", function() {
var alert = null;
beforeEach(function() {
loadFixtures('oa_edit.html');
alert = new OpenAssessment.ValidationAlert(
$("#openassessment_rubric_validation_alert")
);
});
it("shows and hides an alert", function() {
// Initially, the alert should be hidden
expect(alert.isVisible()).toBe(false);
// Show the alert
alert.show();
expect(alert.isVisible()).toBe(true);
// Hide the alert
alert.hide();
expect(alert.isVisible()).toBe(false);
});
it("sets the alert title and message", function() {
// Set the title and message
alert.setMessage("new title", "new message");
expect(alert.getTitle()).toEqual("new title");
expect(alert.getMessage()).toEqual("new message");
});
});
\ No newline at end of file
/**
Common test configuration, loaded before any of the spec files.
**/
// Set the fixture path
jasmine.getFixtures().fixturesPath = 'base/fixtures';
......@@ -44,8 +44,8 @@ including for pre-existing items in the container element.
Templates elements are never deleted, so they should be hidden using CSS styles.
Args:
containerItem (object): The container item object used to access
the contents of items in the container.
containerItem (constructor): The constructor of the container item object
used to access the contents of items in the container.
Kwargs:
containerElement (DOM element): The element representing the container.
......@@ -55,25 +55,33 @@ Kwargs:
There may be one of these for each item in the container.
containerItemClass (string): The CSS class of items in the container.
New items will be assigned this class.
notifier (OpenAssessment.Notifier): Used to send notifications of updates to container items.
**/
OpenAssessment.Container = function(containerItem, kwargs) {
this.containerItem = containerItem;
this.containerElement = kwargs.containerElement;
this.templateElement = kwargs.templateElement;
this.addButtonElement = kwargs.addButtonElement;
this.removeButtonClass = kwargs.removeButtonClass;
this.containerItemClass = kwargs.containerItemClass;
this.notifier = kwargs.notifier;
// Since every container item should be instantiated with
// the notifier we were given, create a helper method
// that does this automatically.
var container = this;
this.createContainerItem = function(element) {
return new containerItem(element, container.notifier);
};
// Install a click handler for the add button
$(this.addButtonElement).click($.proxy(this.add, this));
// Find items already in the container and install click
// handlers for the delete buttons.
var container = this;
$("." + this.removeButtonClass, this.containerElement).click(
function(eventData) {
var item = new container.containerItem(eventData.target);
var item = container.createContainerItem(eventData.target);
container.remove(item);
}
);
......@@ -82,7 +90,7 @@ OpenAssessment.Container = function(containerItem, kwargs) {
// own event handlers.
$("." + this.containerItemClass, this.containerElement).each(
function(index, element) {
new container.containerItem(element);
container.createContainerItem(element);
}
);
};
......@@ -112,13 +120,13 @@ OpenAssessment.Container.prototype = {
var containerItem = $("." + this.containerItemClass, this.containerElement).last();
containerItem.find('.' + this.removeButtonClass)
.click(function(eventData) {
var containerItem = new container.containerItem(eventData.target);
var containerItem = container.createContainerItem(eventData.target);
container.remove(containerItem);
} );
// Initialize the item, allowing it to install event handlers.
// Fire event handler for adding a new element
var handlerItem = new this.containerItem(containerItem);
var handlerItem = container.createContainerItem(containerItem);
handlerItem.addHandler();
},
......@@ -133,7 +141,7 @@ OpenAssessment.Container.prototype = {
**/
remove: function(item) {
var itemElement = $(item.element).closest("." + this.containerItemClass);
var containerItem = new this.containerItem(itemElement);
var containerItem = this.createContainerItem(itemElement);
containerItem.removeHandler();
itemElement.remove();
},
......@@ -152,7 +160,7 @@ OpenAssessment.Container.prototype = {
$("." + this.containerItemClass, this.containerElement).each(
function(index, element) {
var containerItem = new container.containerItem(element);
var containerItem = container.createContainerItem(element);
var fieldValues = containerItem.getFieldValues();
values.push(fieldValues);
}
......@@ -173,7 +181,7 @@ OpenAssessment.Container.prototype = {
**/
getItem: function(index) {
var element = $("." + this.containerItemClass, this.containerElement).get(index);
return (element !== undefined) ? new this.containerItem(element) : null;
return (element !== undefined) ? this.createContainerItem(element) : null;
},
/**
......@@ -186,6 +194,6 @@ OpenAssessment.Container.prototype = {
getAllItems: function() {
var container = this;
return $("." + this.containerItemClass, this.containerElement)
.map(function() { return new container.containerItem(this); });
.map(function() { return container.createContainerItem(this); });
}
};
......@@ -15,7 +15,7 @@ OpenAssessment.ItemUtilities = {
createUniqueName: function(selector, nameAttribute) {
var index = 0;
while (index <= selector.length) {
if (selector.parent().find("*[" + nameAttribute + "='" + index + "']").length == 0) {
if (selector.parent().find("*[" + nameAttribute + "='" + index + "']").length === 0) {
return index.toString();
}
index++;
......@@ -30,13 +30,14 @@ container object. Constructs a new RubricOption element.
Args:
element (OpenAssessment.Container): The container that the option is a member of.
notifier (OpenAssessment.Notifier): Used to send notifications of updates to rubric options.
Returns:
OpenAssessment.RubricOption
**/
OpenAssessment.RubricOption = function(element) {
OpenAssessment.RubricOption = function(element, notifier) {
this.element = element;
this.modificationHandler = new OpenAssessment.RubricEventHandler();
this.notifier = notifier;
$(this.element).focusout($.proxy(this.updateHandler, this));
};
......@@ -78,7 +79,7 @@ OpenAssessment.RubricOption.prototype = {
},
/**
Hook into the event handler for removal of a criterion option.
Hook into the event handler for addition of a criterion option.
*/
addHandler: function (){
......@@ -97,7 +98,7 @@ OpenAssessment.RubricOption.prototype = {
$(".openassessment_criterion_option_name", this.element).attr("value", name);
var fields = this.getFieldValues();
this.modificationHandler.notificationFired(
this.notifier.notificationFired(
"optionAdd",
{
"criterionName": criterionName,
......@@ -116,7 +117,7 @@ OpenAssessment.RubricOption.prototype = {
removeHandler: function (){
var criterionName = $(this.element).data('criterion');
var optionName = $(this.element).data('option');
this.modificationHandler.notificationFired(
this.notifier.notificationFired(
"optionRemove",
{
"criterionName": criterionName,
......@@ -136,7 +137,7 @@ OpenAssessment.RubricOption.prototype = {
var optionName = $(this.element).data('option');
var optionLabel = fields.label;
var optionPoints = fields.points;
this.modificationHandler.notificationFired(
this.notifier.notificationFired(
"optionUpdated",
{
"criterionName": criterionName,
......@@ -154,20 +155,22 @@ the DOM.
Args:
element (JQuery Object): The selection which describes the scope of the criterion.
notifier (OpenAssessment.Notifier): Used to send notifications of updates to rubric criteria.
Returns:
OpenAssessment.RubricCriterion
**/
OpenAssessment.RubricCriterion = function(element) {
OpenAssessment.RubricCriterion = function(element, notifier) {
this.element = element;
this.modificationHandler = new OpenAssessment.RubricEventHandler();
this.notifier = notifier;
this.optionContainer = new OpenAssessment.Container(
OpenAssessment.RubricOption, {
containerElement: $(".openassessment_criterion_option_list", this.element).get(0),
templateElement: $("#openassessment_option_template").get(0),
addButtonElement: $(".openassessment_criterion_add_option", this.element).get(0),
removeButtonClass: "openassessment_criterion_option_remove_button",
containerItemClass: "openassessment_criterion_option"
containerItemClass: "openassessment_criterion_option",
notifier: this.notifier
}
);
......@@ -247,7 +250,7 @@ OpenAssessment.RubricCriterion.prototype = {
*/
removeHandler: function(){
var criterionName = $(this.element).data('criterion');
this.modificationHandler.notificationFired("criterionRemove", {'criterionName': criterionName});
this.notifier.notificationFired("criterionRemove", {'criterionName': criterionName});
},
/**
......@@ -258,7 +261,7 @@ OpenAssessment.RubricCriterion.prototype = {
var fields = this.getFieldValues();
var criterionName = fields.name;
var criterionLabel = fields.label;
this.modificationHandler.notificationFired(
this.notifier.notificationFired(
"criterionUpdated",
{'criterionName': criterionName, 'criterionLabel': criterionLabel}
);
......@@ -270,10 +273,11 @@ OpenAssessment.RubricCriterion.prototype = {
The TrainingExample class is used to construct and retrieve information from its element within the DOM
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:
OpenAssessment.TrainingExample
OpenAssessment.TrainingExample
**/
OpenAssessment.TrainingExample = function(element){
this.element = element;
......@@ -304,5 +308,4 @@ OpenAssessment.TrainingExample.prototype = {
addHandler: function() {},
removeHandler: function() {},
updateHandler: function() {}
};
\ No newline at end of file
......@@ -52,7 +52,10 @@ OpenAssessment.StudioView = function(runtime, element, server) {
// Initialize the rubric tab view
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.StudentTrainingListener()
])
);
// Install the save and cancel buttons
......
......@@ -280,7 +280,7 @@ OpenAssessment.EditStudentTrainingView = function(element) {
removeButtonClass: "openassessment_training_example_remove",
containerItemClass: "openassessment_training_example"
}
)
);
};
OpenAssessment.EditStudentTrainingView.prototype = {
......@@ -333,21 +333,6 @@ OpenAssessment.EditStudentTrainingView.prototype = {
},
/**
Get or set the XML defining the training examples.
Args:
xml (string, optional): The XML of the training example definitions.
Returns:
string
**/
exampleDefinitions: function(xml) {
var sel = $("#student_training_examples", this.element);
return OpenAssessment.Fields.stringField(sel, xml);
},
/**
Gets the ID of the assessment
Returns:
......
OpenAssessment.RubricEventHandler = function () {
this.listeners = [
new OpenAssessment.StudentTrainingListener()
];
};
OpenAssessment.RubricEventHandler.prototype = {
notificationFired: function(name, data) {
for (var i = 0; i < this.listeners.length; i++) {
if (typeof(this.listeners[i][name]) === 'function') {
this.listeners[i][name](data);
}
}
}
};
OpenAssessment.StudentTrainingListener = function () {
/**
Dynamically update student training examples based on
changes to the rubric.
**/
OpenAssessment.StudentTrainingListener = function() {
this.element = $('#oa_student_training_editor');
this.alert = new OpenAssessment.ValidationAlert($('#openassessment_rubric_validation_alert'));
};
OpenAssessment.StudentTrainingListener.prototype = {
generateOptionString: function(name, points){
return name + ' - ' + points + gettext(' points')
},
/**
Event handler for updating training examples when a criterion option has
been updated.
......@@ -38,14 +19,16 @@ OpenAssessment.StudentTrainingListener.prototype = {
label (str): The label for the option.
points (int): The point value for the option.
*/
optionUpdated: function(data){
optionUpdated: function(data) {
var view = this;
$('.openassessment_training_example_criterion[data-criterion="'
+ data.criterionName + '"', this.element).each(function(){
var sel = '.openassessment_training_example_criterion[data-criterion="' + data.criterionName + '"]';
$(sel, this.element).each(
function() {
var criterion = this;
var option = $("option[value='" + data.name + "'", criterion);
$(option).text(view.generateOptionString(data.label, data.points));
});
var option = $('option[value="' + data.name + '"]', criterion);
$(option).text(view._generateOptionString(data.label, data.points));
}
);
},
/**
......@@ -60,24 +43,22 @@ OpenAssessment.StudentTrainingListener.prototype = {
Args:
criterionName (str): The name of the criterion that will have an
additional option.
criterionLabel (str): The label for the criterion that will have an
additional option.
name (str): The name of the new option.
label (str): The new option label.
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
var options = $('.openassessment_training_example_criterion_option[data-criterion="' + data.criterionName + '"]');
var view = this;
var criterionAdded = false;
var examplesUpdated = false;
if (options.length == 0) {
if (options.length === 0) {
this.criterionAdd(data);
criterionAdded = true;
}
$('.openassessment_training_example_criterion_option', this.element).each(function(){
$('.openassessment_training_example_criterion_option', this.element).each(function() {
if ($(this).data('criterion') === data.criterionName) {
var criterion = this;
// Risky; making an assumption that options will remain simple.
......@@ -85,7 +66,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
// but this avoids overly complex templating code.
$(criterion).append($("<option></option>")
.attr("value", data.name)
.text(view.generateOptionString(data.label, data.points)));
.text(view._generateOptionString(data.label, data.points)));
examplesUpdated = true;
}
});
......@@ -93,8 +74,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
if (criterionAdded && examplesUpdated) {
this.displayAlertMsg(
gettext("Criterion Addition requires Training Example Updates"),
gettext("Because you added a criterion, student training examples " +
"will have to be updated.")
gettext("Because you added a criterion, student training examples will have to be updated.")
);
}
},
......@@ -114,10 +94,10 @@ OpenAssessment.StudentTrainingListener.prototype = {
name (str): The option being removed.
*/
optionRemove: function(data){
var validator = this;
optionRemove: function(data) {
var handler = this;
var changed = false;
$('.openassessment_training_example_criterion_option', this.element).each(function(){
$('.openassessment_training_example_criterion_option', this.element).each(function() {
var criterionOption = this;
if ($(criterionOption).data('criterion') === data.criterionName) {
if ($(criterionOption).val() == data.name) {
......@@ -129,12 +109,12 @@ OpenAssessment.StudentTrainingListener.prototype = {
changed = true;
}
$("option[value='" + data.name + "'", criterionOption).remove();
$('option[value="' + data.name + '"]', criterionOption).remove();
// If all options have been removed from the Criterion, remove
// the criterion entirely.
if ($("option", criterionOption).length == 1) {
validator.removeAllOptions(data);
handler.removeAllOptions(data);
return;
}
}
......@@ -143,8 +123,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
if (changed) {
this.displayAlertMsg(
gettext("Option Deletion Led to Invalidation"),
gettext("Because you deleted an option, some student training " +
"examples had to be reset.")
gettext("Because you deleted an option, some student training examples had to be reset.")
);
}
},
......@@ -159,9 +138,9 @@ OpenAssessment.StudentTrainingListener.prototype = {
criterionName (str): The criterion where all options have been removed.
*/
removeAllOptions: function(data){
removeAllOptions: function(data) {
var changed = false;
$('.openassessment_training_example_criterion', this.element).each(function(){
$('.openassessment_training_example_criterion', this.element).each(function() {
var criterion = this;
if ($(criterion).data('criterion') == data.criterionName) {
$(criterion).remove();
......@@ -172,8 +151,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
if (changed) {
this.displayAlertMsg(
gettext("Option Deletion Led to Invalidation"),
gettext("The deletion of the last criterion option caused the " +
"criterion to be removed in the student training examples.")
gettext("The deletion of the last criterion option caused the criterion to be removed in the student training examples.")
);
}
},
......@@ -187,19 +165,20 @@ OpenAssessment.StudentTrainingListener.prototype = {
criterionName (str): The name of the criterion removed.
*/
criterionRemove: function(data){
criterionRemove: function(data) {
var changed = false;
$('.openassessment_training_example_criterion[data-criterion="'
+ data.criterionName + '"', this.element).each(function(){
$(this).remove();
var sel = '.openassessment_training_example_criterion[data-criterion="' + data.criterionName + '"]';
$(sel, this.element).each(
function() {
$(this).remove();
changed = true;
});
}
);
if (changed) {
this.displayAlertMsg(
gettext("Criterion Deletion Led to Invalidation"),
gettext("Because you deleted a criterion, there were student " +
"training examples where the criterion had to be removed.")
gettext("Because you deleted a criterion, there were student training examples where the criterion had to be removed.")
);
}
},
......@@ -212,7 +191,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
msg (str): Message body for the alert.
*/
displayAlertMsg: function(title, msg){
displayAlertMsg: function(title, msg) {
this.alert.setMessage(title, msg);
this.alert.show();
},
......@@ -225,11 +204,14 @@ OpenAssessment.StudentTrainingListener.prototype = {
criterionName (str): Name of the criterion
criterionLabel (str): New label to replace on the training examples.
*/
criterionUpdated: function(data){
$('.openassessment_training_example_criterion[data-criterion="' +
data.criterionName + '"', this.element).each(function(){
$(".openassessment_training_example_criterion_name_wrapper", this).text(data.criterionLabel);
});
criterionUpdated: function(data) {
var sel = '.openassessment_training_example_criterion[data-criterion="' + data.criterionName + '"]';
$(sel, this.element).each(
function() {
$(".openassessment_training_example_criterion_name_wrapper", this)
.text(data.criterionLabel);
}
);
},
/**
......@@ -239,7 +221,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
examples.
Args:
name (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.
*/
criterionAdd: function(data) {
......@@ -252,8 +234,113 @@ OpenAssessment.StudentTrainingListener.prototype = {
.toggleClass('is--hidden', false)
.appendTo(".openassessment_training_example_criteria_selections", view);
criterion.find(".openassessment_training_example_criterion_option").attr('data-criterion', data.criterionName);
criterion.find(".openassessment_training_example_criterion_name_wrapper").text(data.label);
}
criterion.find(".openassessment_training_example_criterion_option")
.attr('data-criterion', data.criterionName);
criterion.find(".openassessment_training_example_criterion_name_wrapper")
.text(data.label);
},
/**
Retrieve the available criteria labels for training examples.
This is mainly useful for testing.
The returned array will always contain an extra example
for the client-side template for new examples.
Returns:
Array of object literals mapping criteria names to labels.
Example usage:
>>> listener.examplesCriteriaLabels();
>>> [
>>> { criterion_1: "abcd", criterion_2: "xyz" },
>>> { criterion_1: "abcd", criterion_2: "xyz" }
>>> ]
**/
examplesCriteriaLabels: function() {
var examples = [];
$(".openassessment_training_example_criteria_selections", this.element).each(
function() {
var exampleDescription = {};
$(".openassessment_training_example_criterion", this).each(
function() {
var criterionName = $(this).data('criterion');
var criterionLabel = $(".openassessment_training_example_criterion_name_wrapper", this)
.text().trim();
exampleDescription[criterionName] = criterionLabel;
}
);
examples.push(exampleDescription);
}
);
return examples;
},
/**
Retrieve the available option labels for training examples.
This is mainly useful for testing.
The returned array will always contain an extra example
for the client-side template for new examples.
Returns:
Array of object literals
Example usage:
>>> listener.examplesOptionsLabels();
>>> [
>>> {
>>> criterion_1: {
>>> "": "Not Scored",
>>> option_1: "First Option - 1 points",
>>> option_2: "Second Option - 2 points",
>>> }
>>> },
>>> {
>>> criterion_1: {
>>> "": "Not Scored",
>>> option_1: "First Option - 1 points",
>>> option_2: "Second Option - 2 points",
>>> }
>>> }
>>> ]
**/
examplesOptionsLabels: function() {
var examples = [];
$(".openassessment_training_example_criteria_selections", this.element).each(
function() {
var exampleDescription = {};
$(".openassessment_training_example_criterion_option", this).each(
function() {
var criterionName = $(this).data('criterion');
exampleDescription[criterionName] = {};
$("option", this).each(
function() {
var optionName = $(this).val();
var optionLabel = $(this).text().trim();
exampleDescription[criterionName][optionName] = optionLabel;
}
);
}
);
examples.push(exampleDescription);
}
);
return examples;
},
/**
Format the option label, including the point value.
Args:
name (string): The option label (e.g. "Good", "Fair").
points (int): The number of points that the option is worth.
Returns:
string
**/
_generateOptionString: function(name, points) {
return name + ' - ' + points + gettext(' points');
}
};
/**
Notify multiple listeners that an event has occurred.
A listener is any object that implements a notification method.
For example, a listener for the notification "foo" might look like:
>>> var fooListener = {
>>> foo: function(data) {};
>>> };
Since `fooListener` implements `foo`, it will be notified when
a "foo" notification fires.
All notification methods must take a single argument, "data",
which is contains arbitrary information associated with the notification.
If a notification is fired that the listener does not respond to,
the listener will ignore the notification.
Args:
listeners (array): List of objects
**/
OpenAssessment.Notifier = function(listeners) {
this.listeners = listeners;
};
OpenAssessment.Notifier.prototype = {
/**
Fire a notification, which will be received
Args:
name (string): The name of the notification. This should
be the same as the name of the method implemented
by the listeners.
data (object literal): Arbitrary data to include with the notification.
**/
notificationFired: function(name, data) {
for (var i = 0; i < this.listeners.length; i++) {
if (typeof(this.listeners[i][name]) === 'function') {
this.listeners[i][name](data);
}
}
}
};
\ No newline at end of file
/**
Interface for editing rubric definitions.
Args:
element (DOM element): The DOM element representing the rubric.
notifier (OpenAssessment.Notifier): Used to notify other views about updates to the rubric.
This view fires the following notification events:
* optionAdd: An option was added to the rubric.
* optionRemove: An option was removed from the rubric.
* optionUpdated: An option's label and/or points were updated in the rubric.
* criterionRemove: A criterion was removed from the rubric.
* criterionUpdated: A criterion's label was updated in the rubric.
**/
OpenAssessment.EditRubricView = function(element) {
OpenAssessment.EditRubricView = function(element, notifier) {
this.element = element;
this.criteriaContainer = new OpenAssessment.Container(
OpenAssessment.RubricCriterion, {
containerElement: $("#openassessment_criterion_list", this.element).get(0),
templateElement: $("#openassessment_criterion_template", this.element).get(0),
addButtonElement: $("#openassessment_rubric_add_criterion", this.element).get(0),
removeButtonClass: "openassessment_criterion_remove_button",
containerItemClass: "openassessment_criterion"
containerItemClass: "openassessment_criterion",
notifier: notifier
}
);
this.alert = new OpenAssessment.ValidationAlert($('#openassessment_rubric_validation_alert', this.element));
......@@ -78,16 +92,6 @@ OpenAssessment.EditRubricView.prototype = {
},
/**
Remove all criteria in this rubric.
Mainly useful for testing.
**/
removeAllCriteria: function() {
var items = this.criteriaContainer.getAllItems();
var view = this;
$.each(items, function() { view.criteriaContainer.remove(this); });
},
/**
Add a new criterion to the rubric.
Uses a client-side template to create the new criterion.
**/
......@@ -96,64 +100,94 @@ OpenAssessment.EditRubricView.prototype = {
},
/**
Retrieve a criterion item (a container item) from the rubric
at a particular index.
Remove a criterion from the rubric.
Args:
item (OpenAssessment.RubricCriterion): The criterion item to remove.
**/
removeCriterion: function(item) {
this.criteriaContainer.remove(item);
},
/**
Retrieve all criteria from the rubric.
Returns:
Array of OpenAssessment.RubricCriterion objects.
**/
getAllCriteria: function() {
return this.criteriaContainer.getAllItems();
},
/**
Retrieve a criterion item from the rubric.
Args:
index (int): The index of the criterion, starting from 0.
Returns:
OpenAssessment.RubricCriterion
OpenAssessment.RubricCriterion or null
**/
getCriterionItem: function(index) {
return this.criteriaContainer.getItem(index);
}
};
/**
A class which controls the validation alert which we place at the top of the rubric page after
changes are made which will propagate to the settings section.
},
Args:
element (element): The element that specifies the div that the validation consists of.
/**
Add a new option to the rubric.
Returns:
Openassessment.ValidationAlert
*/
OpenAssessment.ValidationAlert = function (element) {
this.element = element;
this.title = $(".openassessment_alert_title", this.element);
this.message = $(".openassessment_alert_message", this.element);
};
Args:
criterionIndex (int): The index of the criterion to which
the option will be added (starts from 0).
OpenAssessment.ValidationAlert.prototype = {
**/
addOption: function(criterionIndex) {
var criterionItem = this.getCriterionItem(criterionIndex);
criterionItem.optionContainer.add();
},
/**
Hides the alert.
*/
hide: function () {
this.element.addClass('is--hidden');
Remove an option from the rubric.
Args:
criterionIndex (int): The index of the criterion, starting from 0.
item (OpenAssessment.RubricOption): The option item to remove.
**/
removeOption: function(criterionIndex, item) {
var criterionItem = this.getCriterionItem(criterionIndex);
criterionItem.optionContainer.remove(item);
},
/**
Displays the alert.
*/
show : function () {
this.element.removeClass('is--hidden');
Retrieve all options for a particular criterion.
Args:
criterionIndex (int): The index of the criterion, starting from 0.
Returns:
Array of OpenAssessment.RubricOption
**/
getAllOptions: function(criterionIndex) {
var criterionItem = this.getCriterionItem(criterionIndex);
return criterionItem.optionContainer.getAllItems();
},
/**
Sets the message of the alert.
How will this work with internationalization?
Args:
newTitle (str): the new title that the message will have
newMessage (str): the new text that the message's body will contain
*/
setMessage: function (newTitle, newMessage){
this.title.text(newTitle);
this.message.text(newMessage);
Retrieve a particular option from the rubric.
Args:
criterionIndex (int): The index of the criterion, starting from 0.
optionIndex (int): The index of the option within the criterion,
starting from 0.
Returns:
OpenAssessment.RubricOption
**/
getOptionItem: function(criterionIndex, optionIndex) {
var criterionItem = this.getCriterionItem(criterionIndex);
return criterionItem.optionContainer.getItem(optionIndex);
}
};
......@@ -3,7 +3,7 @@ Editing interface for OpenAssessment settings (including assessments).
Args:
element (DOM element): The DOM element representing this view.
assessmentViews (array): List of assessment view objects.
assessmentViews (object literal): Mapping of CSS IDs to view objects.
Returns:
OpenAssessment.EditSettingsView
......
/**
A class which controls the validation alert which we place at the top of the rubric page after
changes are made which will propagate to the settings section.
Args:
element (element): The element that specifies the div that the validation consists of.
Returns:
Openassessment.ValidationAlert
*/
OpenAssessment.ValidationAlert = function (element) {
this.element = element;
this.title = $(".openassessment_alert_title", this.element);
this.message = $(".openassessment_alert_message", this.element);
};
OpenAssessment.ValidationAlert.prototype = {
/**
Hides the alert.
*/
hide: function() {
this.element.addClass('is--hidden');
},
/**
Displays the alert.
*/
show : function() {
this.element.removeClass('is--hidden');
},
/**
Sets the message of the alert.
How will this work with internationalization?
Args:
newTitle (str): the new title that the message will have
newMessage (str): the new text that the message's body will contain
*/
setMessage: function(newTitle, newMessage) {
this.title.text(newTitle);
this.message.text(newMessage);
},
/**
Check whether the alert is currently visible.
Returns:
boolean
**/
isVisible: function() {
return !this.element.hasClass('is--hidden');
},
/**
Retrieve the title of the alert.
Returns:
string
**/
getTitle: function() {
return this.title.text();
},
/**
Retrieve the message of the alert.
Returns:
string
**/
getMessage: function() {
return this.message.text();
}
};
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