").html(text);
- cnt = 0;
+ htmlString = htmlString.replace(new RegExp(ESCAPED_BACKSLASH, 'g'), '\\\\\\\\');
+ $div = edx.HtmlUtils.setHtml($("
"), edx.HtmlUtils.HTML(htmlString));
$div.find("code").each(function(index, code) {
- $(code).html(processor(codeArchive[cnt], 'code'));
- return cnt += 1;
+ edx.HtmlUtils.setHtml(
+ $(code),
+ edx.HtmlUtils.HTML(processor(codeArchive[index], 'code'))
+ );
});
- text = $div.html();
- return text;
+ return edx.HtmlUtils.HTML($div.html());
};
- DiscussionUtil.unescapeHighlightTag = function(text) {
- return text.replace(
- /\<\;highlight\>\;/g,
- "
").replace(/\<\;\/highlight\>\;/g, ""
+ DiscussionUtil.unescapeHighlightTag = function(htmlSnippet) {
+ return edx.HtmlUtils.HTML(
+ htmlSnippet.toString().replace(
+ /\<\;highlight\>\;/g,
+ "
").replace(/\<\;\/highlight\>\;/g, ""
+ )
);
};
- DiscussionUtil.stripHighlight = function(text) {
- return text.replace(
- /\&(amp\;)?lt\;highlight\&(amp\;)?gt\;/g, "").replace(/\&(amp\;)?lt\;\/highlight\&(amp\;)?gt\;/g, ""
- );
+ DiscussionUtil.stripHighlight = function(htmlString) {
+ return htmlString
+ .replace(/\&(amp\;)?lt\;highlight\&(amp\;)?gt\;/g, "")
+ .replace(/\&(amp\;)?lt\;\/highlight\&(amp\;)?gt\;/g, "");
};
- DiscussionUtil.stripLatexHighlight = function(text) {
- return this.processEachMathAndCode(text, this.stripHighlight);
+ DiscussionUtil.stripLatexHighlight = function(htmlSnippet) {
+ return this.processEachMathAndCode(htmlSnippet, this.stripHighlight);
};
- DiscussionUtil.markdownWithHighlight = function(text) {
+ /**
+ * Processes markdown into formatted text and handles highlighting.
+ * @param unsafeText - raw markdown text, with all HTML entitites being *unescaped*.
+ * @returns HtmlSnippet
+ */
+ DiscussionUtil.markdownWithHighlight = function(unsafeText) {
var converter;
- text = text.replace(/^\>\;/gm, ">");
+ unsafeText = unsafeText.replace(/^\>\;/gm, ">");
converter = Markdown.getMathCompatibleConverter();
- text = this.unescapeHighlightTag(this.stripLatexHighlight(converter.makeHtml(text)));
- return text.replace(/^>/gm, ">");
+ /*
+ * converter.makeHtml and HTML escaping:
+ * - converter.makeHtml is not HtmlSnippet aware, so we must pass unescaped raw text
+ * - converter.makeHtml strips html tags in post body and escapes in code blocks by design.
+ * HTML tags are not supported. Only markdown is supported.
+ */
+ var htmlSnippet = edx.HtmlUtils.HTML(converter.makeHtml(unsafeText));
+ return this.unescapeHighlightTag(this.stripLatexHighlight(htmlSnippet));
};
DiscussionUtil.abbreviateString = function(text, minLength) {
@@ -444,19 +467,48 @@
}
};
- DiscussionUtil.abbreviateHTML = function(html, minLength) {
+ DiscussionUtil.convertMath = function(element) {
+ edx.HtmlUtils.setHtml(
+ element,
+ this.postMathJaxProcessor(this.markdownWithHighlight(element.text()))
+ );
+
+ this.typesetMathJax(element);
+ };
+
+ DiscussionUtil.typesetMathJax = function(element) {
+ if (typeof MathJax !== "undefined" && MathJax !== null) {
+ MathJax.Hub.Queue(["Typeset", MathJax.Hub, element[0]]);
+ }
+ };
+
+ DiscussionUtil.abbreviateHTML = function(htmlSnippet, maxLength) {
var $result, imagesToReplace, truncated_text;
- truncated_text = jQuery.truncate(html, {
- length: minLength,
+ truncated_text = edx.HtmlUtils.HTML(jQuery.truncate(htmlSnippet.toString(), {
+ length: maxLength,
noBreaks: true,
ellipsis: gettext('…')
- });
- $result = $("
" + truncated_text + "
");
+ }));
+ $result = $(edx.HtmlUtils.joinHtml(
+ edx.HtmlUtils.HTML("
"),
+ truncated_text,
+ edx.HtmlUtils.HTML("
")
+ ).toString());
imagesToReplace = $result.find("img:not(:first)");
if (imagesToReplace.length > 0) {
- $result.append("
Some images in this post have been omitted
");
+ edx.HtmlUtils.append(
+ $result,
+ edx.HtmlUtils.interpolateHtml(
+ edx.HtmlUtils.HTML("
{text}
"),
+ {text: gettext("Some images in this post have been omitted")}
+ )
+ );
}
- imagesToReplace.replaceWith("
image omitted");
+ // See TNL-4983 for an explanation of why the linter requires ensureHtml()
+ var afterMessage = edx.HtmlUtils.interpolateHtml(
+ edx.HtmlUtils.HTML("
{text}"), {text: gettext("image omitted")}
+ );
+ imagesToReplace.after(edx.HtmlUtils.ensureHtml(afterMessage).toString()).remove();
return $result.html();
};
diff --git a/common/static/common/js/discussion/views/discussion_content_view.js b/common/static/common/js/discussion/views/discussion_content_view.js
index 4623a49c45..f3900e6308 100644
--- a/common/static/common/js/discussion/views/discussion_content_view.js
+++ b/common/static/common/js/discussion/views/discussion_content_view.js
@@ -271,20 +271,22 @@
return $button.toggleClass("is-checked", endorsed);
},
votes: function(votes) {
- var button, numVotes, selector, votesHtml, votesCountMsg;
+ var button, numVotes, selector, votesText, votesCountMsg;
selector = ".action-vote";
this.updateButtonState(selector, window.user.voted(this.model));
button = this.$el.find(selector);
numVotes = votes.up_count;
votesCountMsg = ngettext(
- "there is currently %(numVotes)s vote", "there are currently %(numVotes)s votes", numVotes
+ "there is currently {numVotes} vote", "there are currently {numVotes} votes", numVotes
);
- button.find(".js-sr-vote-count").html(interpolate(votesCountMsg, {numVotes: numVotes }, true));
- votesHtml = interpolate(ngettext("%(numVotes)s Vote", "%(numVotes)s Votes", numVotes), {
- numVotes: numVotes
- }, true);
- button.find(".vote-count").html(votesHtml);
- return this.$el.find('.display-vote .vote-count').html(votesHtml);
+ button.find(".js-sr-vote-count").empty().text(
+ edx.StringUtils.interpolate(votesCountMsg, {numVotes: numVotes })
+ );
+ votesText = edx.StringUtils.interpolate(
+ ngettext("{numVotes} Vote", "{numVotes} Votes", numVotes),
+ { numVotes: numVotes });
+ button.find(".vote-count").empty().text(votesText);
+ this.$el.find('.display-vote .vote-count').empty().text(votesText);
},
pinned: function(pinned) {
this.updateButtonState(".action-pin", pinned);
@@ -389,18 +391,18 @@
msg = gettext("We had some trouble removing this endorsement. Please try again.");
}
}
- beforeFunc = function() {
- return self.trigger("comment:endorse");
- };
- return DiscussionUtil.updateWithUndo(this.model, updates, {
- url: url,
- type: "POST",
- data: {
- endorsed: is_endorsing
+ return DiscussionUtil.updateWithUndo(
+ this.model,
+ updates,
+ {
+ url: url,
+ type: "POST",
+ data: { endorsed: is_endorsing },
+ $elem: $(event.currentTarget)
},
- beforeSend: beforeFunc,
- $elem: $(event.currentTarget)
- }, msg).always(this.trigger("comment:endorse"));
+ msg,
+ function() { return self.trigger("comment:endorse"); }
+ ).always(this.trigger("comment:endorse"));
};
DiscussionContentShowView.prototype.toggleVote = function(event) {
diff --git a/common/static/common/js/discussion/views/discussion_thread_edit_view.js b/common/static/common/js/discussion/views/discussion_thread_edit_view.js
index 30ca60e92d..8b4d6d9569 100644
--- a/common/static/common/js/discussion/views/discussion_thread_edit_view.js
+++ b/common/static/common/js/discussion/views/discussion_thread_edit_view.js
@@ -25,13 +25,14 @@
},
render: function() {
- var threadTypeTemplate,
- formId = _.uniqueId("form-");
- this.template = _.template($('#thread-edit-template').html());
- this.$el.html(this.template(this.model.toJSON())).appendTo(this.container);
- this.submitBtn = this.$('.post-update');
- threadTypeTemplate = _.template($("#thread-type-template").html());
- this.addField(threadTypeTemplate({form_id: formId}));
+ var formId = _.uniqueId("form-"),
+ threadTypeTemplate = edx.HtmlUtils.template($("#thread-type-template").html()),
+ $threadTypeSelector = $(threadTypeTemplate({form_id: formId}).toString()),
+ mainTemplate = edx.HtmlUtils.template($('#thread-edit-template').html());
+ edx.HtmlUtils.setHtml(this.$el, mainTemplate(this.model.toJSON()));
+ this.container.append(this.$el);
+ this.$submitBtn = this.$('.post-update');
+ this.addField($threadTypeSelector);
this.$("#" + formId + "-post-type-" + this.threadType).attr('checked', true);
// Only allow the topic field for course threads, as standalone threads
// cannot be moved.
@@ -46,8 +47,8 @@
return this;
},
- addField: function(fieldView) {
- this.$('.forum-edit-post-form-wrapper').append(fieldView);
+ addField: function($fieldView) {
+ this.$('.forum-edit-post-form-wrapper').append($fieldView);
return this;
},
@@ -69,8 +70,8 @@
}
return DiscussionUtil.safeAjax({
- $elem: this.submitBtn,
- $loading: this.submitBtn,
+ $elem: this.$submitBtn,
+ $loading: this.$submitBtn,
url: DiscussionUtil.urlFor('update_thread', this.model.id),
type: 'POST',
dataType: 'json',
diff --git a/common/static/common/js/discussion/views/discussion_thread_list_view.js b/common/static/common/js/discussion/views/discussion_thread_list_view.js
index 7fe06e33e6..58061d1520 100644
--- a/common/static/common/js/discussion/views/discussion_thread_list_view.js
+++ b/common/static/common/js/discussion/views/discussion_thread_list_view.js
@@ -123,6 +123,7 @@
return self.displayedCollection.reset(discussion.models);
});
this.collection.on("add", this.addAndSelectThread);
+ this.collection.on("thread:remove", this.threadRemoved);
this.sidebar_padding = 10;
this.boardName = null;
this.template = _.template($("#thread-list-template").html());
@@ -133,11 +134,12 @@
});
this.searchAlertCollection.on("add", function(searchAlert) {
var content;
- content = _.template($("#search-alert-template").html())({
- 'message': searchAlert.attributes.message,
- 'cid': searchAlert.cid
+ content = edx.HtmlUtils.template($("#search-alert-template").html())({
+ 'messageHtml': searchAlert.attributes.message,
+ 'cid': searchAlert.cid,
+ 'css_class': searchAlert.attributes.css_class
});
- self.$(".search-alerts").append(content);
+ edx.HtmlUtils.append(self.$(".search-alerts"), content);
return self.$("#search-alert-" + searchAlert.cid + " a.dismiss")
.bind("click", searchAlert, function(event) {
return self.removeSearchAlert(event.data.cid);
@@ -151,11 +153,19 @@
});
};
- DiscussionThreadListView.prototype.addSearchAlert = function(message) {
+ /**
+ * Creates search alert model and adds it to collection
+ * @param message - alert message
+ * @param css_class - Allows setting custom css class for a message. This can be used to style messages
+ * of different types differently (i.e. other background, completely hide, etc.)
+ * @returns {Backbone.Model}
+ */
+ DiscussionThreadListView.prototype.addSearchAlert = function(message, css_class) {
var m;
- m = new Backbone.Model({
- "message": message
- });
+ if (typeof css_class === 'undefined' || css_class === null) {
+ css_class = "";
+ }
+ m = new Backbone.Model({"message": message, "css_class": css_class});
this.searchAlertCollection.add(m);
return m;
};
@@ -169,13 +179,13 @@
};
DiscussionThreadListView.prototype.reloadDisplayedCollection = function(thread) {
- var active, content, current_el, thread_id;
+ var active, $content, current_el, thread_id;
this.clearSearchAlerts();
thread_id = thread.get('id');
- content = this.renderThread(thread);
+ $content = this.renderThread(thread);
current_el = this.$(".forum-nav-thread[data-id=" + thread_id + "]");
active = current_el.has(".forum-nav-thread-link.is-active").length !== 0;
- current_el.replaceWith(content);
+ current_el.replaceWith($content);
this.showMetadataAccordingToSort();
if (active) {
return this.setActiveThread(thread_id);
@@ -236,12 +246,14 @@
};
DiscussionThreadListView.prototype.render = function() {
- var self = this;
+ var self = this,
+ $elem = this.template({
+ isCohorted: this.courseSettings.get("is_cohorted"),
+ isPrivilegedUser: DiscussionUtil.isPrivilegedUser()
+ });
this.timer = 0;
- this.$el.html(this.template({
- isCohorted: this.courseSettings.get("is_cohorted"),
- isPrivilegedUser: DiscussionUtil.isPrivilegedUser()
- }));
+ this.$el.empty();
+ this.$el.append($elem);
this.$(".forum-nav-sort-control option").removeProp("selected");
this.$(".forum-nav-sort-control option[value=" + this.collection.sort_preference + "]")
.prop("selected", true);
@@ -258,20 +270,17 @@
};
DiscussionThreadListView.prototype.renderThreads = function() {
- var content, rendered, thread, _i, _len, _ref;
- this.$(".forum-nav-thread-list").html("");
- rendered = $("
");
- _ref = this.displayedCollection.models;
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- thread = _ref[_i];
- content = this.renderThread(thread);
- rendered.append(content);
+ var $content, thread, i, len;
+ this.$(".forum-nav-thread-list").empty();
+ for (i = 0, len = this.displayedCollection.models.length; i < len; i++) {
+ thread = this.displayedCollection.models[i];
+ $content = this.renderThread(thread);
+ this.$(".forum-nav-thread-list").append($content);
}
- this.$(".forum-nav-thread-list").html(rendered.html());
this.showMetadataAccordingToSort();
this.renderMorePages();
this.updateSidebar();
- return this.trigger("threads:rendered");
+ this.trigger("threads:rendered");
};
DiscussionThreadListView.prototype.showMetadataAccordingToSort = function() {
@@ -291,19 +300,15 @@
DiscussionThreadListView.prototype.renderMorePages = function() {
if (this.displayedCollection.hasMorePages()) {
- return this.$(".forum-nav-thread-list")
- .append(
- "
" +
- " " + gettext("Load more") + "" +
- ""
- );
+ edx.HtmlUtils.append(
+ this.$(".forum-nav-thread-list"),
+ edx.HtmlUtils.template($("#nav-load-more-link").html())({})
+ );
}
};
DiscussionThreadListView.prototype.getLoadingContent = function(srText) {
- return '
' +
- ' ' + srText + '' +
- '
';
+ return edx.HtmlUtils.template($("#nav-loading-template").html())({srText: srText});
};
DiscussionThreadListView.prototype.loadMorePages = function(event) {
@@ -313,7 +318,8 @@
event.preventDefault();
}
loadMoreElem = this.$(".forum-nav-load-more");
- loadMoreElem.html(this.getLoadingContent(gettext("Loading more threads")));
+ loadMoreElem.empty();
+ edx.HtmlUtils.append(loadMoreElem, this.getLoadingContent(gettext("Loading more threads")));
loadingElem = loadMoreElem.find(".forum-nav-loading");
DiscussionUtil.makeFocusTrap(loadingElem);
loadingElem.focus();
@@ -374,8 +380,8 @@
if (unreadCount > 0) {
content.find('.forum-nav-thread-comments-count').attr(
"data-tooltip",
- interpolate(
- ngettext('%(unread_count)s new comment', '%(unread_count)s new comments', unreadCount),
+ edx.StringUtils.interpolate(
+ ngettext('{unread_count} new comment', '{unread_count} new comments', unreadCount),
{unread_count: unreadCount},
true
)
@@ -392,23 +398,30 @@
return false;
};
- DiscussionThreadListView.prototype.threadRemoved = function(thread_id) {
- return this.trigger("thread:removed", thread_id);
+ DiscussionThreadListView.prototype.threadRemoved = function(thread) {
+ this.trigger("thread:removed", thread);
};
DiscussionThreadListView.prototype.setActiveThread = function(thread_id) {
+ var $srElem;
this.$(".forum-nav-thread-link").find(".sr").remove();
this.$(".forum-nav-thread[data-id!='" + thread_id + "'] .forum-nav-thread-link")
.removeClass("is-active");
+ $srElem = edx.HtmlUtils.joinHtml(
+ edx.HtmlUtils.HTML('
'),
+ edx.HtmlUtils.ensureHtml(gettext("Current conversation")),
+ edx.HtmlUtils.HTML('')
+ ).toString();
this.$(".forum-nav-thread[data-id='" + thread_id + "'] .forum-nav-thread-link")
.addClass("is-active").find(".forum-nav-thread-wrapper-1")
- .prepend('
' + gettext("Current conversation") + '');
+ .prepend($srElem);
};
DiscussionThreadListView.prototype.goHome = function() {
- var thread_id, url;
+ var url, $tpl_content;
this.template = _.template($("#discussion-home-template").html());
- $(".forum-content").html(this.template);
+ $tpl_content = $(this.template());
+ $(".forum-content").empty().append($tpl_content);
$(".forum-nav-thread-list a").removeClass("is-active").find(".sr").remove();
$("input.email-setting").bind("click", this.updateEmailNotifications);
url = DiscussionUtil.urlFor("notifications_status", window.user.get("id"));
@@ -416,19 +429,9 @@
url: url,
type: "GET",
success: function(response) {
- if (response.status) {
- return $('input.email-setting').attr('checked', 'checked');
- } else {
- return $('input.email-setting').removeAttr('checked');
- }
+ $('input.email-setting').prop('checked', response.status);
}
});
- thread_id = null;
- return this.trigger("thread:removed");
- /*
- select all threads
- */
-
};
DiscussionThreadListView.prototype.isBrowseMenuVisible = function() {
@@ -505,19 +508,19 @@
};
DiscussionThreadListView.prototype.getNameWidth = function(name) {
- var test, width;
- test = $("
");
- test.css({
+ var $test, width;
+ $test = $("
");
+ $test.css({
"font-size": this.$(".forum-nav-browse-current").css('font-size'),
opacity: 0,
position: 'absolute',
left: -1000,
top: -1000
});
- $("body").append(test);
- test.html(name);
- width = test.width();
- test.remove();
+ $("body").append($test);
+ $test.text(name);
+ width = $test.width();
+ $test.remove();
return width;
};
@@ -653,8 +656,7 @@
};
DiscussionThreadListView.prototype.searchFor = function(text) {
- var url,
- self = this;
+ var url, self = this;
this.clearSearchAlerts();
this.clearFilters();
this.mode = 'search';
@@ -677,12 +679,16 @@
dataType: 'json',
$loading: $,
loadingCallback: function() {
- return self.$(".forum-nav-thread-list")
- .html(
- "
" +
- self.getLoadingContent(gettext("Loading thread list")) +
- ""
- );
+ var element = self.$(".forum-nav-thread-list");
+ element.empty();
+ edx.HtmlUtils.append(
+ element,
+ edx.HtmlUtils.joinHtml(
+ edx.HtmlUtils.HTML("
"),
+ self.getLoadingContent(gettext("Loading thread list")),
+ edx.HtmlUtils.HTML("")
+ )
+ );
},
loadedCallback: function() {
return self.$(".forum-nav-thread-list .forum-nav-load-more").remove();
@@ -697,17 +703,22 @@
if (!_.isNull(response.corrected_text)) {
noResponseMsg = _.escape(
gettext(
- 'No results found for %(original_query)s. ' +
- 'Showing results for %(suggested_query)s.'
+ 'No results found for {original_query}. ' +
+ 'Showing results for {suggested_query}.'
)
);
- message = interpolate(
+ message = edx.HtmlUtils.interpolateHtml(
noResponseMsg,
{
- "original_query": "
" + _.escape(text) + "",
- "suggested_query": "
" + response.corrected_text + ""
- },
- true
+ "original_query": edx.HtmlUtils.joinHtml(
+ edx.HtmlUtils.HTML("
"), text, edx.HtmlUtils.HTML("")
+ ),
+ "suggested_query": edx.HtmlUtils.joinHtml(
+ edx.HtmlUtils.HTML("
"),
+ response.corrected_text ,
+ edx.HtmlUtils.HTML("")
+ )
+ }
);
self.addSearchAlert(message);
} else if (response.discussion_data.length === 0) {
@@ -731,18 +742,23 @@
url: DiscussionUtil.urlFor("users"),
type: "GET",
dataType: 'json',
- error: function() {
- },
+ error: function() {},
success: function(response) {
- var message;
+ var message, username;
if (response.users.length > 0) {
- message = interpolate(_.escape(gettext('Show posts by %(username)s.')), {
- "username": _.template('
<%- username %>')({
- url: DiscussionUtil.urlFor("user_profile", response.users[0].id),
- username: response.users[0].username
- })
- }, true);
- return self.addSearchAlert(message);
+ username = edx.HtmlUtils.joinHtml(
+ edx.HtmlUtils.interpolateHtml(
+ edx.HtmlUtils.HTML('
'),
+ {url: DiscussionUtil.urlFor("user_profile", response.users[0].id)}
+ ),
+ response.users[0].username,
+ edx.HtmlUtils.HTML("")
+ );
+
+ message = edx.HtmlUtils.interpolateHtml(
+ gettext('Show posts by {username}.'), {"username": username}
+ );
+ return self.addSearchAlert(message, 'search-by-user');
}
}
});
@@ -765,23 +781,17 @@
};
DiscussionThreadListView.prototype.updateEmailNotifications = function() {
- if ($('input.email-setting').attr('checked')) {
- return DiscussionUtil.safeAjax({
- url: DiscussionUtil.urlFor("enable_notifications"),
- type: "POST",
- error: function() {
- return $('input.email-setting').removeAttr('checked');
- }
- });
- } else {
- return DiscussionUtil.safeAjax({
- url: DiscussionUtil.urlFor("disable_notifications"),
- type: "POST",
- error: function() {
- return $('input.email-setting').attr('checked', 'checked');
- }
- });
- }
+ var $checkbox, checked, urlName;
+ $checkbox = $('input.email-setting');
+ checked = $checkbox.prop('checked');
+ urlName = (checked) ? "enable_notifications" : "disable_notifications";
+ DiscussionUtil.safeAjax({
+ url: DiscussionUtil.urlFor(urlName),
+ type: "POST",
+ error: function() {
+ $checkbox.prop('checked', !checked);
+ }
+ });
};
return DiscussionThreadListView;
diff --git a/common/static/common/js/discussion/views/discussion_thread_profile_view.js b/common/static/common/js/discussion/views/discussion_thread_profile_view.js
index 31abb9a7c8..96b84381bb 100644
--- a/common/static/common/js/discussion/views/discussion_thread_profile_view.js
+++ b/common/static/common/js/discussion/views/discussion_thread_profile_view.js
@@ -28,7 +28,7 @@
}
DiscussionThreadProfileView.prototype.render = function() {
- var element, params;
+ var params;
this.convertMath();
this.abbreviateBody();
params = $.extend(this.model.toJSON(), {
@@ -42,26 +42,24 @@
}
});
}
- this.$el.html(_.template($("#profile-thread-template").html())(params));
+ edx.HtmlUtils.setHtml(
+ this.$el,
+ edx.HtmlUtils.template($("#profile-thread-template").html())(params)
+ );
this.$("span.timeago").timeago();
- element = this.$(".post-body");
- if (typeof MathJax !== "undefined" && MathJax !== null) {
- MathJax.Hub.Queue(["Typeset", MathJax.Hub, element[0]]);
- }
+ DiscussionUtil.typesetMathJax(this.$(".post-body"));
return this;
};
DiscussionThreadProfileView.prototype.convertMath = function() {
- return this.model.set(
- 'markdownBody',
- DiscussionUtil.postMathJaxProcessor(DiscussionUtil.markdownWithHighlight(this.model.get('body')))
- );
+ var htmlSnippet = DiscussionUtil.markdownWithHighlight(this.model.get('body'));
+ this.model.set('markdownBody', htmlSnippet);
};
DiscussionThreadProfileView.prototype.abbreviateBody = function() {
var abbreviated;
abbreviated = DiscussionUtil.abbreviateHTML(this.model.get('markdownBody'), 140);
- return this.model.set('abbreviatedBody', abbreviated);
+ this.model.set('abbreviatedBody', abbreviated);
};
return DiscussionThreadProfileView;
diff --git a/common/static/common/js/discussion/views/discussion_thread_show_view.js b/common/static/common/js/discussion/views/discussion_thread_show_view.js
index a5fc0fc12d..6e13898b69 100644
--- a/common/static/common/js/discussion/views/discussion_thread_show_view.js
+++ b/common/static/common/js/discussion/views/discussion_thread_show_view.js
@@ -38,7 +38,6 @@
DiscussionThreadShowView.prototype.renderTemplate = function() {
var context;
- this.template = _.template($("#thread-show-template").html());
context = $.extend({
mode: this.mode,
flagged: this.model.isFlagged(),
@@ -46,27 +45,25 @@
cid: this.model.cid,
readOnly: $('.discussion-module').data('read-only')
}, this.model.attributes);
- return this.template(context);
+ return edx.HtmlUtils.template($("#thread-show-template").html())(context);
};
DiscussionThreadShowView.prototype.render = function() {
- this.$el.html(this.renderTemplate());
+ edx.HtmlUtils.setHtml(
+ this.$el,
+ this.renderTemplate()
+ );
this.delegateEvents();
this.renderAttrs();
this.$("span.timeago").timeago();
this.convertMath();
- this.highlight(this.$(".post-body"));
- this.highlight(this.$("h1,h3"));
+ this.$(".post-body");
+ this.$("h1,h3");
return this;
};
DiscussionThreadShowView.prototype.convertMath = function() {
- var element;
- element = this.$(".post-body");
- element.html(DiscussionUtil.postMathJaxProcessor(DiscussionUtil.markdownWithHighlight(element.text())));
- if (typeof MathJax !== "undefined" && MathJax !== null) {
- return MathJax.Hub.Queue(["Typeset", MathJax.Hub, element[0]]);
- }
+ DiscussionUtil.convertMath(this.$(".post-body"));
};
DiscussionThreadShowView.prototype.edit = function(event) {
@@ -77,12 +74,6 @@
return this.trigger("thread:_delete", event);
};
- DiscussionThreadShowView.prototype.highlight = function(el) {
- if (el.html()) {
- return el.html(el.html().replace(/<mark>/g, "
").replace(/<\/mark>/g, ""));
- }
- };
-
return DiscussionThreadShowView;
})(DiscussionContentShowView);
diff --git a/common/static/common/js/discussion/views/discussion_thread_view.js b/common/static/common/js/discussion/views/discussion_thread_view.js
index 2854690369..8a859e77cb 100644
--- a/common/static/common/js/discussion/views/discussion_thread_view.js
+++ b/common/static/common/js/discussion/views/discussion_thread_view.js
@@ -91,6 +91,7 @@
id = self.model.get("id");
if (collection.get(id)) {
self.model = collection.get(id);
+ self.rerender();
}
});
this.createShowView();
@@ -133,7 +134,9 @@
DiscussionThreadView.prototype.render = function() {
var self = this;
- this.$el.html(this.renderTemplate());
+ var $element = $(this.renderTemplate());
+ this.$el.empty();
+ this.$el.append($element);
this.delegateEvents();
this.renderShowView();
this.renderAttrs();
@@ -215,7 +218,7 @@
}
};
- DiscussionThreadView.prototype.loadResponses = function(responseLimit, elem, firstLoad) {
+ DiscussionThreadView.prototype.loadResponses = function(responseLimit, $elem, firstLoad) {
var takeFocus,
self = this;
takeFocus = this.mode === "tab" ? false : true;
@@ -227,8 +230,8 @@
resp_skip: this.responses.size(),
resp_limit: responseLimit ? responseLimit : void 0
},
- $elem: elem,
- $loading: elem,
+ $elem: $elem,
+ $loading: $elem,
takeFocus: takeFocus,
complete: function() {
self.responsesRequest = null;
@@ -279,20 +282,20 @@
};
DiscussionThreadView.prototype.renderResponseCountAndPagination = function(responseTotal) {
- var buttonText, loadMoreButton, responseCountFormat, responseLimit, responsePagination,
+ var buttonText, $loadMoreButton, responseCountFormat, responseLimit, responsePagination,
responsesRemaining, showingResponsesText, self = this;
if (this.isQuestion() && this.markedAnswers.length !== 0) {
responseCountFormat = ngettext(
- "%(numResponses)s other response", "%(numResponses)s other responses", responseTotal
+ "{numResponses} other response", "{numResponses} other responses", responseTotal
);
} else {
responseCountFormat = ngettext(
- "%(numResponses)s response", "%(numResponses)s responses", responseTotal
+ "{numResponses} response", "{numResponses} responses", responseTotal
);
}
- this.$el.find(".response-count").html(interpolate(responseCountFormat, {
- numResponses: responseTotal
- }, true));
+ this.$el.find(".response-count").text(
+ edx.StringUtils.interpolate(responseCountFormat, {numResponses: responseTotal}, true)
+ );
responsePagination = this.$el.find(".response-pagination");
responsePagination.empty();
if (responseTotal > 0) {
@@ -301,9 +304,9 @@
showingResponsesText = gettext("Showing all responses");
}
else {
- showingResponsesText = interpolate(
+ showingResponsesText = edx.StringUtils.interpolate(
ngettext(
- "Showing first response", "Showing first %(numResponses)s responses",
+ "Showing first response", "Showing first {numResponses} responses",
this.responses.size()
),
{ numResponses: this.responses.size() },
@@ -312,22 +315,22 @@
}
responsePagination.append($("
")
- .addClass("response-display-count").html(_.escape(showingResponsesText)));
+ .addClass("response-display-count").text(showingResponsesText));
if (responsesRemaining > 0) {
if (responsesRemaining < SUBSEQUENT_RESPONSE_PAGE_SIZE) {
responseLimit = null;
buttonText = gettext("Load all responses");
} else {
responseLimit = SUBSEQUENT_RESPONSE_PAGE_SIZE;
- buttonText = interpolate(gettext("Load next %(numResponses)s responses"), {
+ buttonText = edx.StringUtils.interpolate(gettext("Load next {numResponses} responses"), {
numResponses: responseLimit
}, true);
}
- loadMoreButton = $("