diff --git a/cms/static/js/views/settings/advanced.js b/cms/static/js/views/settings/advanced.js
index dd51134aa1..3c1eba2fb2 100644
--- a/cms/static/js/views/settings/advanced.js
+++ b/cms/static/js/views/settings/advanced.js
@@ -1,5 +1,11 @@
-define(["js/views/validation", "jquery", "underscore", "gettext", "codemirror", "js/views/modals/validation_error_modal"],
- function(ValidatingView, $, _, gettext, CodeMirror, ValidationErrorModal) {
+define(["js/views/validation",
+ "jquery",
+ "underscore",
+ "gettext",
+ "codemirror",
+ "js/views/modals/validation_error_modal",
+ 'edx-ui-toolkit/js/utils/html-utils'],
+ function(ValidatingView, $, _, gettext, CodeMirror, ValidationErrorModal, HtmlUtils) {
var AdvancedView = ValidatingView.extend({
error_saving : "error_saving",
@@ -13,7 +19,9 @@ var AdvancedView = ValidatingView.extend({
// TODO enable/disable save based on validation (currently enabled whenever there are changes)
},
initialize : function() {
- this.template = _.template($("#advanced_entry-tpl").text());
+ this.template = HtmlUtils.template(
+ $("#advanced_entry-tpl").text()
+ );
this.listenTo(this.model, 'invalid', this.handleValidationError);
this.render();
},
@@ -33,7 +41,7 @@ var AdvancedView = ValidatingView.extend({
_.each(_.sortBy(_.keys(this.model.attributes), function(key) { return self.model.get(key).display_name; }),
function(key) {
if (self.render_deprecated || !self.model.get(key).deprecated) {
- listEle$.append(self.renderTemplate(key, self.model.get(key)));
+ HtmlUtils.append(listEle$, self.renderTemplate(key, self.model.get(key)));
}
});
diff --git a/cms/static/js/views/settings/grader.js b/cms/static/js/views/settings/grader.js
index 3a125f67d8..cf936f4ff8 100644
--- a/cms/static/js/views/settings/grader.js
+++ b/cms/static/js/views/settings/grader.js
@@ -1,4 +1,10 @@
-define(["js/views/validation", "underscore", "jquery"], function(ValidatingView, _, $) {
+define(["js/views/validation",
+ 'gettext',
+ 'edx-ui-toolkit/js/utils/string-utils',
+ "edx-ui-toolkit/js/utils/html-utils",
+ "underscore",
+ "jquery"],
+ function(ValidatingView, gettext, StringUtils, HtmlUtils, _, $) {
var GraderView = ValidatingView.extend({
// Model class is CMS.Models.Settings.CourseGrader
@@ -49,9 +55,14 @@ var GraderView = ValidatingView.extend({
if (this.setField(event) != this.oldName && !_.isEmpty(this.oldName)) {
// overload the error display logic
this._cacheValidationErrors.push(event.currentTarget);
- $(event.currentTarget).parent().append(
- this.errorTemplate({message : 'For grading to work, you must change all "' + this.oldName +
- '" subsections to "' + this.model.get('type') + '".'}));
+ var message = StringUtils.interpolate(
+ gettext('For grading to work, you must change all {oldName} subsections to {newName}.'),
+ {
+ oldName: this.oldName,
+ newName: this.model.get('type')
+ }
+ );
+ HtmlUtils.append($(event.currentTarget).parent(), this.errorTemplate({message : message}));
}
break;
default:
diff --git a/cms/static/js/views/settings/grading.js b/cms/static/js/views/settings/grading.js
index 8a3bab4fc6..184cba06d2 100644
--- a/cms/static/js/views/settings/grading.js
+++ b/cms/static/js/views/settings/grading.js
@@ -1,5 +1,12 @@
-define(["js/views/validation", "underscore", "jquery", "jquery.ui", "js/views/settings/grader"],
- function(ValidatingView, _, $, ui, GraderView) {
+define(["js/views/validation",
+ "underscore",
+ "jquery",
+ "jquery.ui",
+ "js/views/settings/grader",
+ 'edx-ui-toolkit/js/utils/string-utils',
+ 'edx-ui-toolkit/js/utils/html-utils',
+ ],
+ function(ValidatingView, _, $, ui, GraderView, StringUtils, HtmlUtils) {
var GradingView = ValidatingView.extend({
// Model class is CMS.Models.Settings.CourseGradingPolicy
@@ -21,13 +28,12 @@ var GradingView = ValidatingView.extend({
initialize : function() {
// load template for grading view
var self = this;
- this.template = _.template($("#course_grade_policy-tpl").text());
- this.gradeCutoffTemplate = _.template('
' +
- '<%= descriptor %>' +
- '' +
- '<% if (removable) {%>remove<% ;} %>' +
- '');
-
+ this.template = HtmlUtils.template(
+ $("#course_grade_policy-tpl").text()
+ );
+ this.gradeCutoffTemplate = HtmlUtils.template(
+ $("#course_grade_cutoff-tpl").text()
+ );
this.setupCutoffs();
this.listenTo(this.model, 'invalid', this.handleValidationError);
@@ -68,7 +74,7 @@ var GradingView = ValidatingView.extend({
},
this);
gradeCollection.each(function(gradeModel) {
- $(gradelist).append(self.template({model : gradeModel }));
+ HtmlUtils.append(gradelist, self.template({model : gradeModel }));
var newEle = gradelist.children().last();
var newView = new GraderView({el: newEle,
model : gradeModel, collection : gradeCollection });
@@ -147,7 +153,7 @@ var GradingView = ValidatingView.extend({
gradeBarWidth : null, // cache of value since it won't change (more certain)
renderCutoffBar: function() {
- var gradeBar =this.$el.find('.grade-bar');
+ var gradeBar = this.$el.find('.grade-bar');
this.gradeBarWidth = gradeBar.width();
var gradelist = gradeBar.children('.grades');
// HACK fixing a duplicate call issue by undoing previous call effect. Need to figure out why called 2x
@@ -156,15 +162,15 @@ var GradingView = ValidatingView.extend({
// Can probably be simplified to one variable now.
var removable = false;
var draggable = false; // first and last are not removable, first is not draggable
- _.each(this.descendingCutoffs,
- function(cutoff, index) {
- var newBar = this.gradeCutoffTemplate({
- descriptor : cutoff['designation'] ,
+ _.each(this.descendingCutoffs, function(cutoff) {
+ HtmlUtils.append(gradelist, this.gradeCutoffTemplate({
+ descriptor : cutoff.designation,
width : nextWidth,
- removable : removable });
- gradelist.append(newBar);
+ contenteditable: true,
+ removable : removable})
+ );
if (draggable) {
- newBar = gradelist.children().last(); // get the dom object not the unparsed string
+ var newBar = gradelist.children().last(); // get the dom object not the unparsed string
newBar.resizable({
handles: "e",
containment : "parent",
@@ -174,19 +180,18 @@ var GradingView = ValidatingView.extend({
});
}
// prepare for next
- nextWidth = cutoff['cutoff'];
+ nextWidth = cutoff.cutoff;
removable = true; // first is not removable, all others are
draggable = true;
},
this);
- // add fail which is not in data
- var failBar = $(this.gradeCutoffTemplate({
+ // Add fail which is not in data
+ HtmlUtils.append(gradelist, this.gradeCutoffTemplate({
descriptor : this.failLabel(),
width : nextWidth,
+ contenteditable: false,
removable : false
}));
- failBar.find("span[contenteditable=true]").attr("contenteditable", false);
- gradelist.append(failBar);
gradelist.children().last().resizable({
handles: "e",
containment : "parent",
@@ -298,10 +303,13 @@ var GradingView = ValidatingView.extend({
this.descendingCutoffs.push({designation: this.GRADES[gradeLength], cutoff: failBarWidth});
this.descendingCutoffs[gradeLength - 1]['cutoff'] = Math.round(targetWidth);
- var $newGradeBar = this.gradeCutoffTemplate({ descriptor : this.GRADES[gradeLength],
- width : targetWidth, removable : true });
+ var newGradeHtml = this.gradeCutoffTemplate({
+ descriptor : this.GRADES[gradeLength],
+ width : targetWidth,
+ contenteditable: true,
+ removable : true });
var gradeDom = this.$el.find('.grades');
- gradeDom.children().last().before($newGradeBar);
+ gradeDom.children().last().before(HtmlUtils.ensureHtml(newGradeHtml).toString());
var newEle = gradeDom.children()[gradeLength];
$(newEle).resizable({
handles: "e",
@@ -313,8 +321,8 @@ var GradingView = ValidatingView.extend({
// Munge existing grade labels?
// If going from Pass/Fail to 3 levels, change to Pass to A
- if (gradeLength === 1 && this.descendingCutoffs[0]['designation'] === 'Pass') {
- this.descendingCutoffs[0]['designation'] = this.GRADES[0];
+ if (gradeLength === 1 && this.descendingCutoffs[0].designation === 'Pass') {
+ this.descendingCutoffs[0].designation = this.GRADES[0];
this.setTopGradeLabel();
}
this.setFailLabel();
@@ -349,10 +357,10 @@ var GradingView = ValidatingView.extend({
else return 'F';
},
setFailLabel: function() {
- this.$el.find('.grades .letter-grade').last().html(this.failLabel());
+ this.$el.find('.grades .letter-grade').last().text(this.failLabel());
},
setTopGradeLabel: function() {
- this.$el.find('.grades .letter-grade').first().html(this.descendingCutoffs[0]['designation']);
+ this.$el.find('.grades .letter-grade').first().text(this.descendingCutoffs[0].designation);
},
setupCutoffs: function() {
// Instrument grading scale
diff --git a/cms/static/js/views/settings/main.js b/cms/static/js/views/settings/main.js
index 74aacc24c5..333b5c3a60 100644
--- a/cms/static/js/views/settings/main.js
+++ b/cms/static/js/views/settings/main.js
@@ -1,9 +1,10 @@
define(["js/views/validation", "codemirror", "underscore", "jquery", "jquery.ui", "js/utils/date_utils", "js/models/uploads",
"js/views/uploads", "js/views/license", "js/models/license",
- "common/js/components/views/feedback_notification", "jquery.timepicker", "date", "gettext"],
+ "common/js/components/views/feedback_notification", "jquery.timepicker", "date", "gettext",
+ 'edx-ui-toolkit/js/utils/string-utils'],
function(ValidatingView, CodeMirror, _, $, ui, DateUtils, FileUploadModel,
FileUploadDialog, LicenseView, LicenseModel, NotificationView,
- timepicker, date, gettext) {
+ timepicker, date, gettext, StringUtils) {
var DetailsView = ValidatingView.extend({
// Model class is CMS.Models.Settings.CourseDetails
@@ -25,7 +26,6 @@ var DetailsView = ValidatingView.extend({
initialize : function(options) {
options = options || {};
- this.fileAnchorTemplate = _.template(' <%= filename %>');
// fill in fields
this.$el.find("#course-language").val(this.model.get('language'));
this.$el.find("#course-organization").val(this.model.get('org'));
@@ -115,7 +115,7 @@ var DetailsView = ValidatingView.extend({
paceToggleTip.text(gettext('Course pacing cannot be changed once a course has started.'));
}
- this.licenseView.render()
+ this.licenseView.render();
return this;
},
@@ -139,14 +139,16 @@ var DetailsView = ValidatingView.extend({
var now = new Date(),
hours = now.getUTCHours(),
minutes = now.getUTCMinutes(),
- currentTimeText = gettext('%(hours)s:%(minutes)s (current UTC time)');
+ currentTimeText = StringUtils.interpolate(
+ gettext('{hours}:{minutes} (current UTC time)'),
+ {
+ 'hours': hours,
+ 'minutes': minutes
+ }
+ );
- $(e.currentTarget).attr('title', interpolate(currentTimeText, {
- 'hours': hours,
- 'minutes': minutes
- }, true));
+ $(e.currentTarget).attr('title', currentTimeText);
},
-
updateModel: function(event) {
switch (event.currentTarget.id) {
case 'course-language':
@@ -322,8 +324,8 @@ var DetailsView = ValidatingView.extend({
},
handleLicenseChange: function() {
- this.showNotificationBar()
- this.model.set("license", this.licenseModel.toString())
+ this.showNotificationBar();
+ this.model.set("license", this.licenseModel.toString());
}
});
diff --git a/cms/static/js/views/validation.js b/cms/static/js/views/validation.js
index d0b21e9810..afbe6bedc7 100644
--- a/cms/static/js/views/validation.js
+++ b/cms/static/js/views/validation.js
@@ -1,5 +1,13 @@
-define(["js/views/baseview", "underscore", "jquery", "gettext", "common/js/components/views/feedback_notification", "common/js/components/views/feedback_alert", "js/views/baseview", "jquery.smoothScroll"],
- function(BaseView, _, $, gettext, NotificationView, AlertView) {
+define(["edx-ui-toolkit/js/utils/html-utils",
+ "js/views/baseview",
+ "underscore",
+ "jquery",
+ "gettext",
+ "common/js/components/views/feedback_notification",
+ "common/js/components/views/feedback_alert",
+ "js/views/baseview",
+ "jquery.smoothScroll"],
+ function(HtmlUtils, BaseView, _, $, gettext, NotificationView, AlertView) {
var ValidatingView = BaseView.extend({
// Intended as an abstract class which catches validation errors on the model and
@@ -10,7 +18,7 @@ var ValidatingView = BaseView.extend({
this.selectorToField = _.invert(this.fieldToSelectorMap);
},
- errorTemplate : _.template('<%= message %>'),
+ errorTemplate : HtmlUtils.template('<%- message %>'),
save_title: gettext("You've made some changes"),
save_message: gettext("Your changes will not take effect until you save your progress."),
@@ -34,7 +42,7 @@ var ValidatingView = BaseView.extend({
var ele = this.$el.find('#' + this.fieldToSelectorMap[field]);
this._cacheValidationErrors.push(ele);
this.getInputElements(ele).addClass('error');
- $(ele).parent().append(this.errorTemplate({message : error[field]}));
+ HtmlUtils.append($(ele).parent(), this.errorTemplate({message : error[field]}));
}
$('.wrapper-notification-warning').addClass('wrapper-notification-warning-w-errors');
$('.action-save').addClass('is-disabled');
@@ -60,7 +68,7 @@ var ValidatingView = BaseView.extend({
// Set model field and return the new value.
this.clearValidationErrors();
var field = this.selectorToField[event.currentTarget.id];
- var newVal = ''
+ var newVal = '';
if(event.currentTarget.type == 'checkbox'){
newVal = $(event.currentTarget).is(":checked").toString();
}else{
diff --git a/cms/templates/js/course_grade_cutoff.underscore b/cms/templates/js/course_grade_cutoff.underscore
new file mode 100644
index 0000000000..1a85dd30f7
--- /dev/null
+++ b/cms/templates/js/course_grade_cutoff.underscore
@@ -0,0 +1,5 @@
+
+ <%- descriptor %>
+
+ <% if (removable) {%>remove<% ;} %>
+
diff --git a/cms/templates/settings_graders.html b/cms/templates/settings_graders.html
index 44989d201d..20ca1bc3de 100644
--- a/cms/templates/settings_graders.html
+++ b/cms/templates/settings_graders.html
@@ -15,7 +15,7 @@
%>
<%block name="header_extras">
-% for template_name in ["course_grade_policy"]:
+% for template_name in ["course_grade_policy", "course_grade_cutoff"]: