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 @@
-
+
% if display_name is not UNDEFINED and display_name is not None:
${display_name}
% endif