Commit 11abab35 authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #287 from hypothesis/use-ng-components

Convert element directives to components
parents dc979501 fff61fda
...@@ -135,38 +135,41 @@ module.exports = angular.module('h', [ ...@@ -135,38 +135,41 @@ module.exports = angular.module('h', [
// The root component for the application // The root component for the application
.directive('hypothesisApp', require('./directive/app')) .directive('hypothesisApp', require('./directive/app'))
// UI components and helpers // UI components
.directive('annotation', require('./directive/annotation').directive) .component('annotation', require('./directive/annotation').component)
.directive('annotationShareDialog', require('./directive/annotation-share-dialog')) .component('annotationShareDialog', require('./directive/annotation-share-dialog'))
.directive('annotationThread', require('./directive/annotation-thread')) .component('annotationThread', require('./directive/annotation-thread'))
.directive('dropdownMenuBtn', require('./directive/dropdown-menu-btn')) .component('dropdownMenuBtn', require('./directive/dropdown-menu-btn'))
.component('helpLink', require('./directive/help-link'))
.component('helpPanel', require('./directive/help-panel'))
.component('loggedoutMessage', require('./directive/loggedout-message'))
.component('loginControl', require('./directive/login-control'))
.component('loginForm', require('./directive/login-form').component)
.component('publishAnnotationBtn', require('./directive/publish-annotation-btn'))
.component('searchInput', require('./directive/search-input'))
.component('searchStatusBar', require('./directive/search-status-bar'))
.component('selectionTabs', require('./directive/selection-tabs'))
.component('sidebarTutorial', require('./directive/sidebar-tutorial').component)
.component('shareDialog', require('./directive/share-dialog'))
.component('sortDropdown', require('./directive/sort-dropdown'))
.component('svgIcon', require('./directive/svg-icon'))
.component('tagEditor', require('./directive/tag-editor'))
.component('threadList', require('./directive/thread-list'))
.component('timestamp', require('./directive/timestamp'))
// These should use `component()` but will require some changes.
.directive('groupList', require('./directive/group-list').directive)
.directive('markdown', require('./directive/markdown'))
.directive('topBar', require('./directive/top-bar'))
.directive('excerpt', require('./directive/excerpt').directive) .directive('excerpt', require('./directive/excerpt').directive)
.directive('formInput', require('./directive/form-input')) .directive('formInput', require('./directive/form-input'))
.directive('formValidate', require('./directive/form-validate')) .directive('formValidate', require('./directive/form-validate'))
.directive('groupList', require('./directive/group-list').directive)
.directive('helpLink', require('./directive/help-link'))
.directive('helpPanel', require('./directive/help-panel'))
.directive('hAutofocus', require('./directive/h-autofocus')) .directive('hAutofocus', require('./directive/h-autofocus'))
.directive('hOnTouch', require('./directive/h-on-touch')) .directive('hOnTouch', require('./directive/h-on-touch'))
.directive('hTooltip', require('./directive/h-tooltip')) .directive('hTooltip', require('./directive/h-tooltip'))
.directive('loggedoutMessage', require('./directive/loggedout-message'))
.directive('loginControl', require('./directive/login-control'))
.directive('loginForm', require('./directive/login-form').directive)
.directive('markdown', require('./directive/markdown'))
.directive('publishAnnotationBtn', require('./directive/publish-annotation-btn'))
.directive('searchStatusBar', require('./directive/search-status-bar'))
.directive('shareDialog', require('./directive/share-dialog'))
.directive('sidebarTutorial', require('./directive/sidebar-tutorial').directive)
.directive('searchInput', require('./directive/search-input'))
.directive('selectionTabs', require('./directive/selection-tabs'))
.directive('sortDropdown', require('./directive/sort-dropdown'))
.directive('spinner', require('./directive/spinner')) .directive('spinner', require('./directive/spinner'))
.directive('statusButton', require('./directive/status-button')) .directive('statusButton', require('./directive/status-button'))
.directive('svgIcon', require('./directive/svg-icon'))
.directive('tagEditor', require('./directive/tag-editor'))
.directive('threadList', require('./directive/thread-list'))
.directive('timestamp', require('./directive/timestamp'))
.directive('topBar', require('./directive/top-bar'))
.directive('windowScroll', require('./directive/window-scroll')) .directive('windowScroll', require('./directive/window-scroll'))
.service('analytics', require('./analytics')) .service('analytics', require('./analytics'))
......
...@@ -4,73 +4,69 @@ var angular = require('angular'); ...@@ -4,73 +4,69 @@ var angular = require('angular');
var scopeTimeout = require('../util/scope-timeout'); var scopeTimeout = require('../util/scope-timeout');
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
bindToController: true, template: require('../templates/annotation_share_dialog.html'),
controllerAs: 'vm', // @ngInject
restrict: 'E', controller: function ($scope, $element) {
template: require('../templates/annotation_share_dialog.html'), var shareLinkInput = $element.find('input')[0];
// @ngInject
controller: function ($scope, $element) {
var shareLinkInput = $element.find('input')[0];
$scope.$watch('vm.isOpen', function (isOpen) { $scope.$watch('vm.isOpen', function (isOpen) {
if (isOpen) { if (isOpen) {
// Focus the input and select it once the dialog has become visible // Focus the input and select it once the dialog has become visible
scopeTimeout($scope, function () { scopeTimeout($scope, function () {
shareLinkInput.focus(); shareLinkInput.focus();
shareLinkInput.select(); shareLinkInput.select();
}); });
var hideListener = function (event) { var hideListener = function (event) {
$scope.$apply(function () { $scope.$apply(function () {
if (!$element[0].contains(event.target)) { if (!$element[0].contains(event.target)) {
document.removeEventListener('click', hideListener); document.removeEventListener('click', hideListener);
this.onClose(); this.onClose();
} }
}.bind(this)); }.bind(this));
}.bind(this); }.bind(this);
// Stop listening for clicks outside the dialog once it is closed. // Stop listening for clicks outside the dialog once it is closed.
// The setTimeout() here is to ignore the initial click that opens // The setTimeout() here is to ignore the initial click that opens
// the dialog. // the dialog.
scopeTimeout($scope, function () { scopeTimeout($scope, function () {
document.addEventListener('click', hideListener); document.addEventListener('click', hideListener);
}, 0); }, 0);
} }
}.bind(this)); }.bind(this));
this.copyToClipboard = function (event) { this.copyToClipboard = function (event) {
var $container = angular.element(event.currentTarget).parent(); var $container = angular.element(event.currentTarget).parent();
var shareLinkInput = $container.find('input')[0]; var shareLinkInput = $container.find('input')[0];
try { try {
shareLinkInput.select(); shareLinkInput.select();
// In some browsers, execCommand() returns false if it fails, // In some browsers, execCommand() returns false if it fails,
// in others, it may throw an exception instead. // in others, it may throw an exception instead.
if (!document.execCommand('copy')) { if (!document.execCommand('copy')) {
throw new Error('Copying link failed'); throw new Error('Copying link failed');
}
this.copyToClipboardMessage = 'Link copied to clipboard!';
} catch (ex) {
this.copyToClipboardMessage = 'Select and copy to share.';
} finally {
setTimeout(function () {
this.copyToClipboardMessage = null;
$scope.$digest();
}.bind(this),
1000);
} }
}.bind(this);
}, this.copyToClipboardMessage = 'Link copied to clipboard!';
scope: { } catch (ex) {
group: '<', this.copyToClipboardMessage = 'Select and copy to share.';
uri: '<', } finally {
isPrivate: '<', setTimeout(function () {
isOpen: '<', this.copyToClipboardMessage = null;
onClose: '&', $scope.$digest();
}, }.bind(this),
}; 1000);
}
}.bind(this);
},
bindings: {
group: '<',
uri: '<',
isPrivate: '<',
isOpen: '<',
onClose: '&',
},
}; };
...@@ -97,28 +97,24 @@ function AnnotationThreadController() { ...@@ -97,28 +97,24 @@ function AnnotationThreadController() {
/** /**
* Renders a thread of annotations. * Renders a thread of annotations.
*/ */
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
restrict: 'E', controller: AnnotationThreadController,
bindToController: true, bindings: {
controllerAs: 'vm', /** The annotation thread to render. */
controller: AnnotationThreadController, thread: '<',
scope: { /**
/** The annotation thread to render. */ * Specify whether document information should be shown
thread: '<', * on annotation cards.
/** */
* Specify whether document information should be shown showDocumentInfo: '<',
* on annotation cards. /** Called when the user clicks on the expand/collapse replies toggle. */
*/ onChangeCollapsed: '&',
showDocumentInfo: '<', /**
/** Called when the user clicks on the expand/collapse replies toggle. */ * Called when the user clicks the button to show this thread or
onChangeCollapsed: '&', * one of its replies.
/** */
* Called when the user clicks the button to show this thread or onForceVisible: '&',
* one of its replies. },
*/ template: require('../templates/annotation_thread.html'),
onForceVisible: '&',
},
template: require('../templates/annotation_thread.html'),
};
}; };
...@@ -556,23 +556,18 @@ function AnnotationController( ...@@ -556,23 +556,18 @@ function AnnotationController(
init(); init();
} }
// @ngInject var component = {
function annotation() { controller: AnnotationController,
return { controllerAs: 'vm',
restrict: 'E', bindings: {
bindToController: true, annotation: '<',
controller: AnnotationController, showDocumentInfo: '<',
controllerAs: 'vm', onReplyCountClick: '&',
scope: { replyCount: '<',
annotation: '<', isCollapsed: '<',
showDocumentInfo: '<', },
onReplyCountClick: '&', template: require('../templates/annotation.html'),
replyCount: '<', };
isCollapsed: '<',
},
template: require('../templates/annotation.html'),
};
}
module.exports = { module.exports = {
// These private helper functions aren't meant to be part of the public // These private helper functions aren't meant to be part of the public
...@@ -583,6 +578,6 @@ module.exports = { ...@@ -583,6 +578,6 @@ module.exports = {
updateModel: updateModel, updateModel: updateModel,
// These are meant to be the public API of this module. // These are meant to be the public API of this module.
directive: annotation, component: component,
Controller: AnnotationController, Controller: AnnotationController,
}; };
'use strict'; 'use strict';
// @ngInject // @ngInject
function DropdownMenuBtnController($scope, $timeout) { function DropdownMenuBtnController($timeout) {
this.onClick = function () { var self = this;
$scope.onClick();
};
this.toggleDropdown = function($event) { this.toggleDropdown = function($event) {
$event.stopPropagation(); $event.stopPropagation();
$timeout(function () { $timeout(function () {
$scope.onToggleDropdown(); self.onToggleDropdown();
}, 0); }, 0);
}; };
} }
module.exports = function () { module.exports = {
return { controller: DropdownMenuBtnController,
controller: DropdownMenuBtnController, controllerAs: 'vm',
controllerAs: 'vm', bindings: {
restrict: 'E', isDisabled: '<',
scope: { label: '<',
isDisabled: '<', dropdownMenuLabel: '@',
label: '<', onClick: '&',
dropdownMenuLabel: '@', onToggleDropdown: '&',
onClick: '&', },
onToggleDropdown: '&', template: require('../templates/dropdown_menu_btn.html'),
},
template: require('../templates/dropdown_menu_btn.html'),
};
}; };
'use strict'; 'use strict';
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
bindToController: true, template: require('../templates/help_link.html'),
controllerAs: 'vm', controller: function () {},
restrict: 'E', scope: {
template: require('../templates/help_link.html'), version: '<',
controller: function () {}, userAgent: '<',
scope: { url: '<',
version: '<', documentFingerprint: '<',
userAgent: '<', auth: '<',
url: '<', dateTime: '<',
documentFingerprint: '<', },
auth: '<',
dateTime: '<',
},
};
}; };
...@@ -6,35 +6,31 @@ ...@@ -6,35 +6,31 @@
* @description Displays product version and environment info * @description Displays product version and environment info
*/ */
// @ngInject // @ngInject
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
bindToController: true, // @ngInject
controllerAs: 'vm', controller: function ($scope, $window, annotationUI, serviceUrl) {
// @ngInject this.userAgent = $window.navigator.userAgent;
controller: function ($scope, $window, annotationUI, serviceUrl) { this.version = '__VERSION__'; // replaced by versionify
this.userAgent = $window.navigator.userAgent; this.dateTime = new Date();
this.version = '__VERSION__'; // replaced by versionify this.serviceUrl = serviceUrl;
this.dateTime = new Date();
this.serviceUrl = serviceUrl;
$scope.$watch( $scope.$watch(
function () { function () {
return annotationUI.frames(); return annotationUI.frames();
}, },
function (frames) { function (frames) {
if (frames.length === 0) { if (frames.length === 0) {
return; return;
} }
this.url = frames[0].uri; this.url = frames[0].uri;
this.documentFingerprint = frames[0].documentFingerprint; this.documentFingerprint = frames[0].documentFingerprint;
}.bind(this) }.bind(this)
); );
}, },
restrict: 'E', template: require('../templates/help_panel.html'),
template: require('../templates/help_panel.html'), bindings: {
scope: { auth: '<',
auth: '<', onClose: '&',
onClose: '&', },
},
};
}; };
'use strict'; 'use strict';
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
bindToController: true, //@ngInject
controllerAs: 'vm', controller: function (serviceUrl) {
//@ngInject this.serviceUrl = serviceUrl;
controller: function (serviceUrl) { },
this.serviceUrl = serviceUrl; bindings: {
}, /**
restrict: 'E', * Called when the user clicks on the "Log in" text.
scope: { */
/** onLogin: '&',
* Called when the user clicks on the "Log in" text. },
*/ template: require('../templates/loggedout_message.html'),
onLogin: '&',
},
template: require('../templates/loggedout_message.html'),
};
}; };
...@@ -2,42 +2,38 @@ ...@@ -2,42 +2,38 @@
var persona = require('../filter/persona'); var persona = require('../filter/persona');
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
bindToController: true, //@ngInject
controllerAs: 'vm', controller: function (serviceUrl, settings) {
//@ngInject this.serviceUrl = serviceUrl;
controller: function (serviceUrl, settings) { this.isThirdPartyUser = function() {
this.serviceUrl = serviceUrl; return persona.isThirdPartyUser(this.auth.userid, settings.authDomain);
this.isThirdPartyUser = function() { };
return persona.isThirdPartyUser(this.auth.userid, settings.authDomain); },
}; bindings: {
}, /**
restrict: 'E', * An object representing the current authentication status.
scope: { */
/** auth: '<',
* An object representing the current authentication status. /**
*/ * Called when the user clicks on the "About this version" text.
auth: '<', */
/** onShowHelpPanel: '&',
* Called when the user clicks on the "About this version" text. /**
*/ * Called when the user clicks on the "Log in" text.
onShowHelpPanel: '&', */
/** onLogin: '&',
* Called when the user clicks on the "Log in" text. /**
*/ * Called when the user clicks on the "Log out" text.
onLogin: '&', */
/** onLogout: '&',
* Called when the user clicks on the "Log out" text. /**
*/ * Whether or not to use the new design for the control.
onLogout: '&', *
/** * FIXME: should be removed when the old design is deprecated.
* Whether or not to use the new design for the control. */
* newStyle: '<',
* FIXME: should be removed when the old design is deprecated. },
*/ template: require('../templates/login_control.html'),
newStyle: '<',
},
template: require('../templates/login_control.html'),
};
}; };
...@@ -93,18 +93,16 @@ function Controller($scope, $timeout, flash, session, formRespond, serviceUrl) { ...@@ -93,18 +93,16 @@ function Controller($scope, $timeout, flash, session, formRespond, serviceUrl) {
}); });
} }
module.exports = { var component = {
directive: function () { controller: Controller,
return { controllerAs: 'vm',
bindToController: true, bindings: {
controller: Controller, onClose: '&',
controllerAs: 'vm',
restrict: 'E',
scope: {
onClose: '&',
},
template: require('../templates/login_form.html'),
};
}, },
template: require('../templates/login_form.html'),
};
module.exports = {
component: component,
Controller: Controller, Controller: Controller,
}; };
'use strict'; 'use strict';
/** /**
* @ngdoc directive
* @name publishAnnotationBtn
* @description Displays a combined privacy/selection post button to post * @description Displays a combined privacy/selection post button to post
* a new annotation * a new annotation
*/ */
// @ngInject // @ngInject
module.exports = function () { module.exports = {
return { controller: function () {
bindToController: true, this.showDropdown = false;
controller: function () { this.privateLabel = 'Only Me';
this.showDropdown = false;
this.privateLabel = 'Only Me';
this.publishDestination = function () { this.publishDestination = function () {
return this.isShared ? this.group.name : this.privateLabel; return this.isShared ? this.group.name : this.privateLabel;
}; };
this.groupType = function () { this.groupType = function () {
return this.group.public ? 'public' : 'group'; return this.group.public ? 'public' : 'group';
}; };
this.setPrivacy = function (level) { this.setPrivacy = function (level) {
this.onSetPrivacy({level: level}); this.onSetPrivacy({level: level});
}; };
}, },
controllerAs: 'vm', controllerAs: 'vm',
restrict: 'E', bindings: {
scope: { group: '<',
group: '<', canPost: '<',
canPost: '<', isShared: '<',
isShared: '<', onCancel: '&',
onCancel: '&', onSave: '&',
onSave: '&', onSetPrivacy: '&',
onSetPrivacy: '&', },
}, template: require('../templates/publish_annotation_btn.html'),
template: require('../templates/publish_annotation_btn.html'),
};
}; };
...@@ -32,22 +32,17 @@ function SearchInputController($element, $http, $scope) { ...@@ -32,22 +32,17 @@ function SearchInputController($element, $http, $scope) {
}; };
} }
// @ngInject module.exports = {
module.exports = function () { controller: SearchInputController,
return { controllerAs: 'vm',
bindToController: true, bindings: {
controller: SearchInputController, // Specifies whether the search input field should always be expanded,
controllerAs: 'vm', // regardless of whether the it is focused or has an active query.
restrict: 'E', //
scope: { // If false, it is only expanded when focused or when 'query' is non-empty
// Specifies whether the search input field should always be expanded, alwaysExpanded: '<',
// regardless of whether the it is focused or has an active query. query: '<',
// onSearch: '&',
// If false, it is only expanded when focused or when 'query' is non-empty },
alwaysExpanded: '<', template: require('../templates/search_input.html'),
query: '<',
onSearch: '&',
},
template: require('../templates/search_input.html'),
};
}; };
...@@ -2,27 +2,22 @@ ...@@ -2,27 +2,22 @@
var uiConstants = require('../ui-constants'); var uiConstants = require('../ui-constants');
// @ngInject module.exports = {
module.exports = function () { controllerAs: 'vm',
return { controller: function () {
bindToController: true, this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS;
controllerAs: 'vm', this.TAB_NOTES = uiConstants.TAB_NOTES;
controller: function () { this.TAB_ORPHANS = uiConstants.TAB_ORPHANS;
this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS; },
this.TAB_NOTES = uiConstants.TAB_NOTES; bindings: {
this.TAB_ORPHANS = uiConstants.TAB_ORPHANS; filterActive: '<',
}, filterMatchCount: '<',
restrict: 'E', onClearSelection: '&',
scope: { searchQuery: '<',
filterActive: '<', selectedTab: '<',
filterMatchCount: '<', selectionCount: '<',
onClearSelection: '&', totalAnnotations: '<',
searchQuery: '<', totalNotes: '<',
selectedTab: '<', },
selectionCount: '<', template: require('../templates/search_status_bar.html'),
totalAnnotations: '<',
totalNotes: '<',
},
template: require('../templates/search_status_bar.html'),
};
}; };
...@@ -2,45 +2,41 @@ ...@@ -2,45 +2,41 @@
var uiConstants = require('../ui-constants'); var uiConstants = require('../ui-constants');
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
bindToController: true, //@ngInject
controllerAs: 'vm', controller: function ($element, annotationUI, features) {
//@ngInject this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS;
controller: function ($element, annotationUI, features) { this.TAB_NOTES = uiConstants.TAB_NOTES;
this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS; this.TAB_ORPHANS = uiConstants.TAB_ORPHANS;
this.TAB_NOTES = uiConstants.TAB_NOTES;
this.TAB_ORPHANS = uiConstants.TAB_ORPHANS;
this.selectTab = function (type) { this.selectTab = function (type) {
annotationUI.clearSelectedAnnotations(); annotationUI.clearSelectedAnnotations();
annotationUI.selectTab(type); annotationUI.selectTab(type);
}; };
this.orphansTabFlagEnabled = function () { this.orphansTabFlagEnabled = function () {
return features.flagEnabled('orphans_tab'); return features.flagEnabled('orphans_tab');
}; };
this.showAnnotationsUnavailableMessage = function () { this.showAnnotationsUnavailableMessage = function () {
return this.selectedTab === this.TAB_ANNOTATIONS && return this.selectedTab === this.TAB_ANNOTATIONS &&
this.totalAnnotations === 0 && this.totalAnnotations === 0 &&
!this.isWaitingToAnchorAnnotations; !this.isWaitingToAnchorAnnotations;
}; };
this.showNotesUnavailableMessage = function () { this.showNotesUnavailableMessage = function () {
return this.selectedTab === this.TAB_NOTES && return this.selectedTab === this.TAB_NOTES &&
this.totalNotes === 0; this.totalNotes === 0;
}; };
}, },
restrict: 'E', bindings: {
scope: { isLoading: '<',
isLoading: '<', isWaitingToAnchorAnnotations: '<',
isWaitingToAnchorAnnotations: '<', selectedTab: '<',
selectedTab: '<', totalAnnotations: '<',
totalAnnotations: '<', totalNotes: '<',
totalNotes: '<', totalOrphans: '<',
totalOrphans: '<', },
}, template: require('../templates/selection_tabs.html'),
template: require('../templates/selection_tabs.html'),
};
}; };
...@@ -28,15 +28,11 @@ function ShareDialogController($scope, $element, annotationUI) { ...@@ -28,15 +28,11 @@ function ShareDialogController($scope, $element, annotationUI) {
updateViaLink); updateViaLink);
} }
module.exports = function () { module.exports = {
return { controller: ShareDialogController,
restrict: 'E', controllerAs: 'vm',
bindToController: true, bindings: {
controller: ShareDialogController, onClose: '&',
controllerAs: 'vm', },
scope: { template: require('../templates/share_dialog.html'),
onClose: '&',
},
template: require('../templates/share_dialog.html'),
};
}; };
...@@ -17,21 +17,16 @@ function SidebarTutorialController(session) { ...@@ -17,21 +17,16 @@ function SidebarTutorialController(session) {
} }
/** /**
* @ngdoc directive
* @name sidebarTutorial * @name sidebarTutorial
* @description Displays a short tutorial in the sidebar. * @description Displays a short tutorial in the sidebar.
*/ */
// @ngInject // @ngInject
module.exports = { module.exports = {
directive: function () { component: {
return { controller: SidebarTutorialController,
bindToController: true, controllerAs: 'vm',
controller: SidebarTutorialController, bindings: {},
controllerAs: 'vm', template: require('../templates/sidebar_tutorial.html'),
restrict: 'E',
scope: {},
template: require('../templates/sidebar_tutorial.html'),
};
}, },
Controller: SidebarTutorialController, Controller: SidebarTutorialController,
}; };
'use strict'; 'use strict';
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
controller: function () {}, controller: function () {},
restrict: 'E', bindings: {
scope: { /** The name of the currently selected sort key. */
/** The name of the currently selected sort key. */ sortKey: '<',
sortKey: '<', /** A list of possible keys that the user can opt to sort by. */
/** A list of possible keys that the user can opt to sort by. */ sortKeysAvailable: '<',
sortKeysAvailable: '<', /** Called when the user changes the sort key. */
/** Called when the user changes the sort key. */ onChangeSortKey: '&',
onChangeSortKey: '&', },
}, template: require('../templates/sort_dropdown.html'),
template: require('../templates/sort_dropdown.html'),
};
}; };
...@@ -21,15 +21,11 @@ function SvgIconController($element) { ...@@ -21,15 +21,11 @@ function SvgIconController($element) {
$element[0].innerHTML = icons[this.name]; $element[0].innerHTML = icons[this.name];
} }
module.exports = function () { module.exports = {
return { controllerAs: 'vm',
bindToController: true, controller: SvgIconController,
controllerAs: 'vm', bindings: {
restrict: 'E', /** The name of the icon to load. */
controller: SvgIconController, name: '<',
scope: { },
/** The name of the icon to load. */
name: '<',
},
};
}; };
...@@ -22,16 +22,12 @@ function TagEditorController(tags) { ...@@ -22,16 +22,12 @@ function TagEditorController(tags) {
}; };
} }
module.exports = function () { module.exports = {
return { controller: TagEditorController,
bindToController: true, controllerAs: 'vm',
controller: TagEditorController, bindings: {
controllerAs: 'vm', tags: '<',
restrict: 'E', onEditTags: '&',
scope: { },
tags: '<', template: require('../templates/tag_editor.html'),
onEditTags: '&',
},
template: require('../templates/tag_editor.html'),
};
}; };
...@@ -13,7 +13,7 @@ describe('annotationShareDialog', function () { ...@@ -13,7 +13,7 @@ describe('annotationShareDialog', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('annotationShareDialog', .component('annotationShareDialog',
require('../annotation-share-dialog')) require('../annotation-share-dialog'))
.value('urlEncodeFilter', function (val) { return val; }); .value('urlEncodeFilter', function (val) { return val; });
}); });
......
...@@ -20,7 +20,7 @@ var fakeDocumentMeta = { ...@@ -20,7 +20,7 @@ var fakeDocumentMeta = {
/** /**
* Returns the annotation directive with helpers stubbed out. * Returns the annotation directive with helpers stubbed out.
*/ */
function annotationDirective() { function annotationComponent() {
var noop = function () { return ''; }; var noop = function () { return ''; };
var annotation = proxyquire('../annotation', { var annotation = proxyquire('../annotation', {
...@@ -35,7 +35,7 @@ function annotationDirective() { ...@@ -35,7 +35,7 @@ function annotationDirective() {
}, },
}); });
return annotation.directive; return annotation.component;
} }
describe('annotation', function() { describe('annotation', function() {
...@@ -116,7 +116,7 @@ describe('annotation', function() { ...@@ -116,7 +116,7 @@ describe('annotation', function() {
before(function() { before(function() {
angular.module('h', []) angular.module('h', [])
.directive('annotation', annotationDirective()); .component('annotation', annotationComponent());
}); });
beforeEach(angular.mock.module('h')); beforeEach(angular.mock.module('h'));
......
...@@ -25,7 +25,7 @@ function PageObject(element) { ...@@ -25,7 +25,7 @@ function PageObject(element) {
describe('annotationThread', function () { describe('annotationThread', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('annotationThread', annotationThread); .component('annotationThread', annotationThread);
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -28,7 +28,7 @@ function PageObject(element) { ...@@ -28,7 +28,7 @@ function PageObject(element) {
describe('loginControl', function () { describe('loginControl', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('loginControl', require('../login-control')); .component('loginControl', require('../login-control'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -17,8 +17,8 @@ var fakeLocalStorage = { ...@@ -17,8 +17,8 @@ var fakeLocalStorage = {
describe('publishAnnotationBtn', function () { describe('publishAnnotationBtn', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('dropdownMenuBtn', require('../dropdown-menu-btn')) .component('dropdownMenuBtn', require('../dropdown-menu-btn'))
.directive('publishAnnotationBtn', require('../publish-annotation-btn')) .component('publishAnnotationBtn', require('../publish-annotation-btn'))
.factory('localStorage', function () { .factory('localStorage', function () {
return fakeLocalStorage; return fakeLocalStorage;
}); });
......
...@@ -9,7 +9,7 @@ describe('searchInput', function () { ...@@ -9,7 +9,7 @@ describe('searchInput', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('searchInput', require('../search-input')); .component('searchInput', require('../search-input'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -7,7 +7,7 @@ var util = require('./util'); ...@@ -7,7 +7,7 @@ var util = require('./util');
describe('searchStatusBar', function () { describe('searchStatusBar', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('searchStatusBar', require('../search-status-bar')); .component('searchStatusBar', require('../search-status-bar'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -7,7 +7,7 @@ var util = require('./util'); ...@@ -7,7 +7,7 @@ var util = require('./util');
describe('selectionTabs', function () { describe('selectionTabs', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('selectionTabs', require('../selection-tabs')); .component('selectionTabs', require('../selection-tabs'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -11,7 +11,7 @@ describe('shareDialog', function () { ...@@ -11,7 +11,7 @@ describe('shareDialog', function () {
fakeAnnotationUI = { frames: sinon.stub().returns([]) }; fakeAnnotationUI = { frames: sinon.stub().returns([]) };
angular.module('h', []) angular.module('h', [])
.directive('shareDialog', require('../share-dialog')) .component('shareDialog', require('../share-dialog'))
.value('annotationUI', fakeAnnotationUI) .value('annotationUI', fakeAnnotationUI)
.value('urlEncodeFilter', function (val) { return val; }); .value('urlEncodeFilter', function (val) { return val; });
angular.mock.module('h'); angular.mock.module('h');
......
...@@ -7,7 +7,7 @@ var util = require('./util'); ...@@ -7,7 +7,7 @@ var util = require('./util');
describe('sortDropdown', function () { describe('sortDropdown', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('sortDropdown', require('../sort-dropdown')); .component('sortDropdown', require('../sort-dropdown'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -7,7 +7,7 @@ var util = require('./util'); ...@@ -7,7 +7,7 @@ var util = require('./util');
describe('svgIcon', function () { describe('svgIcon', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('svgIcon', require('../svg-icon')); .component('svgIcon', require('../svg-icon'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -9,7 +9,7 @@ describe('tagEditor', function () { ...@@ -9,7 +9,7 @@ describe('tagEditor', function () {
before(function () { before(function () {
angular.module('app',[]) angular.module('app',[])
.directive('tagEditor', require('../tag-editor')); .component('tagEditor', require('../tag-editor'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -84,7 +84,7 @@ describe('threadList', function () { ...@@ -84,7 +84,7 @@ describe('threadList', function () {
before(function () { before(function () {
angular.module('app', []) angular.module('app', [])
.directive('threadList', threadList); .component('threadList', threadList);
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -11,7 +11,7 @@ describe('timestamp', function () { ...@@ -11,7 +11,7 @@ describe('timestamp', function () {
before(function () { before(function () {
angular.module('app',[]) angular.module('app',[])
.directive('timestamp', require('../timestamp')); .component('timestamp', require('../timestamp'));
}); });
beforeEach(function () { beforeEach(function () {
......
...@@ -126,31 +126,27 @@ function ThreadListController($scope, VirtualThreadList) { ...@@ -126,31 +126,27 @@ function ThreadListController($scope, VirtualThreadList) {
}; };
} }
module.exports = function () { module.exports = {
return { controller: ThreadListController,
bindToController: true, controllerAs: 'vm',
controller: ThreadListController, bindings: {
controllerAs: 'vm', /** The root thread to be displayed by the thread list. */
restrict: 'E', thread: '<',
scope: { showDocumentInfo: '<',
/** The root thread to be displayed by the thread list. */
thread: '<', /**
showDocumentInfo: '<', * Called when the user clicks a link to show an annotation that does not
* match the current filter.
/** */
* Called when the user clicks a link to show an annotation that does not onForceVisible: '&',
* match the current filter. /** Called when the user focuses an annotation by hovering it. */
*/ onFocus: '&',
onForceVisible: '&', /** Called when a user selects an annotation. */
/** Called when the user focuses an annotation by hovering it. */ onSelect: '&',
onFocus: '&', /** Called when a user toggles the expansion state of an annotation thread. */
/** Called when a user selects an annotation. */ onChangeCollapsed: '&',
onSelect: '&', /** Called to clear the current selection. */
/** Called when a user toggles the expansion state of an annotation thread. */ onClearSelection: '&',
onChangeCollapsed: '&', },
/** Called to clear the current selection. */ template: require('../templates/thread_list.html'),
onClearSelection: '&',
},
template: require('../templates/thread_list.html'),
};
}; };
...@@ -42,19 +42,15 @@ function TimestampController($scope, time) { ...@@ -42,19 +42,15 @@ function TimestampController($scope, time) {
}; };
} }
module.exports = function () { module.exports = {
return { controller: TimestampController,
bindToController: true, controllerAs: 'vm',
controller: TimestampController, bindings: {
controllerAs: 'vm', className: '<',
restrict: 'E', href: '<',
scope: { timestamp: '<',
className: '<', },
href: '<', template: ['<a class="{{vm.className}}" target="_blank" ng-title="vm.absoluteTimestamp"',
timestamp: '<', ' href="{{vm.href}}"',
}, '>{{vm.relativeTimestamp}}</a>'].join(''),
template: ['<a class="{{vm.className}}" target="_blank" ng-title="vm.absoluteTimestamp"',
' href="{{vm.href}}"',
'>{{vm.relativeTimestamp}}</a>'].join(''),
};
}; };
<div class="dropdown-menu-btn"> <div class="dropdown-menu-btn">
<button <button
class="dropdown-menu-btn__btn" class="dropdown-menu-btn__btn"
ng-bind="label" ng-bind="vm.label"
ng-click="vm.onClick($event)" ng-click="vm.onClick($event)"
ng-disabled="isDisabled"> ng-disabled="vm.isDisabled">
</button> </button>
<button <button
class="dropdown-menu-btn__dropdown-arrow" class="dropdown-menu-btn__dropdown-arrow"
title="{{dropdownMenuLabel}}" title="{{vm.dropdownMenuLabel}}"
ng-click="vm.toggleDropdown($event)"> ng-click="vm.toggleDropdown($event)">
<div class="dropdown-menu-btn__dropdown-arrow-separator"></div> <div class="dropdown-menu-btn__dropdown-arrow-separator"></div>
<div class="dropdown-menu-btn__dropdown-arrow-indicator"> <div class="dropdown-menu-btn__dropdown-arrow-indicator">
......
...@@ -3,16 +3,16 @@ ...@@ -3,16 +3,16 @@
type="button" type="button"
class="top-bar__btn" class="top-bar__btn"
dropdown-toggle dropdown-toggle
title="Sort by {{sortKey}}"> title="Sort by {{vm.sortKey}}">
<i class="h-icon-sort"></i> <i class="h-icon-sort"></i>
</button> </button>
<div class="dropdown-menu__top-arrow"></div> <div class="dropdown-menu__top-arrow"></div>
<ul class="dropdown-menu pull-right" role="menu"> <ul class="dropdown-menu pull-right" role="menu">
<li class="dropdown-menu__row" <li class="dropdown-menu__row"
ng-repeat="key in sortKeysAvailable" ng-repeat="key in vm.sortKeysAvailable"
ng-click="onChangeSortKey({sortKey: key})" ng-click="vm.onChangeSortKey({sortKey: key})"
><span class="dropdown-menu-radio" ><span class="dropdown-menu-radio"
ng-class="{'is-selected' : sortKey === key}" ng-class="{'is-selected' : vm.sortKey === key}"
></span><a class="dropdown-menu__link" href="">{{key}}</a></li> ></span><a class="dropdown-menu__link" href="">{{key}}</a></li>
</ul> </ul>
</span> </span>
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