From 3d59f6df0bc0a514845dbcce0be1f11be474dedc Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 28 Oct 2015 14:51:30 -0700 Subject: [PATCH] [Representation] Separate out template loading/linking ...from mct-include, to facilitate reuse for MCTRepresentation. --- platform/representation/bundle.json | 8 +- platform/representation/src/MCTInclude.js | 52 ++------- platform/representation/src/TemplateLinker.js | 106 ++++++++++++++++++ 3 files changed, 125 insertions(+), 41 deletions(-) create mode 100644 platform/representation/src/TemplateLinker.js diff --git a/platform/representation/bundle.json b/platform/representation/bundle.json index 6d782b5d95..51ad8a0af8 100644 --- a/platform/representation/bundle.json +++ b/platform/representation/bundle.json @@ -4,7 +4,7 @@ { "key": "mctInclude", "implementation": "MCTInclude.js", - "depends": [ "templates[]", "$sce", "$http", "$compile" ] + "depends": [ "templates[]", "templateLinker" ] }, { "key": "mctRepresentation", @@ -48,6 +48,12 @@ "key": "dndService", "implementation": "services/DndService.js", "depends": [ "$log" ] + }, + { + "key": "templateLinker", + "implementation": "TemplateLinker.js", + "depends": [ "$http", "$compile", "$log" ], + "comment": "For internal use by mct-include and mct-representation." } ], "actions": [ diff --git a/platform/representation/src/MCTInclude.js b/platform/representation/src/MCTInclude.js index 2abbd8ba9c..400a9d3ad8 100644 --- a/platform/representation/src/MCTInclude.js +++ b/platform/representation/src/MCTInclude.js @@ -54,59 +54,31 @@ define( * @param {TemplateDefinition[]} templates an array of * template extensions */ - function MCTInclude(templates, $sce, $http, $compile, $log) { + function MCTInclude(templates, templateLinker) { var templateMap = {}; - function loadTemplate(path) { - return $http.get(path).then(function (response) { - return $compile(response.data); - }); - } + function link(scope, element, attrs, ctrl, transclude) { + var changeTemplates = templateLinker.link( + scope, + element, + transclude + ); - function addTemplate(key, $scope, element) { - // Pass the template URL to ng-include via scope. - //$scope.inclusion = templateMap[$scope.key]; - // ...and add the template to the DOM. - templateMap[key].then(function (template) { - template($scope, function (innerClone) { - element.append(innerClone); - }); - }, function () { - $log.warn("Could not load template " + key); - delete templateMap[key]; - }); - } - - function link($scope, element, attrs, ctrl, transclude) { - var originalElement = element, - activeElement = element; - - $scope.$watch('key', function (key) { - if (templateMap[key]) { - transclude(function (clone) { - activeElement.replaceWith(clone); - activeElement = clone; - activeElement.empty(); - addTemplate(key, $scope, activeElement); - }); - } else if (activeElement !== originalElement) { - // If the key is unknown, remove it from DOM entirely. - activeElement.replaceWith(originalElement); - activeElement = originalElement; - } + scope.$watch('key', function (key) { + changeTemplates(templateMap[key]); }); } // Prepopulate templateMap for easy look up by key templates.forEach(function (template) { var key = template.key, - path = $sce.trustAsResourceUrl([ + path = [ template.bundle.path, template.bundle.resources, template.templateUrl - ].join("/")); + ].join("/"); // First found should win (priority ordering) - templateMap[key] = templateMap[key] || loadTemplate(path); + templateMap[key] = templateMap[key] || path; }); return { diff --git a/platform/representation/src/TemplateLinker.js b/platform/representation/src/TemplateLinker.js new file mode 100644 index 0000000000..0dfa180d51 --- /dev/null +++ b/platform/representation/src/TemplateLinker.js @@ -0,0 +1,106 @@ +/***************************************************************************** + * 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*/ + +define( + [], + function () { + "use strict"; + + /** + * Pre-fetches templates and allows them to be + * + * @param {string[]} URLs to all templates which should be loadable + * @param $http Angular's `$http` service + * @param {Function} $compile Angular's `$compile` service + * @param $log Angular's `$log` service + */ + function TemplateLinker($http, $compile, $log) { + this.templateMap = {}; + this.$http = $http; + this.$compile = $compile; + this.$log = $log; + } + + TemplateLinker.prototype.load = function (templateUrl) { + var $http = this.$http, + $compile = this.$compile, + $log = this.$log, + templateMap = this.templateMap; + + return (templateMap[templateUrl] = templateMap[templateUrl] || + $http.get(templateUrl).then(function (response) { + return $compile(response.data); + }, function () { + $log.warn("Couldn't load template at " + templateUrl); + templateMap[templateUrl] = undefined; + })); + }; + + /** + * @returns {Function} a function which can be called with a template + * URL to switch templates, or `undefined` to remove. + */ + TemplateLinker.prototype.link = function (scope, element, transclude) { + var originalElement = element, + activeElement = element, + self = this; + + function removeElement() { + if (activeElement !== originalElement) { + activeElement.replaceWith(originalElement); + activeElement = originalElement; + } + } + + function replaceElement(clone, template) { + activeElement.replaceWith(clone); + activeElement = clone; + activeElement.empty(); + template(scope, function (innerClone) { + clone.append(innerClone); + }); + } + + function applyTemplate(template) { + if (template) { + transclude(function (clone) { + replaceElement(clone, template); + }); + } else { + removeElement(); + } + } + + return function (templateUrl) { + if (templateUrl) { + self.load(templateUrl).then(applyTemplate); + } else { + removeElement(); + } + }; + }; + + return TemplateLinker; + } +); +