[Representation] Separate out template loading/linking

...from mct-include, to facilitate reuse for MCTRepresentation.
This commit is contained in:
Victor Woeltjen 2015-10-28 14:51:30 -07:00
parent b4a44dee8f
commit 3d59f6df0b
3 changed files with 125 additions and 41 deletions

View File

@ -4,7 +4,7 @@
{ {
"key": "mctInclude", "key": "mctInclude",
"implementation": "MCTInclude.js", "implementation": "MCTInclude.js",
"depends": [ "templates[]", "$sce", "$http", "$compile" ] "depends": [ "templates[]", "templateLinker" ]
}, },
{ {
"key": "mctRepresentation", "key": "mctRepresentation",
@ -48,6 +48,12 @@
"key": "dndService", "key": "dndService",
"implementation": "services/DndService.js", "implementation": "services/DndService.js",
"depends": [ "$log" ] "depends": [ "$log" ]
},
{
"key": "templateLinker",
"implementation": "TemplateLinker.js",
"depends": [ "$http", "$compile", "$log" ],
"comment": "For internal use by mct-include and mct-representation."
} }
], ],
"actions": [ "actions": [

View File

@ -54,59 +54,31 @@ define(
* @param {TemplateDefinition[]} templates an array of * @param {TemplateDefinition[]} templates an array of
* template extensions * template extensions
*/ */
function MCTInclude(templates, $sce, $http, $compile, $log) { function MCTInclude(templates, templateLinker) {
var templateMap = {}; var templateMap = {};
function loadTemplate(path) { function link(scope, element, attrs, ctrl, transclude) {
return $http.get(path).then(function (response) { var changeTemplates = templateLinker.link(
return $compile(response.data); scope,
}); element,
} transclude
);
function addTemplate(key, $scope, element) { scope.$watch('key', function (key) {
// Pass the template URL to ng-include via scope. changeTemplates(templateMap[key]);
//$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;
}
}); });
} }
// Prepopulate templateMap for easy look up by key // Prepopulate templateMap for easy look up by key
templates.forEach(function (template) { templates.forEach(function (template) {
var key = template.key, var key = template.key,
path = $sce.trustAsResourceUrl([ path = [
template.bundle.path, template.bundle.path,
template.bundle.resources, template.bundle.resources,
template.templateUrl template.templateUrl
].join("/")); ].join("/");
// First found should win (priority ordering) // First found should win (priority ordering)
templateMap[key] = templateMap[key] || loadTemplate(path); templateMap[key] = templateMap[key] || path;
}); });
return { return {

View File

@ -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;
}
);