diff --git a/src/lib/viewers/BaseViewer.js b/src/lib/viewers/BaseViewer.js index 7d3115321..e5e57ac15 100644 --- a/src/lib/viewers/BaseViewer.js +++ b/src/lib/viewers/BaseViewer.js @@ -966,6 +966,9 @@ class BaseViewer extends EventEmitter { * @return {void} */ initAnnotations() { + // Annotations must be loaded and ready before scrolling can occur on a deep-linked annotation. + this.annotator.addListener('annotations_initialized', this.handleAnnotationsInitialized); + this.annotator.init(this.scale); // Once the annotator instance has been created, emit it so that clients can attach their events. @@ -1037,6 +1040,27 @@ class BaseViewer extends EventEmitter { this.annotator.scrollToAnnotation(data); } + /** + * Handles retrieving the active annotation id from a deep-linked annotation and scrolls to the annotation. + * @param {Object} event - annotations array from emitted from box-annotations. + * @param {Array} event.annotations - annotations array from emitted from box-annotations. + * @return {void} + */ + handleAnnotationsInitialized = ({ annotations = [] }) => { + const { + file: { id }, + } = this.options; + + const activeAnnotationId = getProp(this.options, `fileOptions.${id}.annotations.activeId`, null); + const annotation = annotations.find(entry => entry.id === activeAnnotationId); + + if (!annotation) { + return; + } + + this.handleScrollToAnnotation(annotation); + }; + /** * Returns whether or not annotations are enabled for this viewer. * diff --git a/src/lib/viewers/__tests__/BaseViewer-test.js b/src/lib/viewers/__tests__/BaseViewer-test.js index 48b3d177f..9a285f686 100644 --- a/src/lib/viewers/__tests__/BaseViewer-test.js +++ b/src/lib/viewers/__tests__/BaseViewer-test.js @@ -1189,8 +1189,12 @@ describe('lib/viewers/BaseViewer', () => { expect(base.addListener).to.be.calledWith('toggleannotationmode', sinon.match.func); expect(base.addListener).to.be.calledWith('scale', sinon.match.func); expect(base.addListener).to.be.calledWith('scrolltoannotation', base.handleScrollToAnnotation); - expect(base.annotator.addListener).to.be.calledWith('annotations_create', base.handleAnnotationCreateEvent); expect(base.annotator.addListener).to.be.calledWith('annotatorevent', sinon.match.func); + expect(base.annotator.addListener).to.be.calledWith('annotations_create', base.handleAnnotationCreateEvent); + expect(base.annotator.addListener).to.be.calledWith( + 'annotations_initialized', + base.handleAnnotationsInitialized, + ); expect(base.emit).to.be.calledWith('annotator', base.annotator); }); @@ -1296,6 +1300,44 @@ describe('lib/viewers/BaseViewer', () => { }); }); + describe('handleAnnotationsInitialized()', () => { + let scrollToAnnotationStub; + + beforeEach(() => { + scrollToAnnotationStub = sandbox.stub(); + + base.annotator = { + init: sandbox.stub(), + scrollToAnnotation: scrollToAnnotationStub, + }; + }); + + it('should not call handleScrollToAnnotation if there is not an active annotation', () => { + base.options.fileOptions = { + '0': { + annotations: {}, + }, + }; + + base.handleAnnotationsInitialized({ annotations: [{ id: '123' }] }); + + expect(scrollToAnnotationStub).not.to.be.called; + }); + it('should call scroll to annotation if active annotation is set', () => { + base.options.fileOptions = { + '0': { + annotations: { + activeId: 'ABC', + }, + }, + }; + + base.handleAnnotationsInitialized({ annotations: [{ id: 'ABC' }] }); + + expect(scrollToAnnotationStub).to.be.calledWith('ABC'); + }); + }); + describe('areAnnotationsEnabled()', () => { beforeEach(() => { stubs.getViewerOption = sandbox