diff --git a/cms/static/js/models/textbook.js b/cms/static/js/models/textbook.js index 51f6e5b6fa..6f4010c050 100644 --- a/cms/static/js/models/textbook.js +++ b/cms/static/js/models/textbook.js @@ -59,25 +59,37 @@ CMS.Models.Textbook = Backbone.AssociatedModel.extend({ }, validate: function(attrs, options) { if (!attrs.name) { - return "Textbook name is required"; + return { + message: "Textbook name is required", + attributes: {name: true} + }; } if (attrs.chapters.length === 0) { - return "Please add at least one asset"; + return { + message: "Please add at least one asset", + attributes: {chapters: true} + }; } else if (attrs.chapters.length === 1) { // only asset_path is required: we don't need a name if (!attrs.chapters.first().get('asset_path')) { - return "Please add at least one asset"; + return { + message: "Please add at least one asset", + attributes: {chapters: true} + }; } } else { // validate all chapters - var allChaptersValid = true; + var invalidChapters = []; attrs.chapters.each(function(chapter) { if(!chapter.isValid()) { - allChaptersValid = false; + invalidChapters.push(chapter); } }); - if(!allChaptersValid) { - return "All chapters must have a name and asset"; + if(invalidChapters) { + return { + message: "All chapters must have a name and asset", + attributes: {chapters: invalidChapters} + }; } } } @@ -119,11 +131,20 @@ CMS.Models.Chapter = Backbone.AssociatedModel.extend({ }, validate: function(attrs, options) { if(!attrs.name && !attrs.asset_path) { - return "Chapter name and asset_path are both required"; + return { + message: "Chapter name and asset_path are both required", + attributes: {name: true, asset_path: true} + }; } else if(!attrs.name) { - return "Chapter name is required"; + return { + message: "Chapter name is required", + attributes: {name: true} + }; } else if (!attrs.asset_path) { - return "asset_path is required"; + return { + message: "asset_path is required", + attributes: {asset_path: true} + }; } } }); @@ -150,7 +171,10 @@ CMS.Models.FileUpload = Backbone.Model.extend({ }, validate: function(attrs, options) { if(attrs.selectedFile && attrs.selectedFile.type !== "application/pdf") { - return gettext("Only PDF files can be uploaded. Please select a file ending in .pdf to upload."); + return { + message: "Only PDF files can be uploaded. Please select a file ending in .pdf to upload.", + attributes: {selectedFile: true} + }; } } }); diff --git a/cms/static/js/views/textbook.js b/cms/static/js/views/textbook.js index 33cebe198f..907cddd239 100644 --- a/cms/static/js/views/textbook.js +++ b/cms/static/js/views/textbook.js @@ -213,7 +213,8 @@ CMS.Views.EditChapter = Backbone.View.extend({ this.$el.html(this.template({ name: this.model.escape('name'), asset_path: this.model.escape('asset_path'), - order: this.model.get('order') + order: this.model.get('order'), + error: this.model.validationError })); return this; }, @@ -267,7 +268,7 @@ CMS.Views.UploadDialog = Backbone.View.extend({ uploadedBytes: this.model.get('uploadedBytes'), totalBytes: this.model.get('totalBytes'), finished: this.model.get('finished'), - error: this.model.get('error') + error: this.model.validationError })); // ideally, we'd like to tell the browser to pre-populate the // with the selectedFile if we have one -- but @@ -286,8 +287,7 @@ CMS.Views.UploadDialog = Backbone.View.extend({ }, selectFile: function(e) { this.model.set({ - selectedFile: e.target.files[0] || null, - error: null + selectedFile: e.target.files[0] || null }); }, show: function(e) { @@ -308,8 +308,7 @@ CMS.Views.UploadDialog = Backbone.View.extend({ }, handleInvalid: function(model, error, options) { model.set({ - selectedFile: null, - error: error + selectedFile: null }); }, upload: function(e) { diff --git a/cms/templates/js/edit-chapter.underscore b/cms/templates/js/edit-chapter.underscore index 95621b6328..8a6367b3c4 100644 --- a/cms/templates/js/edit-chapter.underscore +++ b/cms/templates/js/edit-chapter.underscore @@ -1,9 +1,11 @@ -