diff --git a/common/static/common/js/discussion/discussion_router.js b/common/static/common/js/discussion/discussion_router.js index 14ce7a6bf4..c490d575b9 100644 --- a/common/static/common/js/discussion/discussion_router.js +++ b/common/static/common/js/discussion/discussion_router.js @@ -1,4 +1,4 @@ -/* globals DiscussionThreadListView, DiscussionThreadView, DiscussionUtil, NewPostView */ +/* globals DiscussionThreadListView, DiscussionThreadView, DiscussionUtil, NewPostView, Thread */ (function() { 'use strict'; var __hasProp = {}.hasOwnProperty, @@ -18,9 +18,20 @@ return child; }; + function getSingleThreadRoute(commentable_id, thread_id) { + return commentable_id + "/threads/" + thread_id; + } + if (typeof Backbone !== "undefined" && Backbone !== null) { this.DiscussionRouter = (function(_super) { + var allThreadsRoute = "", + singleThreadRoute = getSingleThreadRoute(":forum_name", ":thread_id"), // :forum_name/threads/:thread_id + routes = {}; + + routes[allThreadsRoute] = "allThreads"; + routes[singleThreadRoute] = "showThread"; + __extends(DiscussionRouter, _super); function DiscussionRouter() { @@ -40,16 +51,16 @@ this.showMain = function() { return DiscussionRouter.prototype.showMain.apply(self, arguments); }; + this.renderThreadView = function() { + return DiscussionRouter.prototype.renderThreadView.apply(self, arguments); + }; this.setActiveThread = function() { return DiscussionRouter.prototype.setActiveThread.apply(self, arguments); }; return DiscussionRouter.__super__.constructor.apply(this, arguments); } - DiscussionRouter.prototype.routes = { - "": "allThreads", - ":forum_name/threads/:thread_id": "showThread" - }; + DiscussionRouter.prototype.routes = routes; DiscussionRouter.prototype.initialize = function(options) { var self = this; @@ -82,23 +93,50 @@ DiscussionRouter.prototype.allThreads = function() { this.nav.updateSidebar(); - return this.nav.goHome(); + this.nav.goHome(); }; DiscussionRouter.prototype.setActiveThread = function() { if (this.thread) { - return this.nav.setActiveThread(this.thread.get("id")); - } else { - return this.nav.goHome; + this.nav.setActiveThread(this.thread.get("id")); } }; DiscussionRouter.prototype.showThread = function(forum_name, thread_id) { + var self = this; this.thread = this.discussion.get(thread_id); + + if (this.thread) { + this.renderThreadView(); + return; + } + + // if thread is not loaded yet for some reason - try loading it + DiscussionUtil.safeAjax({ + url: DiscussionUtil.urlFor('retrieve_single_thread', forum_name, thread_id) + }).done(function(data) { + // if succeded - proceed normally + self.thread = new Thread(data.content); + self.discussion.add(self.thread); + self.renderThreadView(); + }).fail(function(xhr) { + // otherwise display error message and navigate to all threads view + var errorMsg; + if (xhr.status === 404) { + errorMsg = gettext("The thread you selected has been deleted. Please select another thread."); + } else { + errorMsg = gettext("We had some trouble loading more responses. Please try again."); + } + DiscussionUtil.discussionAlert(gettext("Sorry"), errorMsg); + this.allThreads(); + }); + }; + + DiscussionRouter.prototype.renderThreadView = function() { this.thread.set("unread_comments_count", 0); this.thread.set("read", true); this.setActiveThread(); - return this.showMain(); + this.showMain(); }; DiscussionRouter.prototype.showMain = function() { @@ -123,26 +161,23 @@ this.main.on("thread:responses:rendered", function() { return self.nav.updateSidebar(); }); - return this.thread.on("thread:thread_type_updated", this.showMain); + this.thread.on("thread:thread_type_updated", this.showMain); }; DiscussionRouter.prototype.navigateToThread = function(thread_id) { - var thread; + var thread, targetThreadRoute; thread = this.discussion.get(thread_id); - return this.navigate("" + (thread.get("commentable_id")) + "/threads/" + thread_id, { - trigger: true - }); + targetThreadRoute = getSingleThreadRoute(thread.get("commentable_id"), thread_id); + this.navigate(targetThreadRoute, {trigger: true}); }; DiscussionRouter.prototype.navigateToAllThreads = function() { - return this.navigate("", { - trigger: true - }); + this.navigate(allThreadsRoute, {trigger: true}); }; DiscussionRouter.prototype.showNewPost = function() { var self = this; - return $('.forum-content').fadeOut({ + $('.forum-content').fadeOut({ duration: 200, complete: function() { return self.newPost.fadeIn(200).focus(); @@ -151,7 +186,7 @@ }; DiscussionRouter.prototype.hideNewPost = function() { - return this.newPost.fadeOut({ + this.newPost.fadeOut({ duration: 200, complete: function() { return $('.forum-content').fadeIn(200).find('.thread-wrapper').focus(); diff --git a/common/static/common/js/discussion/main.js b/common/static/common/js/discussion/main.js index 866a3491d1..5f34c6af9d 100644 --- a/common/static/common/js/discussion/main.js +++ b/common/static/common/js/discussion/main.js @@ -34,10 +34,11 @@ course_settings: course_settings }); /* jshint +W031*/ - return Backbone.history.start({ - pushState: true, - root: "/courses/" + $$course_id + "/discussion/forum/" - }); + if (!Backbone.History.started) { + Backbone.history.start({pushState: true, root: "/courses/" + $$course_id + "/discussion/forum/"}); + } else { + Backbone.history.loadUrl(window.location.pathname); + } } }; DiscussionProfileApp = { diff --git a/common/static/common/js/discussion/utils.js b/common/static/common/js/discussion/utils.js index be3066b079..e4f7b1cb8a 100644 --- a/common/static/common/js/discussion/utils.js +++ b/common/static/common/js/discussion/utils.js @@ -1,4 +1,4 @@ -/* globals $$course_id, Content, Markdown, URI */ +/* globals $$course_id, Content, Markdown, MathJax, URI */ (function() { 'use strict'; this.DiscussionUtil = (function() { @@ -65,7 +65,7 @@ DiscussionUtil.generateDiscussionLink = function(cls, txt, handler) { return $("") .addClass("discussion-link").attr("href", "#") - .addClass(cls).html(txt).click(function() {return handler(this);}); + .addClass(cls).text(txt).click(function() {return handler(this);}); }; DiscussionUtil.urlFor = function(name, param, param1, param2) { @@ -134,15 +134,17 @@ }; DiscussionUtil.showLoadingIndicator = function(element, takeFocus) { - this.$_loading = $( - "
" + - gettext("Loading content") + - "
" + var animElem = edx.HtmlUtils.joinHtml( + edx.HtmlUtils.HTML("
"), + gettext("Loading content"), + edx.HtmlUtils.HTML("
") ); - element.after(this.$_loading); + var $animElem = $(animElem.toString()); + element.after($animElem); + this.$_loading = $animElem; if (takeFocus) { this.makeFocusTrap(this.$_loading); - return this.$_loading.focus(); + this.$_loading.focus(); } }; @@ -151,42 +153,35 @@ }; DiscussionUtil.discussionAlert = function(header, body) { - var alertDiv, alertTrigger; + var $alertDiv, $alertTrigger; + // Prevents "text" is undefined in underscore.js in tests - looks like some tests use + // discussions somehow, but never append discussion fixtures or reset them; this causes + // entire test suite (lms, cms, common) to fail due to unhandled JS exception + var popupTemplate = $("#alert-popup").html() || ""; if ($("#discussion-alert").length === 0) { - alertDiv = $( - "