Merging in latest github master; resolved conflicts
This commit is contained in:
@@ -54,36 +54,38 @@ define(
|
||||
* @param {TemplateDefinition[]} templates an array of
|
||||
* template extensions
|
||||
*/
|
||||
function MCTInclude(templates, $sce) {
|
||||
function MCTInclude(templates, templateLinker) {
|
||||
var templateMap = {};
|
||||
|
||||
function link(scope, element) {
|
||||
var changeTemplate = templateLinker.link(
|
||||
scope,
|
||||
element,
|
||||
scope.key && templateMap[scope.key]
|
||||
);
|
||||
|
||||
scope.$watch('key', function (key) {
|
||||
changeTemplate(key && templateMap[key]);
|
||||
});
|
||||
}
|
||||
|
||||
// Prepopulate templateMap for easy look up by key
|
||||
templates.forEach(function (template) {
|
||||
var key = template.key,
|
||||
path = $sce.trustAsResourceUrl([
|
||||
template.bundle.path,
|
||||
template.bundle.resources,
|
||||
template.templateUrl
|
||||
].join("/"));
|
||||
var key = template.key;
|
||||
// First found should win (priority ordering)
|
||||
templateMap[key] = templateMap[key] || path;
|
||||
templateMap[key] =
|
||||
templateMap[key] || templateLinker.getPath(template);
|
||||
});
|
||||
|
||||
function controller($scope) {
|
||||
// Pass the template URL to ng-include via scope.
|
||||
$scope.inclusion = templateMap[$scope.key];
|
||||
}
|
||||
|
||||
return {
|
||||
// Only show at the element level
|
||||
restrict: "E",
|
||||
|
||||
// Use the included controller to populate scope
|
||||
controller: controller,
|
||||
link: link,
|
||||
|
||||
// Use ng-include as a template; "inclusion" will be the real
|
||||
// template path
|
||||
template: '<ng-include src="inclusion"></ng-include>',
|
||||
// May hide the element, so let other directives act first
|
||||
priority: -1000,
|
||||
|
||||
// Two-way bind key, ngModel, and parameters
|
||||
scope: { key: "=", ngModel: "=", parameters: "=" }
|
||||
|
||||
@@ -31,7 +31,6 @@ define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
|
||||
/**
|
||||
* Defines the mct-representation directive. This may be used to
|
||||
* present domain objects as HTML (with event wiring), with the
|
||||
@@ -55,7 +54,7 @@ define(
|
||||
* representation extensions
|
||||
* @param {ViewDefinition[]} views an array of view extensions
|
||||
*/
|
||||
function MCTRepresentation(representations, views, representers, $q, $sce, $log) {
|
||||
function MCTRepresentation(representations, views, representers, $q, templateLinker, $log) {
|
||||
var representationMap = {},
|
||||
gestureMap = {};
|
||||
|
||||
@@ -72,11 +71,7 @@ define(
|
||||
|
||||
// Get a path to a representation
|
||||
function getPath(representation) {
|
||||
return $sce.trustAsResourceUrl([
|
||||
representation.bundle.path,
|
||||
representation.bundle.resources,
|
||||
representation.templateUrl
|
||||
].join("/"));
|
||||
return templateLinker.getPath(representation);
|
||||
}
|
||||
|
||||
// Look up a matching representation for this domain object
|
||||
@@ -94,12 +89,16 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
function link($scope, element, attrs) {
|
||||
function link($scope, element, attrs, ctrl, transclude) {
|
||||
var activeRepresenters = representers.map(function (Representer) {
|
||||
return new Representer($scope, element, attrs);
|
||||
}),
|
||||
toClear = [], // Properties to clear out of scope on change
|
||||
counter = 0;
|
||||
counter = 0,
|
||||
couldRepresent = false,
|
||||
lastId,
|
||||
lastKey,
|
||||
changeTemplate = templateLinker.link($scope, element);
|
||||
|
||||
// Populate scope with any capabilities indicated by the
|
||||
// representation's extension definition
|
||||
@@ -144,21 +143,36 @@ define(
|
||||
});
|
||||
}
|
||||
|
||||
function unchanged(canRepresent, id, key) {
|
||||
return canRepresent &&
|
||||
couldRepresent &&
|
||||
id === lastId &&
|
||||
key === lastKey;
|
||||
}
|
||||
|
||||
// General-purpose refresh mechanism; should set up the scope
|
||||
// as appropriate for current representation key and
|
||||
// domain object.
|
||||
function refresh() {
|
||||
var domainObject = $scope.domainObject,
|
||||
representation = lookup($scope.key, domainObject),
|
||||
uses = ((representation || {}).uses || []);
|
||||
path = representation && getPath(representation),
|
||||
uses = ((representation || {}).uses || []),
|
||||
canRepresent = !!(path && domainObject),
|
||||
id = domainObject && domainObject.getId(),
|
||||
key = $scope.key;
|
||||
|
||||
if (unchanged(canRepresent, id, key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create an empty object named "representation", for this
|
||||
// representation to store local variables into.
|
||||
$scope.representation = {};
|
||||
|
||||
// Look up the actual template path, pass it to ng-include
|
||||
// via the "inclusion" field
|
||||
$scope.inclusion = representation && getPath(representation);
|
||||
// Change templates (passing in undefined to clear
|
||||
// if we don't have enough info to show a template.)
|
||||
changeTemplate(canRepresent ? path : undefined);
|
||||
|
||||
// Any existing representers are no longer valid; release them.
|
||||
destroyRepresenters();
|
||||
@@ -174,9 +188,14 @@ define(
|
||||
delete $scope[property];
|
||||
});
|
||||
|
||||
// To allow simplified change detection next time around
|
||||
couldRepresent = canRepresent;
|
||||
lastId = id;
|
||||
lastKey = key;
|
||||
|
||||
// Populate scope with fields associated with the current
|
||||
// domain object (if one has been passed in)
|
||||
if (domainObject) {
|
||||
if (canRepresent) {
|
||||
// Track how many representations we've made in this scope,
|
||||
// to ensure that the correct representations are matched to
|
||||
// the correct object/key pairs.
|
||||
@@ -233,9 +252,8 @@ define(
|
||||
// Handle Angular's linking step
|
||||
link: link,
|
||||
|
||||
// Use ng-include as a template; "inclusion" will be the real
|
||||
// template path
|
||||
template: '<ng-include src="inclusion"></ng-include>',
|
||||
// May hide the element, so let other directives act first
|
||||
priority: -1000,
|
||||
|
||||
// Two-way bind key and parameters, get the represented domain
|
||||
// object as "mct-object"
|
||||
|
||||
163
platform/representation/src/TemplateLinker.js
Normal file
163
platform/representation/src/TemplateLinker.js
Normal file
@@ -0,0 +1,163 @@
|
||||
/*****************************************************************************
|
||||
* 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";
|
||||
|
||||
/**
|
||||
* The `templateLinker` service is intended for internal use by
|
||||
* the `mct-include` and `mct-representation` directives. It is
|
||||
* used to support common behavior of directives; specifically,
|
||||
* loading templates and inserting them into a specified element,
|
||||
* and/or removing that element from the DOM when there is no
|
||||
* template to populate it with.
|
||||
*
|
||||
* @param {Function} $templateRequest Angular's `$templateRequest`
|
||||
* service
|
||||
* @param $sce Angular's `$sce` service
|
||||
* @param {Function} $compile Angular's `$compile` service
|
||||
* @param $log Angular's `$log` service
|
||||
* @private
|
||||
*/
|
||||
function TemplateLinker($templateRequest, $sce, $compile, $log) {
|
||||
this.$templateRequest = $templateRequest;
|
||||
this.$sce = $sce;
|
||||
this.$compile = $compile;
|
||||
this.$log = $log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a template from the given URL. This request will be handled
|
||||
* via `$templateRequest` to ensure caching et cetera.
|
||||
* @param {string} the URL for the template
|
||||
* @returns {Promise.<string>} a promise for the HTML content of
|
||||
* the template
|
||||
* @private
|
||||
*/
|
||||
TemplateLinker.prototype.load = function (templateUrl) {
|
||||
return this.$templateRequest(
|
||||
this.$sce.trustAsResourceUrl(templateUrl),
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a path to a template from an extension definition fo
|
||||
* a template, representation, or view.
|
||||
* @param {TemplateDefinition} extensionDefinition the definition
|
||||
* of the template/representation/view to resolve
|
||||
*/
|
||||
TemplateLinker.prototype.getPath = function (extensionDefinition) {
|
||||
return [
|
||||
extensionDefinition.bundle.path,
|
||||
extensionDefinition.bundle.resources,
|
||||
extensionDefinition.templateUrl
|
||||
].join('/');
|
||||
};
|
||||
|
||||
/**
|
||||
* Populate the given element with templates, within the given scope;
|
||||
* intended to support the `link` function of the supported directives.
|
||||
*
|
||||
* @param {Scope} scope the Angular scope to use when rendering
|
||||
* templates
|
||||
* @param element the jqLite-wrapped element into which templates
|
||||
* should be inserted
|
||||
* @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, templateUrl) {
|
||||
var activeElement = element,
|
||||
activeTemplateUrl,
|
||||
comment = this.$compile('<!-- hidden mct element -->')(scope),
|
||||
activeScope,
|
||||
self = this;
|
||||
|
||||
function destroyScope() {
|
||||
if (activeScope) {
|
||||
activeScope.$destroy();
|
||||
activeScope = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function removeElement() {
|
||||
if (activeElement !== comment) {
|
||||
destroyScope();
|
||||
activeElement.replaceWith(comment);
|
||||
activeElement = comment;
|
||||
}
|
||||
}
|
||||
|
||||
function addElement() {
|
||||
if (activeElement !== element) {
|
||||
activeElement.replaceWith(element);
|
||||
activeElement = element;
|
||||
activeElement.empty();
|
||||
}
|
||||
}
|
||||
|
||||
function populateElement(template) {
|
||||
destroyScope();
|
||||
activeScope = scope.$new(false);
|
||||
element.html(template);
|
||||
self.$compile(element.contents())(activeScope);
|
||||
}
|
||||
|
||||
function badTemplate(templateUrl) {
|
||||
self.$log.warn("Couldn't load template at " + templateUrl);
|
||||
removeElement();
|
||||
}
|
||||
|
||||
function changeTemplate(templateUrl) {
|
||||
if (templateUrl) {
|
||||
destroyScope();
|
||||
addElement();
|
||||
self.load(templateUrl).then(function (template) {
|
||||
// Avoid race conditions
|
||||
if (templateUrl === activeTemplateUrl) {
|
||||
populateElement(template);
|
||||
}
|
||||
}, function () {
|
||||
badTemplate(templateUrl);
|
||||
});
|
||||
} else {
|
||||
removeElement();
|
||||
}
|
||||
activeTemplateUrl = templateUrl;
|
||||
}
|
||||
|
||||
if (templateUrl) {
|
||||
changeTemplate(templateUrl);
|
||||
} else {
|
||||
removeElement();
|
||||
}
|
||||
|
||||
return changeTemplate;
|
||||
};
|
||||
|
||||
return TemplateLinker;
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user