Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
a7014aef
Commit
a7014aef
authored
Sep 10, 2012
by
Matthew Mongeau
Committed by
Ibrahim Awwal
Sep 10, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add backbone checks.
parent
1bd52684
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1082 additions
and
1074 deletions
+1082
-1074
lms/static/coffee/src/discussion/discussion_router.coffee
+39
-38
lms/static/coffee/src/discussion/main.coffee
+17
-16
lms/static/coffee/src/discussion/models/discussion_user.coffee
+12
-11
lms/static/coffee/src/discussion/user_profile.coffee
+29
-28
lms/static/coffee/src/discussion/views/discussion_content_view.coffee
+89
-88
lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee
+213
-212
lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
+243
-246
lms/static/coffee/src/discussion/views/discussion_thread_view.coffee
+79
-78
lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee
+56
-55
lms/static/coffee/src/discussion/views/new_post_view.coffee
+176
-175
lms/static/coffee/src/discussion/views/response_comment_view.coffee
+23
-22
lms/static/coffee/src/discussion/views/thread_response_view.coffee
+106
-105
No files found.
lms/static/coffee/src/discussion/discussion_router.coffee
View file @
a7014aef
class
@
DiscussionRouter
extends
Backbone
.
Router
if
Backbone
?
routes
:
class
@
DiscussionRouter
extends
Backbone
.
Router
""
:
"allThreads"
routes
:
":forum_name/threads/:thread_id"
:
"showThread"
""
:
"allThreads"
":forum_name/threads/:thread_id"
:
"showThread"
initialize
:
(
options
)
->
@
discussion
=
options
[
'discussion'
]
initialize
:
(
options
)
->
@
nav
=
new
DiscussionThreadListView
(
collection
:
@
discussion
,
el
:
$
(
".sidebar"
))
@
discussion
=
options
[
'discussion'
]
@
nav
.
on
"thread:selected"
,
@
navigateToThread
@
nav
=
new
DiscussionThreadListView
(
collection
:
@
discussion
,
el
:
$
(
".sidebar"
))
@
nav
.
on
"thread:removed"
,
@
navigateToAllThreads
@
nav
.
on
"thread:selected"
,
@
navigateToThread
@
nav
.
on
"threads:rendered"
,
@
setActiveThread
@
nav
.
on
"thread:removed"
,
@
navigateToAllThreads
@
nav
.
render
()
@
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
()
allThreads
:
->
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"
,
=>
@
nav
.
updateSidebar
()
@
nav
.
updateSidebar
()
navigateToThread
:
(
thread_id
)
=>
setActiveThread
:
=>
thread
=
@
discussion
.
get
(
thread_id
)
if
@
thread
@
navigate
(
"
#{
thread
.
get
(
"commentable_id"
)
}
/threads/
#{
thread_id
}
"
,
trigger
:
true
)
@
nav
.
setActiveThread
(
@
thread
.
get
(
"id"
)
)
navigateToAllThreads
:
=>
showThread
:
(
forum_name
,
thread_id
)
->
console
.
log
"navigating"
@
thread
=
@
discussion
.
get
(
thread_id
)
@
navigate
(
""
,
trigger
:
true
)
@
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
)
lms/static/coffee/src/discussion/main.coffee
View file @
a7014aef
DiscussionApp
=
if
Backbone
?
start
:
(
elem
)
->
DiscussionApp
=
# TODO: Perhaps eliminate usage of global variables when possible
start
:
(
elem
)
->
element
=
$
(
elem
)
# TODO: Perhaps eliminate usage of global variables when possible
window
.
$
$course_id
=
element
.
data
(
"course-id"
)
element
=
$
(
elem
)
user_info
=
element
.
data
(
"user-info"
)
window
.
$
$course_id
=
element
.
data
(
"course-id"
)
threads
=
element
.
data
(
"threads"
)
user_info
=
element
.
data
(
"user-info"
)
content_info
=
element
.
data
(
"content-info"
)
threads
=
element
.
data
(
"threads"
)
window
.
user
=
new
DiscussionUser
(
user_info
)
content_info
=
element
.
data
(
"content-info"
)
Content
.
loadContentInfos
(
content_info
)
window
.
user
=
new
DiscussionUser
(
user_info
)
discussion
=
new
Discussion
(
threads
)
Content
.
loadContentInfos
(
content_info
)
new
DiscussionRouter
({
discussion
:
discussion
})
discussion
=
new
Discussion
(
threads
)
Backbone
.
history
.
start
({
pushState
:
true
,
root
:
"/courses/
#{
$$course_id
}
/discussion/forum/"
})
new
DiscussionRouter
({
discussion
:
discussion
})
Backbone
.
history
.
start
({
pushState
:
true
,
root
:
"/courses/
#{
$$course_id
}
/discussion/forum/"
})
$
->
$
->
$
(
"section.discussion"
).
each
(
index
,
elem
)
->
$
(
"section.discussion"
).
each
(
index
,
elem
)
->
DiscussionApp
.
start
(
elem
)
DiscussionApp
.
start
(
elem
)
lms/static/coffee/src/discussion/models/discussion_user.coffee
View file @
a7014aef
class
@
DiscussionUser
extends
Backbone
.
Model
if
Backbone
?
following
:
(
thread
)
->
class
@
DiscussionUser
extends
Backbone
.
Model
_
.
include
(
@
get
(
'subscribed_thread_ids'
),
thread
.
id
)
following
:
(
thread
)
->
_
.
include
(
@
get
(
'subscribed_thread_ids'
),
thread
.
id
)
voted
:
(
thread
)
->
voted
:
(
thread
)
->
_
.
include
(
@
get
(
'upvoted_ids'
),
thread
.
id
)
_
.
include
(
@
get
(
'upvoted_ids'
),
thread
.
id
)
vote
:
(
thread
)
->
vote
:
(
thread
)
->
@
get
(
'upvoted_ids'
).
push
(
thread
.
id
)
@
get
(
'upvoted_ids'
).
push
(
thread
.
id
)
thread
.
vote
()
thread
.
vote
()
unvote
:
(
thread
)
->
unvote
:
(
thread
)
->
@
set
(
'upvoted_ids'
,
_
.
without
(
@
get
(
'upvoted_ids'
),
thread
.
id
))
@
set
(
'upvoted_ids'
,
_
.
without
(
@
get
(
'upvoted_ids'
),
thread
.
id
))
thread
.
unvote
()
thread
.
unvote
()
lms/static/coffee/src/discussion/user_profile.coffee
View file @
a7014aef
class
@
DiscussionUserProfileView
extends
Backbone
.
View
if
Backbone
?
toggleModeratorStatus
:
(
event
)
->
class
@
DiscussionUserProfileView
extends
Backbone
.
View
confirmValue
=
confirm
(
"Are you sure?"
)
toggleModeratorStatus
:
(
event
)
->
if
not
confirmValue
then
return
confirmValue
=
confirm
(
"Are you sure?"
)
$elem
=
$
(
event
.
target
)
if
not
confirmValue
then
return
if
$elem
.
hasClass
(
"sidebar-promote-moderator-button"
)
$elem
=
$
(
event
.
target
)
isModerator
=
true
if
$elem
.
hasClass
(
"sidebar-promote-moderator-button"
)
else
if
$elem
.
hasClass
(
"sidebar-revoke-moderator-button"
)
isModerator
=
true
isModerator
=
false
else
if
$elem
.
hasClass
(
"sidebar-revoke-moderator-button"
)
else
isModerator
=
false
console
.
error
"unrecognized moderator status"
else
return
console
.
error
"unrecognized moderator status"
url
=
DiscussionUtil
.
urlFor
(
'update_moderator_status'
,
$$profiled_user_id
)
return
DiscussionUtil
.
safeAjax
url
=
DiscussionUtil
.
urlFor
(
'update_moderator_status'
,
$$profiled_user_id
)
$elem
:
$elem
DiscussionUtil
.
safeAjax
url
:
url
$elem
:
$elem
type
:
"POST"
url
:
url
dataType
:
'json'
type
:
"POST"
data
:
dataType
:
'json'
is_moderator
:
isModerator
data
:
error
:
(
response
,
textStatus
,
e
)
->
is_moderator
:
isModerator
console
.
log
e
error
:
(
response
,
textStatus
,
e
)
->
success
:
(
response
,
textStatus
)
=>
console
.
log
e
parent
=
@
$el
.
parent
()
success
:
(
response
,
textStatus
)
=>
@
$el
.
replaceWith
(
response
.
html
)
parent
=
@
$el
.
parent
()
view
=
new
DiscussionUserProfileView
el
:
parent
.
children
(
".user-profile"
)
@
$el
.
replaceWith
(
response
.
html
)
view
=
new
DiscussionUserProfileView
el
:
parent
.
children
(
".user-profile"
)
events
:
events
:
"click .sidebar-toggle-moderator-button"
:
"toggleModeratorStatus"
"click .sidebar-toggle-moderator-button"
:
"toggleModeratorStatus"
lms/static/coffee/src/discussion/views/discussion_content_view.coffee
View file @
a7014aef
class
@
DiscussionContentView
extends
Backbone
.
View
if
Backbone
?
class
@
DiscussionContentView
extends
Backbone
.
View
attrRenderer
:
endorsed
:
(
endorsed
)
->
attrRenderer
:
if
endorsed
endorsed
:
(
endorsed
)
->
@
$
(
".action-endorse"
).
addClass
(
"is-endorsed"
)
if
endorsed
else
@
$
(
".action-endorse"
).
addClass
(
"is-endorsed"
)
@
$
(
".action-endorse"
).
removeClass
(
"is-endorsed"
)
else
@
$
(
".action-endorse"
).
removeClass
(
"is-endorsed"
)
closed
:
(
closed
)
->
return
if
not
@
$
(
".action-openclose"
).
length
closed
:
(
closed
)
->
return
if
not
@
$
(
".post-status-closed"
).
length
return
if
not
@
$
(
".action-openclose"
).
length
if
closed
return
if
not
@
$
(
".post-status-closed"
).
length
@
$
(
".post-status-closed"
).
show
()
if
closed
@
$
(
".action-openclose"
).
html
(
@
$
(
".action-openclose"
).
html
().
replace
(
"Close"
,
"Open"
))
@
$
(
".post-status-closed"
).
show
()
@
$
(
".discussion-reply-new"
).
hide
()
@
$
(
".action-openclose"
).
html
(
@
$
(
".action-openclose"
).
html
().
replace
(
"Close"
,
"Open"
))
else
@
$
(
".discussion-reply-new"
).
hide
()
@
$
(
".post-status-closed"
).
hide
()
else
@
$
(
".action-openclose"
).
html
(
@
$
(
".action-openclose"
).
html
().
replace
(
"Open"
,
"Close"
))
@
$
(
".post-status-closed"
).
hide
()
@
$
(
".discussion-reply-new"
).
show
()
@
$
(
".action-openclose"
).
html
(
@
$
(
".action-openclose"
).
html
().
replace
(
"Open"
,
"Close"
))
@
$
(
".discussion-reply-new"
).
show
()
voted
:
(
voted
)
->
voted
:
(
voted
)
->
votes_point
:
(
votes_point
)
->
votes_point
:
(
votes_point
)
->
comments_count
:
(
comments_count
)
->
comments_count
:
(
comments_count
)
->
subscribed
:
(
subscribed
)
->
if
subscribed
subscribed
:
(
subscribed
)
->
@
$
(
".dogear"
).
addClass
(
"is-followed"
)
if
subscribed
else
@
$
(
".dogear"
).
addClass
(
"is-followed"
)
@
$
(
".dogear"
).
removeClass
(
"is-followed"
)
ability
:
(
ability
)
->
for
action
,
selector
of
@
abilityRenderer
if
not
ability
[
action
]
selector
.
disable
.
apply
(
@
)
else
else
selector
.
enable
.
apply
(
@
)
@
$
(
".dogear"
).
removeClass
(
"is-followed"
)
abilityRenderer
:
ability
:
(
ability
)
->
editable
:
for
action
,
selector
of
@
abilityRenderer
enable
:
->
@
$
(
".action-edit"
).
closest
(
"li"
).
show
()
if
not
ability
[
action
]
disable
:
->
@
$
(
".action-edit"
).
closest
(
"li"
).
hide
()
selector
.
disable
.
apply
(
@
)
can_delete
:
else
enable
:
->
@
$
(
".action-delete"
).
closest
(
"li"
).
show
()
selector
.
enable
.
apply
(
@
)
disable
:
->
@
$
(
".action-delete"
).
closest
(
"li"
).
hide
()
can_endorse
:
abilityRenderer
:
enable
:
->
@
$
(
".action-endorse"
).
css
(
"cursor"
,
"auto"
)
editable
:
disable
:
->
@
$
(
".action-endorse"
).
css
(
"cursor"
,
"default"
)
enable
:
->
@
$
(
".action-edit"
).
closest
(
"li"
).
show
()
can_openclose
:
disable
:
->
@
$
(
".action-edit"
).
closest
(
"li"
).
hide
()
enable
:
->
@
$
(
".action-openclose"
).
closest
(
"li"
).
show
()
can_delete
:
disable
:
->
@
$
(
".action-openclose"
).
closest
(
"li"
).
hide
()
enable
:
->
@
$
(
".action-delete"
).
closest
(
"li"
).
show
()
disable
:
->
@
$
(
".action-delete"
).
closest
(
"li"
).
hide
()
renderPartialAttrs
:
->
can_endorse
:
for
attr
,
value
of
@
model
.
changedAttributes
()
enable
:
->
@
$
(
".action-endorse"
).
css
(
"cursor"
,
"auto"
)
if
@
attrRenderer
[
attr
]
disable
:
->
@
$
(
".action-endorse"
).
css
(
"cursor"
,
"default"
)
@
attrRenderer
[
attr
].
apply
(
@
,
[
value
])
can_openclose
:
enable
:
->
@
$
(
".action-openclose"
).
closest
(
"li"
).
show
()
renderAttrs
:
->
disable
:
->
@
$
(
".action-openclose"
).
closest
(
"li"
).
hide
()
for
attr
,
value
of
@
model
.
attributes
if
@
attrRenderer
[
attr
]
renderPartialAttrs
:
->
@
attrRenderer
[
attr
].
apply
(
@
,
[
value
])
for
attr
,
value
of
@
model
.
changedAttributes
()
if
@
attrRenderer
[
attr
]
$
:
(
selector
)
->
@
attrRenderer
[
attr
].
apply
(
@
,
[
value
])
@
$local
.
find
(
selector
)
renderAttrs
:
->
initLocal
:
->
for
attr
,
value
of
@
model
.
attributes
@
$local
=
@
$el
.
children
(
".local"
)
if
@
attrRenderer
[
attr
]
if
not
@
$local
.
length
@
attrRenderer
[
attr
].
apply
(
@
,
[
value
])
@
$local
=
@
$el
@
$delegateElement
=
@
$local
$
:
(
selector
)
->
@
$local
.
find
(
selector
)
makeWmdEditor
:
(
cls_identifier
)
=>
if
not
@
$el
.
find
(
".wmd-panel"
).
length
initLocal
:
->
DiscussionUtil
.
makeWmdEditor
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
@
$local
=
@
$el
.
children
(
".local"
)
if
not
@
$local
.
length
getWmdEditor
:
(
cls_identifier
)
=>
@
$local
=
@
$el
DiscussionUtil
.
getWmdEditor
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
@
$delegateElement
=
@
$local
getWmdContent
:
(
cls_identifier
)
=>
makeWmdEditor
:
(
cls_identifier
)
=>
DiscussionUtil
.
getWmdContent
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
if
not
@
$el
.
find
(
".wmd-panel"
).
length
DiscussionUtil
.
makeWmdEditor
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
setWmdContent
:
(
cls_identifier
,
text
)
=>
DiscussionUtil
.
setWmdContent
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
,
text
getWmdEditor
:
(
cls_identifier
)
=>
DiscussionUtil
.
getWmdEditor
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
initialize
:
->
@
initLocal
()
getWmdContent
:
(
cls_identifier
)
=>
@
model
.
bind
(
'change'
,
@
renderPartialAttrs
,
@
)
DiscussionUtil
.
getWmdContent
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
setWmdContent
:
(
cls_identifier
,
text
)
=>
DiscussionUtil
.
setWmdContent
@
$el
,
$
.
proxy
(
@
$
,
@
),
cls_identifier
,
text
initialize
:
->
@
initLocal
()
@
model
.
bind
(
'change'
,
@
renderPartialAttrs
,
@
)
lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee
View file @
a7014aef
class
@
DiscussionThreadInlineView
extends
DiscussionContentView
if
Backbone
?
expanded
=
false
class
@
DiscussionThreadInlineView
extends
DiscussionContentView
events
:
expanded
=
false
"click .discussion-vote"
:
"toggleVote"
events
:
"click .action-follow"
:
"toggleFollowing"
"click .discussion-vote"
:
"toggleVote"
"click .discussion-submit-post"
:
"submitComment"
"click .action-follow"
:
"toggleFollowing"
"click .action-edit"
:
"edit"
"click .discussion-submit-post"
:
"submitComment"
"click .action-delete"
:
"delete"
"click .action-edit"
:
"edit"
"click .action-openclose"
:
"toggleClosed"
"click .action-delete"
:
"delete"
"click .expand-post"
:
"expandPost"
"click .action-openclose"
:
"toggleClosed"
"click .collapse-post"
:
"collapsePost"
"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"
)
initLocal
:
->
@
$delegateElement
=
@
$local
@
$local
=
@
$el
.
children
(
".discussion-article"
).
children
(
".local"
)
@
$delegateElement
=
@
$local
initialize
:
->
super
()
initialize
:
->
@
model
.
on
"change"
,
@
updateModelDetails
super
()
@
model
.
on
"change"
,
@
updateModelDetails
render
:
->
if
not
@
model
.
has
(
'abbreviatedBody'
)
render
:
->
@
abbreviateBody
()
if
not
@
model
.
has
(
'abbreviatedBody'
)
@
$el
.
html
(
Mustache
.
render
(
@
template
(),
$
.
extend
(
@
model
.
toJSON
(),{
expanded
:
@
expanded
})
))
@
abbreviateBody
()
@
initLocal
()
@
$el
.
html
(
Mustache
.
render
(
@
template
(),
$
.
extend
(
@
model
.
toJSON
(),{
expanded
:
@
expanded
})
))
@
delegateEvents
()
@
initLocal
()
@
renderDogear
()
@
delegateEvents
()
@
renderVoted
()
@
renderDogear
()
@
renderAttrs
()
@
renderVoted
()
@
$
(
"span.timeago"
).
timeago
()
@
renderAttrs
()
@
convertMath
()
@
$
(
"span.timeago"
).
timeago
()
if
@
expanded
@
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"
@
makeWmdEditor
"reply-body"
@
renderResponses
()
if
@
$el
.
find
(
'.loading'
).
length
@
@
renderResponses
()
renderDogear
:
->
collapsePost
:
(
event
)
->
if
window
.
user
.
following
(
@
model
)
@
expanded
=
false
@
$
(
".dogear"
).
addClass
(
"is-followed"
)
@
$el
.
removeClass
(
'expanded'
)
@
$el
.
find
(
'.post-body'
).
html
(
@
model
.
get
(
'abbreviatedBody'
))
renderVoted
:
=>
@
convertMath
()
if
window
.
user
.
voted
(
@
model
)
@
$el
.
find
(
'.collapse-post'
).
css
(
'display'
,
'none'
)
@
$
(
"[data-role=discussion-vote]"
).
addClass
(
"is-cast"
)
@
$el
.
find
(
'.post-extended-content'
).
hide
()
else
@
$el
.
find
(
'.expand-post'
).
css
(
'display'
,
'block'
)
@
$
(
"[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'
)
lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
View file @
a7014aef
class
@
DiscussionThreadListView
extends
Backbone
.
View
if
Backbone
?
template
:
_
.
template
(
$
(
"#thread-list-template"
).
html
())
class
@
DiscussionThreadListView
extends
Backbone
.
View
events
:
template
:
_
.
template
(
$
(
"#thread-list-template"
).
html
())
"click .search"
:
"showSearch"
events
:
"click .browse"
:
"toggleTopicDrop"
"click .search"
:
"showSearch"
"keydown .post-search-field"
:
"performSearch"
"click .browse"
:
"toggleTopicDrop"
"click .sort-bar a"
:
"sortThreads"
"keydown .post-search-field"
:
"performSearch"
"click .browse-topic-drop-menu"
:
"filterTopic"
"click .sort-bar a"
:
"sortThreads"
"click .browse-topic-drop-search-input"
:
"ignoreClick"
"click .browse-topic-drop-menu"
:
"filterTopic"
"click .post-list a"
:
"threadSelected"
"click .browse-topic-drop-search-input"
:
"ignoreClick"
"click .post-list a"
:
"threadSelected"
initialize
:
->
@
displayedCollection
=
new
Discussion
(
@
collection
.
models
)
initialize
:
->
@
collection
.
on
"change"
,
@
reloadDisplayedCollection
@
displayedCollection
=
new
Discussion
(
@
collection
.
models
)
@
collection
.
on
"add"
,
@
addAndSelectThread
@
collection
.
on
"change"
,
@
reloadDisplayedCollection
@
sidebar_padding
=
10
@
collection
.
on
"add"
,
@
addAndSelectThread
@
sidebar_header_height
=
87
@
sidebar_padding
=
10
@
boardName
@
sidebar_header_height
=
87
@
boardName
reloadDisplayedCollection
:
(
thread
)
=>
thread_id
=
thread
.
get
(
'id'
)
reloadDisplayedCollection
:
(
thread
)
=>
content
=
@
renderThread
(
thread
)
thread_id
=
thread
.
get
(
'id'
)
current_el
=
@
$
(
"a[data-id=
#{
thread_id
}
]"
)
content
=
@
renderThread
(
thread
)
active
=
current_el
.
hasClass
(
"active"
)
current_el
=
@
$
(
"a[data-id=
#{
thread_id
}
]"
)
current_el
.
replaceWith
(
content
)
active
=
current_el
.
hasClass
(
"active"
)
if
active
current_el
.
replaceWith
(
content
)
@
setActiveThread
(
thread_id
)
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
(
"<li data-id='
#{
thread
.
get
(
'id'
)
}
' />"
)
content
.
click
()
addAndSelectThread
:
(
thread
)
=>
updateSidebar
:
=>
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
(
"<li data-id='
#{
thread
.
get
(
'id'
)
}
' />"
)
content
.
click
()
updateSidebar
:
=>
scrollTop
=
$
(
window
).
scrollTop
();
windowHeight
=
$
(
window
).
height
();
scrollTop
=
$
(
window
).
scrollTop
();
discussionBody
=
$
(
".discussion-article"
)
windowHeight
=
$
(
window
).
height
();
discussionsBodyTop
=
if
discussionBody
[
0
]
then
discussionBody
.
offset
().
top
discussionsBodyBottom
=
discussionsBodyTop
+
discussionBody
.
outerHeight
()
discussionBody
=
$
(
".discussion-article"
)
sidebar
=
$
(
".sidebar"
)
discussionsBodyTop
=
if
discussionBody
[
0
]
then
discussionBody
.
offset
().
top
if
scrollTop
>
discussionsBodyTop
-
@
sidebar_padding
discussionsBodyBottom
=
discussionsBodyTop
+
discussionBody
.
outerHeight
()
sidebar
.
addClass
(
'fixed'
);
sidebar
.
css
(
'top'
,
@
sidebar_padding
);
else
sidebar
.
removeClass
(
'fixed'
);
sidebar
.
css
(
'top'
,
'0'
);
sidebar
=
$
(
".sidebar"
)
sidebarWidth
=
.
31
*
$
(
".discussion-body"
).
width
();
if
scrollTop
>
discussionsBodyTop
-
@
sidebar_padding
sidebar
.
css
(
'width'
,
sidebarWidth
+
'px'
);
sidebar
.
addClass
(
'fixed'
);
sidebar
.
css
(
'top'
,
@
sidebar_padding
);
else
sidebar
.
removeClass
(
'fixed'
);
sidebar
.
css
(
'top'
,
'0'
);
sidebarWidth
=
.
31
*
$
(
".discussion-body"
).
width
();
sidebarHeight
=
windowHeight
-
Math
.
max
(
discussionsBodyTop
-
scrollTop
,
@
sidebar_padding
)
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
)
topOffset
=
scrollTop
+
windowHeigh
t
sidebarHeight
=
sidebarHeight
-
@
sidebar_padding
-
amoun
t
discussionBottomOffset
=
discussionsBodyBottom
+
@
sidebar_padding
sidebarHeight
=
Math
.
min
(
Math
.
max
(
sidebarHeight
,
400
),
discussionBody
.
outerHeight
())
amount
=
Math
.
max
(
topOffset
-
discussionBottomOffset
,
0
)
sidebar
.
css
'height'
,
sidebarHeight
sidebarHeight
=
sidebarHeight
-
@
sidebar_padding
-
amount
postListWrapper
=
@
$
(
'.post-list-wrapper'
)
sidebarHeight
=
Math
.
min
(
Math
.
max
(
sidebarHeight
,
400
),
discussionBody
.
outerHeight
())
postListWrapper
.
css
(
'height'
,
(
sidebarHeight
-
@
sidebar_header_height
-
4
)
+
'px'
)
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
()
# Because we want the behavior that when the body is clicked the menu is
render
:
->
# closed, we need to ignore clicks in the search field and stop propagation.
@
timer
=
0
# Without this, clicking the search field would also close the menu.
@
$el
.
html
(
@
template
())
ignoreClick
:
(
event
)
->
event
.
stopPropagation
()
render
:
->
$
(
window
).
bind
"scroll"
,
@
updateSidebar
@
timer
=
0
$
(
window
).
bind
"resize"
,
@
updateSidebar
@
$el
.
html
(
@
template
())
$
(
window
).
bind
"scroll"
,
@
updateSidebar
@
displayedCollection
.
on
"reset"
,
@
renderThreads
$
(
window
).
bind
"resize"
,
@
updateSidebar
@
displayedCollection
.
on
"thread:remove"
,
@
renderThreads
@
renderThreads
()
@
@
displayedCollection
.
on
"reset"
,
@
renderThreads
renderThreads
:
=>
@
displayedCollection
.
on
"thread:remove"
,
@
renderThreads
@
$
(
".post-list"
).
html
(
""
)
@
renderThreads
()
rendered
=
$
(
"<div></div>"
)
@
for
thread
in
@
displayedCollection
.
models
content
=
@
renderThread
(
thread
)
rendered
.
append
content
content
.
wrap
(
"<li data-id='
#{
thread
.
get
(
'id'
)
}
' />"
)
renderThreads
:
=>
@
$
(
".post-list"
).
html
(
rendered
.
html
())
@
$
(
".post-list"
).
html
(
""
)
@
trigger
"threads:rendered"
rendered
=
$
(
"<div></div>"
)
for
thread
in
@
displayedCollection
.
models
renderThread
:
(
thread
)
=>
content
=
@
renderThread
(
thread
)
content
=
$
(
_
.
template
(
$
(
"#thread-list-item-template"
).
html
())(
thread
.
toJSON
()))
rendered
.
append
content
if
thread
.
get
(
'subscribed'
)
content
.
wrap
(
"<li data-id='
#{
thread
.
get
(
'id'
)
}
' />"
)
content
.
addClass
(
"followed"
)
if
thread
.
get
(
'endorsed'
)
content
.
addClass
(
"resolved"
)
@
highlight
(
content
)
highlight
:
(
el
)
->
el
.
html
(
el
.
html
().
replace
(
/<mark>/g
,
"<mark>"
).
replace
(
/<\/mark>/g
,
"</mark>"
))
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
=
$
(
"<div>"
)
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
+
" ..."
@
$
(
".post-list"
).
html
(
rendered
.
html
())
@
trigger
"threads:rendered"
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
)
highlight
:
(
el
)
->
el
.
html
(
el
.
html
().
replace
(
/<mark>/g
,
"<mark>"
).
replace
(
/<\/mark>/g
,
"</mark>"
))
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
=
$
(
"<div>"
)
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
return
name
path
=
(
x
.
replace
/^\s+|\s+$/g
,
""
for
x
in
name
.
split
(
"/"
))
while
path
.
length
>
1
filterTopic
:
(
event
)
->
path
.
shift
()
@
setTopic
(
event
)
partialName
=
"... / "
+
path
.
join
(
" / "
)
item
=
$
(
event
.
target
).
closest
(
'li'
)
if
@
getNameWidth
(
partialName
)
<
@
maxNameWidth
if
item
.
find
(
"span.board-name"
).
data
(
"discussion_id"
)
==
"#all"
return
partialName
item
=
item
.
parent
()
discussionIds
=
_
.
map
item
.
find
(
".board-name[data-discussion_id]"
),
(
board
)
->
$
(
board
).
data
(
"discussion_id"
).
id
rawName
=
path
[
0
]
filtered
=
@
collection
.
filter
(
thread
)
=>
_
.
include
(
discussionIds
,
thread
.
get
(
'commentable_id'
))
name
=
"... / "
+
rawName
@
displayedCollection
.
reset
filtered
while
@
getNameWidth
(
name
)
>
@
maxNameWidth
sortThreads
:
(
event
)
->
rawName
=
rawName
[
0
...
rawName
.
length
-
1
]
@
$
(
".sort-bar a"
).
removeClass
(
"active"
)
name
=
"... / "
+
rawName
+
" ..."
$
(
event
.
target
).
addClass
(
"active"
)
sortBy
=
$
(
event
.
target
).
data
(
"sort"
)
return
name
if
sortBy
==
"date"
@
displayedCollection
.
comparator
=
@
displayedCollection
.
sortByDateRecentFirst
filterTopic
:
(
event
)
->
else
if
sortBy
==
"votes"
@
setTopic
(
event
)
@
displayedCollection
.
comparator
=
@
displayedCollection
.
sortByVotes
item
=
$
(
event
.
target
).
closest
(
'li'
)
else
if
sortBy
==
"comments"
if
item
.
find
(
"span.board-name"
).
data
(
"discussion_id"
)
==
"#all"
@
displayedCollection
.
comparator
=
@
displayedCollection
.
sortByComments
item
=
item
.
parent
()
@
displayedCollection
.
sort
()
discussionIds
=
_
.
map
item
.
find
(
".board-name[data-discussion_id]"
),
(
board
)
->
$
(
board
).
data
(
"discussion_id"
).
id
filtered
=
@
collection
.
filter
(
thread
)
=>
performSearch
:
(
event
)
->
_
.
include
(
discussionIds
,
thread
.
get
(
'commentable_id'
))
if
event
.
which
==
13
@
displayedCollection
.
reset
filtered
event
.
preventDefault
()
url
=
DiscussionUtil
.
urlFor
(
"search"
)
sortThreads
:
(
event
)
->
text
=
@
$
(
".post-search-field"
).
val
()
@
$
(
".sort-bar a"
).
removeClass
(
"active"
)
DiscussionUtil
.
safeAjax
$
(
event
.
target
).
addClass
(
"active"
)
$elem
:
@
$
(
".post-search-field"
)
sortBy
=
$
(
event
.
target
).
data
(
"sort"
)
data
:
{
text
:
text
}
if
sortBy
==
"date"
url
:
url
@
displayedCollection
.
comparator
=
@
displayedCollection
.
sortByDateRecentFirst
type
:
"GET"
else
if
sortBy
==
"votes"
success
:
(
response
,
textStatus
)
=>
@
displayedCollection
.
comparator
=
@
displayedCollection
.
sortByVotes
if
textStatus
==
'success'
else
if
sortBy
==
"comments"
@
collection
.
reset
(
response
.
discussion_data
)
@
displayedCollection
.
comparator
=
@
displayedCollection
.
sortByComments
@
displayedCollection
.
reset
(
@
collection
.
models
)
@
displayedCollection
.
sort
()
setActiveItem
:
(
event
)
->
performSearch
:
(
event
)
->
if
event
.
which
==
13
if
event
.
which
==
13
$
(
".browse-topic-drop-menu-wrapper .focused"
).
click
()
return
if
event
.
which
!=
40
&&
event
.
which
!=
38
return
event
.
preventDefault
()
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
)
lms/static/coffee/src/discussion/views/discussion_thread_view.coffee
View file @
a7014aef
class
@
DiscussionThreadView
extends
DiscussionContentView
if
Backbone
?
class
@
DiscussionThreadView
extends
DiscussionContentView
events
:
events
:
"click .discussion-submit-post"
:
"submitComment"
"click .discussion-submit-post"
:
"submitComment"
template
:
_
.
template
(
$
(
"#thread-template"
).
html
())
template
:
_
.
template
(
$
(
"#thread-template"
).
html
())
$
:
(
selector
)
->
$
:
(
selector
)
->
@
$el
.
find
(
selector
)
@
$el
.
find
(
selector
)
initialize
:
->
initialize
:
->
super
()
super
()
@
showView
=
new
DiscussionThreadShowView
(
model
:
@
model
)
@
showView
=
new
DiscussionThreadShowView
(
model
:
@
model
)
@
showView
.
bind
"thread:delete"
,
@
delete
@
showView
.
bind
"thread:delete"
,
@
delete
@
showView
.
bind
"thread:edit"
,
@
edit
@
showView
.
bind
"thread:edit"
,
@
edit
render
:
->
render
:
->
@
$el
.
html
(
@
template
(
@
model
.
toJSON
()))
@
$el
.
html
(
@
template
(
@
model
.
toJSON
()))
@
delegateEvents
()
@
delegateEvents
()
@
showView
.
setElement
(
@
$
(
'.thread-content-wrapper'
))
@
showView
.
setElement
(
@
$
(
'.thread-content-wrapper'
))
@
showView
.
render
()
@
showView
.
render
()
@
showView
.
delegateEvents
()
@
showView
.
delegateEvents
()
@
renderAttrs
()
@
renderAttrs
()
@
$
(
"span.timeago"
).
timeago
()
@
$
(
"span.timeago"
).
timeago
()
@
makeWmdEditor
"reply-body"
@
makeWmdEditor
"reply-body"
@
renderResponses
()
@
renderResponses
()
@
@
renderResponses
:
->
renderResponses
:
->
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
url
:
"/courses/
#{
$$course_id
}
/discussion/forum/
#{
@
model
.
get
(
'commentable_id'
)
}
/threads/
#{
@
model
.
id
}
"
url
:
"/courses/
#{
$$course_id
}
/discussion/forum/
#{
@
model
.
get
(
'commentable_id'
)
}
/threads/
#{
@
model
.
id
}
"
success
:
(
data
,
textStatus
,
xhr
)
=>
success
:
(
data
,
textStatus
,
xhr
)
=>
@
$el
.
find
(
".loading"
).
remove
()
@
$el
.
find
(
".loading"
).
remove
()
Content
.
loadContentInfos
(
data
[
'annotated_content_info'
])
Content
.
loadContentInfos
(
data
[
'annotated_content_info'
])
comments
=
new
Comments
(
data
[
'content'
][
'children'
])
comments
=
new
Comments
(
data
[
'content'
][
'children'
])
comments
.
each
@
renderResponse
comments
.
each
@
renderResponse
@
trigger
"thread:responses:rendered"
@
trigger
"thread:responses:rendered"
renderResponse
:
(
response
)
=>
renderResponse
:
(
response
)
=>
response
.
set
(
'thread'
,
@
model
)
response
.
set
(
'thread'
,
@
model
)
view
=
new
ThreadResponseView
(
model
:
response
)
view
=
new
ThreadResponseView
(
model
:
response
)
view
.
on
"comment:add"
,
@
addComment
view
.
on
"comment:add"
,
@
addComment
view
.
on
"comment:endorse"
,
@
endorseThread
view
.
on
"comment:endorse"
,
@
endorseThread
view
.
render
()
view
.
render
()
@
$el
.
find
(
".responses"
).
append
(
view
.
el
)
@
$el
.
find
(
".responses"
).
append
(
view
.
el
)
addComment
:
=>
addComment
:
=>
@
model
.
comment
()
@
model
.
comment
()
endorseThread
:
(
endorsed
)
=>
endorseThread
:
(
endorsed
)
=>
is_endorsed
=
@
$el
.
find
(
".is-endorsed"
).
length
is_endorsed
=
@
$el
.
find
(
".is-endorsed"
).
length
@
model
.
set
'endorsed'
,
is_endorsed
@
model
.
set
'endorsed'
,
is_endorsed
submitComment
:
(
event
)
->
submitComment
:
(
event
)
->
event
.
preventDefault
()
event
.
preventDefault
()
url
=
@
model
.
urlFor
(
'reply'
)
url
=
@
model
.
urlFor
(
'reply'
)
body
=
@
getWmdContent
(
"reply-body"
)
body
=
@
getWmdContent
(
"reply-body"
)
return
if
not
body
.
trim
().
length
return
if
not
body
.
trim
().
length
@
setWmdContent
(
"reply-body"
,
""
)
@
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
=
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'
))
comment
.
set
(
'thread'
,
@
model
.
get
(
'thread'
))
@
renderResponse
(
comment
)
@
renderResponse
(
comment
)
@
model
.
addComment
()
@
model
.
addComment
()
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
$elem
:
$
(
event
.
target
)
$elem
:
$
(
event
.
target
)
url
:
url
url
:
url
type
:
"POST"
type
:
"POST"
dataType
:
'json'
dataType
:
'json'
data
:
data
:
body
:
body
body
:
body
success
:
(
data
,
textStatus
)
=>
success
:
(
data
,
textStatus
)
=>
comment
.
updateInfo
(
data
.
annotated_content_info
)
comment
.
updateInfo
(
data
.
annotated_content_info
)
comment
.
set
(
data
.
content
)
comment
.
set
(
data
.
content
)
edit
:
->
edit
:
->
delete
:
(
event
)
->
delete
:
(
event
)
->
url
=
@
model
.
urlFor
(
'delete'
)
url
=
@
model
.
urlFor
(
'delete'
)
if
not
@
model
.
can
(
'can_delete'
)
if
not
@
model
.
can
(
'can_delete'
)
return
return
if
not
confirm
"Are you sure to delete thread
\"
#{
@
model
.
get
(
'title'
)
}
\"
?"
if
not
confirm
"Are you sure to delete thread
\"
#{
@
model
.
get
(
'title'
)
}
\"
?"
return
return
@
model
.
remove
()
@
model
.
remove
()
@
$el
.
empty
()
@
$el
.
empty
()
$elem
=
$
(
event
.
target
)
$elem
=
$
(
event
.
target
)
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
$elem
:
$elem
$elem
:
$elem
url
:
url
url
:
url
type
:
"POST"
type
:
"POST"
success
:
(
response
,
textStatus
)
=>
success
:
(
response
,
textStatus
)
=>
lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee
View file @
a7014aef
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.
# Because we want the behavior that when the body is clicked the menu is
# Without this, clicking the search field would also close the menu.
# closed, we need to ignore clicks in the search field and stop propagation.
ignoreClick
:
(
event
)
->
# Without this, clicking the search field would also close the menu.
event
.
stopPropagation
()
ignoreClick
:
(
event
)
->
event
.
stopPropagation
()
createPost
:
(
event
)
->
event
.
preventDefault
()
createPost
:
(
event
)
->
title
=
@
$
(
".new-post-title"
).
val
()
event
.
preventDefault
()
body
=
@
$
(
".new-post-body"
).
find
(
".wmd-input"
).
val
()
title
=
@
$
(
".new-post-title"
).
val
()
tags
=
@
$
(
".new-post-tags"
).
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
)
DiscussionUtil
.
safeAjax
$loading
:
$
(
event
.
target
)
if
event
$elem
:
$
(
event
.
target
)
url
:
url
$loading
:
$
(
event
.
target
)
if
event
type
:
"POST"
url
:
url
dataType
:
'json'
type
:
"POST"
async
:
false
# TODO when the rest of the stuff below is made to work properly..
dataType
:
'json'
data
:
async
:
false
# TODO when the rest of the stuff below is made to work properly..
title
:
title
data
:
body
:
body
title
:
title
tags
:
tags
body
:
body
anonymous
:
anonymous
tags
:
tags
auto_subscribe
:
follow
anonymous
:
anonymous
error
:
DiscussionUtil
.
formErrorHandler
(
@
$
(
".new-post-form-errors"
))
auto_subscribe
:
follow
success
:
(
response
,
textStatus
)
=>
error
:
DiscussionUtil
.
formErrorHandler
(
@
$
(
".new-post-form-errors"
))
# TODO: Move this out of the callback, this makes it feel sluggish
success
:
(
response
,
textStatus
)
=>
thread
=
new
Thread
response
[
'content'
]
# TODO: Move this out of the callback, this makes it feel sluggish
DiscussionUtil
.
clearFormErrors
(
@
$
(
".new-post-form-errors"
))
thread
=
new
Thread
response
[
'content'
]
@
$el
.
hide
()
DiscussionUtil
.
clearFormErrors
(
@
$
(
".new-post-form-errors"
))
@
$
(
".new-post-title"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$el
.
hide
()
@
$
(
".new-post-body textarea"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$
(
".new-post-title"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$
(
".new-post-tags"
).
val
(
""
)
@
$
(
".new-post-body textarea"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$
(
".new-post-tags"
).
importTags
(
""
)
@
$
(
".new-post-tags"
).
val
(
""
)
@
collection
.
add
thread
@
$
(
".new-post-tags"
).
importTags
(
""
)
@
collection
.
add
thread
lms/static/coffee/src/discussion/views/new_post_view.coffee
View file @
a7014aef
class
@
NewPostView
extends
Backbone
.
View
if
Backbone
?
class
@
NewPostView
extends
Backbone
.
View
initialize
:
()
->
@
dropdownButton
=
@
$
(
".topic_dropdown_button"
)
initialize
:
()
->
@
topicMenu
=
@
$
(
".topic_menu_wrapper"
)
@
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"
events
:
"click .topic_dropdown_button"
:
"toggleTopicDropdown"
"submit .new-post-form"
:
"createPost"
"click .topic_menu_wrapper"
:
"setTopic"
"click .topic_dropdown_button"
:
"toggleTopicDropdown"
"click .topic_menu_search"
:
"ignoreClick"
"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.
# Because we want the behavior that when the body is clicked the menu is
# Without this, clicking the search field would also close the menu.
# closed, we need to ignore clicks in the search field and stop propagation.
ignoreClick
:
(
event
)
->
# Without this, clicking the search field would also close the menu.
event
.
stopPropagation
()
ignoreClick
:
(
event
)
->
event
.
stopPropagation
()
toggleTopicDropdown
:
(
event
)
->
event
.
stopPropagation
()
toggleTopicDropdown
:
(
event
)
->
if
@
menuOpen
event
.
stopPropagation
()
@
hideTopicDropdown
()
if
@
menuOpen
else
@
hideTopicDropdown
()
@
showTopicDropdown
()
else
@
showTopicDropdown
()
showTopicDropdown
:
()
->
@
menuOpen
=
true
showTopicDropdown
:
()
->
@
dropdownButton
.
addClass
(
'dropped'
)
@
menuOpen
=
true
@
topicMenu
.
show
()
@
dropdownButton
.
addClass
(
'dropped'
)
$
(
".form-topic-drop-search-input"
).
focus
()
@
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
# Set here because 1) the window might get resized and things could
@
maxNameWidth
=
@
dropdownButton
.
width
()
*
0.9
# 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
:
()
=>
# Need a fat arrow because hideTopicDropdown is passed as a callback to bind
@
menuOpen
=
false
hideTopicDropdown
:
()
=>
@
dropdownButton
.
removeClass
(
'dropped'
)
@
menuOpen
=
false
@
topicMenu
.
hide
()
@
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
)
setTopic
:
(
event
)
->
if
$target
.
data
(
'discussion_id'
)
$target
=
$
(
event
.
target
)
@
topicText
=
$target
.
html
()
if
$target
.
data
(
'discussion_id'
)
@
topicText
=
@
getFullTopicName
(
$target
)
@
topicText
=
$target
.
html
()
@
topicId
=
$target
.
data
(
'discussion_id'
)
@
topicText
=
@
getFullTopicName
(
$target
)
@
setSelectedTopic
()
@
topicId
=
$target
.
data
(
'discussion_id'
)
@
setSelectedTopic
()
setSelectedTopic
:
->
@
dropdownButton
.
html
(
@
fitName
(
@
topicText
)
+
' <span class="drop-arrow">▾</span>'
)
setSelectedTopic
:
->
@
dropdownButton
.
html
(
@
fitName
(
@
topicText
)
+
' <span class="drop-arrow">▾</span>'
)
getFullTopicName
:
(
topicElement
)
->
name
=
topicElement
.
html
()
getFullTopicName
:
(
topicElement
)
->
topicElement
.
parents
(
'ul'
).
not
(
'.topic_menu'
).
each
->
name
=
topicElement
.
html
()
name
=
$
(
this
).
siblings
(
'a'
).
html
()
+
' / '
+
name
topicElement
.
parents
(
'ul'
).
not
(
'.topic_menu'
).
each
->
return
name
name
=
$
(
this
).
siblings
(
'a'
).
html
()
+
' / '
+
name
return
name
getNameWidth
:
(
name
)
->
test
=
$
(
"<div>"
)
getNameWidth
:
(
name
)
->
test
.
css
test
=
$
(
"<div>"
)
"font-size"
:
@
dropdownButton
.
css
(
'font-size'
)
test
.
css
opacity
:
0
"font-size"
:
@
dropdownButton
.
css
(
'font-size'
)
position
:
'absolute'
opacity
:
0
left
:
-
1000
position
:
'absolute'
top
:
-
1000
left
:
-
1000
$
(
"body"
).
append
(
test
)
top
:
-
1000
test
.
html
(
name
)
$
(
"body"
).
append
(
test
)
width
=
test
.
width
()
test
.
html
(
name
)
test
.
remove
()
width
=
test
.
width
()
return
width
test
.
remove
()
return
width
fitName
:
(
name
)
->
width
=
@
getNameWidth
(
name
)
fitName
:
(
name
)
->
if
width
<
@
maxNameWidth
width
=
@
getNameWidth
(
name
)
return
name
if
width
<
@
maxNameWidth
path
=
(
x
.
replace
/^\s+|\s+$/g
,
""
for
x
in
name
.
split
(
"/"
))
return
name
while
path
.
length
>
1
path
=
(
x
.
replace
/^\s+|\s+$/g
,
""
for
x
in
name
.
split
(
"/"
))
path
.
shift
()
while
path
.
length
>
1
partialName
=
"... / "
+
path
.
join
(
" / "
)
path
.
shift
()
if
@
getNameWidth
(
partialName
)
<
@
maxNameWidth
partialName
=
"... / "
+
path
.
join
(
" / "
)
return
partialName
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
]
while
@
getNameWidth
(
name
)
>
@
maxNameWidth
name
=
"... / "
+
rawName
+
" ..."
rawName
=
rawName
[
0
...
rawName
.
length
-
1
]
name
=
"... / "
+
rawName
+
" ..."
return
name
return
name
createPost
:
(
event
)
->
event
.
preventDefault
()
createPost
:
(
event
)
->
title
=
@
$
(
".new-post-title"
).
val
()
event
.
preventDefault
()
body
=
@
$
(
".new-post-body"
).
find
(
".wmd-input"
).
val
()
title
=
@
$
(
".new-post-title"
).
val
()
tags
=
@
$
(
".new-post-tags"
).
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
)
DiscussionUtil
.
safeAjax
$loading
:
$
(
event
.
target
)
if
event
$elem
:
$
(
event
.
target
)
url
:
url
$loading
:
$
(
event
.
target
)
if
event
type
:
"POST"
url
:
url
dataType
:
'json'
type
:
"POST"
async
:
false
# TODO when the rest of the stuff below is made to work properly..
dataType
:
'json'
data
:
async
:
false
# TODO when the rest of the stuff below is made to work properly..
title
:
title
data
:
body
:
body
title
:
title
tags
:
tags
body
:
body
anonymous
:
anonymous
tags
:
tags
auto_subscribe
:
follow
anonymous
:
anonymous
error
:
DiscussionUtil
.
formErrorHandler
(
@
$
(
".new-post-form-errors"
))
auto_subscribe
:
follow
success
:
(
response
,
textStatus
)
=>
error
:
DiscussionUtil
.
formErrorHandler
(
@
$
(
".new-post-form-errors"
))
# TODO: Move this out of the callback, this makes it feel sluggish
success
:
(
response
,
textStatus
)
=>
thread
=
new
Thread
response
[
'content'
]
# TODO: Move this out of the callback, this makes it feel sluggish
DiscussionUtil
.
clearFormErrors
(
@
$
(
".new-post-form-errors"
))
thread
=
new
Thread
response
[
'content'
]
@
$el
.
hide
()
DiscussionUtil
.
clearFormErrors
(
@
$
(
".new-post-form-errors"
))
@
$
(
".new-post-title"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$el
.
hide
()
@
$
(
".new-post-body textarea"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$
(
".new-post-title"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$
(
".new-post-tags"
).
val
(
""
)
@
$
(
".new-post-body textarea"
).
val
(
""
).
attr
(
"prev-text"
,
""
)
@
$
(
".new-post-tags"
).
importTags
(
""
)
@
$
(
".new-post-tags"
).
val
(
""
)
@
collection
.
add
thread
@
$
(
".new-post-tags"
).
importTags
(
""
)
@
collection
.
add
thread
setActiveItem
:
(
event
)
->
if
event
.
which
==
13
setActiveItem
:
(
event
)
->
$
(
".topic_menu_wrapper .focused"
).
click
()
if
event
.
which
==
13
return
$
(
".topic_menu_wrapper .focused"
).
click
()
if
event
.
which
!=
40
&&
event
.
which
!=
38
return
return
if
event
.
which
!=
40
&&
event
.
which
!=
38
event
.
preventDefault
()
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
==
40
if
event
.
which
==
38
index
=
Math
.
min
(
index
+
1
,
items
.
length
-
1
)
index
=
Math
.
max
(
index
-
1
,
0
)
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
()
itemTop
=
$
(
items
[
index
]).
parent
().
offset
().
top
itemFromTop
=
$
(
".topic_menu"
).
offset
().
top
-
itemTop
scrollTop
=
$
(
".topic_menu"
).
scrollTop
()
scrollTarget
=
Math
.
min
(
scrollTop
-
itemFromTop
,
scrollTop
)
itemFromTop
=
$
(
".topic_menu"
).
offset
().
top
-
itemTop
scrollTarget
=
Math
.
max
(
scrollTop
-
itemFromTop
-
$
(
".topic_menu"
).
height
()
+
$
(
items
[
index
]).
height
()
+
20
,
scrollTarget
)
scrollTarget
=
Math
.
min
(
scrollTop
-
itemFromTop
,
scrollTop
)
$
(
".topic_menu"
).
scrollTop
(
scrollTarget
)
scrollTarget
=
Math
.
max
(
scrollTop
-
itemFromTop
-
$
(
".topic_menu"
).
height
()
+
$
(
items
[
index
]).
height
()
+
20
,
scrollTarget
)
$
(
".topic_menu"
).
scrollTop
(
scrollTarget
)
lms/static/coffee/src/discussion/views/response_comment_view.coffee
View file @
a7014aef
class
@
ResponseCommentView
extends
DiscussionContentView
if
Backbone
?
tagName
:
"li"
class
@
ResponseCommentView
extends
DiscussionContentView
template
:
_
.
template
(
$
(
"#response-comment-template"
).
html
())
tagName
:
"li"
initLocal
:
->
template
:
_
.
template
(
$
(
"#response-comment-template"
).
html
())
# TODO .response-local is the parent of the comments so @$local is null, not sure what was intended here...
initLocal
:
->
@
$local
=
@
$el
.
find
(
".response-local"
)
# TODO .response-local is the parent of the comments so @$local is null, not sure what was intended here...
@
$delegateElement
=
@
$local
@
$local
=
@
$el
.
find
(
".response-local"
)
@
$delegateElement
=
@
$local
render
:
->
render
:
->
@
$el
.
html
(
@
template
(
@
model
.
toJSON
()))
@
$el
.
html
(
@
template
(
@
model
.
toJSON
()))
@
initLocal
()
@
initLocal
()
@
delegateEvents
()
@
delegateEvents
()
@
renderAttrs
()
@
renderAttrs
()
@
$el
.
find
(
".timeago"
).
timeago
()
@
$el
.
find
(
".timeago"
).
timeago
()
@
convertMath
()
@
convertMath
()
@
@
convertMath
:
->
convertMath
:
->
body
=
@
$el
.
find
(
".response-body"
)
body
=
@
$el
.
find
(
".response-body"
)
body
.
html
DiscussionUtil
.
postMathJaxProcessor
DiscussionUtil
.
markdownWithHighlight
body
.
html
()
body
.
html
DiscussionUtil
.
postMathJaxProcessor
DiscussionUtil
.
markdownWithHighlight
body
.
html
()
# This removes paragraphs so that comments are more compact
# This removes paragraphs so that comments are more compact
body
.
children
(
"p"
).
each
(
index
,
elem
)
->
body
.
children
(
"p"
).
each
(
index
,
elem
)
->
$
(
elem
).
replaceWith
(
$
(
elem
).
html
())
$
(
elem
).
replaceWith
(
$
(
elem
).
html
())
MathJax
.
Hub
.
Queue
[
"Typeset"
,
MathJax
.
Hub
,
body
[
0
]]
MathJax
.
Hub
.
Queue
[
"Typeset"
,
MathJax
.
Hub
,
body
[
0
]]
lms/static/coffee/src/discussion/views/thread_response_view.coffee
View file @
a7014aef
class
@
ThreadResponseView
extends
DiscussionContentView
if
Backbone
?
tagName
:
"li"
class
@
ThreadResponseView
extends
DiscussionContentView
template
:
_
.
template
(
$
(
"#thread-response-template"
).
html
())
tagName
:
"li"
template
:
_
.
template
(
$
(
"#thread-response-template"
).
html
())
events
:
events
:
"click .vote-btn"
:
"toggleVote"
"click .vote-btn"
:
"toggleVote"
"submit .comment-form"
:
"submitComment"
"submit .comment-form"
:
"submitComment"
"click .action-endorse"
:
"toggleEndorse"
"click .action-endorse"
:
"toggleEndorse"
"click .action-delete"
:
"delete"
"click .action-delete"
:
"delete"
render
:
->
render
:
->
@
$el
.
html
(
@
template
(
@
model
.
toJSON
()))
@
$el
.
html
(
@
template
(
@
model
.
toJSON
()))
@
initLocal
()
@
initLocal
()
@
delegateEvents
()
@
delegateEvents
()
if
window
.
user
.
voted
(
@
model
)
if
window
.
user
.
voted
(
@
model
)
@
$
(
".vote-btn"
).
addClass
(
"is-cast"
)
@
$
(
".vote-btn"
).
addClass
(
"is-cast"
)
@
renderAttrs
()
@
renderAttrs
()
@
$el
.
find
(
".posted-details"
).
timeago
()
@
$el
.
find
(
".posted-details"
).
timeago
()
@
convertMath
()
@
convertMath
()
@
renderComments
()
@
renderComments
()
@
@
convertMath
:
->
convertMath
:
->
element
=
@
$
(
".response-body"
)
element
=
@
$
(
".response-body"
)
element
.
html
DiscussionUtil
.
postMathJaxProcessor
DiscussionUtil
.
markdownWithHighlight
element
.
html
()
element
.
html
DiscussionUtil
.
postMathJaxProcessor
DiscussionUtil
.
markdownWithHighlight
element
.
html
()
MathJax
.
Hub
.
Queue
[
"Typeset"
,
MathJax
.
Hub
,
element
[
0
]]
MathJax
.
Hub
.
Queue
[
"Typeset"
,
MathJax
.
Hub
,
element
[
0
]]
renderComments
:
->
renderComments
:
->
@
model
.
get
(
"comments"
).
each
@
renderComment
@
model
.
get
(
"comments"
).
each
@
renderComment
renderComment
:
(
comment
)
=>
renderComment
:
(
comment
)
=>
comment
.
set
(
'thread'
,
@
model
.
get
(
'thread'
))
comment
.
set
(
'thread'
,
@
model
.
get
(
'thread'
))
view
=
new
ResponseCommentView
(
model
:
comment
)
view
=
new
ResponseCommentView
(
model
:
comment
)
view
.
render
()
view
.
render
()
@
$el
.
find
(
".comments li:last"
).
before
(
view
.
el
)
@
$el
.
find
(
".comments li:last"
).
before
(
view
.
el
)
toggleVote
:
(
event
)
->
toggleVote
:
(
event
)
->
event
.
preventDefault
()
event
.
preventDefault
()
@
$
(
".vote-btn"
).
toggleClass
(
"is-cast"
)
@
$
(
".vote-btn"
).
toggleClass
(
"is-cast"
)
if
@
$
(
".vote-btn"
).
hasClass
(
"is-cast"
)
if
@
$
(
".vote-btn"
).
hasClass
(
"is-cast"
)
@
vote
()
@
vote
()
else
else
@
unvote
()
@
unvote
()
vote
:
->
vote
:
->
url
=
@
model
.
urlFor
(
"upvote"
)
url
=
@
model
.
urlFor
(
"upvote"
)
@
$
(
".votes-count-number"
).
html
(
parseInt
(
@
$
(
".votes-count-number"
).
html
())
+
1
)
@
$
(
".votes-count-number"
).
html
(
parseInt
(
@
$
(
".votes-count-number"
).
html
())
+
1
)
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
$elem
:
@
$
(
".discussion-vote"
)
$elem
:
@
$
(
".discussion-vote"
)
url
:
url
url
:
url
type
:
"POST"
type
:
"POST"
success
:
(
response
,
textStatus
)
=>
success
:
(
response
,
textStatus
)
=>
if
textStatus
==
'success'
if
textStatus
==
'success'
@
model
.
set
(
response
)
@
model
.
set
(
response
)
unvote
:
->
unvote
:
->
url
=
@
model
.
urlFor
(
"unvote"
)
url
=
@
model
.
urlFor
(
"unvote"
)
@
$
(
".votes-count-number"
).
html
(
parseInt
(
@
$
(
".votes-count-number"
).
html
())
-
1
)
@
$
(
".votes-count-number"
).
html
(
parseInt
(
@
$
(
".votes-count-number"
).
html
())
-
1
)
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
$elem
:
@
$
(
".discussion-vote"
)
$elem
:
@
$
(
".discussion-vote"
)
url
:
url
url
:
url
type
:
"POST"
type
:
"POST"
success
:
(
response
,
textStatus
)
=>
success
:
(
response
,
textStatus
)
=>
if
textStatus
==
'success'
if
textStatus
==
'success'
@
model
.
set
(
response
)
@
model
.
set
(
response
)
submitComment
:
(
event
)
->
submitComment
:
(
event
)
->
event
.
preventDefault
()
event
.
preventDefault
()
url
=
@
model
.
urlFor
(
'reply'
)
url
=
@
model
.
urlFor
(
'reply'
)
body
=
@
$
(
".comment-form-input"
).
val
()
body
=
@
$
(
".comment-form-input"
).
val
()
if
not
body
.
trim
().
length
if
not
body
.
trim
().
length
return
return
comment
=
new
Comment
(
body
:
body
,
created_at
:
(
new
Date
()).
toISOString
(),
username
:
window
.
user
.
get
(
"username"
),
user_id
:
window
.
user
.
get
(
"id"
))
comment
=
new
Comment
(
body
:
body
,
created_at
:
(
new
Date
()).
toISOString
(),
username
:
window
.
user
.
get
(
"username"
),
user_id
:
window
.
user
.
get
(
"id"
))
@
renderComment
(
comment
)
@
renderComment
(
comment
)
@
trigger
"comment:add"
,
comment
@
trigger
"comment:add"
,
comment
@
$
(
".comment-form-input"
).
val
(
""
)
@
$
(
".comment-form-input"
).
val
(
""
)
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
$elem
:
$
(
event
.
target
)
$elem
:
$
(
event
.
target
)
url
:
url
url
:
url
type
:
"POST"
type
:
"POST"
dataType
:
'json'
dataType
:
'json'
data
:
data
:
body
:
body
body
:
body
delete
:
(
event
)
->
delete
:
(
event
)
->
event
.
preventDefault
()
event
.
preventDefault
()
if
not
@
model
.
can
(
'can_delete'
)
if
not
@
model
.
can
(
'can_delete'
)
return
return
console
.
log
$
(
event
.
target
)
console
.
log
$
(
event
.
target
)
url
=
@
model
.
urlFor
(
'delete'
)
url
=
@
model
.
urlFor
(
'delete'
)
if
not
confirm
"Are you sure to delete this response? "
if
not
confirm
"Are you sure to delete this response? "
return
return
@
model
.
remove
()
@
model
.
remove
()
@
$el
.
remove
()
@
$el
.
remove
()
$elem
=
$
(
event
.
target
)
$elem
=
$
(
event
.
target
)
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
$elem
:
$elem
$elem
:
$elem
url
:
url
url
:
url
type
:
"POST"
type
:
"POST"
success
:
(
response
,
textStatus
)
=>
success
:
(
response
,
textStatus
)
=>
toggleEndorse
:
(
event
)
->
toggleEndorse
:
(
event
)
->
event
.
preventDefault
()
event
.
preventDefault
()
if
not
@
model
.
can
(
'can_endorse'
)
if
not
@
model
.
can
(
'can_endorse'
)
return
return
$elem
=
$
(
event
.
target
)
$elem
=
$
(
event
.
target
)
url
=
@
model
.
urlFor
(
'endorse'
)
url
=
@
model
.
urlFor
(
'endorse'
)
endorsed
=
@
model
.
get
(
'endorsed'
)
endorsed
=
@
model
.
get
(
'endorsed'
)
data
=
{
endorsed
:
not
endorsed
}
data
=
{
endorsed
:
not
endorsed
}
@
model
.
set
(
'endorsed'
,
not
endorsed
)
@
model
.
set
(
'endorsed'
,
not
endorsed
)
@
trigger
"comment:endorse"
,
not
endorsed
@
trigger
"comment:endorse"
,
not
endorsed
DiscussionUtil
.
safeAjax
DiscussionUtil
.
safeAjax
$elem
:
$elem
$elem
:
$elem
url
:
url
url
:
url
data
:
data
data
:
data
type
:
"POST"
type
:
"POST"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment