/***************************************************************************** * Open MCT, Copyright (c) 2014-2017, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * Open MCT 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 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. *****************************************************************************/ /** * This bundle implements Browse mode. * @namespace platform/commonUI/browse */ define( [], function () { /** * The BrowseController is used to populate the initial scope in Browse * mode. It loads the root object from the objectService and makes it * available in the scope for Angular template's; this is the point at * which Angular templates first have access to the domain object * hierarchy. * * @memberof platform/commonUI/browse * @constructor */ function BrowseController( $scope, $route, $location, objectService, navigationService, urlService, defaultPath ) { var initialPath = ($route.current.params.ids || defaultPath).split("/"); var currentIds; $scope.treeModel = { selectedObject: undefined, onSelection: function (object) { navigationService.setNavigation(object, true); }, allowSelection: function (object) { return navigationService.shouldNavigate(); } }; function idsForObject(domainObject) { return urlService .urlForLocation("", domainObject) .replace('/', ''); } // Find an object in an array of objects. function findObject(domainObjects, id) { var i; for (i = 0; i < domainObjects.length; i += 1) { if (domainObjects[i].getId() === id) { return domainObjects[i]; } } } // helper, fetch a single object from the object service. function getObject(id) { return objectService.getObjects([id]) .then(function (results) { return results[id]; }); } // recursively locate and return an object inside of a container // via a path. If at any point in the recursion it fails to find // the next object, it will return the parent. function findViaComposition(containerObject, path) { var nextId = path.shift(); if (!nextId) { return containerObject; } return containerObject.useCapability('composition') .then(function (composees) { var nextObject = findObject(composees, nextId); if (!nextObject) { return containerObject; } if (!nextObject.hasCapability('composition')) { return nextObject; } return findViaComposition(nextObject, path); }); } function navigateToObject(desiredObject) { $scope.navigatedObject = desiredObject; $scope.treeModel.selectedObject = desiredObject; currentIds = idsForObject(desiredObject); $route.current.pathParams.ids = currentIds; $location.path('/browse/' + currentIds); } function navigateToPath(path) { return getObject('ROOT') .then(function (root) { return findViaComposition(root, path); }) .then(function (object) { navigationService.setNavigation(object); }); } getObject('ROOT') .then(function (root) { $scope.domainObject = root; navigateToPath(initialPath); }); // Handle navigation events from view service. Only navigates // if path has changed. function navigateDirectlyToModel(domainObject) { var newIds = idsForObject(domainObject); if (currentIds !== newIds) { currentIds = newIds; navigateToObject(domainObject); } } // Listen for changes in navigation state. navigationService.addListener(navigateDirectlyToModel); // Listen for route changes which are caused by browser events // (e.g. bookmarks to pages in OpenMCT) and prevent them. Instead, // navigate to the path ourselves, which results in it being // properly set. $scope.$on('$routeChangeStart', function (event, route) { if (route.$$route === $route.current.$$route && route.pathParams.ids !== $route.current.pathParams.ids) { event.preventDefault(); navigateToPath(route.pathParams.ids.split('/')); } }); // Clean up when the scope is destroyed $scope.$on("$destroy", function () { navigationService.removeListener(navigateDirectlyToModel); }); } return BrowseController; } );