From 4122be021158cd4a6000a48f040ab56d2a255466 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Wed, 18 Mar 2015 11:22:05 -0400 Subject: [PATCH] Document multi-select-list directive --- awx/ui/static/js/docs.js | 2 +- awx/ui/static/js/forms/CustomInventory.js | 2 +- awx/ui/static/js/helpers/ConfigureTower.js | 2 +- awx/ui/static/js/helpers/CustomInventory.js | 2 +- awx/ui/static/js/helpers/Survey.js | 2 +- .../multi-select-list.controller.js | 109 ++++++++++++++- .../multi-select-list.directive.js | 71 +++++++++- .../multi-select-list/select-all.directive.js | 131 +++++++++++++++++- .../multi-select-list/select-all.partial.html | 2 +- .../select-list-item.directive.js | 18 +++ awx/ui/static/js/widgets/PortalJobs.js | 2 +- 11 files changed, 331 insertions(+), 12 deletions(-) diff --git a/awx/ui/static/js/docs.js b/awx/ui/static/js/docs.js index 9398fde08c..8f51c66bf2 100644 --- a/awx/ui/static/js/docs.js +++ b/awx/ui/static/js/docs.js @@ -1 +1 @@ -import 'tower/debug'; +import 'tower/shared/multi-select-list/main.js'; diff --git a/awx/ui/static/js/forms/CustomInventory.js b/awx/ui/static/js/forms/CustomInventory.js index 45f2279781..df9aaf9f23 100644 --- a/awx/ui/static/js/forms/CustomInventory.js +++ b/awx/ui/static/js/forms/CustomInventory.js @@ -8,7 +8,7 @@ */ /** * @ngdoc function - * @name forms.function:Organizations + * @name forms.function:CustomInventory * @description This form is for adding/editing an organization */ diff --git a/awx/ui/static/js/helpers/ConfigureTower.js b/awx/ui/static/js/helpers/ConfigureTower.js index 3bda266ca9..15142da257 100644 --- a/awx/ui/static/js/helpers/ConfigureTower.js +++ b/awx/ui/static/js/helpers/ConfigureTower.js @@ -3,7 +3,7 @@ */ /** * @ngdoc function - * @name helpers.function:Schedules + * @name helpers.function:ConfigureTower * @description * Schedules Helper * diff --git a/awx/ui/static/js/helpers/CustomInventory.js b/awx/ui/static/js/helpers/CustomInventory.js index 6ca3ba4834..b5a7167efb 100644 --- a/awx/ui/static/js/helpers/CustomInventory.js +++ b/awx/ui/static/js/helpers/CustomInventory.js @@ -3,7 +3,7 @@ */ /** * @ngdoc function - * @name helpers.function:Schedules + * @name helpers.function:CustomInventory * @description * Schedules Helper * diff --git a/awx/ui/static/js/helpers/Survey.js b/awx/ui/static/js/helpers/Survey.js index 06984e0402..b41b345eba 100644 --- a/awx/ui/static/js/helpers/Survey.js +++ b/awx/ui/static/js/helpers/Survey.js @@ -3,7 +3,7 @@ */ /** * @ngdoc function - * @name helpers.function:Schedules + * @name helpers.function:Survey * @description * Schedules Helper * diff --git a/awx/ui/static/js/shared/multi-select-list/multi-select-list.controller.js b/awx/ui/static/js/shared/multi-select-list/multi-select-list.controller.js index f7a8c52849..d55bd2e2e9 100644 --- a/awx/ui/static/js/shared/multi-select-list/multi-select-list.controller.js +++ b/awx/ui/static/js/shared/multi-select-list/multi-select-list.controller.js @@ -1,3 +1,12 @@ +/** + * @ngdoc object + * @name multiSelectList.controller:multiSelectList + * + * @description + * + * `multiSelectList` controller provides the API for the {@link multiSelectList.directive:multiSelectList `multiSelectList`} directive. The controller contains methods for selecting/deselecting items, controlling the extended selection, registering items to be selectable and emitting an event on the directive's `$scope`. + * + */ export default ['$scope', function ($scope) { $scope.items = []; @@ -7,10 +16,11 @@ export default ['$scope', deselectedItems: [] }; + // Makes $scope.selection.length an alias for $scope.selectedItems.length Object.defineProperty($scope.selection, 'length', { get: function() { - return this.items.length; + return this.selectedItems.length; } }); @@ -26,15 +36,41 @@ export default ['$scope', _items.pluck('value').difference($scope.selection.selectedItems) .value(); + /** + * + * @ngdoc event + * @name multiSelectList.selectionChanged + * @eventOf multiSelectList.directive:multiSelectList + * + */ $scope.$emit('multiSelectList.selectionChanged', $scope.selection); } + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#registerItem + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Prepares an object to be tracked in the select list. Returns the + * decorated item created by + * {@link multiSelectList.controller:multiSelectList#decorateItem `decorateItem`} + */ this.registerItem = function(item) { var decoratedItem = this.decorateItem(item); $scope.items = $scope.items.concat(decoratedItem); return decoratedItem; }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#deregisterItem + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Removes an item from the list; called if the item is removed from the display + * so that it is no longer tracked as a selectable item. + */ this.deregisterItem = function(leavingItem) { $scope.items = $scope.items.filter(function(item) { return leavingItem !== item; @@ -42,6 +78,18 @@ export default ['$scope', rebuildSelections(); }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#decorateItem + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * + * This decorates an item with an object that has an `isSelected` property. + * This value is used to determine the lists of selected and non-selected + * items to emit with the `multiSelectList.selectionChanged` + * event. + */ this.decorateItem = function(item) { return { isSelected: false, @@ -49,12 +97,31 @@ export default ['$scope', }; }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#selectAll + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Marks all items in the list as selected. + * Triggers {@link multiSelectList.selectionChanged `multiSelectList.selectionChanged`} + */ this.selectAll = function() { $scope.items.forEach(function(item) { item.isSelected = true; }); + rebuildSelections(); }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#deselectAll + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Marks all items in the list as not selected. + * Triggers {@link multiSelectList.selectionChanged `multiSelectList.selectionChanged`} + */ this.deselectAll = function() { $scope.items.forEach(function(item) { item.isSelected = false; @@ -64,19 +131,59 @@ export default ['$scope', }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#deselectAllExtended + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Disables extended selection. + * Triggers {@link multiSelectList.selectionChanged `multiSelectList.selectionChanged`} + */ this.deselectAllExtended = function(extendedLength) { $scope.selection.isExtended = false; + rebuildSelections(); }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#selectAllExtended + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Enables extended selection. + * Triggers {@link multiSelectList.selectionChanged `multiSelectList.selectionChanged`} + */ this.selectAllExtended = function(extendedLength) { $scope.selection.isExtended = true; + rebuildSelections(); }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#selectItem + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Marks an item as selected. + * Triggers {@link multiSelectList.selectionChanged `multiSelectList.selectionChanged`} + * + */ this.selectItem = function(item) { item.isSelected = true; rebuildSelections(); }; + /** + * @ngdoc + * @name multiSelectList.controller:multiSelectList#deregisterItem + * @methodOf multiSelectList.controller:multiSelectList + * + * @description + * Marks an item as not selected. + * Triggers {@link multiSelectList.selectionChanged `multiSelectList.selectionChanged`} + * + */ this.deselectItem = function(item) { item.isSelected = false; rebuildSelections(); diff --git a/awx/ui/static/js/shared/multi-select-list/multi-select-list.directive.js b/awx/ui/static/js/shared/multi-select-list/multi-select-list.directive.js index 0f80b99433..f65d8a2f4d 100644 --- a/awx/ui/static/js/shared/multi-select-list/multi-select-list.directive.js +++ b/awx/ui/static/js/shared/multi-select-list/multi-select-list.directive.js @@ -1,8 +1,75 @@ +/** + * @ngdoc overview + * @name multiSelectList + * @scope + * @description Does some stuff + * + * @ngdoc directive + * @name multiSelectList.directive:multiSelectList + * @description + * The `multiSelectList` directive works in conjunction with the + * `selectListItem` and (optionally) the `selectAll` directives to + * render checkboxes with list items and tracking the selected state + * of each item. The `selectListItem` directive renders a checkbox, + * and the `multiSelectList` directive tracks the selected state + * of list items. The `selectAll` directive renders a checkbox that + * will select/deselect all items in the list. + * + * + * This directive exposes a special object on its local scope called + * `selection` that is used to access the current selection state. + * The following properties on `selection` are available: + * + * | Property | Type | Details | + * |-------------------|-----------------|-------------------------------------------------------------| + * | `selectedItems` | {@type array} | The items that are currently selected | + * | `deselectedItem` | {@type array} | The items that are currently _not_ selected | + * | `isExtended` | {@type boolean} | Indicates that the user has requested an extended selection | + * | `length` | {@type number} | The length of the selected items array | + * + * Use the `multi-select-list` directive to indicate that you want + * to allow users to select items in a list. To display a checkbox + * next to each item, use the {@link multiSelectList.directive:selectListItem `select-list-item`} directive. + * + * # Rendering a basic multi-select list + * + * @example + * + * This example creates a list of names and then + * uses `multiSelectList` to make the names + * selectable: + * + + +
+
    +
  • + + {{item.name}} +
  • +
+
+
+ +
+ * +*/ import controller from './multi-select-list.controller'; export default - [ function() { - return { +[ function() { + return { restrict: 'A', scope: { }, diff --git a/awx/ui/static/js/shared/multi-select-list/select-all.directive.js b/awx/ui/static/js/shared/multi-select-list/select-all.directive.js index 2c7fa8fc1b..bbeee0e5bd 100644 --- a/awx/ui/static/js/shared/multi-select-list/select-all.directive.js +++ b/awx/ui/static/js/shared/multi-select-list/select-all.directive.js @@ -1,3 +1,122 @@ +/** + * @ngdoc directive + * @name multiSelectList.directive:selectAll + * @scope + * @restrict E + * + * @param {string} label The text that will appear next to the checkbox + * @param {number} itemsLength The number of displayed items in the list + * @param {number} extendedItemsLength The total number of items in the list used for extended mode (see below) + * @param {string_expression} extendedLabel A custom label to display when prompting the user to extend the selection; this is an expression so strings must be in single quotes ('), but you can use scope varibles here to display the count of items with the `extendedItemsLength` property + * @param {boolean_expression} selectionsEmpty An expression that evaluates to a truthy value used to disable + * the select all checkbox when the displayed list is empty + * + * @description + * + * Use the `select-all` directive as a child of a `multi-select-list` + * to present the user with a checkbox that, when checked, checks all + * `select-list-item` children, and when unchecked it unchecks them. + * + * + +
+
    +
  • + +
  • +
  • + + {{item.name}} +
  • +
+
+
+ + *
+ * + * ## Extended Selections + * + * In some cases the list items you are displaying are only a subset of + * a larger list (eg. using pagination or infinite scroll to seperate + * items). In these cases, when a user checks "select all", it may be + * useful to give them the option to also select all the remaining + * items in the list. + * + * This behavior is controlled by the `extendedItemsLength` property + * of this directive. Set it to the total length of items in the list. + * For example, if you have a list of 100 items, displayed 10 per page, + * then `itemsLength` would be 10 and `extendedItemsLength` would be 100. + * When the user checks "select all" in the above example, it will show + * a button prompting them to "Select all 100 items". When the user selects + * this option, the `select-all` directive tells the `multiSelectList` + * controller that the selection is "extended" to all the items in the list. + * Listeners to the `multiSelectList.selectionChanged` event can then use this + * flag to respond differently when all items are selected. + * + * + * + + angular.module('extendedSelectionExample', ['multiSelectList']) + .controller('namesController', ['$scope', function($scope) { + + var cleanup = $scope.$on('multiSelectList.selectionChanged', function(e, selection) { + $scope.isSelectionExtended = selection.isExtended; + }); + + $scope.$on('$destroy', cleanup); + + $scope.allNames = + [ { name: 'John' + }, + { name: 'Jared' + }, + { name: 'Joe' + }, + { name: 'James' + }, + { name: 'Matt' + }, + { name: 'Luke' + }, + { name: 'Chris' + } + ]; + + $scope.firstPageOfNames = + $scope.allNames.slice(0,3); + }]); + + +
+

Extended Selection

+
    +
  • + +
  • +
  • + + {{item.name}} +
  • +
+
+
+ *
+ */ // TODO: Extract to its own helper // Example: // template('shared/multi-select-list/select-all') @@ -17,14 +136,14 @@ export default label: '@', itemsLength: '=', extendedItemsLength: '=', - isSelectionExtended: '=', + extendedLabel: '&', isSelectionEmpty: '=selectionsEmpty' }, templateUrl: template('shared/multi-select-list/select-all'), link: function(scope, element, attrs, controller) { scope.label = scope.label || 'All'; - scope.selectExtendedLabel = scope.extendedLabel || 'Select all ' + scope.extendedItemsLength + ' items'; + scope.selectExtendedLabel = scope.extendedLabel() || 'Select all ' + scope.extendedItemsLength + ' items'; scope.deselectExtendedLabel = scope.deselectExtendedLabel || 'Deselect extra items'; scope.doSelectAll = function(e) { @@ -36,6 +155,12 @@ export default } } else { controller.deselectAll(); + + if (scope.isSelectionExtended) { + scope.deselectAllExtended(); + } + + scope.showExtendedMessage = false; } }; @@ -51,10 +176,12 @@ export default scope.selectAllExtended = function() { controller.selectAllExtended(scope.extendedItemsLength); + scope.isSelectionExtended = true; }; scope.deselectAllExtended = function() { controller.deselectAllExtended(scope.extendedItemsLength); + scope.isSelectionExtended = false; }; } diff --git a/awx/ui/static/js/shared/multi-select-list/select-all.partial.html b/awx/ui/static/js/shared/multi-select-list/select-all.partial.html index 9b5e62a3f9..8cf597c10c 100644 --- a/awx/ui/static/js/shared/multi-select-list/select-all.partial.html +++ b/awx/ui/static/js/shared/multi-select-list/select-all.partial.html @@ -13,6 +13,6 @@ diff --git a/awx/ui/static/js/shared/multi-select-list/select-list-item.directive.js b/awx/ui/static/js/shared/multi-select-list/select-list-item.directive.js index ecba972cc9..726fb044a0 100644 --- a/awx/ui/static/js/shared/multi-select-list/select-list-item.directive.js +++ b/awx/ui/static/js/shared/multi-select-list/select-list-item.directive.js @@ -1,3 +1,21 @@ +/** + * @ngdoc directive + * @name multiSelectList.directive:selectListItem + * @restrict E + * @scope + * @description + * + The `select-list-item` directive renders a checkbox for tracking + the state of a given item in a list. When the user checks the + checkbox it tells the `multi-select-list` controller to select + the item; when the user unchecks the checkbox it tells the controller + to deselect the item. + + @example + + For examples of using this directive, see {@link multiSelectList.directive:multiSelectList multiSelectList}. + + */ export default [ function() { return { diff --git a/awx/ui/static/js/widgets/PortalJobs.js b/awx/ui/static/js/widgets/PortalJobs.js index ffd8005aba..b51a388a7d 100644 --- a/awx/ui/static/js/widgets/PortalJobs.js +++ b/awx/ui/static/js/widgets/PortalJobs.js @@ -3,7 +3,7 @@ */ /** * @ngdoc function - * @name widgets.function:DashboardJobs + * @name widgets.function:PortalJobs * @description * */