diff --git a/platform/features/rtscrolling/README.md b/platform/features/rtscrolling/README.md
new file mode 100644
index 0000000000..955329129e
--- /dev/null
+++ b/platform/features/rtscrolling/README.md
@@ -0,0 +1,2 @@
+This is a placeholder implementation of a Scrolling List view
+which is compatible with realtime-only data.
diff --git a/platform/features/rtscrolling/bundle.json b/platform/features/rtscrolling/bundle.json
new file mode 100644
index 0000000000..b387a655a2
--- /dev/null
+++ b/platform/features/rtscrolling/bundle.json
@@ -0,0 +1,25 @@
+{
+ "name": "Scrolling Lists",
+ "description": "Time-ordered list of latest data.",
+ "extensions": {
+ "views": [
+ {
+ "key": "scrolling",
+ "name": "Scrolling",
+ "glyph": "5",
+ "description": "Scrolling list of data values.",
+ "templateUrl": "templates/rtscrolling.html",
+ "needs": [ "telemetry" ],
+ "delegation": true
+ }
+ ],
+ "controllers": [
+ {
+ "key": "RTScrollingListController",
+ "implementation": "RTScrollingListController.js",
+ "depends": [ "$scope", "telemetryHandler", "telemetryFormatter" ]
+ }
+ ]
+ }
+
+}
diff --git a/platform/features/rtscrolling/res/templates/rtscrolling.html b/platform/features/rtscrolling/res/templates/rtscrolling.html
new file mode 100644
index 0000000000..94d6343004
--- /dev/null
+++ b/platform/features/rtscrolling/res/templates/rtscrolling.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+ {{header}}
+ |
+
+
+
+
+
+
+ {{cell.text}}
+ |
+
+
+
+
+
+
+
diff --git a/platform/features/rtscrolling/src/DomainColumn.js b/platform/features/rtscrolling/src/DomainColumn.js
new file mode 100644
index 0000000000..c4f8a2a143
--- /dev/null
+++ b/platform/features/rtscrolling/src/DomainColumn.js
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * Open MCT Web, Copyright (c) 2014-2015, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT Web is licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ * Open MCT Web includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+/*global define,moment*/
+
+/**
+ * Module defining DomainColumn. Created by vwoeltje on 11/18/14.
+ */
+define(
+ [],
+ function () {
+ "use strict";
+
+ /**
+ * A column which will report telemetry domain values
+ * (typically, timestamps.) Used by the ScrollingListController.
+ *
+ * @constructor
+ * @param domainMetadata an object with the machine- and human-
+ * readable names for this domain (in `key` and `name`
+ * fields, respectively.)
+ * @param {TelemetryFormatter} telemetryFormatter the telemetry
+ * formatting service, for making values human-readable.
+ */
+ function DomainColumn(telemetryFormatter) {
+ return {
+ /**
+ * Get the title to display in this column's header.
+ * @returns {string} the title to display
+ */
+ getTitle: function () {
+ return "Time";
+ },
+ /**
+ * Get the text to display inside a row under this
+ * column.
+ * @returns {string} the text to display
+ */
+ getValue: function (domainObject, handle) {
+ return {
+ text: telemetryFormatter.formatDomainValue(
+ handle.getDomainValue(domainObject)
+ )
+ };
+ }
+ };
+ }
+
+ return DomainColumn;
+ }
+);
diff --git a/platform/features/rtscrolling/src/NameColumn.js b/platform/features/rtscrolling/src/NameColumn.js
new file mode 100644
index 0000000000..eb08ebc7ed
--- /dev/null
+++ b/platform/features/rtscrolling/src/NameColumn.js
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * Open MCT Web, Copyright (c) 2014-2015, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT Web is licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ * Open MCT Web includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+/*global define,Promise*/
+
+/**
+ * Module defining NameColumn. Created by vwoeltje on 11/18/14.
+ */
+define(
+ [],
+ function () {
+ "use strict";
+
+ /**
+ * A column which will report the name of the domain object
+ * which exposed specific telemetry values.
+ *
+ * @constructor
+ */
+ function NameColumn() {
+ return {
+ /**
+ * Get the title to display in this column's header.
+ * @returns {string} the title to display
+ */
+ getTitle: function () {
+ return "Name";
+ },
+ /**
+ * Get the text to display inside a row under this
+ * column. This returns the domain object's name.
+ * @returns {string} the text to display
+ */
+ getValue: function (domainObject) {
+ return {
+ text: domainObject.getModel().name
+ };
+ }
+ };
+ }
+
+ return NameColumn;
+ }
+);
diff --git a/platform/features/rtscrolling/src/RTScrollingListController.js b/platform/features/rtscrolling/src/RTScrollingListController.js
new file mode 100644
index 0000000000..65aaa9835b
--- /dev/null
+++ b/platform/features/rtscrolling/src/RTScrollingListController.js
@@ -0,0 +1,136 @@
+/*****************************************************************************
+ * Open MCT Web, Copyright (c) 2014-2015, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT Web is licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ * Open MCT Web includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+/*global define,Promise*/
+
+/**
+ * Module defining ListController. Created by vwoeltje on 11/18/14.
+ */
+define(
+ ["./NameColumn", "./DomainColumn", "./RangeColumn"],
+ function (NameColumn, DomainColumn, RangeColumn) {
+ "use strict";
+
+ var ROW_COUNT = 18;
+
+ /**
+ * The RTScrollingListController is responsible for populating
+ * the contents of the scrolling list view.
+ * @constructor
+ */
+ function RTScrollingListController($scope, telemetryHandler, telemetryFormatter) {
+ var handle,
+ lastUpdated = {},
+ lastIds = [],
+ columns = [],
+ headers = [],
+ rows = [];
+
+ function getTelemetryObjects() {
+ return handle ? handle.getTelemetryObjects() : [];
+ }
+
+ function idsChanged(telemetryObjects) {
+ function mismatch(id, index) {
+ return id !== telemetryObjects[index].getId();
+ }
+
+ return lastIds.length !== telemetryObjects.length ||
+ lastIds.some(mismatch);
+ }
+
+ function setupColumns(telemetryObjects) {
+ var id = $scope.domainObject && $scope.domainObject.getId(),
+ firstId =
+ telemetryObjects[0] && telemetryObjects[0].getId();
+
+ columns = [];
+
+ if (telemetryObjects > 1 || id !== firstId) {
+ columns.push(new NameColumn());
+ }
+ columns.push(new DomainColumn(telemetryFormatter));
+ columns.push(new RangeColumn());
+
+ headers = columns.map(function (column) {
+ return column.getTitle();
+ });
+ }
+
+ function updateObjects(telemetryObjects) {
+ if (idsChanged(telemetryObjects)) {
+ setupColumns(telemetryObjects);
+ lastIds = telemetryObjects.map(function (telemetryObject) {
+ return telemetryObject.getId();
+ });
+ }
+ }
+
+ function addRow(telemetryObject) {
+ var id = telemetryObject.getId(),
+ domainValue = handle.getDomainValue(telemetryObject);
+ if (lastUpdated[id] !== domainValue &&
+ domainValue !== undefined) {
+ rows.unshift(columns.map(function (column) {
+ return column.getValue(telemetryObject, handle);
+ }));
+ lastUpdated[id] = domainValue;
+ }
+ }
+
+ function updateValues() {
+ getTelemetryObjects().forEach(addRow);
+ }
+
+ function releaseSubscription() {
+ if (handle) {
+ handle.unsubscribe();
+ }
+ }
+
+ function makeSubscription(domainObject) {
+ releaseSubscription();
+ rows = [];
+ handle = telemetryHandler.handle(
+ domainObject,
+ updateValues,
+ true
+ );
+ }
+
+ $scope.$on("$destroy", releaseSubscription);
+
+ $scope.$watch("domainObject", makeSubscription);
+ $scope.$watch(getTelemetryObjects, updateObjects);
+
+ return {
+ rows: function () {
+ return rows;
+ },
+ headers: function () {
+ return headers;
+ }
+ };
+ }
+
+ return RTScrollingListController;
+ }
+);
diff --git a/platform/features/rtscrolling/src/RangeColumn.js b/platform/features/rtscrolling/src/RangeColumn.js
new file mode 100644
index 0000000000..255291ad2b
--- /dev/null
+++ b/platform/features/rtscrolling/src/RangeColumn.js
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * Open MCT Web, Copyright (c) 2014-2015, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT Web is licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ * Open MCT Web includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+/*global define,moment*/
+
+/**
+ * Module defining DomainColumn. Created by vwoeltje on 11/18/14.
+ */
+define(
+ [],
+ function () {
+ "use strict";
+
+ /**
+ * A column which will report telemetry range values
+ * (typically, measurements.) Used by the RTScrollingListController.
+ *
+ * @constructor
+ * @param rangeMetadata an object with the machine- and human-
+ * readable names for this range (in `key` and `name`
+ * fields, respectively.)
+ * @param {TelemetryFormatter} telemetryFormatter the telemetry
+ * formatting service, for making values human-readable.
+ */
+ function RangeColumn() {
+ return {
+ /**
+ * Get the title to display in this column's header.
+ * @returns {string} the title to display
+ */
+ getTitle: function () {
+ return "Value";
+ },
+ /**
+ * Get the text to display inside a row under this
+ * column.
+ * @returns {string} the text to display
+ */
+ getValue: function (domainObject, handle) {
+ return {
+ text: handle.getRangeValue(domainObject)
+ };
+ }
+ };
+ }
+
+ return RangeColumn;
+ }
+);