Skip to content

Commit

Permalink
Merge pull request #3131 from hypothesis/t256-annotation-ui-decaf
Browse files Browse the repository at this point in the history
Convert AnnotationUI, AnnotationUISync from CoffeeScript to JS
  • Loading branch information
nickstenning committed Mar 24, 2016
2 parents 5c2f69a + ec61471 commit 3b165f0
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 251 deletions.
18 changes: 0 additions & 18 deletions h/static/scripts/annotation-ui-controller.coffee

This file was deleted.

32 changes: 32 additions & 0 deletions h/static/scripts/annotation-ui-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

/** Watch the UI state and update scope properties. */
// @ngInject
function AnnotationUIController($rootScope, $scope, annotationUI) {
$rootScope.$watch(function () {
return annotationUI.selectedAnnotationMap;
}, function (map) {
map = map || {};
var count = Object.keys(map).length;
$scope.selectedAnnotationsCount = count;

if (count) {
$scope.selectedAnnotations = map;
} else {
$scope.selectedAnnotations = null;
}
});

$rootScope.$watch(function () {
return annotationUI.focusedAnnotationMap;
}, function (map) {
map = map || {};
$scope.focusedAnnotations = map;
});

$rootScope.$on('annotationDeleted', function (event, annotation) {
annotationUI.removeSelectedAnnotation(annotation);
});
}

module.exports = AnnotationUIController;
54 changes: 0 additions & 54 deletions h/static/scripts/annotation-ui-sync.coffee

This file was deleted.

82 changes: 82 additions & 0 deletions h/static/scripts/annotation-ui-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

/**
* Uses a channel between the sidebar and the attached frames to ensure
* the interface remains in sync.
*
* @name AnnotationUISync
* @param {$window} $window An Angular window service.
* @param {Bridge} bridge
* @param {AnnotationSync} annotationSync
* @param {AnnotationUI} annotationUI An instance of the AnnotatonUI service
* @description
* Listens for incoming events over the bridge concerning the annotation
* interface and updates the applications internal state. It also ensures
* that the messages are broadcast out to other frames.
*/
// @ngInject
function AnnotationUISync($rootScope, $window, bridge, annotationSync,
annotationUI) {
// Retrieves annotations from the annotationSync cache.
var getAnnotationsByTags = function (tags) {
return tags.map(annotationSync.getAnnotationForTag, annotationSync);
};

var channelListeners = {
showAnnotations: function (tags) {
tags = tags || [];
var annotations = getAnnotationsByTags(tags);
annotationUI.selectAnnotations(annotations);
},
focusAnnotations: function (tags) {
tags = tags || [];
var annotations = getAnnotationsByTags(tags);
annotationUI.focusAnnotations(annotations);
},
toggleAnnotationSelection: function (tags) {
tags = tags || [];
var annotations = getAnnotationsByTags(tags);
annotationUI.xorSelectedAnnotations(annotations);
},
setVisibleHighlights: function (state) {
if (typeof state !== 'boolean') {
state = true;
}
if (annotationUI.visibleHighlights !== state) {
annotationUI.visibleHighlights = state;
bridge.call('setVisibleHighlights', state);
}
}
};

// Because the channel events are all outside of the angular framework we
// need to inform Angular that it needs to re-check it's state and re-draw
// any UI that may have been affected by the handlers.
var ensureDigest = function (fn) {
return function () {
fn.apply(this, arguments);
$rootScope.$digest();
};
};

for (var channel in channelListeners) {
if (Object.prototype.hasOwnProperty.call(channelListeners, channel)) {
var listener = channelListeners[channel];
bridge.on(channel, ensureDigest(listener));
}
}

var onConnect = function (channel, source) {
if (source === $window.parent) {
// The host initializes its own state
return;
} else {
// Synchronize the state of guests
channel.call('setVisibleHighlights', annotationUI.visibleHighlights);
}
};

bridge.onConnect(onConnect);
}

module.exports = AnnotationUISync;
56 changes: 0 additions & 56 deletions h/static/scripts/test/annotation-ui-controller-test.coffee

This file was deleted.

73 changes: 73 additions & 0 deletions h/static/scripts/test/annotation-ui-controller-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
'use strict';

var angular = require('angular');

describe('AnnotationUIController', function () {
var $scope;
var $rootScope;
var annotationUI;
var sandbox;

before(function () {
angular.module('h', [])
.controller('AnnotationUIController',
require('../annotation-ui-controller'));
});

beforeEach(angular.mock.module('h'));
beforeEach(angular.mock.inject(function ($controller, _$rootScope_) {
sandbox = sinon.sandbox.create();

$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$scope.search = {};

annotationUI = {
tool: 'comment',
selectedAnnotationMap: null,
focusedAnnotationsMap: null,
removeSelectedAnnotation: sandbox.stub()
};

$controller('AnnotationUIController', {
$scope: $scope,
annotationUI: annotationUI,
});
}));

afterEach(function () {
sandbox.restore();
});

it('updates the view when the selection changes', function () {
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', function () {
annotationUI.selectedAnnotationMap = { 1: true, 2: true };
$rootScope.$digest();
assert.deepEqual($scope.selectedAnnotationsCount, 2);
});

it('clears the selection when no annotations are selected', function () {
annotationUI.selectedAnnotationMap = {};
$rootScope.$digest();
assert.deepEqual($scope.selectedAnnotations, null);
assert.deepEqual($scope.selectedAnnotationsCount, 0);
});

it('updates the focused annotations when the focus map changes', function () {
annotationUI.focusedAnnotationMap = { 1: true, 2: true };
$rootScope.$digest();
assert.deepEqual($scope.focusedAnnotations, { 1: true, 2: true });
});

describe('on annotationDeleted', function () {
it('removes the deleted annotation from the selection', function () {
$rootScope.$emit('annotationDeleted', { id: 1 });
assert.calledWith(annotationUI.removeSelectedAnnotation, { id: 1 });
});
});
});

0 comments on commit 3b165f0

Please sign in to comment.