Refactored the coffeescript behavior so it is a bit more testable.
This commit is contained in:
@@ -60,4 +60,8 @@ span.annotatable {
|
||||
right: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&.opaque {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,72 @@
|
||||
class @Annotatable
|
||||
@_debug: true
|
||||
|
||||
wrapperSelector: '.annotatable-wrapper'
|
||||
spanSelector: 'span.annotatable[data-span-id]'
|
||||
discussionSelector: '.annotatable-discussion[data-discussion-id]'
|
||||
|
||||
constructor: (el) ->
|
||||
console.log 'loaded Annotatable' if @_debug
|
||||
@el = el
|
||||
@spandata = $('.annotatable-wrapper', @el).data "spans"
|
||||
@initSpans()
|
||||
@init()
|
||||
|
||||
initSpans: () ->
|
||||
selector = 'span.annotatable[data-span-id]'
|
||||
$(@el).find(selector).on 'click', (e) =>
|
||||
@onClickSpan.call this, e
|
||||
init: () ->
|
||||
@loadSpanData()
|
||||
@initEvents()
|
||||
|
||||
onClickSpan: (e) ->
|
||||
span_id = e.target.getAttribute('data-span-id')
|
||||
discussion_id = @spandata[span_id]
|
||||
selector = '.annotatable-discussion[data-discussion-id="'+discussion_id+'"]';
|
||||
$discussion = $(selector, @el)
|
||||
padding = 20
|
||||
top = $discussion.offset().top - padding
|
||||
highlighted = false
|
||||
complete = () ->
|
||||
if !highlighted
|
||||
$discussion.effect('highlight', {}, 1000)
|
||||
highlighted = true
|
||||
initEvents: () ->
|
||||
$(@wrapperSelector, @el).delegate(@spanSelector, {
|
||||
'click': @_bind @onSpanEvent @onClickSpan
|
||||
'mouseenter': @_bind @onSpanEvent @onEnterSpan
|
||||
'mouseleave': @_bind @onSpanEvent @onLeaveSpan
|
||||
})
|
||||
|
||||
$('html, body').animate({
|
||||
scrollTop: top,
|
||||
}, 1000, 'swing', complete)
|
||||
loadSpanData: () ->
|
||||
@spandata = $(@wrapperSelector, @el).data('spans')
|
||||
|
||||
getDiscussionId: (span_id) ->
|
||||
@spandata[span_id]
|
||||
|
||||
getDiscussionEl: (discussion_id) ->
|
||||
$(@discussionSelector, @el).filter('[data-discussion-id="'+discussion_id+'"]')
|
||||
|
||||
onSpanEvent: (fn) ->
|
||||
(e) =>
|
||||
span_id = e.target.getAttribute('data-span-id')
|
||||
discussion_id = @getDiscussionId(span_id)
|
||||
span = {
|
||||
id: span_id,
|
||||
el: e.target
|
||||
}
|
||||
discussion = {
|
||||
id: discussion_id,
|
||||
el: @getDiscussionEl(discussion_id)
|
||||
}
|
||||
fn.call this, span, discussion
|
||||
|
||||
onClickSpan: (span, discussion) ->
|
||||
@scrollToDiscussion(discussion.el)
|
||||
|
||||
onEnterSpan: (span, discussion) ->
|
||||
$(@discussionSelector, @el).not(discussion.el).toggleClass('opaque', true)
|
||||
|
||||
onLeaveSpan: (span, discussion) ->
|
||||
$(@discussionSelector, @el).not(discussion.el).toggleClass('opaque', false)
|
||||
|
||||
scrollToDiscussion: (el) ->
|
||||
complete = @makeHighlighter(el)
|
||||
top = el.offset().top - 20 # with some padding
|
||||
|
||||
$('html, body').animate({ scrollTop: top }, 750, 'swing', complete)
|
||||
|
||||
makeHighlighter: (el) ->
|
||||
return @_once -> el.effect('highlight', {}, 750)
|
||||
|
||||
_once: (fn) ->
|
||||
done = false
|
||||
return =>
|
||||
fn.call this unless done
|
||||
done = true
|
||||
|
||||
_bind: (fn) ->
|
||||
return => fn.apply(this, arguments)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="annotatable-wrapper" id="${element_id}">
|
||||
<div class="annotatable-wrapper" id="${element_id}-wrapper">
|
||||
|
||||
<div class="annotatable-header">
|
||||
<div class="help-icon"></div>
|
||||
@@ -14,9 +14,7 @@
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
// TODO pass spans to module directly
|
||||
var el = $('#${element_id}.annotatable-wrapper');
|
||||
el.data('spans', ${json_discussion_for});
|
||||
$('#${element_id}-wrapper').data('spans', ${json_discussion_for});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user