diff --git a/docs/src/guide/index.md b/docs/src/guide/index.md index 93cb95bb7a..7016462a5a 100644 --- a/docs/src/guide/index.md +++ b/docs/src/guide/index.md @@ -6,12 +6,13 @@ Victor Woeltjen September 23, 2015 Document Version 1.1 -Date | Version | Summary of Changes | Author -------------------- | --------- | ----------------------- | --------------- -April 29, 2015 | 0 | Initial Draft | Victor Woeltjen -May 12, 2015 | 0.1 | | Victor Woeltjen -June 4, 2015 | 1.0 | Name Changes | Victor Woeltjen -October 4, 2015 | 1.1 | Conversion to MarkDown | Andrew Henry +Date | Version | Summary of Changes | Author +------------------- | --------- | ------------------------- | --------------- +April 29, 2015 | 0 | Initial Draft | Victor Woeltjen +May 12, 2015 | 0.1 | | Victor Woeltjen +June 4, 2015 | 1.0 | Name Changes | Victor Woeltjen +October 4, 2015 | 1.1 | Conversion to MarkDown | Andrew Henry +April 5, 2016 | 1.2 | Added Mct-table directive | Andrew Henry # Introduction The purpose of this guide is to familiarize software developers with the Open @@ -1600,6 +1601,61 @@ there are items . ] } +## Table + +The `mct-table` directive provides a generic table component, with optional +sorting and filtering capabilities. The table can be pre-populated with data +by setting the `rows` parameter, and it can be updated in real-time using the +`add:row` and `remove:row` broadcast events. The table will expand to occupy +100% of the size of its containing element. The table is highly optimized for +very large data sets. + +### Events + +The table supports two events for notifying that the rows have changed. For +performance reasons, the table does not monitor the content of `rows` +constantly. + +* `add:row`: A `$broadcast` event that will notify the table that a new row +has been added to the table. + +eg. The code below adds a new row, and alerts the table using the `add:row` +event. Sorting and filtering will be applied automatically by the table component. + +``` +$scope.rows.push(newRow); +$scope.$broadcast('add:row', $scope.rows.length-1); +``` + +* `remove:row`: A `$broadcast` event that will notify the table that a row +should be removed from the table. + +eg. The code below removes a row from the rows array, and then alerts the table +to its removal. + +``` +$scope.rows.slice(5, 1); +$scope.$broadcast('remove:row', 5); +``` + +### Parameters + +* `headers`: An array of string values which will constitute the column titles + that appear at the top of the table. Corresponding values are specified in + the rows using the header title provided here. +* `rows`: An array of objects containing row values. Each element in the +array must be an associative array, where the key corresponds to a column header. +* `enableFilter`: A boolean that if true, will enable searching and result +filtering. When enabled, each column will have a text input field that can be +used to filter the table rows in real time. +* `enableSort`: A boolean determining whether rows can be sorted. If true, +sorting will be enabled allowing sorting by clicking on column headers. Only +one column may be sorted at a time. +* `autoScroll`: A boolean value that if true, will cause the table to automatically +scroll to the bottom as new data arrives. Auto-scroll can be disengaged manually +by scrolling away from the bottom of the table, and can also be enabled manually +by scrolling to the bottom of the table rows. + # Services The Open MCT Web platform provides a variety of services which can be retrieved diff --git a/platform/features/table/src/controllers/MCTTableController.js b/platform/features/table/src/controllers/MCTTableController.js index 477707e84b..7b4c748c7b 100644 --- a/platform/features/table/src/controllers/MCTTableController.js +++ b/platform/features/table/src/controllers/MCTTableController.js @@ -85,7 +85,7 @@ define( then: function (callback) { return fastPromise(callback(returnValue)); } - } + }; } /** diff --git a/platform/features/table/src/controllers/RealtimeTableController.js b/platform/features/table/src/controllers/RealtimeTableController.js index cf58cb236e..3f983207bc 100644 --- a/platform/features/table/src/controllers/RealtimeTableController.js +++ b/platform/features/table/src/controllers/RealtimeTableController.js @@ -68,6 +68,10 @@ define( RealtimeTableController.prototype = Object.create(TableController.prototype); + /** + * Overrides method on TelemetryTableController providing handling + * for realtime data. + */ RealtimeTableController.prototype.addRealtimeData = function() { var self = this, datum, @@ -89,7 +93,7 @@ define( self.$scope.rows.length - 1); } }); - } + }; return RealtimeTableController; } diff --git a/platform/features/table/src/controllers/TableOptionsController.js b/platform/features/table/src/controllers/TableOptionsController.js index 499e91efbc..a28411e7d0 100644 --- a/platform/features/table/src/controllers/TableOptionsController.js +++ b/platform/features/table/src/controllers/TableOptionsController.js @@ -55,8 +55,15 @@ define( $scope.columnsForm = {}; + function unlisten() { + self.listeners.forEach(function (listener) { + listener(); + }); + } + $scope.$watch('domainObject', function(domainObject) { - self.populateForm(domainObject.getModel()); + unlisten(); + self.populateForm(domainObject.getModel()); self.listeners.push(self.domainObject.getCapability('mutation').listen(function (model) { self.populateForm(model); @@ -79,11 +86,7 @@ define( /** * Destroy all mutation listeners */ - $scope.$on('$destroy', function () { - self.listeners.forEach(function (listener) { - listener(); - }); - }) + $scope.$on('$destroy', unlisten); } diff --git a/platform/features/table/src/controllers/TelemetryTableController.js b/platform/features/table/src/controllers/TelemetryTableController.js index b41cb940f5..36f54b1ac6 100644 --- a/platform/features/table/src/controllers/TelemetryTableController.js +++ b/platform/features/table/src/controllers/TelemetryTableController.js @@ -77,7 +77,7 @@ define( return listener && listener(); }); this.changeListeners = []; - } + }; /** * Defer registration of change listeners until domain object is @@ -156,7 +156,7 @@ define( if (handle) { handle.promiseTelemetryObjects().then(function () { - self.$scope.headers = [] + self.$scope.headers = []; self.$scope.rows = []; table.populateColumns(handle.getMetadata()); diff --git a/platform/features/table/src/directives/MCTTable.js b/platform/features/table/src/directives/MCTTable.js index 575e830395..2d61669a2e 100644 --- a/platform/features/table/src/directives/MCTTable.js +++ b/platform/features/table/src/directives/MCTTable.js @@ -12,6 +12,51 @@ define( * Defines a generic 'Table' component. The table can be populated * en-masse by setting the rows attribute, or rows can be added as * needed via a broadcast 'addRow' event. + * + * This directive accepts parameters specifying header and row + * content, as well as some additional options. + * + * Two broadcast events for notifying the table that the rows have + * changed. For performance reasons, the table does not monitor the + * content of `rows` constantly. + * - 'add:row': A $broadcast event that will notify the table that + * a new row has been added to the table. + * eg. + *

