diff --git a/lms/static/coffee/src/discussion/discussion_router.coffee b/lms/static/coffee/src/discussion/discussion_router.coffee
index 9d48ccb08a..53ada7a596 100644
--- a/lms/static/coffee/src/discussion/discussion_router.coffee
+++ b/lms/static/coffee/src/discussion/discussion_router.coffee
@@ -1,41 +1,42 @@
-class @DiscussionRouter extends Backbone.Router
- routes:
- "": "allThreads"
- ":forum_name/threads/:thread_id" : "showThread"
+if Backbone?
+ class @DiscussionRouter extends Backbone.Router
+ routes:
+ "": "allThreads"
+ ":forum_name/threads/:thread_id" : "showThread"
- initialize: (options) ->
- @discussion = options['discussion']
- @nav = new DiscussionThreadListView(collection: @discussion, el: $(".sidebar"))
- @nav.on "thread:selected", @navigateToThread
- @nav.on "thread:removed", @navigateToAllThreads
- @nav.on "threads:rendered", @setActiveThread
- @nav.render()
+ initialize: (options) ->
+ @discussion = options['discussion']
+ @nav = new DiscussionThreadListView(collection: @discussion, el: $(".sidebar"))
+ @nav.on "thread:selected", @navigateToThread
+ @nav.on "thread:removed", @navigateToAllThreads
+ @nav.on "threads:rendered", @setActiveThread
+ @nav.render()
- @newPostView = new NewPostView(el: $(".new-post-article"), collection: @discussion)
- @newPostView.on "thread:created", @navigateToThread
+ @newPostView = new NewPostView(el: $(".new-post-article"), collection: @discussion)
+ @newPostView.on "thread:created", @navigateToThread
- allThreads: ->
- @nav.updateSidebar()
-
- setActiveThread: =>
- if @thread
- @nav.setActiveThread(@thread.get("id"))
-
- showThread: (forum_name, thread_id) ->
- @thread = @discussion.get(thread_id)
- @setActiveThread()
- if(@main)
- @main.undelegateEvents()
-
- @main = new DiscussionThreadView(el: $(".discussion-column"), model: @thread)
- @main.render()
- @main.on "thread:responses:rendered", =>
+ allThreads: ->
@nav.updateSidebar()
- navigateToThread: (thread_id) =>
- thread = @discussion.get(thread_id)
- @navigate("#{thread.get("commentable_id")}/threads/#{thread_id}", trigger: true)
+ setActiveThread: =>
+ if @thread
+ @nav.setActiveThread(@thread.get("id"))
- navigateToAllThreads: =>
- console.log "navigating"
- @navigate("", trigger: true)
+ showThread: (forum_name, thread_id) ->
+ @thread = @discussion.get(thread_id)
+ @setActiveThread()
+ if(@main)
+ @main.undelegateEvents()
+
+ @main = new DiscussionThreadView(el: $(".discussion-column"), model: @thread)
+ @main.render()
+ @main.on "thread:responses:rendered", =>
+ @nav.updateSidebar()
+
+ navigateToThread: (thread_id) =>
+ thread = @discussion.get(thread_id)
+ @navigate("#{thread.get("commentable_id")}/threads/#{thread_id}", trigger: true)
+
+ navigateToAllThreads: =>
+ console.log "navigating"
+ @navigate("", trigger: true)
diff --git a/lms/static/coffee/src/discussion/main.coffee b/lms/static/coffee/src/discussion/main.coffee
index 6d7818c223..ed31a532c1 100644
--- a/lms/static/coffee/src/discussion/main.coffee
+++ b/lms/static/coffee/src/discussion/main.coffee
@@ -1,17 +1,18 @@
-DiscussionApp =
- start: (elem)->
- # TODO: Perhaps eliminate usage of global variables when possible
- element = $(elem)
- window.$$course_id = element.data("course-id")
- user_info = element.data("user-info")
- threads = element.data("threads")
- content_info = element.data("content-info")
- window.user = new DiscussionUser(user_info)
- Content.loadContentInfos(content_info)
- discussion = new Discussion(threads)
- new DiscussionRouter({discussion: discussion})
- Backbone.history.start({pushState: true, root: "/courses/#{$$course_id}/discussion/forum/"})
+if Backbone?
+ DiscussionApp =
+ start: (elem)->
+ # TODO: Perhaps eliminate usage of global variables when possible
+ element = $(elem)
+ window.$$course_id = element.data("course-id")
+ user_info = element.data("user-info")
+ threads = element.data("threads")
+ content_info = element.data("content-info")
+ window.user = new DiscussionUser(user_info)
+ Content.loadContentInfos(content_info)
+ discussion = new Discussion(threads)
+ new DiscussionRouter({discussion: discussion})
+ Backbone.history.start({pushState: true, root: "/courses/#{$$course_id}/discussion/forum/"})
-$ ->
- $("section.discussion").each (index, elem) ->
- DiscussionApp.start(elem)
+ $ ->
+ $("section.discussion").each (index, elem) ->
+ DiscussionApp.start(elem)
diff --git a/lms/static/coffee/src/discussion/models/discussion_user.coffee b/lms/static/coffee/src/discussion/models/discussion_user.coffee
index 6449e80b85..892727c523 100644
--- a/lms/static/coffee/src/discussion/models/discussion_user.coffee
+++ b/lms/static/coffee/src/discussion/models/discussion_user.coffee
@@ -1,14 +1,15 @@
-class @DiscussionUser extends Backbone.Model
- following: (thread) ->
- _.include(@get('subscribed_thread_ids'), thread.id)
+if Backbone?
+ class @DiscussionUser extends Backbone.Model
+ following: (thread) ->
+ _.include(@get('subscribed_thread_ids'), thread.id)
- voted: (thread) ->
- _.include(@get('upvoted_ids'), thread.id)
+ voted: (thread) ->
+ _.include(@get('upvoted_ids'), thread.id)
- vote: (thread) ->
- @get('upvoted_ids').push(thread.id)
- thread.vote()
+ vote: (thread) ->
+ @get('upvoted_ids').push(thread.id)
+ thread.vote()
- unvote: (thread) ->
- @set('upvoted_ids', _.without(@get('upvoted_ids'), thread.id))
- thread.unvote()
+ unvote: (thread) ->
+ @set('upvoted_ids', _.without(@get('upvoted_ids'), thread.id))
+ thread.unvote()
diff --git a/lms/static/coffee/src/discussion/user_profile.coffee b/lms/static/coffee/src/discussion/user_profile.coffee
index ed4f6ea988..9f0600dd1d 100644
--- a/lms/static/coffee/src/discussion/user_profile.coffee
+++ b/lms/static/coffee/src/discussion/user_profile.coffee
@@ -1,29 +1,30 @@
-class @DiscussionUserProfileView extends Backbone.View
- toggleModeratorStatus: (event) ->
- confirmValue = confirm("Are you sure?")
- if not confirmValue then return
- $elem = $(event.target)
- if $elem.hasClass("sidebar-promote-moderator-button")
- isModerator = true
- else if $elem.hasClass("sidebar-revoke-moderator-button")
- isModerator = false
- else
- console.error "unrecognized moderator status"
- return
- url = DiscussionUtil.urlFor('update_moderator_status', $$profiled_user_id)
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- type: "POST"
- dataType: 'json'
- data:
- is_moderator: isModerator
- error: (response, textStatus, e) ->
- console.log e
- success: (response, textStatus) =>
- parent = @$el.parent()
- @$el.replaceWith(response.html)
- view = new DiscussionUserProfileView el: parent.children(".user-profile")
+if Backbone?
+ class @DiscussionUserProfileView extends Backbone.View
+ toggleModeratorStatus: (event) ->
+ confirmValue = confirm("Are you sure?")
+ if not confirmValue then return
+ $elem = $(event.target)
+ if $elem.hasClass("sidebar-promote-moderator-button")
+ isModerator = true
+ else if $elem.hasClass("sidebar-revoke-moderator-button")
+ isModerator = false
+ else
+ console.error "unrecognized moderator status"
+ return
+ url = DiscussionUtil.urlFor('update_moderator_status', $$profiled_user_id)
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ type: "POST"
+ dataType: 'json'
+ data:
+ is_moderator: isModerator
+ error: (response, textStatus, e) ->
+ console.log e
+ success: (response, textStatus) =>
+ parent = @$el.parent()
+ @$el.replaceWith(response.html)
+ view = new DiscussionUserProfileView el: parent.children(".user-profile")
- events:
- "click .sidebar-toggle-moderator-button": "toggleModeratorStatus"
+ events:
+ "click .sidebar-toggle-moderator-button": "toggleModeratorStatus"
diff --git a/lms/static/coffee/src/discussion/views/discussion_content_view.coffee b/lms/static/coffee/src/discussion/views/discussion_content_view.coffee
index 247261c587..98f0eb6137 100644
--- a/lms/static/coffee/src/discussion/views/discussion_content_view.coffee
+++ b/lms/static/coffee/src/discussion/views/discussion_content_view.coffee
@@ -1,89 +1,90 @@
-class @DiscussionContentView extends Backbone.View
+if Backbone?
+ class @DiscussionContentView extends Backbone.View
- attrRenderer:
- endorsed: (endorsed) ->
- if endorsed
- @$(".action-endorse").addClass("is-endorsed")
- else
- @$(".action-endorse").removeClass("is-endorsed")
-
- closed: (closed) ->
- return if not @$(".action-openclose").length
- return if not @$(".post-status-closed").length
- if closed
- @$(".post-status-closed").show()
- @$(".action-openclose").html(@$(".action-openclose").html().replace("Close", "Open"))
- @$(".discussion-reply-new").hide()
- else
- @$(".post-status-closed").hide()
- @$(".action-openclose").html(@$(".action-openclose").html().replace("Open", "Close"))
- @$(".discussion-reply-new").show()
-
- voted: (voted) ->
-
- votes_point: (votes_point) ->
-
- comments_count: (comments_count) ->
-
- subscribed: (subscribed) ->
- if subscribed
- @$(".dogear").addClass("is-followed")
- else
- @$(".dogear").removeClass("is-followed")
-
- ability: (ability) ->
- for action, selector of @abilityRenderer
- if not ability[action]
- selector.disable.apply(@)
+ attrRenderer:
+ endorsed: (endorsed) ->
+ if endorsed
+ @$(".action-endorse").addClass("is-endorsed")
else
- selector.enable.apply(@)
+ @$(".action-endorse").removeClass("is-endorsed")
- abilityRenderer:
- editable:
- enable: -> @$(".action-edit").closest("li").show()
- disable: -> @$(".action-edit").closest("li").hide()
- can_delete:
- enable: -> @$(".action-delete").closest("li").show()
- disable: -> @$(".action-delete").closest("li").hide()
- can_endorse:
- enable: -> @$(".action-endorse").css("cursor", "auto")
- disable: -> @$(".action-endorse").css("cursor", "default")
- can_openclose:
- enable: -> @$(".action-openclose").closest("li").show()
- disable: -> @$(".action-openclose").closest("li").hide()
+ closed: (closed) ->
+ return if not @$(".action-openclose").length
+ return if not @$(".post-status-closed").length
+ if closed
+ @$(".post-status-closed").show()
+ @$(".action-openclose").html(@$(".action-openclose").html().replace("Close", "Open"))
+ @$(".discussion-reply-new").hide()
+ else
+ @$(".post-status-closed").hide()
+ @$(".action-openclose").html(@$(".action-openclose").html().replace("Open", "Close"))
+ @$(".discussion-reply-new").show()
- renderPartialAttrs: ->
- for attr, value of @model.changedAttributes()
- if @attrRenderer[attr]
- @attrRenderer[attr].apply(@, [value])
+ voted: (voted) ->
- renderAttrs: ->
- for attr, value of @model.attributes
- if @attrRenderer[attr]
- @attrRenderer[attr].apply(@, [value])
+ votes_point: (votes_point) ->
- $: (selector) ->
- @$local.find(selector)
+ comments_count: (comments_count) ->
- initLocal: ->
- @$local = @$el.children(".local")
- if not @$local.length
- @$local = @$el
- @$delegateElement = @$local
+ subscribed: (subscribed) ->
+ if subscribed
+ @$(".dogear").addClass("is-followed")
+ else
+ @$(".dogear").removeClass("is-followed")
- makeWmdEditor: (cls_identifier) =>
- if not @$el.find(".wmd-panel").length
- DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), cls_identifier
+ ability: (ability) ->
+ for action, selector of @abilityRenderer
+ if not ability[action]
+ selector.disable.apply(@)
+ else
+ selector.enable.apply(@)
- getWmdEditor: (cls_identifier) =>
- DiscussionUtil.getWmdEditor @$el, $.proxy(@$, @), cls_identifier
+ abilityRenderer:
+ editable:
+ enable: -> @$(".action-edit").closest("li").show()
+ disable: -> @$(".action-edit").closest("li").hide()
+ can_delete:
+ enable: -> @$(".action-delete").closest("li").show()
+ disable: -> @$(".action-delete").closest("li").hide()
+ can_endorse:
+ enable: -> @$(".action-endorse").css("cursor", "auto")
+ disable: -> @$(".action-endorse").css("cursor", "default")
+ can_openclose:
+ enable: -> @$(".action-openclose").closest("li").show()
+ disable: -> @$(".action-openclose").closest("li").hide()
- getWmdContent: (cls_identifier) =>
- DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), cls_identifier
+ renderPartialAttrs: ->
+ for attr, value of @model.changedAttributes()
+ if @attrRenderer[attr]
+ @attrRenderer[attr].apply(@, [value])
- setWmdContent: (cls_identifier, text) =>
- DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), cls_identifier, text
+ renderAttrs: ->
+ for attr, value of @model.attributes
+ if @attrRenderer[attr]
+ @attrRenderer[attr].apply(@, [value])
- initialize: ->
- @initLocal()
- @model.bind('change', @renderPartialAttrs, @)
+ $: (selector) ->
+ @$local.find(selector)
+
+ initLocal: ->
+ @$local = @$el.children(".local")
+ if not @$local.length
+ @$local = @$el
+ @$delegateElement = @$local
+
+ makeWmdEditor: (cls_identifier) =>
+ if not @$el.find(".wmd-panel").length
+ DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), cls_identifier
+
+ getWmdEditor: (cls_identifier) =>
+ DiscussionUtil.getWmdEditor @$el, $.proxy(@$, @), cls_identifier
+
+ getWmdContent: (cls_identifier) =>
+ DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), cls_identifier
+
+ setWmdContent: (cls_identifier, text) =>
+ DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), cls_identifier, text
+
+ initialize: ->
+ @initLocal()
+ @model.bind('change', @renderPartialAttrs, @)
diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee
index 1c0dbc996f..cddd9e556c 100644
--- a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee
+++ b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee
@@ -1,213 +1,214 @@
-class @DiscussionThreadInlineView extends DiscussionContentView
- expanded = false
- events:
- "click .discussion-vote": "toggleVote"
- "click .action-follow": "toggleFollowing"
- "click .discussion-submit-post": "submitComment"
- "click .action-edit": "edit"
- "click .action-delete": "delete"
- "click .action-openclose": "toggleClosed"
- "click .expand-post": "expandPost"
- "click .collapse-post": "collapsePost"
+if Backbone?
+ class @DiscussionThreadInlineView extends DiscussionContentView
+ expanded = false
+ events:
+ "click .discussion-vote": "toggleVote"
+ "click .action-follow": "toggleFollowing"
+ "click .discussion-submit-post": "submitComment"
+ "click .action-edit": "edit"
+ "click .action-delete": "delete"
+ "click .action-openclose": "toggleClosed"
+ "click .expand-post": "expandPost"
+ "click .collapse-post": "collapsePost"
- template: -> DiscussionUtil.getTemplate("_inline_thread")
+ template: -> DiscussionUtil.getTemplate("_inline_thread")
- initLocal: ->
- @$local = @$el.children(".discussion-article").children(".local")
- @$delegateElement = @$local
+ initLocal: ->
+ @$local = @$el.children(".discussion-article").children(".local")
+ @$delegateElement = @$local
- initialize: ->
- super()
- @model.on "change", @updateModelDetails
+ initialize: ->
+ super()
+ @model.on "change", @updateModelDetails
- render: ->
- if not @model.has('abbreviatedBody')
- @abbreviateBody()
- @$el.html(Mustache.render(@template(), $.extend(@model.toJSON(),{expanded: @expanded}) ))
- @initLocal()
- @delegateEvents()
- @renderDogear()
- @renderVoted()
- @renderAttrs()
- @$("span.timeago").timeago()
- @convertMath()
- if @expanded
+ render: ->
+ if not @model.has('abbreviatedBody')
+ @abbreviateBody()
+ @$el.html(Mustache.render(@template(), $.extend(@model.toJSON(),{expanded: @expanded}) ))
+ @initLocal()
+ @delegateEvents()
+ @renderDogear()
+ @renderVoted()
+ @renderAttrs()
+ @$("span.timeago").timeago()
+ @convertMath()
+ if @expanded
+ @makeWmdEditor "reply-body"
+ @renderResponses()
+ @
+
+ renderDogear: ->
+ if window.user.following(@model)
+ @$(".dogear").addClass("is-followed")
+
+ renderVoted: =>
+ if window.user.voted(@model)
+ @$("[data-role=discussion-vote]").addClass("is-cast")
+ else
+ @$("[data-role=discussion-vote]").removeClass("is-cast")
+
+ updateModelDetails: =>
+ @renderVoted()
+ @$("[data-role=discussion-vote] .votes-count-number").html(@model.get("votes")["up_count"])
+
+ convertMath: ->
+ element = @$(".post-body")
+ element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html()
+ MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]]
+
+ renderResponses: ->
+ DiscussionUtil.safeAjax
+ url: "/courses/#{$$course_id}/discussion/forum/#{@model.get('commentable_id')}/threads/#{@model.id}"
+ $loading: @$el
+ success: (data, textStatus, xhr) =>
+ @$el.find(".loading").remove()
+ Content.loadContentInfos(data['annotated_content_info'])
+ comments = new Comments(data['content']['children'])
+ comments.each @renderResponse
+ @trigger "thread:responses:rendered"
+
+ renderResponse: (response) =>
+ response.set('thread', @model)
+ view = new ThreadResponseView(model: response)
+ view.on "comment:add", @addComment
+ view.render()
+ @$el.find(".responses").append(view.el)
+
+ addComment: =>
+ @model.comment()
+
+ toggleVote: (event) ->
+ event.preventDefault()
+ if window.user.voted(@model)
+ @unvote()
+ else
+ @vote()
+
+ toggleFollowing: (event) ->
+ $elem = $(event.target)
+ url = null
+ console.log "follow"
+ if not @model.get('subscribed')
+ @model.follow()
+ url = @model.urlFor("follow")
+ else
+ @model.unfollow()
+ url = @model.urlFor("unfollow")
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ type: "POST"
+
+ vote: ->
+ window.user.vote(@model)
+ url = @model.urlFor("upvote")
+ DiscussionUtil.safeAjax
+ $elem: @$(".discussion-vote")
+ url: url
+ type: "POST"
+ success: (response, textStatus) =>
+ if textStatus == 'success'
+ @model.set(response)
+
+ unvote: ->
+ window.user.unvote(@model)
+ url = @model.urlFor("unvote")
+ DiscussionUtil.safeAjax
+ $elem: @$(".discussion-vote")
+ url: url
+ type: "POST"
+ success: (response, textStatus) =>
+ if textStatus == 'success'
+ @model.set(response)
+
+ submitComment: (event) ->
+ event.preventDefault()
+ url = @model.urlFor('reply')
+ body = @getWmdContent("reply-body")
+ return if not body.trim().length
+ @setWmdContent("reply-body", "")
+ comment = new Comment(body: body, created_at: (new Date()).toISOString(), username: window.user.get("username"), votes: { up_count: 0 }, endorsed: false, user_id: window.user.get("id"))
+ comment.set('thread', @model.get('thread'))
+ @renderResponse(comment)
+ @model.addComment()
+
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ url: url
+ type: "POST"
+ dataType: 'json'
+ data:
+ body: body
+ success: (data, textStatus) =>
+ comment.updateInfo(data.annotated_content_info)
+ comment.set(data.content)
+
+ edit: ->
+
+
+ delete: (event) ->
+ url = @model.urlFor('delete')
+ if not @model.can('can_delete')
+ return
+ if not confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
+ return
+ @model.remove()
+ @$el.empty()
+ $elem = $(event.target)
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ type: "POST"
+ success: (response, textStatus) =>
+
+ toggleClosed: (event) ->
+ $elem = $(event.target)
+ url = @model.urlFor('close')
+ closed = @model.get('closed')
+ data = { closed: not closed }
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ data: data
+ type: "POST"
+ success: (response, textStatus) =>
+ @model.set('closed', not closed)
+ @model.set('ability', response.ability)
+
+ toggleEndorse: (event) ->
+ $elem = $(event.target)
+ url = @model.urlFor('endorse')
+ endorsed = @model.get('endorsed')
+ data = { endorsed: not endorsed }
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ data: data
+ type: "POST"
+ success: (response, textStatus) =>
+ @model.set('endorsed', not endorsed)
+
+ abbreviateBody: ->
+ abbreviated = DiscussionUtil.abbreviateString @model.get('body'), 140
+ @model.set('abbreviatedBody', abbreviated)
+
+ expandPost: (event) ->
+ @expanded = true
+ @$el.addClass('expanded')
+ @$el.find('.post-body').html(@model.get('body'))
+ @convertMath()
+ @$el.find('.expand-post').css('display', 'none')
+ @$el.find('.collapse-post').css('display', 'block')
+ @$el.find('.post-extended-content').show()
@makeWmdEditor "reply-body"
- @renderResponses()
- @
+ if @$el.find('.loading').length
+ @renderResponses()
- renderDogear: ->
- if window.user.following(@model)
- @$(".dogear").addClass("is-followed")
-
- renderVoted: =>
- if window.user.voted(@model)
- @$("[data-role=discussion-vote]").addClass("is-cast")
- else
- @$("[data-role=discussion-vote]").removeClass("is-cast")
-
- updateModelDetails: =>
- @renderVoted()
- @$("[data-role=discussion-vote] .votes-count-number").html(@model.get("votes")["up_count"])
-
- convertMath: ->
- element = @$(".post-body")
- element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html()
- MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]]
-
- renderResponses: ->
- DiscussionUtil.safeAjax
- url: "/courses/#{$$course_id}/discussion/forum/#{@model.get('commentable_id')}/threads/#{@model.id}"
- $loading: @$el
- success: (data, textStatus, xhr) =>
- @$el.find(".loading").remove()
- Content.loadContentInfos(data['annotated_content_info'])
- comments = new Comments(data['content']['children'])
- comments.each @renderResponse
- @trigger "thread:responses:rendered"
-
- renderResponse: (response) =>
- response.set('thread', @model)
- view = new ThreadResponseView(model: response)
- view.on "comment:add", @addComment
- view.render()
- @$el.find(".responses").append(view.el)
-
- addComment: =>
- @model.comment()
-
- toggleVote: (event) ->
- event.preventDefault()
- if window.user.voted(@model)
- @unvote()
- else
- @vote()
-
- toggleFollowing: (event) ->
- $elem = $(event.target)
- url = null
- console.log "follow"
- if not @model.get('subscribed')
- @model.follow()
- url = @model.urlFor("follow")
- else
- @model.unfollow()
- url = @model.urlFor("unfollow")
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- type: "POST"
-
- vote: ->
- window.user.vote(@model)
- url = @model.urlFor("upvote")
- DiscussionUtil.safeAjax
- $elem: @$(".discussion-vote")
- url: url
- type: "POST"
- success: (response, textStatus) =>
- if textStatus == 'success'
- @model.set(response)
-
- unvote: ->
- window.user.unvote(@model)
- url = @model.urlFor("unvote")
- DiscussionUtil.safeAjax
- $elem: @$(".discussion-vote")
- url: url
- type: "POST"
- success: (response, textStatus) =>
- if textStatus == 'success'
- @model.set(response)
-
- submitComment: (event) ->
- event.preventDefault()
- url = @model.urlFor('reply')
- body = @getWmdContent("reply-body")
- return if not body.trim().length
- @setWmdContent("reply-body", "")
- comment = new Comment(body: body, created_at: (new Date()).toISOString(), username: window.user.get("username"), votes: { up_count: 0 }, endorsed: false, user_id: window.user.get("id"))
- comment.set('thread', @model.get('thread'))
- @renderResponse(comment)
- @model.addComment()
-
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- url: url
- type: "POST"
- dataType: 'json'
- data:
- body: body
- success: (data, textStatus) =>
- comment.updateInfo(data.annotated_content_info)
- comment.set(data.content)
-
- edit: ->
-
-
- delete: (event) ->
- url = @model.urlFor('delete')
- if not @model.can('can_delete')
- return
- if not confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
- return
- @model.remove()
- @$el.empty()
- $elem = $(event.target)
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- type: "POST"
- success: (response, textStatus) =>
-
- toggleClosed: (event) ->
- $elem = $(event.target)
- url = @model.urlFor('close')
- closed = @model.get('closed')
- data = { closed: not closed }
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- data: data
- type: "POST"
- success: (response, textStatus) =>
- @model.set('closed', not closed)
- @model.set('ability', response.ability)
-
- toggleEndorse: (event) ->
- $elem = $(event.target)
- url = @model.urlFor('endorse')
- endorsed = @model.get('endorsed')
- data = { endorsed: not endorsed }
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- data: data
- type: "POST"
- success: (response, textStatus) =>
- @model.set('endorsed', not endorsed)
-
- abbreviateBody: ->
- abbreviated = DiscussionUtil.abbreviateString @model.get('body'), 140
- @model.set('abbreviatedBody', abbreviated)
-
- expandPost: (event) ->
- @expanded = true
- @$el.addClass('expanded')
- @$el.find('.post-body').html(@model.get('body'))
- @convertMath()
- @$el.find('.expand-post').css('display', 'none')
- @$el.find('.collapse-post').css('display', 'block')
- @$el.find('.post-extended-content').show()
- @makeWmdEditor "reply-body"
- if @$el.find('.loading').length
- @renderResponses()
-
- collapsePost: (event) ->
- @expanded = false
- @$el.removeClass('expanded')
- @$el.find('.post-body').html(@model.get('abbreviatedBody'))
- @convertMath()
- @$el.find('.collapse-post').css('display', 'none')
- @$el.find('.post-extended-content').hide()
- @$el.find('.expand-post').css('display', 'block')
+ collapsePost: (event) ->
+ @expanded = false
+ @$el.removeClass('expanded')
+ @$el.find('.post-body').html(@model.get('abbreviatedBody'))
+ @convertMath()
+ @$el.find('.collapse-post').css('display', 'none')
+ @$el.find('.post-extended-content').hide()
+ @$el.find('.expand-post').css('display', 'block')
diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
index 08f9fb754f..367803f6bd 100644
--- a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
+++ b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
@@ -1,269 +1,266 @@
-class @DiscussionThreadListView extends Backbone.View
- template: _.template($("#thread-list-template").html())
- events:
- "click .search": "showSearch"
- "click .browse": "toggleTopicDrop"
- "keydown .post-search-field": "performSearch"
- "click .sort-bar a": "sortThreads"
- "click .browse-topic-drop-menu": "filterTopic"
- "click .browse-topic-drop-search-input": "ignoreClick"
- "click .post-list a": "threadSelected"
+if Backbone?
+ class @DiscussionThreadListView extends Backbone.View
+ template: _.template($("#thread-list-template").html())
+ events:
+ "click .search": "showSearch"
+ "click .browse": "toggleTopicDrop"
+ "keydown .post-search-field": "performSearch"
+ "click .sort-bar a": "sortThreads"
+ "click .browse-topic-drop-menu": "filterTopic"
+ "click .browse-topic-drop-search-input": "ignoreClick"
+ "click .post-list a": "threadSelected"
- initialize: ->
- @displayedCollection = new Discussion(@collection.models)
- @collection.on "change", @reloadDisplayedCollection
- @collection.on "add", @addAndSelectThread
- @sidebar_padding = 10
- @sidebar_header_height = 87
- @boardName
+ initialize: ->
+ @displayedCollection = new Discussion(@collection.models)
+ @collection.on "change", @reloadDisplayedCollection
+ @collection.on "add", @addAndSelectThread
+ @sidebar_padding = 10
+ @sidebar_header_height = 87
+ @boardName
- reloadDisplayedCollection: (thread) =>
- thread_id = thread.get('id')
- content = @renderThread(thread)
- current_el = @$("a[data-id=#{thread_id}]")
- active = current_el.hasClass("active")
- current_el.replaceWith(content)
- if active
- @setActiveThread(thread_id)
-
- addAndSelectThread: (thread) =>
- commentable_id = thread.get("commentable_id")
- commentable = @$(".board-name[data-discussion_id]").filter(-> $(this).data("discussion_id").id == commentable_id)
- commentable.click()
- @displayedCollection.add thread
- content = @renderThread(thread)
- $(".post-list").prepend content
- content.wrap("
")
- content.click()
-
- updateSidebar: =>
-
- scrollTop = $(window).scrollTop();
- windowHeight = $(window).height();
-
- discussionBody = $(".discussion-article")
- discussionsBodyTop = if discussionBody[0] then discussionBody.offset().top
- discussionsBodyBottom = discussionsBodyTop + discussionBody.outerHeight()
-
- sidebar = $(".sidebar")
- if scrollTop > discussionsBodyTop - @sidebar_padding
- sidebar.addClass('fixed');
- sidebar.css('top', @sidebar_padding);
- else
- sidebar.removeClass('fixed');
- sidebar.css('top', '0');
-
- sidebarWidth = .31 * $(".discussion-body").width();
- sidebar.css('width', sidebarWidth + 'px');
-
- sidebarHeight = windowHeight - Math.max(discussionsBodyTop - scrollTop, @sidebar_padding)
-
- topOffset = scrollTop + windowHeight
- discussionBottomOffset = discussionsBodyBottom + @sidebar_padding
- amount = Math.max(topOffset - discussionBottomOffset, 0)
-
- sidebarHeight = sidebarHeight - @sidebar_padding - amount
- sidebarHeight = Math.min(Math.max(sidebarHeight, 400), discussionBody.outerHeight())
- sidebar.css 'height', sidebarHeight
-
- postListWrapper = @$('.post-list-wrapper')
- postListWrapper.css('height', (sidebarHeight - @sidebar_header_height - 4) + 'px')
-
-
- # Because we want the behavior that when the body is clicked the menu is
- # closed, we need to ignore clicks in the search field and stop propagation.
- # Without this, clicking the search field would also close the menu.
- ignoreClick: (event) ->
- event.stopPropagation()
-
- render: ->
- @timer = 0
- @$el.html(@template())
-
- $(window).bind "scroll", @updateSidebar
- $(window).bind "resize", @updateSidebar
-
- @displayedCollection.on "reset", @renderThreads
- @displayedCollection.on "thread:remove", @renderThreads
- @renderThreads()
- @
-
- renderThreads: =>
- @$(".post-list").html("")
- rendered = $("")
- for thread in @displayedCollection.models
+ reloadDisplayedCollection: (thread) =>
+ thread_id = thread.get('id')
content = @renderThread(thread)
- rendered.append content
+ current_el = @$("a[data-id=#{thread_id}]")
+ active = current_el.hasClass("active")
+ current_el.replaceWith(content)
+ if active
+ @setActiveThread(thread_id)
+
+ addAndSelectThread: (thread) =>
+ commentable_id = thread.get("commentable_id")
+ commentable = @$(".board-name[data-discussion_id]").filter(-> $(this).data("discussion_id").id == commentable_id)
+ commentable.click()
+ @displayedCollection.add thread
+ content = @renderThread(thread)
+ $(".post-list").prepend content
content.wrap("")
+ content.click()
- @$(".post-list").html(rendered.html())
- @trigger "threads:rendered"
+ updateSidebar: =>
- renderThread: (thread) =>
- content = $(_.template($("#thread-list-item-template").html())(thread.toJSON()))
- if thread.get('subscribed')
- content.addClass("followed")
- if thread.get('endorsed')
- content.addClass("resolved")
- @highlight(content)
+ scrollTop = $(window).scrollTop();
+ windowHeight = $(window).height();
+
+ discussionBody = $(".discussion-article")
+ discussionsBodyTop = if discussionBody[0] then discussionBody.offset().top
+ discussionsBodyBottom = discussionsBodyTop + discussionBody.outerHeight()
+
+ sidebar = $(".sidebar")
+ if scrollTop > discussionsBodyTop - @sidebar_padding
+ sidebar.addClass('fixed');
+ sidebar.css('top', @sidebar_padding);
+ else
+ sidebar.removeClass('fixed');
+ sidebar.css('top', '0');
+
+ sidebarWidth = .31 * $(".discussion-body").width();
+ sidebar.css('width', sidebarWidth + 'px');
+
+ sidebarHeight = windowHeight - Math.max(discussionsBodyTop - scrollTop, @sidebar_padding)
+
+ topOffset = scrollTop + windowHeight
+ discussionBottomOffset = discussionsBodyBottom + @sidebar_padding
+ amount = Math.max(topOffset - discussionBottomOffset, 0)
+
+ sidebarHeight = sidebarHeight - @sidebar_padding - amount
+ sidebarHeight = Math.min(Math.max(sidebarHeight, 400), discussionBody.outerHeight())
+ sidebar.css 'height', sidebarHeight
+
+ postListWrapper = @$('.post-list-wrapper')
+ postListWrapper.css('height', (sidebarHeight - @sidebar_header_height - 4) + 'px')
- highlight: (el) ->
- el.html(el.html().replace(/<mark>/g, "").replace(/<\/mark>/g, ""))
+ # Because we want the behavior that when the body is clicked the menu is
+ # closed, we need to ignore clicks in the search field and stop propagation.
+ # Without this, clicking the search field would also close the menu.
+ ignoreClick: (event) ->
+ event.stopPropagation()
- renderThreadListItem: (thread) =>
- view = new ThreadListItemView(model: thread)
- view.on "thread:selected", @threadSelected
- view.on "thread:removed", @threadRemoved
- view.render()
- @$(".post-list").append(view.el)
+ render: ->
+ @timer = 0
+ @$el.html(@template())
- threadSelected: (e) =>
- thread_id = $(e.target).closest("a").data("id")
- @setActiveThread(thread_id)
- @trigger("thread:selected", thread_id)
- false
+ $(window).bind "scroll", @updateSidebar
+ $(window).bind "resize", @updateSidebar
- threadRemoved: (thread_id) =>
- @trigger("thread:removed", thread_id)
+ @displayedCollection.on "reset", @renderThreads
+ @displayedCollection.on "thread:remove", @renderThreads
+ @renderThreads()
+ @
- setActiveThread: (thread_id) ->
- @$("a[data-id!='#{thread_id}']").removeClass("active")
- @$("a[data-id='#{thread_id}']").addClass("active")
+ renderThreads: =>
+ @$(".post-list").html("")
+ rendered = $("")
+ for thread in @displayedCollection.models
+ content = @renderThread(thread)
+ rendered.append content
+ content.wrap("")
- showSearch: ->
- @$(".search").addClass('is-open')
- @$(".browse").removeClass('is-open')
- setTimeout (-> @$(".post-search-field").focus()), 200
+ @$(".post-list").html(rendered.html())
+ @trigger "threads:rendered"
- toggleTopicDrop: (event) =>
- event.stopPropagation()
- @$(".browse").toggleClass('is-dropped')
- if @$(".browse").hasClass('is-dropped')
- @$(".browse-topic-drop-menu-wrapper").show()
- $(".browse-topic-drop-search-input").focus()
- $("body").bind "click", @toggleTopicDrop
- $("body").bind "keydown", @setActiveItem
- else
- @$(".browse-topic-drop-menu-wrapper").hide()
- $("body").unbind "click", @toggleTopicDrop
- $("body").unbind "keydown", @setActiveItem
+ renderThread: (thread) =>
+ content = $(_.template($("#thread-list-item-template").html())(thread.toJSON()))
+ if thread.get('subscribed')
+ content.addClass("followed")
+ if thread.get('endorsed')
+ content.addClass("resolved")
+ @highlight(content)
- setTopic: (event) ->
- item = $(event.target).closest('a')
- boardName = item.find(".board-name").html()
- _.each item.parents('ul').not('.browse-topic-drop-menu'), (parent) ->
- boardName = $(parent).siblings('a').find('.board-name').html() + ' / ' + boardName
- @$(".current-board").html(@fitName(boardName))
- fontSize = 16
- @$(".current-board").css('font-size', '16px')
- while @$(".current-board").width() > (@$el.width() * .8) - 40
- fontSize--
- if fontSize < 11
- break
- @$(".current-board").css('font-size', fontSize + 'px')
- setSelectedTopic: (name) ->
- @$(".current-board").html(@fitName(name))
+ highlight: (el) ->
+ el.html(el.html().replace(/<mark>/g, "").replace(/<\/mark>/g, ""))
- getNameWidth: (name) ->
- test = $("")
- test.css
- "font-size": @$(".current-board").css('font-size')
- opacity: 0
- position: 'absolute'
- left: -1000
- top: -1000
- $("body").append(test)
- test.html(name)
- width = test.width()
- test.remove()
- return width
+ renderThreadListItem: (thread) =>
+ view = new ThreadListItemView(model: thread)
+ view.on "thread:selected", @threadSelected
+ view.on "thread:removed", @threadRemoved
+ view.render()
+ @$(".post-list").append(view.el)
+
+ threadSelected: (e) =>
+ thread_id = $(e.target).closest("a").data("id")
+ @setActiveThread(thread_id)
+ @trigger("thread:selected", thread_id)
+ false
+
+ threadRemoved: (thread_id) =>
+ @trigger("thread:removed", thread_id)
+
+ setActiveThread: (thread_id) ->
+ @$("a[data-id!='#{thread_id}']").removeClass("active")
+ @$("a[data-id='#{thread_id}']").addClass("active")
+
+ showSearch: ->
+ @$(".search").addClass('is-open')
+ @$(".browse").removeClass('is-open')
+ setTimeout (-> @$(".post-search-field").focus()), 200
+
+ toggleTopicDrop: (event) =>
+ event.stopPropagation()
+ @$(".browse").toggleClass('is-dropped')
+ if @$(".browse").hasClass('is-dropped')
+ @$(".browse-topic-drop-menu-wrapper").show()
+ $(".browse-topic-drop-search-input").focus()
+ $("body").bind "click", @toggleTopicDrop
+ $("body").bind "keydown", @setActiveItem
+ else
+ @$(".browse-topic-drop-menu-wrapper").hide()
+ $("body").unbind "click", @toggleTopicDrop
+ $("body").unbind "keydown", @setActiveItem
+
+ setTopic: (event) ->
+ item = $(event.target).closest('a')
+ boardName = item.find(".board-name").html()
+ _.each item.parents('ul').not('.browse-topic-drop-menu'), (parent) ->
+ boardName = $(parent).siblings('a').find('.board-name').html() + ' / ' + boardName
+ @$(".current-board").html(@fitName(boardName))
+ fontSize = 16
+ @$(".current-board").css('font-size', '16px')
+ while @$(".current-board").width() > (@$el.width() * .8) - 40
+ fontSize--
+ if fontSize < 11
+ break
+ @$(".current-board").css('font-size', fontSize + 'px')
+
+ setSelectedTopic: (name) ->
+ @$(".current-board").html(@fitName(name))
+
+ getNameWidth: (name) ->
+ test = $("
")
+ test.css
+ "font-size": @$(".current-board").css('font-size')
+ opacity: 0
+ position: 'absolute'
+ left: -1000
+ top: -1000
+ $("body").append(test)
+ test.html(name)
+ width = test.width()
+ test.remove()
+ return width
+
+ fitName: (name) ->
+ width = @getNameWidth(name)
+ if width < @maxNameWidth
+ return name
+ path = (x.replace /^\s+|\s+$/g, "" for x in name.split("/"))
+ while path.length > 1
+ path.shift()
+ partialName = "... / " + path.join(" / ")
+ if @getNameWidth(partialName) < @maxNameWidth
+ return partialName
+
+ rawName = path[0]
+
+ name = "... / " + rawName
+
+ while @getNameWidth(name) > @maxNameWidth
+ rawName = rawName[0...rawName.length-1]
+ name = "... / " + rawName + " ..."
- fitName: (name) ->
- width = @getNameWidth(name)
- if width < @maxNameWidth
return name
- path = (x.replace /^\s+|\s+$/g, "" for x in name.split("/"))
- while path.length > 1
- path.shift()
- partialName = "... / " + path.join(" / ")
- if @getNameWidth(partialName) < @maxNameWidth
- return partialName
- rawName = path[0]
+ filterTopic: (event) ->
+ @setTopic(event)
+ item = $(event.target).closest('li')
+ if item.find("span.board-name").data("discussion_id") == "#all"
+ item = item.parent()
+ discussionIds = _.map item.find(".board-name[data-discussion_id]"), (board) -> $(board).data("discussion_id").id
+ filtered = @collection.filter (thread) =>
+ _.include(discussionIds, thread.get('commentable_id'))
+ @displayedCollection.reset filtered
- name = "... / " + rawName
+ sortThreads: (event) ->
+ @$(".sort-bar a").removeClass("active")
+ $(event.target).addClass("active")
+ sortBy = $(event.target).data("sort")
+ if sortBy == "date"
+ @displayedCollection.comparator = @displayedCollection.sortByDateRecentFirst
+ else if sortBy == "votes"
+ @displayedCollection.comparator = @displayedCollection.sortByVotes
+ else if sortBy == "comments"
+ @displayedCollection.comparator = @displayedCollection.sortByComments
+ @displayedCollection.sort()
- while @getNameWidth(name) > @maxNameWidth
- rawName = rawName[0...rawName.length-1]
- name = "... / " + rawName + " ..."
+ performSearch: (event) ->
+ if event.which == 13
+ event.preventDefault()
+ url = DiscussionUtil.urlFor("search")
+ text = @$(".post-search-field").val()
+ DiscussionUtil.safeAjax
+ $elem: @$(".post-search-field")
+ data: { text: text }
+ url: url
+ type: "GET"
+ success: (response, textStatus) =>
+ if textStatus == 'success'
+ @collection.reset(response.discussion_data)
+ @displayedCollection.reset(@collection.models)
- return name
-
- filterTopic: (event) ->
- @setTopic(event)
- item = $(event.target).closest('li')
- if item.find("span.board-name").data("discussion_id") == "#all"
- item = item.parent()
- discussionIds = _.map item.find(".board-name[data-discussion_id]"), (board) -> $(board).data("discussion_id").id
- filtered = @collection.filter (thread) =>
- _.include(discussionIds, thread.get('commentable_id'))
- @displayedCollection.reset filtered
-
- sortThreads: (event) ->
- @$(".sort-bar a").removeClass("active")
- $(event.target).addClass("active")
- sortBy = $(event.target).data("sort")
- if sortBy == "date"
- @displayedCollection.comparator = @displayedCollection.sortByDateRecentFirst
- else if sortBy == "votes"
- @displayedCollection.comparator = @displayedCollection.sortByVotes
- else if sortBy == "comments"
- @displayedCollection.comparator = @displayedCollection.sortByComments
- @displayedCollection.sort()
-
- performSearch: (event) ->
- if event.which == 13
+ setActiveItem: (event) ->
+ if event.which == 13
+ $(".browse-topic-drop-menu-wrapper .focused").click()
+ return
+ if event.which != 40 && event.which != 38
+ return
event.preventDefault()
- url = DiscussionUtil.urlFor("search")
- text = @$(".post-search-field").val()
- DiscussionUtil.safeAjax
- $elem: @$(".post-search-field")
- data: { text: text }
- url: url
- type: "GET"
- success: (response, textStatus) =>
- if textStatus == 'success'
- @collection.reset(response.discussion_data)
- @displayedCollection.reset(@collection.models)
-
- setActiveItem: (event) ->
- if event.which == 13
- $(".browse-topic-drop-menu-wrapper .focused").click()
- return
- if event.which != 40 && event.which != 38
- return
- event.preventDefault()
-
- items = $.makeArray($(".browse-topic-drop-menu-wrapper a").not(".hidden"))
- index = items.indexOf($('.browse-topic-drop-menu-wrapper .focused')[0])
-
- if event.which == 40
- index = Math.min(index + 1, items.length - 1)
- if event.which == 38
- index = Math.max(index - 1, 0)
-
- $(".browse-topic-drop-menu-wrapper .focused").removeClass("focused")
- $(items[index]).addClass("focused")
-
- itemTop = $(items[index]).parent().offset().top
- scrollTop = $(".browse-topic-drop-menu").scrollTop()
- itemFromTop = $(".browse-topic-drop-menu").offset().top - itemTop
- scrollTarget = Math.min(scrollTop - itemFromTop, scrollTop)
- scrollTarget = Math.max(scrollTop - itemFromTop - $(".browse-topic-drop-menu").height() + $(items[index]).height(), scrollTarget)
- $(".browse-topic-drop-menu").scrollTop(scrollTarget)
+ items = $.makeArray($(".browse-topic-drop-menu-wrapper a").not(".hidden"))
+ index = items.indexOf($('.browse-topic-drop-menu-wrapper .focused')[0])
+ if event.which == 40
+ index = Math.min(index + 1, items.length - 1)
+ if event.which == 38
+ index = Math.max(index - 1, 0)
+ $(".browse-topic-drop-menu-wrapper .focused").removeClass("focused")
+ $(items[index]).addClass("focused")
+ itemTop = $(items[index]).parent().offset().top
+ scrollTop = $(".browse-topic-drop-menu").scrollTop()
+ itemFromTop = $(".browse-topic-drop-menu").offset().top - itemTop
+ scrollTarget = Math.min(scrollTop - itemFromTop, scrollTop)
+ scrollTarget = Math.max(scrollTop - itemFromTop - $(".browse-topic-drop-menu").height() + $(items[index]).height(), scrollTarget)
+ $(".browse-topic-drop-menu").scrollTop(scrollTarget)
diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee
index 8d97c4b74e..8bb207da2b 100644
--- a/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee
+++ b/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee
@@ -1,93 +1,94 @@
-class @DiscussionThreadView extends DiscussionContentView
+if Backbone?
+ class @DiscussionThreadView extends DiscussionContentView
- events:
- "click .discussion-submit-post": "submitComment"
+ events:
+ "click .discussion-submit-post": "submitComment"
- template: _.template($("#thread-template").html())
+ template: _.template($("#thread-template").html())
- $: (selector) ->
- @$el.find(selector)
+ $: (selector) ->
+ @$el.find(selector)
- initialize: ->
- super()
- @showView = new DiscussionThreadShowView(model: @model)
- @showView.bind "thread:delete", @delete
- @showView.bind "thread:edit", @edit
+ initialize: ->
+ super()
+ @showView = new DiscussionThreadShowView(model: @model)
+ @showView.bind "thread:delete", @delete
+ @showView.bind "thread:edit", @edit
- render: ->
- @$el.html(@template(@model.toJSON()))
- @delegateEvents()
+ render: ->
+ @$el.html(@template(@model.toJSON()))
+ @delegateEvents()
- @showView.setElement(@$('.thread-content-wrapper'))
- @showView.render()
- @showView.delegateEvents()
+ @showView.setElement(@$('.thread-content-wrapper'))
+ @showView.render()
+ @showView.delegateEvents()
- @renderAttrs()
- @$("span.timeago").timeago()
- @makeWmdEditor "reply-body"
- @renderResponses()
- @
+ @renderAttrs()
+ @$("span.timeago").timeago()
+ @makeWmdEditor "reply-body"
+ @renderResponses()
+ @
- renderResponses: ->
- DiscussionUtil.safeAjax
- url: "/courses/#{$$course_id}/discussion/forum/#{@model.get('commentable_id')}/threads/#{@model.id}"
- success: (data, textStatus, xhr) =>
- @$el.find(".loading").remove()
- Content.loadContentInfos(data['annotated_content_info'])
- comments = new Comments(data['content']['children'])
- comments.each @renderResponse
- @trigger "thread:responses:rendered"
+ renderResponses: ->
+ DiscussionUtil.safeAjax
+ url: "/courses/#{$$course_id}/discussion/forum/#{@model.get('commentable_id')}/threads/#{@model.id}"
+ success: (data, textStatus, xhr) =>
+ @$el.find(".loading").remove()
+ Content.loadContentInfos(data['annotated_content_info'])
+ comments = new Comments(data['content']['children'])
+ comments.each @renderResponse
+ @trigger "thread:responses:rendered"
- renderResponse: (response) =>
- response.set('thread', @model)
- view = new ThreadResponseView(model: response)
- view.on "comment:add", @addComment
- view.on "comment:endorse", @endorseThread
- view.render()
- @$el.find(".responses").append(view.el)
+ renderResponse: (response) =>
+ response.set('thread', @model)
+ view = new ThreadResponseView(model: response)
+ view.on "comment:add", @addComment
+ view.on "comment:endorse", @endorseThread
+ view.render()
+ @$el.find(".responses").append(view.el)
- addComment: =>
- @model.comment()
+ addComment: =>
+ @model.comment()
- endorseThread: (endorsed) =>
- is_endorsed = @$el.find(".is-endorsed").length
- @model.set 'endorsed', is_endorsed
+ endorseThread: (endorsed) =>
+ is_endorsed = @$el.find(".is-endorsed").length
+ @model.set 'endorsed', is_endorsed
- submitComment: (event) ->
- event.preventDefault()
- url = @model.urlFor('reply')
- body = @getWmdContent("reply-body")
- return if not body.trim().length
- @setWmdContent("reply-body", "")
- comment = new Comment(body: body, created_at: (new Date()).toISOString(), username: window.user.get("username"), votes: { up_count: 0 }, endorsed: false, user_id: window.user.get("id"))
- comment.set('thread', @model.get('thread'))
- @renderResponse(comment)
- @model.addComment()
+ submitComment: (event) ->
+ event.preventDefault()
+ url = @model.urlFor('reply')
+ body = @getWmdContent("reply-body")
+ return if not body.trim().length
+ @setWmdContent("reply-body", "")
+ comment = new Comment(body: body, created_at: (new Date()).toISOString(), username: window.user.get("username"), votes: { up_count: 0 }, endorsed: false, user_id: window.user.get("id"))
+ comment.set('thread', @model.get('thread'))
+ @renderResponse(comment)
+ @model.addComment()
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- url: url
- type: "POST"
- dataType: 'json'
- data:
- body: body
- success: (data, textStatus) =>
- comment.updateInfo(data.annotated_content_info)
- comment.set(data.content)
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ url: url
+ type: "POST"
+ dataType: 'json'
+ data:
+ body: body
+ success: (data, textStatus) =>
+ comment.updateInfo(data.annotated_content_info)
+ comment.set(data.content)
- edit: ->
+ edit: ->
- delete: (event) ->
- url = @model.urlFor('delete')
- if not @model.can('can_delete')
- return
- if not confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
- return
- @model.remove()
- @$el.empty()
- $elem = $(event.target)
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- type: "POST"
- success: (response, textStatus) =>
+ delete: (event) ->
+ url = @model.urlFor('delete')
+ if not @model.can('can_delete')
+ return
+ if not confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
+ return
+ @model.remove()
+ @$el.empty()
+ $elem = $(event.target)
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ type: "POST"
+ success: (response, textStatus) =>
diff --git a/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee
index f3b04d14ce..4b00cd25f0 100644
--- a/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee
+++ b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee
@@ -1,55 +1,56 @@
-class @NewPostInlineView extends Backbone.View
+if Backbone?
+ class @NewPostInlineView extends Backbone.View
- initialize: () ->
+ initialize: () ->
- @topicId = @$(".topic").first().data("discussion-id")
+ @topicId = @$(".topic").first().data("discussion-id")
- @maxNameWidth = 100
+ @maxNameWidth = 100
- DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
- @$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
+ DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
+ @$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
- events:
- "submit .new-post-form": "createPost"
+ events:
+ "submit .new-post-form": "createPost"
- # Because we want the behavior that when the body is clicked the menu is
- # closed, we need to ignore clicks in the search field and stop propagation.
- # Without this, clicking the search field would also close the menu.
- ignoreClick: (event) ->
- event.stopPropagation()
+ # Because we want the behavior that when the body is clicked the menu is
+ # closed, we need to ignore clicks in the search field and stop propagation.
+ # Without this, clicking the search field would also close the menu.
+ ignoreClick: (event) ->
+ event.stopPropagation()
- createPost: (event) ->
- event.preventDefault()
- title = @$(".new-post-title").val()
- body = @$(".new-post-body").find(".wmd-input").val()
- tags = @$(".new-post-tags").val()
+ createPost: (event) ->
+ event.preventDefault()
+ title = @$(".new-post-title").val()
+ body = @$(".new-post-body").find(".wmd-input").val()
+ tags = @$(".new-post-tags").val()
- anonymous = false || @$("input.discussion-anonymous").is(":checked")
- follow = false || @$("input.discussion-follow").is(":checked")
+ anonymous = false || @$("input.discussion-anonymous").is(":checked")
+ follow = false || @$("input.discussion-follow").is(":checked")
- url = DiscussionUtil.urlFor('create_thread', @topicId)
+ url = DiscussionUtil.urlFor('create_thread', @topicId)
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- $loading: $(event.target) if event
- url: url
- type: "POST"
- dataType: 'json'
- async: false # TODO when the rest of the stuff below is made to work properly..
- data:
- title: title
- body: body
- tags: tags
- anonymous: anonymous
- auto_subscribe: follow
- error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
- success: (response, textStatus) =>
- # TODO: Move this out of the callback, this makes it feel sluggish
- thread = new Thread response['content']
- DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
- @$el.hide()
- @$(".new-post-title").val("").attr("prev-text", "")
- @$(".new-post-body textarea").val("").attr("prev-text", "")
- @$(".new-post-tags").val("")
- @$(".new-post-tags").importTags("")
- @collection.add thread
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ $loading: $(event.target) if event
+ url: url
+ type: "POST"
+ dataType: 'json'
+ async: false # TODO when the rest of the stuff below is made to work properly..
+ data:
+ title: title
+ body: body
+ tags: tags
+ anonymous: anonymous
+ auto_subscribe: follow
+ error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
+ success: (response, textStatus) =>
+ # TODO: Move this out of the callback, this makes it feel sluggish
+ thread = new Thread response['content']
+ DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
+ @$el.hide()
+ @$(".new-post-title").val("").attr("prev-text", "")
+ @$(".new-post-body textarea").val("").attr("prev-text", "")
+ @$(".new-post-tags").val("")
+ @$(".new-post-tags").importTags("")
+ @collection.add thread
diff --git a/lms/static/coffee/src/discussion/views/new_post_view.coffee b/lms/static/coffee/src/discussion/views/new_post_view.coffee
index 927aa76536..8969d25748 100644
--- a/lms/static/coffee/src/discussion/views/new_post_view.coffee
+++ b/lms/static/coffee/src/discussion/views/new_post_view.coffee
@@ -1,175 +1,176 @@
-class @NewPostView extends Backbone.View
+if Backbone?
+ class @NewPostView extends Backbone.View
- initialize: () ->
- @dropdownButton = @$(".topic_dropdown_button")
- @topicMenu = @$(".topic_menu_wrapper")
+ initialize: () ->
+ @dropdownButton = @$(".topic_dropdown_button")
+ @topicMenu = @$(".topic_menu_wrapper")
- @menuOpen = @dropdownButton.hasClass('dropped')
+ @menuOpen = @dropdownButton.hasClass('dropped')
- @topicId = @$(".topic").first().data("discussion_id")
- @topicText = @getFullTopicName(@$(".topic").first())
+ @topicId = @$(".topic").first().data("discussion_id")
+ @topicText = @getFullTopicName(@$(".topic").first())
- @maxNameWidth = 100
- @setSelectedTopic()
+ @maxNameWidth = 100
+ @setSelectedTopic()
- DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
- @$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
+ DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
+ @$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
- events:
- "submit .new-post-form": "createPost"
- "click .topic_dropdown_button": "toggleTopicDropdown"
- "click .topic_menu_wrapper": "setTopic"
- "click .topic_menu_search": "ignoreClick"
+ events:
+ "submit .new-post-form": "createPost"
+ "click .topic_dropdown_button": "toggleTopicDropdown"
+ "click .topic_menu_wrapper": "setTopic"
+ "click .topic_menu_search": "ignoreClick"
- # Because we want the behavior that when the body is clicked the menu is
- # closed, we need to ignore clicks in the search field and stop propagation.
- # Without this, clicking the search field would also close the menu.
- ignoreClick: (event) ->
- event.stopPropagation()
+ # Because we want the behavior that when the body is clicked the menu is
+ # closed, we need to ignore clicks in the search field and stop propagation.
+ # Without this, clicking the search field would also close the menu.
+ ignoreClick: (event) ->
+ event.stopPropagation()
- toggleTopicDropdown: (event) ->
- event.stopPropagation()
- if @menuOpen
- @hideTopicDropdown()
- else
- @showTopicDropdown()
+ toggleTopicDropdown: (event) ->
+ event.stopPropagation()
+ if @menuOpen
+ @hideTopicDropdown()
+ else
+ @showTopicDropdown()
- showTopicDropdown: () ->
- @menuOpen = true
- @dropdownButton.addClass('dropped')
- @topicMenu.show()
- $(".form-topic-drop-search-input").focus()
+ showTopicDropdown: () ->
+ @menuOpen = true
+ @dropdownButton.addClass('dropped')
+ @topicMenu.show()
+ $(".form-topic-drop-search-input").focus()
- $("body").bind "keydown", @setActiveItem
- $("body").bind "click", @hideTopicDropdown
+ $("body").bind "keydown", @setActiveItem
+ $("body").bind "click", @hideTopicDropdown
- # Set here because 1) the window might get resized and things could
- # change and 2) can't set in initialize because the button is hidden
- @maxNameWidth = @dropdownButton.width() * 0.9
+ # Set here because 1) the window might get resized and things could
+ # change and 2) can't set in initialize because the button is hidden
+ @maxNameWidth = @dropdownButton.width() * 0.9
- # Need a fat arrow because hideTopicDropdown is passed as a callback to bind
- hideTopicDropdown: () =>
- @menuOpen = false
- @dropdownButton.removeClass('dropped')
- @topicMenu.hide()
+ # Need a fat arrow because hideTopicDropdown is passed as a callback to bind
+ hideTopicDropdown: () =>
+ @menuOpen = false
+ @dropdownButton.removeClass('dropped')
+ @topicMenu.hide()
- $("body").unbind "keydown", @setActiveItem
- $("body").unbind "click", @hideTopicDropdown
+ $("body").unbind "keydown", @setActiveItem
+ $("body").unbind "click", @hideTopicDropdown
- setTopic: (event) ->
- $target = $(event.target)
- if $target.data('discussion_id')
- @topicText = $target.html()
- @topicText = @getFullTopicName($target)
- @topicId = $target.data('discussion_id')
- @setSelectedTopic()
+ setTopic: (event) ->
+ $target = $(event.target)
+ if $target.data('discussion_id')
+ @topicText = $target.html()
+ @topicText = @getFullTopicName($target)
+ @topicId = $target.data('discussion_id')
+ @setSelectedTopic()
- setSelectedTopic: ->
- @dropdownButton.html(@fitName(@topicText) + '
▾')
+ setSelectedTopic: ->
+ @dropdownButton.html(@fitName(@topicText) + '
▾')
- getFullTopicName: (topicElement) ->
- name = topicElement.html()
- topicElement.parents('ul').not('.topic_menu').each ->
- name = $(this).siblings('a').html() + ' / ' + name
- return name
+ getFullTopicName: (topicElement) ->
+ name = topicElement.html()
+ topicElement.parents('ul').not('.topic_menu').each ->
+ name = $(this).siblings('a').html() + ' / ' + name
+ return name
- getNameWidth: (name) ->
- test = $("
")
- test.css
- "font-size": @dropdownButton.css('font-size')
- opacity: 0
- position: 'absolute'
- left: -1000
- top: -1000
- $("body").append(test)
- test.html(name)
- width = test.width()
- test.remove()
- return width
+ getNameWidth: (name) ->
+ test = $("
")
+ test.css
+ "font-size": @dropdownButton.css('font-size')
+ opacity: 0
+ position: 'absolute'
+ left: -1000
+ top: -1000
+ $("body").append(test)
+ test.html(name)
+ width = test.width()
+ test.remove()
+ return width
- fitName: (name) ->
- width = @getNameWidth(name)
- if width < @maxNameWidth
- return name
- path = (x.replace /^\s+|\s+$/g, "" for x in name.split("/"))
- while path.length > 1
- path.shift()
- partialName = "... / " + path.join(" / ")
- if @getNameWidth(partialName) < @maxNameWidth
- return partialName
+ fitName: (name) ->
+ width = @getNameWidth(name)
+ if width < @maxNameWidth
+ return name
+ path = (x.replace /^\s+|\s+$/g, "" for x in name.split("/"))
+ while path.length > 1
+ path.shift()
+ partialName = "... / " + path.join(" / ")
+ if @getNameWidth(partialName) < @maxNameWidth
+ return partialName
- rawName = path[0]
+ rawName = path[0]
- name = "... / " + rawName
+ name = "... / " + rawName
- while @getNameWidth(name) > @maxNameWidth
- rawName = rawName[0...rawName.length-1]
- name = "... / " + rawName + " ..."
+ while @getNameWidth(name) > @maxNameWidth
+ rawName = rawName[0...rawName.length-1]
+ name = "... / " + rawName + " ..."
- return name
+ return name
- createPost: (event) ->
- event.preventDefault()
- title = @$(".new-post-title").val()
- body = @$(".new-post-body").find(".wmd-input").val()
- tags = @$(".new-post-tags").val()
+ createPost: (event) ->
+ event.preventDefault()
+ title = @$(".new-post-title").val()
+ body = @$(".new-post-body").find(".wmd-input").val()
+ tags = @$(".new-post-tags").val()
- anonymous = false || @$("input.discussion-anonymous").is(":checked")
- follow = false || @$("input.discussion-follow").is(":checked")
+ anonymous = false || @$("input.discussion-anonymous").is(":checked")
+ follow = false || @$("input.discussion-follow").is(":checked")
- $formTopicDropBtn.bind('click', showFormTopicDrop)
- $formTopicDropMenu.bind('click', setFormTopic)
+ $formTopicDropBtn.bind('click', showFormTopicDrop)
+ $formTopicDropMenu.bind('click', setFormTopic)
- url = DiscussionUtil.urlFor('create_thread', @topicId)
+ url = DiscussionUtil.urlFor('create_thread', @topicId)
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- $loading: $(event.target) if event
- url: url
- type: "POST"
- dataType: 'json'
- async: false # TODO when the rest of the stuff below is made to work properly..
- data:
- title: title
- body: body
- tags: tags
- anonymous: anonymous
- auto_subscribe: follow
- error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
- success: (response, textStatus) =>
- # TODO: Move this out of the callback, this makes it feel sluggish
- thread = new Thread response['content']
- DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
- @$el.hide()
- @$(".new-post-title").val("").attr("prev-text", "")
- @$(".new-post-body textarea").val("").attr("prev-text", "")
- @$(".new-post-tags").val("")
- @$(".new-post-tags").importTags("")
- @collection.add thread
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ $loading: $(event.target) if event
+ url: url
+ type: "POST"
+ dataType: 'json'
+ async: false # TODO when the rest of the stuff below is made to work properly..
+ data:
+ title: title
+ body: body
+ tags: tags
+ anonymous: anonymous
+ auto_subscribe: follow
+ error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
+ success: (response, textStatus) =>
+ # TODO: Move this out of the callback, this makes it feel sluggish
+ thread = new Thread response['content']
+ DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
+ @$el.hide()
+ @$(".new-post-title").val("").attr("prev-text", "")
+ @$(".new-post-body textarea").val("").attr("prev-text", "")
+ @$(".new-post-tags").val("")
+ @$(".new-post-tags").importTags("")
+ @collection.add thread
- setActiveItem: (event) ->
- if event.which == 13
- $(".topic_menu_wrapper .focused").click()
- return
- if event.which != 40 && event.which != 38
- return
- event.preventDefault()
+ setActiveItem: (event) ->
+ if event.which == 13
+ $(".topic_menu_wrapper .focused").click()
+ return
+ if event.which != 40 && event.which != 38
+ return
+ event.preventDefault()
- items = $.makeArray($(".topic_menu_wrapper a").not(".hidden"))
- index = items.indexOf($('.topic_menu_wrapper .focused')[0])
+ items = $.makeArray($(".topic_menu_wrapper a").not(".hidden"))
+ index = items.indexOf($('.topic_menu_wrapper .focused')[0])
- if event.which == 40
- index = Math.min(index + 1, items.length - 1)
- if event.which == 38
- index = Math.max(index - 1, 0)
+ if event.which == 40
+ index = Math.min(index + 1, items.length - 1)
+ if event.which == 38
+ index = Math.max(index - 1, 0)
- $(".topic_menu_wrapper .focused").removeClass("focused")
- $(items[index]).addClass("focused")
+ $(".topic_menu_wrapper .focused").removeClass("focused")
+ $(items[index]).addClass("focused")
- itemTop = $(items[index]).parent().offset().top
- scrollTop = $(".topic_menu").scrollTop()
- itemFromTop = $(".topic_menu").offset().top - itemTop
- scrollTarget = Math.min(scrollTop - itemFromTop, scrollTop)
- scrollTarget = Math.max(scrollTop - itemFromTop - $(".topic_menu").height() + $(items[index]).height() + 20, scrollTarget)
- $(".topic_menu").scrollTop(scrollTarget)
+ itemTop = $(items[index]).parent().offset().top
+ scrollTop = $(".topic_menu").scrollTop()
+ itemFromTop = $(".topic_menu").offset().top - itemTop
+ scrollTarget = Math.min(scrollTop - itemFromTop, scrollTop)
+ scrollTarget = Math.max(scrollTop - itemFromTop - $(".topic_menu").height() + $(items[index]).height() + 20, scrollTarget)
+ $(".topic_menu").scrollTop(scrollTarget)
diff --git a/lms/static/coffee/src/discussion/views/response_comment_view.coffee b/lms/static/coffee/src/discussion/views/response_comment_view.coffee
index 262617eb84..5fff33e6bb 100644
--- a/lms/static/coffee/src/discussion/views/response_comment_view.coffee
+++ b/lms/static/coffee/src/discussion/views/response_comment_view.coffee
@@ -1,23 +1,24 @@
-class @ResponseCommentView extends DiscussionContentView
- tagName: "li"
- template: _.template($("#response-comment-template").html())
- initLocal: ->
- # TODO .response-local is the parent of the comments so @$local is null, not sure what was intended here...
- @$local = @$el.find(".response-local")
- @$delegateElement = @$local
+if Backbone?
+ class @ResponseCommentView extends DiscussionContentView
+ tagName: "li"
+ template: _.template($("#response-comment-template").html())
+ initLocal: ->
+ # TODO .response-local is the parent of the comments so @$local is null, not sure what was intended here...
+ @$local = @$el.find(".response-local")
+ @$delegateElement = @$local
- render: ->
- @$el.html(@template(@model.toJSON()))
- @initLocal()
- @delegateEvents()
- @renderAttrs()
- @$el.find(".timeago").timeago()
- @convertMath()
- @
- convertMath: ->
- body = @$el.find(".response-body")
- body.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight body.html()
- # This removes paragraphs so that comments are more compact
- body.children("p").each (index, elem) ->
- $(elem).replaceWith($(elem).html())
- MathJax.Hub.Queue ["Typeset", MathJax.Hub, body[0]]
+ render: ->
+ @$el.html(@template(@model.toJSON()))
+ @initLocal()
+ @delegateEvents()
+ @renderAttrs()
+ @$el.find(".timeago").timeago()
+ @convertMath()
+ @
+ convertMath: ->
+ body = @$el.find(".response-body")
+ body.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight body.html()
+ # This removes paragraphs so that comments are more compact
+ body.children("p").each (index, elem) ->
+ $(elem).replaceWith($(elem).html())
+ MathJax.Hub.Queue ["Typeset", MathJax.Hub, body[0]]
diff --git a/lms/static/coffee/src/discussion/views/thread_response_view.coffee b/lms/static/coffee/src/discussion/views/thread_response_view.coffee
index 86deb82e6d..dac30401d8 100644
--- a/lms/static/coffee/src/discussion/views/thread_response_view.coffee
+++ b/lms/static/coffee/src/discussion/views/thread_response_view.coffee
@@ -1,117 +1,118 @@
-class @ThreadResponseView extends DiscussionContentView
- tagName: "li"
- template: _.template($("#thread-response-template").html())
+if Backbone?
+ class @ThreadResponseView extends DiscussionContentView
+ tagName: "li"
+ template: _.template($("#thread-response-template").html())
- events:
- "click .vote-btn": "toggleVote"
- "submit .comment-form": "submitComment"
- "click .action-endorse": "toggleEndorse"
- "click .action-delete": "delete"
+ events:
+ "click .vote-btn": "toggleVote"
+ "submit .comment-form": "submitComment"
+ "click .action-endorse": "toggleEndorse"
+ "click .action-delete": "delete"
- render: ->
- @$el.html(@template(@model.toJSON()))
- @initLocal()
- @delegateEvents()
- if window.user.voted(@model)
- @$(".vote-btn").addClass("is-cast")
- @renderAttrs()
- @$el.find(".posted-details").timeago()
- @convertMath()
- @renderComments()
- @
+ render: ->
+ @$el.html(@template(@model.toJSON()))
+ @initLocal()
+ @delegateEvents()
+ if window.user.voted(@model)
+ @$(".vote-btn").addClass("is-cast")
+ @renderAttrs()
+ @$el.find(".posted-details").timeago()
+ @convertMath()
+ @renderComments()
+ @
- convertMath: ->
- element = @$(".response-body")
- element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html()
- MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]]
+ convertMath: ->
+ element = @$(".response-body")
+ element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html()
+ MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]]
- renderComments: ->
- @model.get("comments").each @renderComment
+ renderComments: ->
+ @model.get("comments").each @renderComment
- renderComment: (comment) =>
- comment.set('thread', @model.get('thread'))
- view = new ResponseCommentView(model: comment)
- view.render()
- @$el.find(".comments li:last").before(view.el)
+ renderComment: (comment) =>
+ comment.set('thread', @model.get('thread'))
+ view = new ResponseCommentView(model: comment)
+ view.render()
+ @$el.find(".comments li:last").before(view.el)
- toggleVote: (event) ->
- event.preventDefault()
- @$(".vote-btn").toggleClass("is-cast")
- if @$(".vote-btn").hasClass("is-cast")
- @vote()
- else
- @unvote()
+ toggleVote: (event) ->
+ event.preventDefault()
+ @$(".vote-btn").toggleClass("is-cast")
+ if @$(".vote-btn").hasClass("is-cast")
+ @vote()
+ else
+ @unvote()
- vote: ->
- url = @model.urlFor("upvote")
- @$(".votes-count-number").html(parseInt(@$(".votes-count-number").html()) + 1)
- DiscussionUtil.safeAjax
- $elem: @$(".discussion-vote")
- url: url
- type: "POST"
- success: (response, textStatus) =>
- if textStatus == 'success'
- @model.set(response)
+ vote: ->
+ url = @model.urlFor("upvote")
+ @$(".votes-count-number").html(parseInt(@$(".votes-count-number").html()) + 1)
+ DiscussionUtil.safeAjax
+ $elem: @$(".discussion-vote")
+ url: url
+ type: "POST"
+ success: (response, textStatus) =>
+ if textStatus == 'success'
+ @model.set(response)
- unvote: ->
- url = @model.urlFor("unvote")
- @$(".votes-count-number").html(parseInt(@$(".votes-count-number").html()) - 1)
- DiscussionUtil.safeAjax
- $elem: @$(".discussion-vote")
- url: url
- type: "POST"
- success: (response, textStatus) =>
- if textStatus == 'success'
- @model.set(response)
+ unvote: ->
+ url = @model.urlFor("unvote")
+ @$(".votes-count-number").html(parseInt(@$(".votes-count-number").html()) - 1)
+ DiscussionUtil.safeAjax
+ $elem: @$(".discussion-vote")
+ url: url
+ type: "POST"
+ success: (response, textStatus) =>
+ if textStatus == 'success'
+ @model.set(response)
- submitComment: (event) ->
- event.preventDefault()
- url = @model.urlFor('reply')
- body = @$(".comment-form-input").val()
- if not body.trim().length
- return
- comment = new Comment(body: body, created_at: (new Date()).toISOString(), username: window.user.get("username"), user_id: window.user.get("id"))
- @renderComment(comment)
- @trigger "comment:add", comment
- @$(".comment-form-input").val("")
+ submitComment: (event) ->
+ event.preventDefault()
+ url = @model.urlFor('reply')
+ body = @$(".comment-form-input").val()
+ if not body.trim().length
+ return
+ comment = new Comment(body: body, created_at: (new Date()).toISOString(), username: window.user.get("username"), user_id: window.user.get("id"))
+ @renderComment(comment)
+ @trigger "comment:add", comment
+ @$(".comment-form-input").val("")
- DiscussionUtil.safeAjax
- $elem: $(event.target)
- url: url
- type: "POST"
- dataType: 'json'
- data:
- body: body
+ DiscussionUtil.safeAjax
+ $elem: $(event.target)
+ url: url
+ type: "POST"
+ dataType: 'json'
+ data:
+ body: body
- delete: (event) ->
- event.preventDefault()
- if not @model.can('can_delete')
- return
- console.log $(event.target)
- url = @model.urlFor('delete')
- if not confirm "Are you sure to delete this response? "
- return
- @model.remove()
- @$el.remove()
- $elem = $(event.target)
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- type: "POST"
- success: (response, textStatus) =>
+ delete: (event) ->
+ event.preventDefault()
+ if not @model.can('can_delete')
+ return
+ console.log $(event.target)
+ url = @model.urlFor('delete')
+ if not confirm "Are you sure to delete this response? "
+ return
+ @model.remove()
+ @$el.remove()
+ $elem = $(event.target)
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ type: "POST"
+ success: (response, textStatus) =>
- toggleEndorse: (event) ->
- event.preventDefault()
- if not @model.can('can_endorse')
- return
- $elem = $(event.target)
- url = @model.urlFor('endorse')
- endorsed = @model.get('endorsed')
- data = { endorsed: not endorsed }
- @model.set('endorsed', not endorsed)
- @trigger "comment:endorse", not endorsed
- DiscussionUtil.safeAjax
- $elem: $elem
- url: url
- data: data
- type: "POST"
+ toggleEndorse: (event) ->
+ event.preventDefault()
+ if not @model.can('can_endorse')
+ return
+ $elem = $(event.target)
+ url = @model.urlFor('endorse')
+ endorsed = @model.get('endorsed')
+ data = { endorsed: not endorsed }
+ @model.set('endorsed', not endorsed)
+ @trigger "comment:endorse", not endorsed
+ DiscussionUtil.safeAjax
+ $elem: $elem
+ url: url
+ data: data
+ type: "POST"