diff --git a/common/lib/xmodule/xmodule/annotatable_module.py b/common/lib/xmodule/xmodule/annotatable_module.py
index 5b3cc15c77..c2fd973918 100644
--- a/common/lib/xmodule/xmodule/annotatable_module.py
+++ b/common/lib/xmodule/xmodule/annotatable_module.py
@@ -30,20 +30,20 @@ class AnnotatableModule(XModule):
def _is_span(self, element):
""" Returns true if the element is a valid annotation span, false otherwise. """
- return element.tag == 'span' and element.get('class') == 'annotatable'
+ return element.get('class') == 'annotatable'
def _iterspans(self, xmltree, callbacks):
- """ Iterates over span elements and invokes each callback on the span. """
+ """ Iterates over elements and invokes each callback on the span. """
index = 0
- for element in xmltree.iter('span'):
+ for element in xmltree.iter():
if self._is_span(element):
for callback in callbacks:
callback(element, index, xmltree)
index += 1
def _set_span_data(self, span, index, xmltree):
- """ Sets an ID and discussion anchor for the span. """
+ """ Sets the discussion anchor for the span. """
if 'anchor' in span.attrib:
span.set('data-discussion-anchor', span.get('anchor'))
@@ -52,13 +52,12 @@ class AnnotatableModule(XModule):
def _decorate_span(self, span, index, xmltree):
""" Decorates the span with an icon and highlight. """
- cls = ['annotatable', ]
+ cls = ['annotatable-span', 'highlight']
marker = self._get_marker_color(span)
- if marker is None:
- cls.append('highlight-yellow')
- else:
+ if marker is not None:
cls.append('highlight-'+marker)
+ span.tag = 'div'
span.set('class', ' '.join(cls))
span_icon = etree.Element('span', { 'class': 'annotatable-icon'} )
span_icon.text = '';
@@ -76,9 +75,12 @@ class AnnotatableModule(XModule):
break
if comment is not None:
+ comment.tag = 'div'
comment.set('class', 'annotatable-comment')
def _get_marker_color(self, span):
+ """ Returns the name of the marker color for the span if it is valid, otherwise none."""
+
valid_markers = ['yellow', 'orange', 'purple', 'blue', 'green']
if 'marker' in span.attrib:
marker = span.attrib['marker']
diff --git a/common/lib/xmodule/xmodule/css/annotatable/display.scss b/common/lib/xmodule/xmodule/css/annotatable/display.scss
index d1f39332f6..a8024a6d14 100644
--- a/common/lib/xmodule/xmodule/css/annotatable/display.scss
+++ b/common/lib/xmodule/xmodule/css/annotatable/display.scss
@@ -19,7 +19,8 @@
font-size: $body-font-size;
}
-span.annotatable {
+.annotatable-span {
+ display: inline;
cursor: pointer;
@each $highlight in (
(yellow rgb(239, 255, 0)),
@@ -27,9 +28,10 @@ span.annotatable {
(purple rgb(255,0,197)),
(blue rgb(0,90,255)),
(green rgb(111,255,9))) {
- &.highlight-#{nth($highlight,1)} {
- background-color: #{lighten(nth($highlight,2), 20%)};
- }
+ $marker: nth($highlight,1);
+ $color: lighten(nth($highlight,2), 20%);
+ @if $marker == yellow { &.highlight { background-color: $color; } }
+ &.highlight-#{$marker} { background-color: $color; }
}
&.hide {
cursor: none;
@@ -50,7 +52,7 @@ span.annotatable {
.annotatable-icon {
display: inline-block;
vertical-align: middle;
- width: 16px;
+ width: 17px;
height: 17px;
background: url(../images/link-icon.png) no-repeat;
}
@@ -60,12 +62,12 @@ span.annotatable {
margin: 1em 0 .5em 0;
}
-.help-icon {
+.annotatable-help-icon {
display: block;
position: absolute;
right: 0;
top: 33%;
- width: 16px;
+ width: 17px;
height: 17px;
margin: 0 7px 0 0;
background: url(../images/info-icon.png) no-repeat;
@@ -80,11 +82,14 @@ span.annotatable {
background: rgba(255, 255, 255, 0.9);
border: 1px solid $border-color;
color: #000;
+ font-weight: normal;
margin-bottom: 6px;
margin-right: 0;
- overflow: visible;
padding: 4px;
text-align: left;
+ max-width: 300px;
+ max-height: 300px;
+ overflow: auto;
-webkit-font-smoothing: antialiased;
}
-}
\ No newline at end of file
+}
diff --git a/common/lib/xmodule/xmodule/js/src/annotatable/display.coffee b/common/lib/xmodule/xmodule/js/src/annotatable/display.coffee
index 45cbb20bec..a021b3e9d8 100644
--- a/common/lib/xmodule/xmodule/js/src/annotatable/display.coffee
+++ b/common/lib/xmodule/xmodule/js/src/annotatable/display.coffee
@@ -3,64 +3,89 @@ class @Annotatable
wrapperSelector: '.annotatable-wrapper'
toggleSelector: '.annotatable-toggle'
- spanSelector: 'span.annotatable'
+ spanSelector: '.annotatable-span'
commentSelector: '.annotatable-comment'
- replySelector: 'a.annotatable-reply'
+ replySelector: '.annotatable-reply'
+ helpSelector: '.annotatable-help-icon'
constructor: (el) ->
console.log 'loaded Annotatable' if @_debug
- @init(el)
+ @el = el
+ @init()
$: (selector) ->
$(selector, @el)
- init: (el) ->
- @el = el
- @hideAnnotations = false
+ init: () ->
@initEvents()
- @initToolTips()
+ @initTips()
initEvents: () ->
+ @annotationsHidden = false
@$(@toggleSelector).bind 'click', @onClickToggleAnnotations
@$(@wrapperSelector).delegate @replySelector, 'click', @onClickReply
-
- initToolTips: () ->
+
+ initTips: () ->
+ @visibleTips = []
@$(@spanSelector).each (index, el) =>
$(el).qtip(@getTipOptions el)
+ @$(@helpSelector).qtip
+ position:
+ my: 'right top'
+ at: 'bottom left'
+ content:
+ title: 'Annotated Reading Help'
+ text: "To reveal annotations in the reading, click the highlighted areas.
+ Discuss the annotations in the forums using the reply link at the
+ end of the annotation.
+ To conceal annotations, use the Hide Annotations button."
+
getTipOptions: (el) ->
content:
- title:
+ title:
text: @makeTipTitle(el)
button: 'Close'
- text: @makeTipComment(el)
+ text: @makeTipContent(el)
position:
my: 'bottom center' # of tooltip
at: 'top center' # of target
target: 'mouse'
container: @$(@wrapperSelector)
- adjust:
+ adjust:
mouse: false # dont follow the mouse
- method: 'shift none'
- show:
+ show:
event: 'click'
hide:
event: 'click'
style:
classes: 'ui-tooltip-annotatable'
events:
- show: @onShowTipComment
+ render: @onRenderTip
+ show: @onShowTip
- onShowTipComment: (event, api) =>
- event.preventDefault() if @hideAnnotations
+ onRenderTip: (event, api) =>
+ $(api.elements.tooltip).draggable
+ handle: '.ui-tooltip-title'
+ cursor: 'move'
+
+ onShowTip: (event, api) =>
+ event.preventDefault() if @annotationsHidden
onClickToggleAnnotations: (e) =>
- @hideAnnotations = !@hideAnnotations
- hide = @hideAnnotations
+ toggle = @$(@toggleSelector)
+ spans = @$(@spanSelector)
- @hideAllTips() if hide
- @$(@spanSelector).toggleClass('hide', hide)
- @$(@toggleSelector).text((if hide then 'Show' else 'Hide') + ' Annotations')
+ @annotationsHidden = !@annotationsHidden
+ if @annotationsHidden
+ spans.toggleClass('hide', true)
+ toggle.text('Show Annotations')
+ @visibleTips = @getVisibleTips()
+ @hideTips(@visibleTips)
+ else
+ spans.toggleClass('hide', false)
+ toggle.text('Hide Annotations')
+ @showTips(@visibleTips)
onClickReply: (e) =>
hash = $(e.currentTarget).attr('href')
@@ -70,11 +95,16 @@ class @Annotatable
@scrollTo(anchor) if anchor.length == 1
scrollTo: (el, padding = 20) ->
- scrollTop = el.offset().top - padding
- $('html,body').animate(scrollTop: scrollTop, 500, 'swing')
+ props =
+ scrollTop: (el.offset().top - padding)
+ opts =
+ duration: 500
+ complete: @_once -> el.effect 'highlight', {}, 2000
- makeTipComment: (el) ->
- return (api) =>
+ $('html,body').animate(props, opts)
+
+ makeTipContent: (el) ->
+ (api) =>
comment = $(@commentSelector, el).first().clone()
anchor = $(el).data('discussion-anchor')
if anchor
@@ -82,13 +112,36 @@ class @Annotatable
comment.contents()
makeTipTitle: (el) ->
- return (api) =>
+ (api) =>
comment = $(@commentSelector, el).first()
title = comment.attr('title')
(if title then title else 'Commentary')
createReplyLink: (anchor) ->
- $("Reply to Comment")
+ $("Reply to this comment")
+
+ getVisibleTips: () ->
+ visible = []
+ @$(@spanSelector).each (index, el) ->
+ api = $(el).qtip('api')
+ tip = $(api?.elements.tooltip)
+ if tip.is(':visible')
+ visible.push [el, tip.offset()]
+ visible
- hideAllTips: () ->
- @$(@spanSelector).each (index, el) -> $(el).qtip('api').hide()
\ No newline at end of file
+ hideTips: (items) ->
+ elements = (pair[0] for pair in items)
+ $(elements).qtip('hide')
+
+ showTips: (items) ->
+ $.each items, (index, item) ->
+ [el, offset] = item
+ api = $(el).qtip('api')
+ api?.show()
+ $(api?.elements.tooltip).offset(offset)
+
+ _once: (fn) ->
+ done = false
+ return =>
+ fn.call this unless done
+ done = true
diff --git a/lms/templates/annotatable.html b/lms/templates/annotatable.html
index 5f60c6cba2..1cb40a0068 100644
--- a/lms/templates/annotatable.html
+++ b/lms/templates/annotatable.html
@@ -1,6 +1,6 @@