+         * $scope.rows.push(newRow);
+         * $scope.$broadcast('add:row', $scope.rows.length-1);
+         * 
+ * The code above adds a new row, and alerts the table using the + * add:row event. Sorting and filtering will be applied + * automatically by the table component. + * + * - 'remove:row': A $broadcast event that will notify the table that a + * row should be removed from the table. + * eg. + *

+         * $scope.rows.slice(5, 1);
+         * $scope.$broadcast('remove:row', 5);
+         * 
+ * The code above removes a row from the rows array, and then alerts + * the table to its removal. + * + * @memberof platform/features/table + * @param {string[]} headers The column titles to appear at the top + * of the table. Corresponding values are specified in the rows + * using the header title provided here. + * @param {Object[]} rows The row content. Each row is an object + * with key-value pairs where the key corresponds to a header + * specified in the headers parameter. + * @param {boolean} enableFilter If true, values will be searchable + * and results filtered + * @param {boolean} enableSort If true, sorting will be enabled + * allowing sorting by clicking on column headers + * @param {boolean} autoScroll If true, table will automatically + * scroll to the bottom as new data arrives. Auto-scroll can be + * disengaged manually by scrolling away from the bottom of the + * table, and can also be enabled manually by scrolling to the bottom of + * the table rows. + * * @constructor */ function MCTTable($timeout) { diff --git a/platform/features/table/test/controllers/TableOptionsControllerSpec.js b/platform/features/table/test/controllers/TableOptionsControllerSpec.js index 483696e0e2..fd6d8b43fe 100644 --- a/platform/features/table/test/controllers/TableOptionsControllerSpec.js +++ b/platform/features/table/test/controllers/TableOptionsControllerSpec.js @@ -63,6 +63,18 @@ define( controller = new TableOptionsController(mockScope); }); + it('Listens for changing domain object', function() { + expect(mockScope.$watch).toHaveBeenCalledWith('domainObject', jasmine.any(Function)); + }); + + it('On destruction of controller, destroys listeners', function() { + var unlistenFunc = jasmine.createSpy("unlisten"); + controller.listeners.push(unlistenFunc); + expect(mockScope.$on).toHaveBeenCalledWith('$destroy', jasmine.any(Function)); + mockScope.$on.mostRecentCall.args[1](); + expect(unlistenFunc).toHaveBeenCalled(); + }); + it('Registers a listener for mutation events on the object', function() { mockScope.$watch.mostRecentCall.args[1](mockDomainObject); expect(mockCapability.listen).toHaveBeenCalled();