Commit 9423f971 authored by Randall Leeds's avatar Randall Leeds

Inject AnnotationUI ctrl and digest in cross frame

Keep the AppController away from the root scope and just emit the
lifecycle events for the services. Instantiate AnnotationUIController
with proper injection. Handle digests in the cross-frame service.
parent c2dc963f
# Keeps the annotation scope properties up to date by watching for changes
# in the annotationUI object and reacting to user input. This is not a
# controller in the Angular sense, but rather just keeps UI and state in sync.
# Watch the UI state and update scope properties.
class AnnotationUIController
constructor: (annotationUI, $rootScope, appScope) ->
this.$inject = ['$rootScope', '$scope', 'annotationUI']
constructor: ( $rootScope, $scope, annotationUI ) ->
$rootScope.$watch (-> annotationUI.selectedAnnotationMap), (map={}) ->
count = Object.keys(map).length
appScope.selectedAnnotationsCount = count
$scope.selectedAnnotationsCount = count
if count
appScope.selectedAnnotations = map
$scope.selectedAnnotations = map
else
appScope.selectedAnnotations = null
$scope.selectedAnnotations = null
$rootScope.$watch (-> annotationUI.focusedAnnotationMap), (map={}) ->
appScope.focusedAnnotations = map
$rootScope.$on 'getDocumentInfo', ->
appScope.$digest()
appScope.$evalAsync(angular.noop)
$rootScope.$on 'beforeAnnotationCreated', ->
appScope.$evalAsync(angular.noop)
$rootScope.$on 'annotationsLoaded', ->
appScope.$evalAsync(angular.noop)
$scope.focusedAnnotations = map
$rootScope.$on 'annotationDeleted', (event, annotation) ->
annotationUI.removeSelectedAnnotation(annotation)
......@@ -31,18 +20,18 @@ class AnnotationUIController
class AppController
this.$inject = [
'$document', '$location', '$route', '$scope', '$window', '$rootScope',
'$controller', '$document', '$location', '$route', '$scope', '$window',
'auth', 'drafts', 'identity',
'permissions', 'streamer', 'streamfilter', 'annotationUI',
'annotationMapper', 'threading'
]
constructor: (
$document, $location, $route, $scope, $window, $rootScope,
$controller, $document, $location, $route, $scope, $window,
auth, drafts, identity,
permissions, streamer, streamfilter, annotationUI,
annotationMapper, threading
) ->
new AnnotationUIController(annotationUI, $rootScope, $scope)
$controller(AnnotationUIController, {$scope})
$scope.auth = auth
isFirstRun = $location.search().hasOwnProperty('firstrun')
......@@ -59,7 +48,7 @@ class AppController
annotationMapper.loadAnnotations data
when 'delete'
for annotation in data
$rootScope.$emit('annotationDeleted', annotation)
$scope.$emit('annotationDeleted', annotation)
streamer.onmessage = (data) ->
return if !data or data.type != 'annotation-notification'
......@@ -76,11 +65,11 @@ class AppController
for id, container of $scope.threading.idTable when container.message
# Remove annotations not belonging to this user when highlighting.
if annotationUI.tool is 'highlight' and annotation.user != auth.user
$rootScope.$emit('annotationDeleted', container.message)
$scope.$emit('annotationDeleted', container.message)
drafts.remove annotation
# Remove annotations the user is not authorized to view.
else if not permissions.permits 'read', container.message, auth.user
$rootScope.$emit('annotationDeleted', container.message)
$scope.$emit('annotationDeleted', container.message)
drafts.remove container.message
$scope.$watch 'sort.name', (name) ->
......@@ -101,7 +90,7 @@ class AppController
# Update any edits in progress.
for draft in drafts.all()
$rootScope.$emit('beforeAnnotationCreated', draft)
$scope.$emit('beforeAnnotationCreated', draft)
# Reopen the streamer.
streamer.close()
......@@ -251,4 +240,4 @@ angular.module('h')
.controller('AppController', AppController)
.controller('ViewerController', ViewerController)
.controller('AnnotationViewerController', AnnotationViewerController)
.value('AnnotationUIController', AnnotationUIController)
.controller('AnnotationUIController', AnnotationUIController)
......@@ -40,9 +40,11 @@ class CrossFrameService
parsed[k] = v
parsed
emit: (args...) ->
$rootScope.$emit.call($rootScope, args...)
$rootScope.$apply ->
$rootScope.$emit.call($rootScope, args...)
on: (event, handler) ->
$rootScope.$on(event, (event, args...) -> handler.apply(this, args))
$rootScope.$apply ->
$rootScope.$on(event, (event, args...) -> handler.apply(this, args))
new AnnotationSync(bridge, options)
......@@ -55,9 +57,9 @@ class CrossFrameService
channel.call
method: 'getDocumentInfo'
success: (info) =>
provider.entities = (link.href for link in info.metadata.link)
@providers.push(provider)
$rootScope.$emit('getDocumentInfo')
$rootScope.$apply =>
provider.entities = (link.href for link in info.metadata.link)
@providers.push(provider)
this.connect = ->
discovery = createDiscovery()
......
......@@ -86,55 +86,43 @@ describe 'h', ->
describe 'AnnotationUIController', ->
$scope = null
$rootScope = null
fakeAnnotationUI = null
annotationUI = null
beforeEach module('h')
beforeEach inject (_$rootScope_, AnnotationUIController) ->
beforeEach inject ($controller, _$rootScope_) ->
$rootScope = _$rootScope_
$scope = $rootScope.$new()
$scope.search = {}
fakeAnnotationUI =
annotationUI =
tool: 'comment'
selectedAnnotationMap: null
focusedAnnotationsMap: null
removeSelectedAnnotation: sandbox.stub()
new AnnotationUIController(fakeAnnotationUI, $rootScope, $scope)
$controller 'AnnotationUIController', {$scope, annotationUI}
it 'updates the view when the selection changes', ->
fakeAnnotationUI.selectedAnnotationMap = {1: true, 2: true}
annotationUI.selectedAnnotationMap = {1: true, 2: true}
$rootScope.$digest()
assert.deepEqual($scope.selectedAnnotations, {1: true, 2: true})
it 'updates the selection counter when the selection changes', ->
fakeAnnotationUI.selectedAnnotationMap = {1: true, 2: true}
annotationUI.selectedAnnotationMap = {1: true, 2: true}
$rootScope.$digest()
assert.deepEqual($scope.selectedAnnotationsCount, 2)
it 'clears the selection when no annotations are selected', ->
fakeAnnotationUI.selectedAnnotationMap = {}
annotationUI.selectedAnnotationMap = {}
$rootScope.$digest()
assert.deepEqual($scope.selectedAnnotations, null)
assert.deepEqual($scope.selectedAnnotationsCount, 0)
it 'updates the focused annotations when the focus map changes', ->
fakeAnnotationUI.focusedAnnotationMap = {1: true, 2: true}
annotationUI.focusedAnnotationMap = {1: true, 2: true}
$rootScope.$digest()
assert.deepEqual($scope.focusedAnnotations, {1: true, 2: true})
describe 'on annotationsLoaded', ->
it 'enqueues a re-render of the current scope', ->
target = sandbox.stub($scope, '$evalAsync')
$rootScope.$emit('annotationsLoaded', [{}, {}, {}])
assert.called(target)
describe 'on getDocumentInfo', ->
it 'enqueues a re-render of the current scope', ->
target = sandbox.stub($scope, '$evalAsync')
$rootScope.$emit('getDocumentInfo', [{}, {}, {}])
assert.called(target)
describe 'on annotationDeleted', ->
it 'removes the deleted annotation from the selection', ->
$rootScope.$emit('annotationDeleted', {id: 1})
assert.calledWith(fakeAnnotationUI.removeSelectedAnnotation, {id: 1})
assert.calledWith(annotationUI.removeSelectedAnnotation, {id: 1})
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