Merge remote-tracking branch 'origin/open591' into open-master

This commit is contained in:
bwyu 2015-01-16 15:40:44 -08:00
commit af3175ca07
8 changed files with 179 additions and 23 deletions

View File

@ -3,23 +3,6 @@
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet"
type="text/css",
href="platform/commonUI/general/res/css/normalize.min.css">
<link rel="stylesheet"
type="text/css",
href="platform/commonUI/general/res/css/theme-espresso.css">
<link rel="stylesheet"
type="text/css",
href="platform/commonUI/general/res/css/items.css">
<link rel="stylesheet"
type="text/css",
href="platform/commonUI/general/res/css/tree.css">
<script type="text/javascript"
src="platform/framework/lib/require.js"
data-main="platform/framework/src/Main.js">

View File

@ -1,3 +1,17 @@
This directory contains bundles containing common user interface
elements of Open MCT Web; that is, the user interface for the application
as a whole (as opposed to for specific features) is implemented here.
# Extensions
This bundles adds a `stylesheets` extension category used to inject CSS
from bundles. These extensions are declaration-only (no scripted
implementation is needed or used); a single property, `stylesheetUrl`,
should be provided, with a path to the relevant CSS file (including
extension) relative to the resources directory for that bundle.
Links to these CSS files are appended to the head when the application
is started. These are added in standard priority order (see documentation
for the framework layer); the order of inclusion of style sheets can
change the way they are handled/understood by the browser, so priority
can be used to provide control over this order.

View File

@ -3,6 +3,30 @@
"description": "General UI elements, meant to be reused across modes.",
"resources": "res",
"extensions": {
"runs": [
{
"implementation": "StyleSheetLoader.js",
"depends": [ "stylesheets[]", "$document" ]
}
],
"stylesheets": [
{
"stylesheetUrl": "css/normalize.min.css",
"priority": "mandatory"
},
{
"stylesheetUrl": "css/theme-espresso.css",
"priority": 1000
},
{
"stylesheetUrl": "css/items.css",
"priority": 901
},
{
"stylesheetUrl": "css/tree.css",
"priority": 900
}
],
"templates": [
{
"key": "bottombar",

View File

@ -0,0 +1,44 @@
/*global define*/
define(
[],
function () {
"use strict";
/**
* The StyleSheetLoader adds links to style sheets exposed from
* various bundles as extensions of category `stylesheets`.
* @constructor
* @param {object[]} stylesheets stylesheet extension definitions
* @param $document Angular's jqLite-wrapped document element
*/
function StyleSheetLoader(stylesheets, $document) {
var head = $document.find('head'),
document = $document[0];
// Procedure for adding a single stylesheet
function addStyleSheet(stylesheet) {
// Create a link element, and construct full path
var link = document.createElement('link'),
path = [
stylesheet.bundle.path,
stylesheet.bundle.resources,
stylesheet.stylesheetUrl
].join("/");
// Initialize attributes on the link
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", path);
// Append the link to the head element
head.append(link);
}
// Add all stylesheets from extensions
stylesheets.forEach(addStyleSheet);
}
return StyleSheetLoader;
}
);

View File

@ -0,0 +1,57 @@
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
define(
["../src/StyleSheetLoader"],
function (StyleSheetLoader) {
"use strict";
describe("The style sheet loader", function () {
var testStyleSheets,
mockDocument,
mockPlainDocument,
mockHead,
mockElement,
loader;
beforeEach(function () {
var testBundle = {
path: "a/b",
resources: "c"
};
testStyleSheets = [
{ stylesheetUrl: "d.css", bundle: testBundle },
{ stylesheetUrl: "e.css", bundle: testBundle },
{ stylesheetUrl: "f.css", bundle: testBundle }
];
mockPlainDocument =
jasmine.createSpyObj("document", ["createElement"]);
mockDocument = [ mockPlainDocument ];
mockDocument.find = jasmine.createSpy("$document.find");
mockHead = jasmine.createSpyObj("head", ["append"]);
mockElement = jasmine.createSpyObj("link", ["setAttribute"]);
mockDocument.find.andReturn(mockHead);
mockPlainDocument.createElement.andReturn(mockElement);
loader = new StyleSheetLoader(testStyleSheets, mockDocument);
});
it("appends one link per stylesheet extension", function () {
expect(mockHead.append.calls.length)
.toEqual(testStyleSheets.length);
});
it("appends links to the head", function () {
expect(mockDocument.find).toHaveBeenCalledWith('head');
});
it("adjusts link locations", function () {
expect(mockElement.setAttribute)
.toHaveBeenCalledWith('href', "a/b/c/d.css");
});
});
}
);

View File

@ -9,5 +9,6 @@
"controllers/ViewSwitcherController",
"directives/MCTContainer",
"directives/MCTDrag",
"directives/MCTResize"
"directives/MCTResize",
"StyleSheetLoader"
]

View File

@ -72,6 +72,21 @@ define(
}
// Custom registration function for extensions of category "runs"
function registerRun(extension) {
if (typeof extension === 'function') {
// Prepend dependencies, and schedule to run
app.run((extension.depends || []).concat([extension]));
} else {
// If it's not a function, no implementation was given
$log.warn([
"Cannot register run extension from ",
(extension.bundle || {}).path,
"; no implementation."
].join(""));
}
}
// Custom registration function for extensions of category "route"
function registerRoute(extension) {
var route = Object.create(extension);
@ -121,6 +136,7 @@ define(
directives: mapUpon(new CustomRegistrar("directive")),
controllers: mapUpon(new CustomRegistrar("controller")),
services: mapUpon(new CustomRegistrar("service")),
runs: mapUpon(registerRun),
components: registerComponents
};
}

View File

@ -20,7 +20,8 @@ define(
"directive",
"service",
"constant",
"config"
"config",
"run"
]);
mockLog = jasmine.createSpyObj("$log", [
@ -39,6 +40,7 @@ define(
expect(customRegistrars.services).toBeTruthy();
expect(customRegistrars.routes).toBeTruthy();
expect(customRegistrars.constants).toBeTruthy();
expect(customRegistrars.runs).toBeTruthy();
});
it("invokes built-in functions on the app", function () {
@ -58,6 +60,11 @@ define(
expect(mockApp.constant.calls.length).toEqual(0);
customRegistrars.constants([{ key: "a", value: "b" }, { key: "b", value: "c" }, { key: "c", value: "d" }]);
expect(mockApp.constant.calls.length).toEqual(3);
expect(mockApp.run.calls.length).toEqual(0);
customRegistrars.runs([jasmine.createSpy("a"), jasmine.createSpy("a"), jasmine.createSpy("a")]);
expect(mockApp.run.calls.length).toEqual(3);
});
it("warns when keys are not defined, then skips", function () {
@ -81,6 +88,8 @@ define(
customRegistrars.constants([{ }, { }, { }]);
expect(mockApp.constant.calls.length).toEqual(0);
expect(mockLog.warn.calls.length).toEqual(9);
// Notably, keys are not needed for run calls
});
it("allows routes to be registered", function () {
@ -126,6 +135,14 @@ define(
expect(customRegistrars.components).toBeTruthy();
customRegistrars.components([]);
});
it("warns if no implementation is provided for runs", function () {
// Verify precondition
expect(mockLog.warn).not.toHaveBeenCalled();
customRegistrars.runs([{ something: "that is not a function"}]);
expect(mockLog.warn).toHaveBeenCalledWith(jasmine.any(String));
expect(mockApp.run).not.toHaveBeenCalled();
});
});
}
);