diff --git a/lms/static/coffee/src/discussion/content.coffee b/lms/static/coffee/src/discussion/content.coffee
index d427a348b3..69073e1890 100644
--- a/lms/static/coffee/src/discussion/content.coffee
+++ b/lms/static/coffee/src/discussion/content.coffee
@@ -1,410 +1,411 @@
-class @Content extends Backbone.Model
+if Backbone?
+ class @Content extends Backbone.Model
- template: -> DiscussionUtil.getTemplate('_content')
+ template: -> DiscussionUtil.getTemplate('_content')
- actions:
- editable: '.admin-edit'
- can_reply: '.discussion-reply'
- can_endorse: '.admin-endorse'
- can_delete: '.admin-delete'
- can_openclose: '.admin-openclose'
-
- urlMappers: {}
+ actions:
+ editable: '.admin-edit'
+ can_reply: '.discussion-reply'
+ can_endorse: '.admin-endorse'
+ can_delete: '.admin-delete'
+ can_openclose: '.admin-openclose'
+
+ urlMappers: {}
- urlFor: (name) ->
- @urlMappers[name].apply(@)
+ urlFor: (name) ->
+ @urlMappers[name].apply(@)
- can: (action) ->
- DiscussionUtil.getContentInfo @id, action
+ can: (action) ->
+ DiscussionUtil.getContentInfo @id, action
- updateInfo: (info) ->
- @set('ability', info.ability)
- @set('voted', info.voted)
- @set('subscribed', info.subscribed)
+ updateInfo: (info) ->
+ @set('ability', info.ability)
+ @set('voted', info.voted)
+ @set('subscribed', info.subscribed)
- addComment: (comment, options) ->
- options ||= {}
- if not options.silent
+ addComment: (comment, options) ->
+ options ||= {}
+ if not options.silent
+ thread = @get('thread')
+ comments_count = parseInt(thread.get('comments_count'))
+ thread.set('comments_count', comments_count + 1)
+ @get('children').push comment
+ model = new Comment $.extend {}, comment, { thread: @get('thread') }
+ @get('comments').add model
+ model
+
+ removeComment: (comment) ->
thread = @get('thread')
comments_count = parseInt(thread.get('comments_count'))
- thread.set('comments_count', comments_count + 1)
- @get('children').push comment
- model = new Comment $.extend {}, comment, { thread: @get('thread') }
- @get('comments').add model
- model
+ thread.set('comments_count', comments_count - 1 - comment.getCommentsCount())
- removeComment: (comment) ->
- thread = @get('thread')
- comments_count = parseInt(thread.get('comments_count'))
- thread.set('comments_count', comments_count - 1 - comment.getCommentsCount())
+ resetComments: (children) ->
+ @set 'children', []
+ @set 'comments', new Comments()
+ for comment in (children || [])
+ @addComment comment, { silent: true }
- resetComments: (children) ->
- @set 'children', []
- @set 'comments', new Comments()
- for comment in (children || [])
- @addComment comment, { silent: true }
-
- initialize: ->
- DiscussionUtil.addContent @id, @
- @resetComments(@get('children'))
-
-
-class @ContentView extends Backbone.View
-
- $: (selector) ->
- @$local.find(selector)
-
- partial:
- endorsed: (endorsed) ->
- if endorsed
- @$el.addClass("endorsed")
- else
- @$el.removeClass("endorsed")
-
- closed: (closed) -> # we should just re-render the whole thread, or update according to new abilities
- if closed
- @$el.addClass("closed")
- @$(".admin-openclose").text "Re-open Thread"
- else
- @$el.removeClass("closed")
- @$(".admin-openclose").text "Close Thread"
-
- voted: (voted) ->
- @$(".discussion-vote-up").removeClass("voted") if voted != "up"
- @$(".discussion-vote-down").removeClass("voted") if voted != "down"
- @$(".discussion-vote-#{voted}").addClass("voted") if voted in ["up", "down"]
-
- votes_point: (votes_point) ->
- @$(".discussion-votes-point").html(votes_point)
-
- comments_count: (comments_count) ->
- @$(".comments-count").html(comments_count)
+ initialize: ->
+ DiscussionUtil.addContent @id, @
+ @resetComments(@get('children'))
- subscribed: (subscribed) ->
- if subscribed
- @$(".discussion-follow-thread").addClass("discussion-unfollow-thread").html("Unfollow")
+
+ class @ContentView extends Backbone.View
+
+ $: (selector) ->
+ @$local.find(selector)
+
+ partial:
+ endorsed: (endorsed) ->
+ if endorsed
+ @$el.addClass("endorsed")
+ else
+ @$el.removeClass("endorsed")
+
+ closed: (closed) -> # we should just re-render the whole thread, or update according to new abilities
+ if closed
+ @$el.addClass("closed")
+ @$(".admin-openclose").text "Re-open Thread"
+ else
+ @$el.removeClass("closed")
+ @$(".admin-openclose").text "Close Thread"
+
+ voted: (voted) ->
+ @$(".discussion-vote-up").removeClass("voted") if voted != "up"
+ @$(".discussion-vote-down").removeClass("voted") if voted != "down"
+ @$(".discussion-vote-#{voted}").addClass("voted") if voted in ["up", "down"]
+
+ votes_point: (votes_point) ->
+ @$(".discussion-votes-point").html(votes_point)
+
+ comments_count: (comments_count) ->
+ @$(".comments-count").html(comments_count)
+
+ subscribed: (subscribed) ->
+ if subscribed
+ @$(".discussion-follow-thread").addClass("discussion-unfollow-thread").html("Unfollow")
+ else
+ @$(".discussion-follow-thread").removeClass("discussion-unfollow-thread").html("Follow")
+
+ ability: (ability) ->
+ for action, elemSelector of @model.actions
+ if not ability[action]
+ @$(elemSelector).parent().remove()
+
+ $discussionContent: ->
+ @_discussionContent ||= @$el.children(".discussion-content")
+
+ $showComments: ->
+ @_showComments ||= @$(".discussion-show-comments")
+
+ updateShowComments: ->
+ if @showed
+ @$showComments().html @$showComments().html().replace "Show", "Hide"
else
- @$(".discussion-follow-thread").removeClass("discussion-unfollow-thread").html("Follow")
+ @$showComments().html @$showComments().html().replace "Hide", "Show"
- ability: (ability) ->
- for action, elemSelector of @model.actions
- if not ability[action]
- @$(elemSelector).parent().remove()
-
- $discussionContent: ->
- @_discussionContent ||= @$el.children(".discussion-content")
-
- $showComments: ->
- @_showComments ||= @$(".discussion-show-comments")
-
- updateShowComments: ->
- if @showed
- @$showComments().html @$showComments().html().replace "Show", "Hide"
- else
- @$showComments().html @$showComments().html().replace "Hide", "Show"
-
- retrieved: ->
- @$showComments().hasClass("retrieved")
-
- hideSingleThread: (event) ->
- @$el.children(".comments").hide()
- @showed = false
- @updateShowComments()
-
- showSingleThread: (event) ->
- if @retrieved()
- @$el.children(".comments").show()
- @showed = true
+ retrieved: ->
+ @$showComments().hasClass("retrieved")
+
+ hideSingleThread: (event) ->
+ @$el.children(".comments").hide()
+ @showed = false
@updateShowComments()
- else
- $elem = $.merge @$(".thread-title"), @$showComments()
- url = @model.urlFor('retrieve')
- DiscussionUtil.get $elem, url, {}, (response, textStatus) =>
+
+ showSingleThread: (event) ->
+ if @retrieved()
+ @$el.children(".comments").show()
@showed = true
@updateShowComments()
- @$showComments().addClass("retrieved")
- @$el.children(".comments").replaceWith response.html
- @model.resetComments response.content.children
- @initCommentViews()
- DiscussionUtil.bulkUpdateContentInfo response.annotated_content_info
-
- toggleSingleThread: (event) ->
- if @showed
- @hideSingleThread(event)
- else
- @showSingleThread(event)
-
- initCommentViews: ->
- @$el.children(".comments").children(".comment").each (index, elem) =>
- model = @model.get('comments').find $(elem).attr("_id")
- if not model.view
- commentView = new CommentView el: elem, model: model
-
- reply: ->
- if @model.get('type') == 'thread'
- @showSingleThread()
- $replyView = @$(".discussion-reply-new")
- if $replyView.length
- $replyView.show()
- else
- view = {}
- view.id = @model.id
- view.showWatchCheckbox = not @model.get('thread').get('subscribed')
- html = Mustache.render DiscussionUtil.getTemplate('_reply'), view
- @$discussionContent().append html
- DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "reply-body"
- @$(".discussion-submit-post").click $.proxy(@submitReply, @)
- @$(".discussion-cancel-post").click $.proxy(@cancelReply, @)
- @$(".discussion-reply").hide()
- @$(".discussion-edit").hide()
-
- submitReply: (event) ->
- url = @model.urlFor('reply')
-
- body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "reply-body"
-
- anonymous = false || @$(".discussion-post-anonymously").is(":checked")
- autowatch = false || @$(".discussion-auto-watch").is(":checked")
-
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- url: url
- type: "POST"
- dataType: 'json'
- data:
- body: body
- anonymous: anonymous
- auto_subscribe: autowatch
- error: DiscussionUtil.formErrorHandler @$(".discussion-errors")
- success: (response, textStatus) =>
- DiscussionUtil.clearFormErrors @$(".discussion-errors")
- $comment = $(response.html)
- @$el.children(".comments").prepend $comment
- DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "reply-body", ""
- comment = @model.addComment response.content
- commentView = new CommentView el: $comment[0], model: comment
- comment.updateInfo response.annotated_content_info
- @cancelReply()
-
- cancelReply: ->
- $replyView = @$(".discussion-reply-new")
- if $replyView.length
- $replyView.hide()
- @$(".discussion-reply").show()
- @$(".discussion-edit").show()
-
- unvote: (event) ->
- url = @model.urlFor('unvote')
- $elem = @$(".discussion-vote")
- DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
- @model.set('voted', '')
- @model.set('votes_point', response.votes.point)
-
- vote: (event, value) ->
- url = @model.urlFor("#{value}vote")
- $elem = @$(".discussion-vote")
- DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
- @model.set('voted', value)
- @model.set('votes_point', response.votes.point)
-
- toggleVote: (event) ->
- $elem = $(event.target)
- value = $elem.attr("value")
- if @model.get("voted") == value
- @unvote(event)
- else
- @vote(event, value)
-
- toggleEndorse: (event) ->
- $elem = $(event.target)
- url = @model.urlFor('endorse')
- endorsed = @model.get('endorsed')
- data = { endorsed: not endorsed }
- DiscussionUtil.post $elem, url, data, (response, textStatus) =>
- @model.set('endorsed', not endorsed)
-
- toggleFollow: (event) ->
- $elem = $(event.target)
- subscribed = @model.get('subscribed')
- if subscribed
- url = @model.urlFor('unfollow')
- else
- url = @model.urlFor('follow')
- DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
- @model.set('subscribed', not subscribed)
-
- toggleClosed: (event) ->
- $elem = $(event.target)
- url = @model.urlFor('close')
- closed = @model.get('closed')
- data = { closed: not closed }
- DiscussionUtil.post $elem, url, data, (response, textStatus) =>
- @model.set('closed', not closed)
-
- edit: (event) ->
- @$(".discussion-content-wrapper").hide()
- $editView = @$(".discussion-content-edit")
- if $editView.length
- $editView.show()
- else
- view = {}
- view.id = @model.id
- if @model.get('type') == 'thread'
- view.title = @$(".thread-raw-title").html()
- view.body = @$(".thread-raw-body").html()
- view.tags = @$(".thread-raw-tags").html()
else
- view.body = @$(".comment-raw-body").html()
- @$discussionContent().append Mustache.render DiscussionUtil.getTemplate("_edit_#{@model.get('type')}"), view
- Discussion.makeWmdEditor @$el, $.proxy(@$, @), "#{@model.get('type')}-body-edit"
- @$(".thread-tags-edit").tagsInput DiscussionUtil.tagsInputOptions()
- @$(".discussion-submit-update").unbind("click").click $.proxy(@submitEdit, @)
- @$(".discussion-cancel-update").unbind("click").click $.proxy(@cancelEdit, @)
+ $elem = $.merge @$(".thread-title"), @$showComments()
+ url = @model.urlFor('retrieve')
+ DiscussionUtil.get $elem, url, {}, (response, textStatus) =>
+ @showed = true
+ @updateShowComments()
+ @$showComments().addClass("retrieved")
+ @$el.children(".comments").replaceWith response.html
+ @model.resetComments response.content.children
+ @initCommentViews()
+ DiscussionUtil.bulkUpdateContentInfo response.annotated_content_info
- submitEdit: (event) ->
+ toggleSingleThread: (event) ->
+ if @showed
+ @hideSingleThread(event)
+ else
+ @showSingleThread(event)
+
+ initCommentViews: ->
+ @$el.children(".comments").children(".comment").each (index, elem) =>
+ model = @model.get('comments').find $(elem).attr("_id")
+ if not model.view
+ commentView = new CommentView el: elem, model: model
- url = @model.urlFor('update')
- data = {}
- if @model.get('type') == 'thread'
- data.title = @$(".thread-title-edit").val()
- data.body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "thread-body-edit"
- data.tags = @$(".thread-tags-edit").val()
- else
- data.body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "comment-body-edit"
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- url: url
- type: "POST"
- dataType: 'json'
- data: data
- error: DiscussionUtil.formErrorHandler @$(".discussion-update-errors")
- success: (response, textStatus) =>
- DiscussionUtil.clearFormErrors @$(".discussion-update-errors")
- @$discussionContent().replaceWith(response.html)
- @model.set response.content
- @model.updateInfo response.annotated_content_info
+ reply: ->
+ if @model.get('type') == 'thread'
+ @showSingleThread()
+ $replyView = @$(".discussion-reply-new")
+ if $replyView.length
+ $replyView.show()
+ else
+ view = {}
+ view.id = @model.id
+ view.showWatchCheckbox = not @model.get('thread').get('subscribed')
+ html = Mustache.render DiscussionUtil.getTemplate('_reply'), view
+ @$discussionContent().append html
+ DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "reply-body"
+ @$(".discussion-submit-post").click $.proxy(@submitReply, @)
+ @$(".discussion-cancel-post").click $.proxy(@cancelReply, @)
+ @$(".discussion-reply").hide()
+ @$(".discussion-edit").hide()
- cancelEdit: (event) ->
- @$(".discussion-content-edit").hide()
- @$(".discussion-content-wrapper").show()
+ submitReply: (event) ->
+ url = @model.urlFor('reply')
- delete: (event) ->
- url = @model.urlFor('delete')
- if @model.get('type') == 'thread'
- c = confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
- else
- c = confirm "Are you sure to delete this comment? "
- if not c
- return
- $elem = $(event.target)
- DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
- @$el.remove()
- @model.get('thread').removeComment(@model)
+ body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "reply-body"
+
+ anonymous = false || @$(".discussion-post-anonymously").is(":checked")
+ autowatch = false || @$(".discussion-auto-watch").is(":checked")
+
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ url: url
+ type: "POST"
+ dataType: 'json'
+ data:
+ body: body
+ anonymous: anonymous
+ auto_subscribe: autowatch
+ error: DiscussionUtil.formErrorHandler @$(".discussion-errors")
+ success: (response, textStatus) =>
+ DiscussionUtil.clearFormErrors @$(".discussion-errors")
+ $comment = $(response.html)
+ @$el.children(".comments").prepend $comment
+ DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "reply-body", ""
+ comment = @model.addComment response.content
+ commentView = new CommentView el: $comment[0], model: comment
+ comment.updateInfo response.annotated_content_info
+ @cancelReply()
+
+ cancelReply: ->
+ $replyView = @$(".discussion-reply-new")
+ if $replyView.length
+ $replyView.hide()
+ @$(".discussion-reply").show()
+ @$(".discussion-edit").show()
+
+ unvote: (event) ->
+ url = @model.urlFor('unvote')
+ $elem = @$(".discussion-vote")
+ DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
+ @model.set('voted', '')
+ @model.set('votes_point', response.votes.point)
+
+ vote: (event, value) ->
+ url = @model.urlFor("#{value}vote")
+ $elem = @$(".discussion-vote")
+ DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
+ @model.set('voted', value)
+ @model.set('votes_point', response.votes.point)
+
+ toggleVote: (event) ->
+ $elem = $(event.target)
+ value = $elem.attr("value")
+ if @model.get("voted") == value
+ @unvote(event)
+ else
+ @vote(event, value)
+
+ toggleEndorse: (event) ->
+ $elem = $(event.target)
+ url = @model.urlFor('endorse')
+ endorsed = @model.get('endorsed')
+ data = { endorsed: not endorsed }
+ DiscussionUtil.post $elem, url, data, (response, textStatus) =>
+ @model.set('endorsed', not endorsed)
+
+ toggleFollow: (event) ->
+ $elem = $(event.target)
+ subscribed = @model.get('subscribed')
+ if subscribed
+ url = @model.urlFor('unfollow')
+ else
+ url = @model.urlFor('follow')
+ DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
+ @model.set('subscribed', not subscribed)
+
+ toggleClosed: (event) ->
+ $elem = $(event.target)
+ url = @model.urlFor('close')
+ closed = @model.get('closed')
+ data = { closed: not closed }
+ DiscussionUtil.post $elem, url, data, (response, textStatus) =>
+ @model.set('closed', not closed)
+
+ edit: (event) ->
+ @$(".discussion-content-wrapper").hide()
+ $editView = @$(".discussion-content-edit")
+ if $editView.length
+ $editView.show()
+ else
+ view = {}
+ view.id = @model.id
+ if @model.get('type') == 'thread'
+ view.title = @$(".thread-raw-title").html()
+ view.body = @$(".thread-raw-body").html()
+ view.tags = @$(".thread-raw-tags").html()
+ else
+ view.body = @$(".comment-raw-body").html()
+ @$discussionContent().append Mustache.render DiscussionUtil.getTemplate("_edit_#{@model.get('type')}"), view
+ Discussion.makeWmdEditor @$el, $.proxy(@$, @), "#{@model.get('type')}-body-edit"
+ @$(".thread-tags-edit").tagsInput DiscussionUtil.tagsInputOptions()
+ @$(".discussion-submit-update").unbind("click").click $.proxy(@submitEdit, @)
+ @$(".discussion-cancel-update").unbind("click").click $.proxy(@cancelEdit, @)
+
+ submitEdit: (event) ->
+
+ url = @model.urlFor('update')
+ data = {}
+ if @model.get('type') == 'thread'
+ data.title = @$(".thread-title-edit").val()
+ data.body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "thread-body-edit"
+ data.tags = @$(".thread-tags-edit").val()
+ else
+ data.body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "comment-body-edit"
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ url: url
+ type: "POST"
+ dataType: 'json'
+ data: data
+ error: DiscussionUtil.formErrorHandler @$(".discussion-update-errors")
+ success: (response, textStatus) =>
+ DiscussionUtil.clearFormErrors @$(".discussion-update-errors")
+ @$discussionContent().replaceWith(response.html)
+ @model.set response.content
+ @model.updateInfo response.annotated_content_info
+
+ cancelEdit: (event) ->
+ @$(".discussion-content-edit").hide()
+ @$(".discussion-content-wrapper").show()
+
+ delete: (event) ->
+ url = @model.urlFor('delete')
+ if @model.get('type') == 'thread'
+ c = confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
+ else
+ c = confirm "Are you sure to delete this comment? "
+ if not c
+ return
+ $elem = $(event.target)
+ DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
+ @$el.remove()
+ @model.get('thread').removeComment(@model)
+
+ events:
+ "click .discussion-follow-thread": "toggleFollow"
+ "click .thread-title": "toggleSingleThread"
+ "click .discussion-show-comments": "toggleSingleThread"
+ "click .discussion-reply-thread": "reply"
+ "click .discussion-reply-comment": "reply"
+ "click .discussion-cancel-reply": "cancelReply"
+ "click .discussion-vote-up": "toggleVote"
+ "click .discussion-vote-down": "toggleVote"
+ "click .admin-endorse": "toggleEndorse"
+ "click .admin-openclose": "toggleClosed"
+ "click .admin-edit": "edit"
+ "click .admin-delete": "delete"
+
+ initLocal: ->
+ @$local = @$el.children(".local")
+ @$delegateElement = @$local
+
+ initTitle: ->
+ $contentTitle = @$(".thread-title")
+ if $contentTitle.length
+ $contentTitle.html DiscussionUtil.unescapeHighlightTag DiscussionUtil.stripLatexHighlight $contentTitle.html()
+
+ initBody: ->
+ $contentBody = @$(".content-body")
+ $contentBody.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight $contentBody.html()
+ MathJax.Hub.Queue ["Typeset", MathJax.Hub, $contentBody.attr("id")]
+
+ initTimeago: ->
+ @$("span.timeago").timeago()
+
+ initPermalink: ->
+ @$(".discussion-permanent-link").attr "href", @model.permalink()
+
+ renderPartial: ->
+ for attr, value of @model.changedAttributes()
+ if @partial[attr]
+ @partial[attr].apply(@, [value])
+
+ initBindings: ->
+ @model.view = @
+ @model.bind('change', @renderPartial, @)
+
+ initialize: ->
+ @initBindings()
+ @initLocal()
+ @initTimeago()
+ @initTitle()
+ @initBody()
+ @initCommentViews()
- events:
- "click .discussion-follow-thread": "toggleFollow"
- "click .thread-title": "toggleSingleThread"
- "click .discussion-show-comments": "toggleSingleThread"
- "click .discussion-reply-thread": "reply"
- "click .discussion-reply-comment": "reply"
- "click .discussion-cancel-reply": "cancelReply"
- "click .discussion-vote-up": "toggleVote"
- "click .discussion-vote-down": "toggleVote"
- "click .admin-endorse": "toggleEndorse"
- "click .admin-openclose": "toggleClosed"
- "click .admin-edit": "edit"
- "click .admin-delete": "delete"
+ class @Thread extends @Content
+ urlMappers:
+ 'retrieve' : -> DiscussionUtil.urlFor('retrieve_single_thread', @discussion.id, @id)
+ 'reply' : -> DiscussionUtil.urlFor('create_comment', @id)
+ 'unvote' : -> DiscussionUtil.urlFor("undo_vote_for_#{@get('type')}", @id)
+ 'upvote' : -> DiscussionUtil.urlFor("upvote_#{@get('type')}", @id)
+ 'downvote' : -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
+ 'close' : -> DiscussionUtil.urlFor('openclose_thread', @id)
+ 'update' : -> DiscussionUtil.urlFor('update_thread', @id)
+ 'delete' : -> DiscussionUtil.urlFor('delete_thread', @id)
+ 'follow' : -> DiscussionUtil.urlFor('follow_thread', @id)
+ 'unfollow' : -> DiscussionUtil.urlFor('unfollow_thread', @id)
- initLocal: ->
- @$local = @$el.children(".local")
- @$delegateElement = @$local
+ initialize: ->
+ @set('thread', @)
+ super()
- initTitle: ->
- $contentTitle = @$(".thread-title")
- if $contentTitle.length
- $contentTitle.html DiscussionUtil.unescapeHighlightTag DiscussionUtil.stripLatexHighlight $contentTitle.html()
+ permalink: ->
+ discussion_id = @get('commentable_id')
+ return Discussion.urlFor("permanent_link_thread", discussion_id, @id)
- initBody: ->
- $contentBody = @$(".content-body")
- $contentBody.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight $contentBody.html()
- MathJax.Hub.Queue ["Typeset", MathJax.Hub, $contentBody.attr("id")]
+ class @ThreadView extends @ContentView
- initTimeago: ->
- @$("span.timeago").timeago()
+ class @Comment extends @Content
+ urlMappers:
+ 'reply': -> DiscussionUtil.urlFor('create_sub_comment', @id)
+ 'unvote': -> DiscussionUtil.urlFor("undo_vote_for_#{@get('type')}", @id)
+ 'upvote': -> DiscussionUtil.urlFor("upvote_#{@get('type')}", @id)
+ 'downvote': -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
+ 'endorse': -> DiscussionUtil.urlFor('endorse_comment', @id)
+ 'update': -> DiscussionUtil.urlFor('update_comment', @id)
+ 'delete': -> DiscussionUtil.urlFor('delete_comment', @id)
- initPermalink: ->
- @$(".discussion-permanent-link").attr "href", @model.permalink()
+ permalink: ->
+ thread_id = @get('thread').id
+ discussion_id = @get('thread').get('commentable_id')
+ return Discussion.urlFor("permanent_link_comment", discussion_id, thread_id, @id)
- renderPartial: ->
- for attr, value of @model.changedAttributes()
- if @partial[attr]
- @partial[attr].apply(@, [value])
+ getCommentsCount: ->
+ count = 0
+ @get('comments').each (comment) ->
+ count += comment.getCommentsCount() + 1
+ count
- initBindings: ->
- @model.view = @
- @model.bind('change', @renderPartial, @)
+ class @CommentView extends @ContentView
- initialize: ->
- @initBindings()
- @initLocal()
- @initTimeago()
- @initTitle()
- @initBody()
- @initCommentViews()
-
-class @Thread extends @Content
- urlMappers:
- 'retrieve' : -> DiscussionUtil.urlFor('retrieve_single_thread', @discussion.id, @id)
- 'reply' : -> DiscussionUtil.urlFor('create_comment', @id)
- 'unvote' : -> DiscussionUtil.urlFor("undo_vote_for_#{@get('type')}", @id)
- 'upvote' : -> DiscussionUtil.urlFor("upvote_#{@get('type')}", @id)
- 'downvote' : -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
- 'close' : -> DiscussionUtil.urlFor('openclose_thread', @id)
- 'update' : -> DiscussionUtil.urlFor('update_thread', @id)
- 'delete' : -> DiscussionUtil.urlFor('delete_thread', @id)
- 'follow' : -> DiscussionUtil.urlFor('follow_thread', @id)
- 'unfollow' : -> DiscussionUtil.urlFor('unfollow_thread', @id)
+ class @Comments extends Backbone.Collection
- initialize: ->
- @set('thread', @)
- super()
+ model: Comment
- permalink: ->
- discussion_id = @get('commentable_id')
- return Discussion.urlFor("permanent_link_thread", discussion_id, @id)
+ initialize: ->
+ @bind "add", (item) =>
+ item.collection = @
-class @ThreadView extends @ContentView
-
-class @Comment extends @Content
- urlMappers:
- 'reply': -> DiscussionUtil.urlFor('create_sub_comment', @id)
- 'unvote': -> DiscussionUtil.urlFor("undo_vote_for_#{@get('type')}", @id)
- 'upvote': -> DiscussionUtil.urlFor("upvote_#{@get('type')}", @id)
- 'downvote': -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
- 'endorse': -> DiscussionUtil.urlFor('endorse_comment', @id)
- 'update': -> DiscussionUtil.urlFor('update_comment', @id)
- 'delete': -> DiscussionUtil.urlFor('delete_comment', @id)
-
- permalink: ->
- thread_id = @get('thread').id
- discussion_id = @get('thread').get('commentable_id')
- return Discussion.urlFor("permanent_link_comment", discussion_id, thread_id, @id)
-
- getCommentsCount: ->
- count = 0
- @get('comments').each (comment) ->
- count += comment.getCommentsCount() + 1
- count
-
-class @CommentView extends @ContentView
-
-class @Comments extends Backbone.Collection
-
- model: Comment
-
- initialize: ->
- @bind "add", (item) =>
- item.collection = @
-
- find: (id) ->
- _.first @where(id: id)
+ find: (id) ->
+ _.first @where(id: id)
diff --git a/lms/static/coffee/src/discussion/discussion.coffee b/lms/static/coffee/src/discussion/discussion.coffee
index 4764784789..0b6c59964b 100644
--- a/lms/static/coffee/src/discussion/discussion.coffee
+++ b/lms/static/coffee/src/discussion/discussion.coffee
@@ -1,168 +1,169 @@
-class @Discussion extends Backbone.Collection
- model: Thread
+if Backbone?
+ class @Discussion extends Backbone.Collection
+ model: Thread
- initialize: ->
- DiscussionUtil.addDiscussion @id, @
- @bind "add", (item) =>
- item.discussion = @
+ initialize: ->
+ DiscussionUtil.addDiscussion @id, @
+ @bind "add", (item) =>
+ item.discussion = @
- find: (id) ->
- _.first @where(id: id)
+ find: (id) ->
+ _.first @where(id: id)
- addThread: (thread, options) ->
- options ||= {}
- model = new Thread thread
- @add model
- model
+ addThread: (thread, options) ->
+ options ||= {}
+ model = new Thread thread
+ @add model
+ model
-class @DiscussionView extends Backbone.View
+ class @DiscussionView extends Backbone.View
- $: (selector) ->
- @$local.find(selector)
+ $: (selector) ->
+ @$local.find(selector)
- initLocal: ->
- @$local = @$el.children(".local")
- @$delegateElement = @$local
+ initLocal: ->
+ @$local = @$el.children(".local")
+ @$delegateElement = @$local
- initialize: ->
- @initLocal()
- @model.id = @$el.attr("_id")
- @model.view = @
- @$el.children(".threads").children(".thread").each (index, elem) =>
- threadView = new ThreadView el: elem, model: @model.find $(elem).attr("_id")
- if @$el.hasClass("forum-discussion")
- $(".discussion-sidebar").find(".sidebar-new-post-button")
- .unbind('click').click $.proxy @newPost, @
- else if @$el.hasClass("inline-discussion")
- @newPost()
+ initialize: ->
+ @initLocal()
+ @model.id = @$el.attr("_id")
+ @model.view = @
+ @$el.children(".threads").children(".thread").each (index, elem) =>
+ threadView = new ThreadView el: elem, model: @model.find $(elem).attr("_id")
+ if @$el.hasClass("forum-discussion")
+ $(".discussion-sidebar").find(".sidebar-new-post-button")
+ .unbind('click').click $.proxy @newPost, @
+ else if @$el.hasClass("inline-discussion")
+ @newPost()
- reload: ($elem, url) ->
- if not url then return
- DiscussionUtil.get $elem, url, {}, (response, textStatus) =>
- $parent = @$el.parent()
- @$el.replaceWith(response.html)
- $discussion = $parent.find("section.discussion")
- @model.reset(response.discussionData, { silent: false })
- view = new DiscussionView el: $discussion[0], model: @model
- DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
- $("html, body").animate({ scrollTop: 0 }, 0)
+ reload: ($elem, url) ->
+ if not url then return
+ DiscussionUtil.get $elem, url, {}, (response, textStatus) =>
+ $parent = @$el.parent()
+ @$el.replaceWith(response.html)
+ $discussion = $parent.find("section.discussion")
+ @model.reset(response.discussionData, { silent: false })
+ view = new DiscussionView el: $discussion[0], model: @model
+ DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
+ $("html, body").animate({ scrollTop: 0 }, 0)
- loadSimilarPost: (event) ->
- $title = @$(".new-post-title")
- $wrapper = @$(".new-post-similar-posts-wrapper")
- $similarPosts = @$(".new-post-similar-posts")
- prevText = $title.attr("prev-text")
- text = $title.val()
- if text == prevText
- if @$(".similar-post").length
- $wrapper.show()
- else if $.trim(text).length
- $elem = $(event.target)
- url = DiscussionUtil.urlFor 'search_similar_threads', @model.id
- data = { text: @$(".new-post-title").val() }
- DiscussionUtil.get $elem, url, data, (response, textStatus) =>
- $similarPosts.empty()
- if $.type(response) == "array" and response.length
+ loadSimilarPost: (event) ->
+ $title = @$(".new-post-title")
+ $wrapper = @$(".new-post-similar-posts-wrapper")
+ $similarPosts = @$(".new-post-similar-posts")
+ prevText = $title.attr("prev-text")
+ text = $title.val()
+ if text == prevText
+ if @$(".similar-post").length
$wrapper.show()
- for thread in response
- $similarPost = $("").addClass("similar-post")
- .html(thread["title"])
- .attr("href", "javascript:void(0)") #TODO
- .appendTo($similarPosts)
- else
- $wrapper.hide()
- else
- $wrapper.hide()
- $title.attr("prev-text", text)
+ else if $.trim(text).length
+ $elem = $(event.target)
+ url = DiscussionUtil.urlFor 'search_similar_threads', @model.id
+ data = { text: @$(".new-post-title").val() }
+ DiscussionUtil.get $elem, url, data, (response, textStatus) =>
+ $similarPosts.empty()
+ if $.type(response) == "array" and response.length
+ $wrapper.show()
+ for thread in response
+ $similarPost = $("").addClass("similar-post")
+ .html(thread["title"])
+ .attr("href", "javascript:void(0)") #TODO
+ .appendTo($similarPosts)
+ else
+ $wrapper.hide()
+ else
+ $wrapper.hide()
+ $title.attr("prev-text", text)
- newPost: ->
- if not @$(".wmd-panel").length
- view = { discussion_id: @model.id }
- @$el.children(".discussion-non-content").append Mustache.render DiscussionUtil.getTemplate("_new_post"), view
- $newPostBody = @$(".new-post-body")
- DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
+ newPost: ->
+ if not @$(".wmd-panel").length
+ view = { discussion_id: @model.id }
+ @$el.children(".discussion-non-content").append Mustache.render DiscussionUtil.getTemplate("_new_post"), view
+ $newPostBody = @$(".new-post-body")
+ DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
- $input = DiscussionUtil.getWmdInput @$el, $.proxy(@$, @), "new-post-body"
- $input.attr("placeholder", "post a new topic...")
- if @$el.hasClass("inline-discussion")
- $input.bind 'focus', (e) =>
+ $input = DiscussionUtil.getWmdInput @$el, $.proxy(@$, @), "new-post-body"
+ $input.attr("placeholder", "post a new topic...")
+ if @$el.hasClass("inline-discussion")
+ $input.bind 'focus', (e) =>
+ @$(".new-post-form").removeClass('collapsed')
+ else if @$el.hasClass("forum-discussion")
@$(".new-post-form").removeClass('collapsed')
- else if @$el.hasClass("forum-discussion")
- @$(".new-post-form").removeClass('collapsed')
- @$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
+ @$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
- @$(".new-post-title").blur $.proxy(@loadSimilarPost, @)
+ @$(".new-post-title").blur $.proxy(@loadSimilarPost, @)
- @$(".hide-similar-posts").click =>
- @$(".new-post-similar-posts-wrapper").hide()
+ @$(".hide-similar-posts").click =>
+ @$(".new-post-similar-posts-wrapper").hide()
- @$(".discussion-submit-post").click $.proxy(@submitNewPost, @)
- @$(".discussion-cancel-post").click $.proxy(@cancelNewPost, @)
-
-
- @$(".new-post-form").show()
-
- submitNewPost: (event) ->
- title = @$(".new-post-title").val()
- body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "new-post-body"
- tags = @$(".new-post-tags").val()
- anonymous = false || @$(".discussion-post-anonymously").is(":checked")
- autowatch = false || @$(".discussion-auto-watch").is(":checked")
- url = DiscussionUtil.urlFor('create_thread', @model.id)
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- url: url
- type: "POST"
- dataType: 'json'
- data:
- title: title
- body: body
- tags: tags
- anonymous: anonymous
- auto_subscribe: autowatch
- error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
- success: (response, textStatus) =>
- DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
- $thread = $(response.html)
- @$el.children(".threads").prepend($thread)
-
- @$(".new-post-title").val("")
- DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "new-post-body", ""
- @$(".new-post-tags").val("")
- @$(".new-post-tags").importTags("")
-
- thread = @model.addThread response.content
- threadView = new ThreadView el: $thread[0], model: thread
- thread.updateInfo response.annotated_content_info
- @cancelNewPost()
+ @$(".discussion-submit-post").click $.proxy(@submitNewPost, @)
+ @$(".discussion-cancel-post").click $.proxy(@cancelNewPost, @)
- cancelNewPost: (event) ->
- if @$el.hasClass("inline-discussion")
- @$(".new-post-form").addClass("collapsed")
- else if @$el.hasClass("forum-discussion")
- @$(".new-post-form").hide()
+ @$(".new-post-form").show()
- search: (event) ->
- event.preventDefault()
- $elem = $(event.target)
- url = URI($elem.attr("action")).addSearch({text: @$(".search-input").val()})
- @reload($elem, url)
+ submitNewPost: (event) ->
+ title = @$(".new-post-title").val()
+ body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "new-post-body"
+ tags = @$(".new-post-tags").val()
+ anonymous = false || @$(".discussion-post-anonymously").is(":checked")
+ autowatch = false || @$(".discussion-auto-watch").is(":checked")
+ url = DiscussionUtil.urlFor('create_thread', @model.id)
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ url: url
+ type: "POST"
+ dataType: 'json'
+ data:
+ title: title
+ body: body
+ tags: tags
+ anonymous: anonymous
+ auto_subscribe: autowatch
+ error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
+ success: (response, textStatus) =>
+ DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
+ $thread = $(response.html)
+ @$el.children(".threads").prepend($thread)
- sort: ->
- $elem = $(event.target)
- url = $elem.attr("sort-url")
- @reload($elem, url)
+ @$(".new-post-title").val("")
+ DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "new-post-body", ""
+ @$(".new-post-tags").val("")
+ @$(".new-post-tags").importTags("")
- page: (event) ->
- $elem = $(event.target)
- url = $elem.attr("page-url")
- @reload($elem, url)
+ thread = @model.addThread response.content
+ threadView = new ThreadView el: $thread[0], model: thread
+ thread.updateInfo response.annotated_content_info
+ @cancelNewPost()
+
- events:
- "submit .search-wrapper>.discussion-search-form": "search"
- "click .discussion-search-link": "search"
- "click .discussion-sort-link": "sort"
- "click .discussion-page-link": "page"
+ cancelNewPost: (event) ->
+ if @$el.hasClass("inline-discussion")
+ @$(".new-post-form").addClass("collapsed")
+ else if @$el.hasClass("forum-discussion")
+ @$(".new-post-form").hide()
+
+ search: (event) ->
+ event.preventDefault()
+ $elem = $(event.target)
+ url = URI($elem.attr("action")).addSearch({text: @$(".search-input").val()})
+ @reload($elem, url)
+
+ sort: ->
+ $elem = $(event.target)
+ url = $elem.attr("sort-url")
+ @reload($elem, url)
+
+ page: (event) ->
+ $elem = $(event.target)
+ url = $elem.attr("page-url")
+ @reload($elem, url)
+
+ events:
+ "submit .search-wrapper>.discussion-search-form": "search"
+ "click .discussion-search-link": "search"
+ "click .discussion-sort-link": "sort"
+ "click .discussion-page-link": "page"
diff --git a/lms/static/coffee/src/discussion/discussion_module.coffee b/lms/static/coffee/src/discussion/discussion_module.coffee
index 38f44be1f1..0f3e306379 100644
--- a/lms/static/coffee/src/discussion/discussion_module.coffee
+++ b/lms/static/coffee/src/discussion/discussion_module.coffee
@@ -1,32 +1,33 @@
-class @DiscussionModuleView extends Backbone.View
- events:
- "click .discussion-show": "toggleDiscussion"
- toggleDiscussion: (event) ->
- if @showed
- @$("section.discussion").hide()
- $(event.target).html("Show Discussion")
- @showed = false
- else
- if @retrieved
- @$("section.discussion").show()
- $(event.target).html("Hide Discussion")
- @showed = true
+if Backbone?
+ class @DiscussionModuleView extends Backbone.View
+ events:
+ "click .discussion-show": "toggleDiscussion"
+ toggleDiscussion: (event) ->
+ if @showed
+ @$("section.discussion").hide()
+ $(event.target).html("Show Discussion")
+ @showed = false
else
- $elem = $(event.target)
- discussion_id = $elem.attr("discussion_id")
- url = DiscussionUtil.urlFor 'retrieve_discussion', discussion_id
- Discussion.safeAjax
- $elem: $elem
- url: url
- type: "GET"
- dataType: 'json'
- success: (response, textStatus) =>
- @$el.append(response.html)
- $discussion = @$el.find("section.discussion")
- $(event.target).html("Hide Discussion")
- discussion = new Discussion()
- discussion.reset(response.discussionData, {silent: false})
- view = new DiscussionView(el: $discussion[0], model: discussion)
- DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
- @retrieved = true
- @showed = true
+ if @retrieved
+ @$("section.discussion").show()
+ $(event.target).html("Hide Discussion")
+ @showed = true
+ else
+ $elem = $(event.target)
+ discussion_id = $elem.attr("discussion_id")
+ url = DiscussionUtil.urlFor 'retrieve_discussion', discussion_id
+ Discussion.safeAjax
+ $elem: $elem
+ url: url
+ type: "GET"
+ dataType: 'json'
+ success: (response, textStatus) =>
+ @$el.append(response.html)
+ $discussion = @$el.find("section.discussion")
+ $(event.target).html("Hide Discussion")
+ discussion = new Discussion()
+ discussion.reset(response.discussionData, {silent: false})
+ view = new DiscussionView(el: $discussion[0], model: discussion)
+ DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
+ @retrieved = true
+ @showed = true
diff --git a/lms/static/coffee/src/discussion/main.coffee b/lms/static/coffee/src/discussion/main.coffee
index 2266e136ed..2f26211424 100644
--- a/lms/static/coffee/src/discussion/main.coffee
+++ b/lms/static/coffee/src/discussion/main.coffee
@@ -12,4 +12,5 @@ $ ->
discussion.reset(discussionData, {silent: false})
view = new DiscussionView(el: elem, model: discussion)
- DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
+ if window.$$annotated_content_info?
+ DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)