Commit ebd62105 authored by csillag's avatar csillag

Small refactorings + tests for anchoring

API Changes:
 - Introduce the getAnchors() method
 - Make chooseAccessPolicy() public.

Implementation changes:
 - Add the reference pointing to the newly created anchor to
   annotation object right insite the enhanced anchoring plugin,
   instead of in the Monkey code.
 - Fix access to the Annotator class

Added some test cases for EnhancedAnchoring
parent e6cd0656
...@@ -26,9 +26,6 @@ Annotator.prototype.setupAnnotation = (annotation) -> ...@@ -26,9 +26,6 @@ Annotator.prototype.setupAnnotation = (annotation) ->
t.diffHTML = anchor.diffHTML t.diffHTML = anchor.diffHTML
t.diffCaseOnly = anchor.diffCaseOnly t.diffCaseOnly = anchor.diffCaseOnly
# Store this anchor for the annotation
annotation.anchors.push anchor
catch exception catch exception
console.log "Error in setupAnnotation for", annotation.id, console.log "Error in setupAnnotation for", annotation.id,
":", exception.stack ? exception ":", exception.stack ? exception
......
Annotator = @Annotator
$ = Annotator.$
# Fake two-phase / pagination support, used for HTML documents # Fake two-phase / pagination support, used for HTML documents
class DummyDocumentAccess class DummyDocumentAccess
...@@ -47,7 +49,7 @@ class Anchor ...@@ -47,7 +49,7 @@ class Anchor
# Don't call TextHighlight directly; instead, make a system # Don't call TextHighlight directly; instead, make a system
# For registering highlight creators, or publish an event, or # For registering highlight creators, or publish an event, or
# whatever # whatever
@highlight[page] = @Annotator.TextHighlight.createFrom @_getSegment(page), this, page @highlight[page] = Annotator.TextHighlight.createFrom @_getSegment(page), this, page
# Check if everything is rendered now # Check if everything is rendered now
@fullyRealized = renderedPages.length is @endPage - @startPage + 1 @fullyRealized = renderedPages.length is @endPage - @startPage + 1
...@@ -103,7 +105,7 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin ...@@ -103,7 +105,7 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin
# Initializes the components used for analyzing the document # Initializes the components used for analyzing the document
_chooseAccessPolicy: -> chooseAccessPolicy: ->
if @document? then return if @document? then return
# Go over the available strategies # Go over the available strategies
...@@ -134,7 +136,7 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin ...@@ -134,7 +136,7 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin
# Perform a scan of the DOM. Required for finding anchors. # Perform a scan of the DOM. Required for finding anchors.
_scan: -> _scan: ->
# Ensure that we have a document access strategy # Ensure that we have a document access strategy
this._chooseAccessPolicy() @chooseAccessPolicy()
try try
@pendingScan = @document.scan() @pendingScan = @document.scan()
catch catch
...@@ -144,7 +146,6 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin ...@@ -144,7 +146,6 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin
# Plugin initialization # Plugin initialization
pluginInit: -> pluginInit: ->
@$ = Annotator.$
@selectorCreators = [] @selectorCreators = []
@strategies = [] @strategies = []
@_setupDocumentAccessStrategies() @_setupDocumentAccessStrategies()
...@@ -176,6 +177,9 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin ...@@ -176,6 +177,9 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin
try try
a = s.code.call this, annotation, target a = s.code.call this, annotation, target
if a if a
# Store this anchor for the annotation
annotation.anchors.push a
# Store the anchor for all involved pages # Store the anchor for all involved pages
for pageIndex in [a.startPage .. a.endPage] for pageIndex in [a.startPage .. a.endPage]
@anchors[pageIndex] ?= [] @anchors[pageIndex] ?= []
...@@ -219,17 +223,23 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin ...@@ -219,17 +223,23 @@ class Annotator.Plugin.EnhancedAnchoring extends Annotator.Plugin
# Collect all the highlights (optionally for a given set of annotations) # Collect all the highlights (optionally for a given set of annotations)
getHighlights: (annotations) -> getHighlights: (annotations) ->
results = []
for anchor in @getAnchors(annotations)
for page, highlight of anchor.highlight
results.push highlight
results
# Collect all the anchors (optionally for a given set of annotations)
getAnchors: (annotations) ->
results = [] results = []
if annotations? if annotations?
# Collect only the given set of annotations # Collect only the given set of annotations
for annotation in annotations for annotation in annotations
for anchor in annotation.anchors $.merge results, annotation.anchors
for page, hl of anchor.highlight
results.push hl
else else
# Collect from everywhere # Collect from everywhere
for page, anchors of @anchors for page, anchors of @anchors
@$.merge results, (anchor.highlight[page] for anchor in anchors when anchor.highlight[page]?) $.merge results, anchors
results results
......
...@@ -45,6 +45,7 @@ module.exports = function(config) { ...@@ -45,6 +45,7 @@ module.exports = function(config) {
'h/static/scripts/vendor/angular-route.js', 'h/static/scripts/vendor/angular-route.js',
'h/static/scripts/vendor/angular-sanitize.js', 'h/static/scripts/vendor/angular-sanitize.js',
'h/static/scripts/vendor/ng-tags-input.js', 'h/static/scripts/vendor/ng-tags-input.js',
'h/static/scripts/annotator/plugin/texthighlights.js',
'h/static/scripts/app.js', 'h/static/scripts/app.js',
'h/static/scripts/account.js', 'h/static/scripts/account.js',
'h/static/scripts/helpers.js', 'h/static/scripts/helpers.js',
......
assert = chai.assert
# In order to be able to create highlights,
# the Annotator.TextHighlight class must exist.
# This class is registered then the TextHighlights plugin
# is initialized, so we will do that.
th = new Annotator.Plugin.TextHighlights()
th.pluginInit()
# Then Anchor class is not supposed to be used directly.
# Every concrete implementation should have it's own class,
# encompassing a way to identify the given segment of the document.
#
# For testing, we will use the TestAnchor class,
# which does not actually identify a real segment of the HTML document.
class TestAnchor extends Annotator.Anchor
_getSegment: -> "html segment for " + @id
constructor: (manager, annotation, target) ->
super manager, annotation, target, 42, 42,
"fake quote for" + target.id
@id = "fake anchor for " + target.id
describe 'Annotator.Plugin.EnhancedAnchoring', ->
sandbox = null
createAnchoringManager = ->
annotator =
publish: (event) ->
am = new Annotator.Plugin.EnhancedAnchoring()
am.annotator = annotator
am.pluginInit()
am.chooseAccessPolicy()
am.strategies.push
name: "dummy anchoring strategy"
code: (annotation, target) ->
new TestAnchor am, annotation, target
am
createTestAnnotation = (id, targets = 1) ->
id: "annotation " + id
target: (("target " + id + "-" + num) for num in [1 .. targets])
anchors: []
beforeEach ->
sandbox = sinon.sandbox.create()
sandbox.stub Annotator.TextHighlight, 'createFrom',
(segment, anchor, page) -> {segment, anchor, page}
afterEach ->
sandbox.restore()
describe "createAnchor", ->
it 'adds an anchor property to the annotations', ->
am = createAnchoringManager()
ann = createTestAnnotation "a1", 2
anchor1 = am.createAnchor(ann, ann.target[0]).result
anchor2 = am.createAnchor(ann, ann.target[1]).result
assert.isArray ann.anchors
assert.include ann.anchors, anchor1
assert.include ann.anchors, anchor2
assert.equal ann.anchors.length, 2
it 'adds an annotation property to the created anchors', ->
am = createAnchoringManager()
ann = createTestAnnotation "a1"
anchor = am.createAnchor(ann, ann.target[0]).result
assert.equal anchor.annotation, ann
it 'adds a target property to the created anchors', ->
am = createAnchoringManager()
ann = createTestAnnotation "a1"
anchor = am.createAnchor(ann, ann.target[0]).result
assert.equal anchor.target, ann.target[0]
it 'creates the anchors from the right targets', ->
am = createAnchoringManager()
ann = createTestAnnotation "a1"
anchor = am.createAnchor(ann, ann.target[0]).result
assert.equal anchor.id, "fake anchor for " + anchor.target.id
it 'adds the created anchors to the correct per-page array', ->
am = createAnchoringManager()
ann = createTestAnnotation "a1"
anchor = am.createAnchor(ann, ann.target[0]).result
assert.include am.anchors[anchor.startPage], anchor
it 'adds the created highlights to the anchors', ->
am = createAnchoringManager()
ann = createTestAnnotation "a1"
anchor = am.createAnchor(ann, ann.target[0]).result
assert.isObject anchor.highlight
page = anchor.startPage
hl = anchor.highlight[page]
assert.ok hl
assert.equal hl.page, page
it 'adds an anchor property to the created Highlights', ->
am = createAnchoringManager()
ann = createTestAnnotation "a1"
anchor = am.createAnchor(ann, ann.target[0]).result
page = anchor.startPage
hl = anchor.highlight[page]
assert.equal hl.anchor, anchor
describe "getAnchors", ->
it 'returns an empty array by default', ->
am = createAnchoringManager()
anchors = am.getAnchors()
assert.isArray anchors
assert.equal anchors.length, 0
it 'returns all the anchors', ->
am = createAnchoringManager()
ann1 = createTestAnnotation "a1", 2
ann2 = createTestAnnotation "a2"
ann3 = createTestAnnotation "a3"
anchor11 = am.createAnchor(ann1, ann1.target[0]).result
anchor12 = am.createAnchor(ann1, ann1.target[1]).result
anchor2 = am.createAnchor(ann2, ann2.target).result
anchor3 = am.createAnchor(ann3, ann2.target).result
anchors = am.getAnchors()
assert.isArray anchors
assert.include anchors, anchor11
assert.include anchors, anchor12
assert.include anchors, anchor2
assert.include anchors, anchor3
it 'returns the anchors belonging to a set of annotations', ->
am = createAnchoringManager()
ann1 = createTestAnnotation "a1", 2
ann2 = createTestAnnotation "a2"
ann3 = createTestAnnotation "a3"
anchor11 = am.createAnchor(ann1, ann1.target[0]).result
anchor12 = am.createAnchor(ann1, ann1.target[1]).result
anchor2 = am.createAnchor(ann2, ann2.target).result
anchor3 = am.createAnchor(ann3, ann2.target).result
anchors = am.getAnchors [ann1, ann2]
assert.isArray anchors
assert.include anchors, anchor11
assert.include anchors, anchor12
assert.include anchors, anchor2
assert.notInclude anchors, anchor3
describe 'getHighlights', ->
it 'returns an empty array by default', ->
am = createAnchoringManager()
hls = am.getHighlights()
assert.isArray hls
assert.equal hls.length, 0
it 'returns all the highlights', ->
am = createAnchoringManager()
ann1 = createTestAnnotation "a1", 2
ann2 = createTestAnnotation "a2"
ann3 = createTestAnnotation "a3"
anchor11 = am.createAnchor(ann1, ann1.target[0]).result
anchor12 = am.createAnchor(ann1, ann1.target[1]).result
anchor2 = am.createAnchor(ann2, ann2.target).result
anchor3 = am.createAnchor(ann3, ann2.target).result
hls = am.getHighlights()
assert.isArray hls
assert.include hls, anchor11.highlight[anchor11.startPage]
assert.include hls, anchor12.highlight[anchor12.startPage]
assert.include hls, anchor2.highlight[anchor2.startPage]
assert.include hls, anchor3.highlight[anchor3.startPage]
it 'returns the highlights belonging to a set of annotations', ->
am = createAnchoringManager()
ann1 = createTestAnnotation "a1", 2
ann2 = createTestAnnotation "a2"
ann3 = createTestAnnotation "a3"
anchor11 = am.createAnchor(ann1, ann1.target[0]).result
anchor12 = am.createAnchor(ann1, ann1.target[1]).result
anchor2 = am.createAnchor(ann2, ann2.target).result
anchor3 = am.createAnchor(ann3, ann2.target).result
hls = am.getHighlights [ann1, ann2]
assert.isArray hls
assert.include hls, anchor11.highlight[anchor11.startPage]
assert.include hls, anchor12.highlight[anchor12.startPage]
assert.include hls, anchor2.highlight[anchor2.startPage]
assert.notInclude hls, anchor3.highlight[anchor3.startPage]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment