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