diff --git a/docs/src/guide/index.md b/docs/src/guide/index.md index 7b35dd66cc..1469a05c71 100644 --- a/docs/src/guide/index.md +++ b/docs/src/guide/index.md @@ -1106,6 +1106,8 @@ property: * `stylesheetUrl`: Path and filename, including extension, for the stylesheet to include. This path is relative to the bundle's resources folder (by default, `res`) +* `theme`: Optional; if present, this stylesheet will only be included if this +value matches the `THEME` constant. To control the order of CSS files, use priority (see the section on Extension Definitions above.) @@ -2323,7 +2325,12 @@ default paths to reach external services are all correct. ### Configuration Constants + The following configuration constants are recognized by Open MCT Web bundles: +* Common UI elements - `platform/commonUI/general` + * `THEME`: A string identifying the current theme symbolically. Individual + stylesheets (the `stylesheets` extension category) may specify an optional + `theme` property which will be matched against this before inclusion. * CouchDB adapter - `platform/persistence/couch` * `COUCHDB_PATH`: URL or path to the CouchDB database to be used for domain object persistence. Should not include a trailing slash. diff --git a/platform/commonUI/general/bundle.json b/platform/commonUI/general/bundle.json index edaa8ec103..5976b912cc 100644 --- a/platform/commonUI/general/bundle.json +++ b/platform/commonUI/general/bundle.json @@ -18,7 +18,7 @@ "runs": [ { "implementation": "StyleSheetLoader.js", - "depends": [ "stylesheets[]", "$document" ] + "depends": [ "stylesheets[]", "$document", "THEME" ] } ], "stylesheets": [ @@ -194,6 +194,11 @@ { "key": "MCT_SCROLL_Y_ATTRIBUTE", "value": "mctScrollY" + }, + { + "key": "THEME", + "value": "unspecified", + "priority": "fallback" } ], "containers": [ diff --git a/platform/commonUI/general/src/StyleSheetLoader.js b/platform/commonUI/general/src/StyleSheetLoader.js index 19c0ffc291..9b64303df1 100644 --- a/platform/commonUI/general/src/StyleSheetLoader.js +++ b/platform/commonUI/general/src/StyleSheetLoader.js @@ -38,8 +38,9 @@ define( * @constructor * @param {object[]} stylesheets stylesheet extension definitions * @param $document Angular's jqLite-wrapped document element + * @param {string} activeTheme the theme in use */ - function StyleSheetLoader(stylesheets, $document) { + function StyleSheetLoader(stylesheets, $document, activeTheme) { var head = $document.find('head'), document = $document[0]; @@ -62,8 +63,15 @@ define( head.append(link); } + // Stylesheets which specify themes should only be applied + // when that theme has been declared. + function matchesTheme(stylesheet) { + return stylesheet.theme === undefined || + stylesheet.theme === activeTheme; + } + // Add all stylesheets from extensions - stylesheets.forEach(addStyleSheet); + stylesheets.filter(matchesTheme).forEach(addStyleSheet); } return StyleSheetLoader; diff --git a/platform/commonUI/general/test/StyleSheetLoaderSpec.js b/platform/commonUI/general/test/StyleSheetLoaderSpec.js index b2c1a7da93..c1db25fb0a 100644 --- a/platform/commonUI/general/test/StyleSheetLoaderSpec.js +++ b/platform/commonUI/general/test/StyleSheetLoaderSpec.js @@ -32,10 +32,11 @@ define( mockPlainDocument, mockHead, mockElement, + testBundle, loader; beforeEach(function () { - var testBundle = { + testBundle = { path: "a/b", resources: "c" }; @@ -72,6 +73,40 @@ define( expect(mockElement.setAttribute) .toHaveBeenCalledWith('href', "a/b/c/d.css"); }); + + describe("for themed stylesheets", function () { + var testTheme = "test-theme"; + + beforeEach(function () { + testStyleSheets = [{ + stylesheetUrl: "themed.css", + bundle: testBundle, + theme: testTheme + }, { + stylesheetUrl: "bad-theme.css", + bundle: testBundle, + theme: 'bad-theme' + }]; + + loader = new StyleSheetLoader( + testStyleSheets, + mockDocument, + testTheme + ); + }); + + it("includes matching themes", function () { + expect(mockElement.setAttribute) + .toHaveBeenCalledWith('href', "a/b/c/themed.css"); + }); + + it("excludes mismatching themes", function () { + expect(mockElement.setAttribute) + .not.toHaveBeenCalledWith('href', "a/b/c/bad-theme.css"); + }); + }); + + }); } ); diff --git a/platform/commonUI/themes/espresso/bundle.json b/platform/commonUI/themes/espresso/bundle.json index 37cab3e412..94c7259027 100644 --- a/platform/commonUI/themes/espresso/bundle.json +++ b/platform/commonUI/themes/espresso/bundle.json @@ -1,12 +1,18 @@ { - "name": "Espresso", - "description": "Espresso theme: dark and rich", - "extensions": { - "stylesheets": [ - { - "stylesheetUrl": "css/theme-espresso.css", - "priority": 1000 - } - ] - } -} \ No newline at end of file + "name": "Espresso", + "description": "Espresso theme: dark and rich", + "extensions": { + "stylesheets": [ + { + "stylesheetUrl": "css/theme-espresso.css", + "priority": 1000 + } + ], + "constants": [ + { + "key": "THEME", + "value": "espresso" + } + ] + } +} diff --git a/platform/commonUI/themes/snow/bundle.json b/platform/commonUI/themes/snow/bundle.json index 6db1ba21c1..6780df8e33 100644 --- a/platform/commonUI/themes/snow/bundle.json +++ b/platform/commonUI/themes/snow/bundle.json @@ -1,12 +1,18 @@ { - "name": "Sonw", - "description": "Snow theme: light and cool", - "extensions": { - "stylesheets": [ - { - "stylesheetUrl": "css/theme-snow.css", - "priority": 1000 - } - ] - } -} \ No newline at end of file + "name": "Snow", + "description": "Snow theme: light and cool", + "extensions": { + "stylesheets": [ + { + "stylesheetUrl": "css/theme-snow.css", + "priority": 1000 + } + ], + "constants": [ + { + "key": "THEME", + "value": "snow" + } + ] + } +}