[Merge] Merge in open-master, resolve conflicts in _constants.scss

This commit is contained in:
Charles Hacskaylo 2015-06-10 14:04:48 -07:00
commit d7e43026cd
36 changed files with 845 additions and 121 deletions

3
.gitignore vendored
View File

@ -17,3 +17,6 @@ target
# Closed source libraries
closed-lib
# Node dependencies
node_modules

62
app.js Normal file
View File

@ -0,0 +1,62 @@
/*global require,process,console*/
/**
* Usage:
*
* npm install minimist express
* node app.js [options]
*/
(function () {
"use strict";
var BUNDLE_FILE = 'bundles.json',
options = require('minimist')(process.argv.slice(2)),
express = require('express'),
app = express(),
fs = require('fs'),
bundles = JSON.parse(fs.readFileSync(BUNDLE_FILE, 'utf8'));
// Defaults
options.port = options.port || options.p || 8080;
['include', 'exclude', 'i', 'x'].forEach(function (opt) {
options[opt] = options[opt] || [];
// Make sure includes/excludes always end up as arrays
options[opt] = Array.isArray(options[opt]) ?
options[opt] : [options[opt]];
});
options.include = options.include.concat(options.i);
options.exclude = options.exclude.concat(options.x);
// Show command line options
if (options.help || options.h) {
console.log("\nUsage: node app.js [options]\n");
console.log("Options:");
console.log(" --help, -h Show this message.");
console.log(" --port, -p <number> Specify port.");
console.log(" --include, -i <bundle> Include the specified bundle.");
console.log(" --exclude, -x <bundle> Exclude the specified bundle.");
console.log("");
process.exit(0);
}
// Handle command line inclusions/exclusions
bundles = bundles.concat(options.include);
bundles = bundles.filter(function (bundle) {
return options.exclude.indexOf(bundle) === -1;
});
bundles = bundles.filter(function (bundle, index) { // Uniquify
return bundles.indexOf(bundle) === index;
});
// Override bundles.json for HTTP requests
app.use('/' + BUNDLE_FILE, function (req, res) {
res.send(JSON.stringify(bundles));
});
// Expose everything else as static files
app.use(express['static']('.'));
// Finally, open the HTTP server
app.listen(options.port);
}());

View File

@ -16,8 +16,8 @@
"platform/features/scrolling",
"platform/forms",
"platform/persistence/queue",
"platform/persistence/elastic",
"platform/policy",
"example/persistence",
"example/generator"
]

View File

@ -122,6 +122,12 @@
"depends": [ "typeService", "dialogService", "creationService", "policyService" ]
}
],
"runs": [
{
"implementation": "windowing/WindowTitler.js",
"depends": [ "navigationService", "$rootScope", "$document" ]
}
],
"licenses": [
{
"name": "screenfull.js",

View File

@ -46,6 +46,7 @@ define(
function setNavigation(domainObject) {
$scope.navigatedObject = domainObject;
$scope.treeModel.selectedObject = domainObject;
navigationService.setNavigation(domainObject);
}
// Load the root object, put it in the scope.

View File

@ -45,8 +45,9 @@ define(
properties = type.getProperties();
function validateLocation(locatingObject) {
var locatingType = locatingObject.getCapability('type');
return policyService.allow(
var locatingType = locatingObject &&
locatingObject.getCapability('type');
return locatingType && policyService.allow(
"composition",
locatingType,
type

View File

@ -45,10 +45,12 @@ define(
// Setter for navigation; invokes callbacks
function setNavigation(value) {
navigated = value;
callbacks.forEach(function (callback) {
callback(value);
});
if (navigated !== value) {
navigated = value;
callbacks.forEach(function (callback) {
callback(value);
});
}
}
// Adds a callback

View File

@ -0,0 +1,52 @@
/*****************************************************************************
* 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";
/**
* Updates the title of the current window to reflect the name
* of the currently navigated-to domain object.
* @constructor
*/
function WindowTitler(navigationService, $rootScope, $document) {
// Look up name of the navigated domain object...
function getNavigatedObjectName() {
var navigatedObject = navigationService.getNavigation();
return navigatedObject && navigatedObject.getModel().name;
}
// Set the window title...
function setTitle(name) {
$document[0].title = name;
}
// Watch the former, and invoke the latter
$rootScope.$watch(getNavigatedObjectName, setTitle);
}
return WindowTitler;
}
);

View File

@ -62,6 +62,16 @@ define(
expect(callback).toHaveBeenCalledWith(testObject);
});
it("does not notify listeners when no changes occur", function () {
var testObject = { someKey: 42 },
callback = jasmine.createSpy("callback");
navigationService.addListener(callback);
navigationService.setNavigation(testObject);
navigationService.setNavigation(testObject);
expect(callback.calls.length).toEqual(1);
});
it("stops notifying listeners after removal", function () {
var testObject = { someKey: 42 },
callback = jasmine.createSpy("callback");

View File

@ -8,5 +8,6 @@
"creation/LocatorController",
"navigation/NavigateAction",
"navigation/NavigationService",
"windowing/FullscreenAction"
"windowing/FullscreenAction",
"windowing/WindowTitler"
]

View File

@ -0,0 +1,80 @@
/*****************************************************************************
* 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,describe,it,expect,beforeEach,waitsFor,jasmine*/
/**
* WindowTitlerSpec. Created by vwoeltje on 11/6/14.
*/
define(
["../../src/windowing/WindowTitler"],
function (WindowTitler) {
"use strict";
describe("The window titler", function () {
var mockNavigationService,
mockRootScope,
mockDocument,
mockDomainObject,
titler;
beforeEach(function () {
mockNavigationService = jasmine.createSpyObj(
'navigationService',
[ 'getNavigation' ]
);
mockRootScope = jasmine.createSpyObj(
'$rootScope',
[ '$watch' ]
);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['getModel']
);
mockDocument = [{}];
mockDomainObject.getModel.andReturn({ name: 'Test name' });
mockNavigationService.getNavigation.andReturn(mockDomainObject);
titler = new WindowTitler(
mockNavigationService,
mockRootScope,
mockDocument
);
});
it("listens for changes to the name of the navigated object", function () {
expect(mockRootScope.$watch).toHaveBeenCalledWith(
jasmine.any(Function),
jasmine.any(Function)
);
expect(mockRootScope.$watch.mostRecentCall.args[0]())
.toEqual('Test name');
});
it("sets the title to the name of the navigated object", function () {
mockRootScope.$watch.mostRecentCall.args[1]("Some name");
expect(mockDocument[0].title).toEqual("Some name");
});
});
}
);

View File

@ -43,6 +43,10 @@
{
"key": "indicator",
"templateUrl": "templates/indicator.html"
},
{
"key": "time-controller",
"templateUrl": "templates/controls/time-controller.html"
}
],
"controllers": [

View File

@ -302,7 +302,8 @@ label.form-control.checkbox input {
* at runtime from the About dialog for additional information.
*****************************************************************************/
/* line 22, ../sass/forms/_text-input.scss */
input[type="text"] {
input[type="text"],
input[type="date"] {
-moz-appearance: none;
-webkit-appearance: none;
-moz-border-radius: 3px;
@ -321,10 +322,32 @@ input[type="text"] {
outline: none;
padding: 0 3px; }
/* line 33, ../sass/forms/_mixins.scss */
input[type="text"].error {
input[type="text"].error,
input[type="date"].error {
background: rgba(255, 0, 0, 0.5); }
/* line 29, ../sass/forms/_text-input.scss */
input[type="text"].numeric {
/* line 61, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]:-moz-placeholder,
input[type="date"]:-moz-placeholder {
color: gray;
font-style: italic; }
/* line 64, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]::-moz-placeholder,
input[type="date"]::-moz-placeholder {
color: gray;
font-style: italic; }
/* line 67, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]:-ms-input-placeholder,
input[type="date"]:-ms-input-placeholder {
color: gray;
font-style: italic; }
/* line 56, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]::-webkit-input-placeholder,
input[type="date"]::-webkit-input-placeholder {
color: gray;
font-style: italic; }
/* line 34, ../sass/forms/_text-input.scss */
input[type="text"].numeric,
input[type="date"].numeric {
text-align: right; }
/*****************************************************************************

View File

@ -84,7 +84,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/* line 5, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 5, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
@ -105,38 +105,38 @@ time, mark, audio, video {
font-size: 100%;
vertical-align: baseline; }
/* line 22, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 22, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html {
line-height: 1; }
/* line 24, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 24, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
ol, ul {
list-style: none; }
/* line 26, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 26, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
table {
border-collapse: collapse;
border-spacing: 0; }
/* line 28, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 28, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle; }
/* line 30, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 30, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q, blockquote {
quotes: none; }
/* line 103, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 103, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none; }
/* line 32, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 32, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
a img {
border: none; }
/* line 116, ../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
/* line 116, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
display: block; }
@ -2050,7 +2050,11 @@ label.checkbox.custom {
margin-right: 50px; }
/******************************************************** SLIDERS */
/* line 444, ../sass/controls/_controls.scss */
/* line 439, ../sass/controls/_controls.scss */
.wrapper-slider {
position: relative; }
/* line 447, ../sass/controls/_controls.scss */
.slider .slot {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@ -2064,14 +2068,30 @@ label.checkbox.custom {
background-color: rgba(0, 0, 0, 0.4);
border-bottom: 1px solid rgba(77, 77, 77, 0.4);
border-right: 1px solid rgba(77, 77, 77, 0.4);
height: 50%;
height: auto;
width: auto;
position: absolute;
top: 25%;
top: 10%;
right: 0;
bottom: auto;
left: 0; }
/* line 455, ../sass/controls/_controls.scss */
bottom: 10%;
left: 0;
z-index: 0; }
/* line 459, ../sass/controls/_controls.scss */
.slider .slot .range {
background: rgba(0, 153, 204, 0.3);
cursor: ew-resize;
position: absolute;
top: 0;
right: auto;
bottom: 0;
left: auto;
height: auto;
width: auto;
z-index: 1; }
/* line 470, ../sass/controls/_controls.scss */
.slider .slot .range:hover {
background: rgba(0, 153, 204, 0.5); }
/* line 475, ../sass/controls/_controls.scss */
.slider .knob {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQwNDA0MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
@ -2092,14 +2112,17 @@ label.checkbox.custom {
border-top: 1px solid #666666;
color: #999;
display: inline-block;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
cursor: ew-resize;
position: absolute;
height: 100%;
height: auto;
width: 12px;
top: 0;
auto: 0;
bottom: auto;
left: auto; }
bottom: 0;
left: auto;
z-index: 2; }
/* line 148, ../sass/_mixins.scss */
.slider .knob:not(.disabled):hover {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2NjY2NiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
@ -2122,28 +2145,20 @@ label.checkbox.custom {
/* line 141, ../sass/_mixins.scss */
.slider .knob:not(.disabled):hover:before {
border-color: rgba(0, 153, 204, 0.9); }
/* line 466, ../sass/controls/_controls.scss */
/* line 487, ../sass/controls/_controls.scss */
.slider .knob.knob-l {
margin-left: -6px; }
/* line 488, ../sass/controls/_controls.scss */
.slider .knob.knob-r {
margin-right: -6px; }
/* line 489, ../sass/controls/_controls.scss */
.slider .knob:before {
top: 1px;
bottom: 3px;
left: 5px; }
/* line 473, ../sass/controls/_controls.scss */
.slider .range {
background: rgba(0, 153, 204, 0.6);
cursor: ew-resize;
position: absolute;
top: 0;
right: auto;
bottom: 0;
left: auto;
height: auto;
width: auto; }
/* line 483, ../sass/controls/_controls.scss */
.slider .range:hover {
background: rgba(0, 153, 204, 0.7); }
left: 45%; }
/******************************************************** BROWSER ELEMENTS */
/* line 491, ../sass/controls/_controls.scss */
/* line 501, ../sass/controls/_controls.scss */
::-webkit-scrollbar {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@ -2160,7 +2175,7 @@ label.checkbox.custom {
height: 10px;
width: 10px; }
/* line 497, ../sass/controls/_controls.scss */
/* line 507, ../sass/controls/_controls.scss */
::-webkit-scrollbar-thumb {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2NjY2NiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
@ -2178,7 +2193,7 @@ label.checkbox.custom {
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
border-top: 1px solid gray; }
/* line 504, ../sass/controls/_controls.scss */
/* line 514, ../sass/controls/_controls.scss */
::-webkit-scrollbar-thumb:hover {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzgwODA4MCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzczNzM3MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
@ -2187,7 +2202,7 @@ label.checkbox.custom {
background-image: -webkit-linear-gradient(#808080, #737373 20px);
background-image: linear-gradient(#808080, #737373 20px); }
/* line 509, ../sass/controls/_controls.scss */
/* line 519, ../sass/controls/_controls.scss */
::-webkit-scrollbar-corner {
background: rgba(0, 0, 0, 0.4); }
@ -2448,6 +2463,103 @@ label.checkbox.custom {
right: 0;
width: auto; }
/* line 1, ../sass/controls/_time-controller.scss */
.l-time-controller {
position: relative;
margin: 10px 0;
min-width: 400px; }
/* line 12, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-inputs-holder,
.l-time-controller .l-time-range-slider {
font-size: 0.8em; }
/* line 17, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-inputs-holder,
.l-time-controller .l-time-range-slider-holder,
.l-time-controller .l-time-range-ticks-holder {
margin-bottom: 5px;
position: relative; }
/* line 24, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-slider,
.l-time-controller .l-time-range-ticks {
overflow: visible;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: auto;
height: auto; }
/* line 30, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-inputs-holder {
height: 20px; }
/* line 34, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-slider,
.l-time-controller .l-time-range-ticks {
left: 90px;
right: 90px; }
/* line 40, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-slider-holder {
height: 30px; }
/* line 42, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-slider-holder .range-holder {
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
background: none;
border: none;
height: 75%; }
/* line 50, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-ticks-holder {
height: 10px; }
/* line 52, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-ticks-holder .l-time-range-ticks {
border-top: 1px solid #4d4d4d; }
/* line 54, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-ticks-holder .l-time-range-ticks .tick {
background-color: #4d4d4d;
border: none;
width: 1px;
margin-left: -1px; }
/* line 59, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-ticks-holder .l-time-range-ticks .tick:first-child {
margin-left: 0; }
/* line 62, ../sass/controls/_time-controller.scss */
.l-time-controller .l-time-range-ticks-holder .l-time-range-ticks .tick .l-time-range-tick-label {
color: gray;
font-size: 0.7em;
position: absolute;
margin-left: -25px;
text-align: center;
top: 10px;
width: 50px;
z-index: 2; }
/* line 76, ../sass/controls/_time-controller.scss */
.l-time-controller .knob {
width: 9px; }
/* line 78, ../sass/controls/_time-controller.scss */
.l-time-controller .knob .range-value {
position: absolute;
top: 50%;
margin-top: -7px;
white-space: nowrap;
width: 75px; }
/* line 87, ../sass/controls/_time-controller.scss */
.l-time-controller .knob:hover .range-value {
color: #0099cc; }
/* line 90, ../sass/controls/_time-controller.scss */
.l-time-controller .knob.knob-l {
margin-left: -4.5px; }
/* line 92, ../sass/controls/_time-controller.scss */
.l-time-controller .knob.knob-l .range-value {
text-align: right;
right: 14px; }
/* line 97, ../sass/controls/_time-controller.scss */
.l-time-controller .knob.knob-r {
margin-right: -4.5px; }
/* line 99, ../sass/controls/_time-controller.scss */
.l-time-controller .knob.knob-r .range-value {
left: 14px; }
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
@ -2697,7 +2809,8 @@ span.req {
* at runtime from the About dialog for additional information.
*****************************************************************************/
/* line 22, ../sass/forms/_text-input.scss */
input[type="text"] {
input[type="text"],
input[type="date"] {
-moz-appearance: none;
-webkit-appearance: none;
-moz-border-radius: 3px;
@ -2716,10 +2829,32 @@ input[type="text"] {
outline: none;
padding: 0 3px; }
/* line 33, ../sass/forms/_mixins.scss */
input[type="text"].error {
input[type="text"].error,
input[type="date"].error {
background: rgba(255, 0, 0, 0.5); }
/* line 29, ../sass/forms/_text-input.scss */
input[type="text"].numeric {
/* line 61, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]:-moz-placeholder,
input[type="date"]:-moz-placeholder {
color: gray;
font-style: italic; }
/* line 64, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]::-moz-placeholder,
input[type="date"]::-moz-placeholder {
color: gray;
font-style: italic; }
/* line 67, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]:-ms-input-placeholder,
input[type="date"]:-ms-input-placeholder {
color: gray;
font-style: italic; }
/* line 56, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
input[type="text"]::-webkit-input-placeholder,
input[type="date"]::-webkit-input-placeholder {
color: gray;
font-style: italic; }
/* line 34, ../sass/forms/_text-input.scss */
input[type="text"].numeric,
input[type="date"].numeric {
text-align: right; }
/*****************************************************************************

View File

@ -2,7 +2,7 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg>
<metadata>
Created by FontForge 20090622 at Tue Apr 28 20:52:23 2015
Created by FontForge 20090622 at Mon May 4 20:21:42 2015
By deploy user
Copyright 2015 Adobe Systems Incorporated. All rights reserved.
</metadata>
@ -224,6 +224,14 @@ d="M188 235h-160q-28 67 -28 140q0 156 110 265.5t265 109.5q88 0 164 -37t129 -103h
q39 0 66 27.5t27 66.5v93h2h186q39 0 66.5 27.5t27.5 66.5v94h1z" />
<glyph glyph-name="ecircumflex" unicode="&#xea;" horiz-adv-x="751"
d="M376 750v-375h375v-235q0 -58 -41.5 -99t-99.5 -41h-469q-58 0 -99 41t-41 99v469q0 58 41 99.5t99 41.5h235zM470 750l281 -281h-281v281z" />
<glyph glyph-name="edieresis" unicode="&#xeb;" horiz-adv-x="748"
d="M374 376l374 -375h-749zM374 750l374 -374h-749z" />
<glyph glyph-name="igrave" unicode="&#xec;" horiz-adv-x="748"
d="M748 750l-375 -750l-374 750h749z" />
<glyph glyph-name="iacute" unicode="&#xed;" horiz-adv-x="748"
d="M-1 0l375 750l374 -750h-749z" />
<glyph glyph-name="icircumflex" unicode="&#xee;" horiz-adv-x="748"
d="M748 750l-375 -375l-374 375h749zM748 375l-375 -374l-374 374h749z" />
<glyph glyph-name="fraction" unicode="&#x2044;" horiz-adv-x="761"
d="M380 751q158 0 269.5 -111.5t111.5 -268.5q0 -133 -82.5 -236.5t-209.5 -134.5l-4 491l-176 -490q-126 31 -207.5 134.5t-81.5 235.5q0 157 111.5 268.5t268.5 111.5zM168 488l55 20l-34 94l-56 -20zM410 530v100h-59v-100h59zM593 488l34 94l-55 20l-34 -94z" />
<glyph glyph-name="H.002" horiz-adv-x="803"

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -45,6 +45,7 @@
@import "controls/controls";
@import "controls/lists";
@import "controls/menus";
@import "controls/time-controller";
@import "forms/mixins";
@import "forms/elems";
@import "forms/validation";

View File

@ -436,52 +436,62 @@ label.checkbox.custom {
}
/******************************************************** SLIDERS */
.wrapper-slider {
position: relative;
}
.slider {
$knobH: 100%; //14px;
//$knobH: 70%; //14px;
$knobW: 12px;
$slotH: 50%;
$slotH: 80%;
$rangeO: 0.3;
.slot {
// @include border-radius($basicCr * .75);
// @include border-radius($basicCr * .75);
@include sliderTrack();
height: $slotH;
height: auto;
width: auto;
position: absolute;
top: ($knobH - $slotH) / 2;
//top: ($knobH - $slotH) / 2;
top: (100% - $slotH)/2;
right: 0;
bottom: auto;
bottom: (100% - $slotH)/2;
left: 0;
z-index: 0;
.range {
background: rgba($colorKey, $rangeO);
cursor: ew-resize;
position: absolute;
top: 0;
right: auto;
bottom: 0;
left: auto;
height: auto;
width: auto;
z-index: 1;
&:hover {
background: rgba($colorKey, $rangeO + 0.2);
}
}
}
.knob {
@include btnSubtle();
@include controlGrippy(rgba(black, 0.3), vertical, 1px, solid);
@include border-radius(2px);
cursor: ew-resize;
position: absolute;
height: $knobH;
height: auto;
width: $knobW;
top: 0;
auto: 0;
bottom: auto;
bottom: 0;
left: auto;
z-index: 2;
&.knob-l { margin-left: $knobW / -2; }
&.knob-r { margin-right: $knobW / -2; }
&:before {
top: 1px;
bottom: 3px;
left: ($knobW / 2) - 1;
}
}
.range {
background: rgba($colorKey, 0.6);
cursor: ew-resize;
position: absolute;
top: 0;
right: auto;
bottom: 0;
left: auto;
height: auto;
width: auto;
&:hover {
background: rgba($colorKey, 0.7);
//left: ($knobW / 2) - 1;
//margin-left: -1px;
left: 45%;
}
}
}

View File

@ -0,0 +1,104 @@
.l-time-controller {
$inputTxtW: 90px;
$knobW: 9px;
$r1H: 20px;
$r2H: 30px;
$r3H: 10px;
position: relative;
margin: $interiorMarginLg 0;
min-width: 400px;
.l-time-range-inputs-holder,
.l-time-range-slider {
font-size: 0.8em;
}
.l-time-range-inputs-holder,
.l-time-range-slider-holder,
.l-time-range-ticks-holder
{
margin-bottom: $interiorMargin;
position: relative;
}
.l-time-range-slider,
.l-time-range-ticks {
//@include test(red, 0.1);
@include absPosDefault(0, visible);
}
.l-time-range-inputs-holder {
height: $r1H;
}
.l-time-range-slider,
.l-time-range-ticks {
left: $inputTxtW; right: $inputTxtW;
}
.l-time-range-slider-holder {
height: $r2H;
.range-holder {
@include box-shadow(none);
background: none;
border: none;
height: 75%;
}
}
.l-time-range-ticks-holder {
height: $r3H;
.l-time-range-ticks {
border-top: 1px solid $colorInteriorBorder;
.tick {
background-color: $colorInteriorBorder;
border:none;
width: 1px;
margin-left: -1px;
&:first-child {
margin-left: 0;
}
.l-time-range-tick-label {
color: lighten($colorInteriorBorder, 20%);
font-size: 0.7em;
position: absolute;
margin-left: -0.5 * $tickLblW;
text-align: center;
top: $r3H;
width: $tickLblW;
z-index: 2;
}
}
}
}
.knob {
width: $knobW;
.range-value {
$w: 75px;
//@include test();
position: absolute;
top: 50%;
margin-top: -7px; // Label is 13px high
white-space: nowrap;
width: $w;
}
&:hover .range-value {
color: $colorKey;
}
&.knob-l {
margin-left: $knobW / -2;
.range-value {
text-align: right;
right: $knobW + $interiorMargin;
}
}
&.knob-r {
margin-right: $knobW / -2;
.range-value {
left: $knobW + $interiorMargin;
}
}
}
}

View File

@ -19,13 +19,18 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
input[type="text"] {
input[type="text"],
input[type="date"] {
@include nice-input();
&.filter {
&.ng-dirty {
// background: red;
}
}
@include input-placeholder {
color: darken($colorBodyFg, 10%);
font-style: italic;
}
&.filter {
&.ng-dirty {
// background: red;
}
}
&.numeric {
text-align: right;
}

View File

@ -0,0 +1,15 @@
<div ng-init="bcItems=[
{type: 'folder', glyph: 'F', name: 'My Items'},
{type: 'layout', glyph: 'L', name: 'Layout with a somewhat long name'},
{type: 'telemetry-panel', glyph: 't', name: 'Panel, My Panel'},
{type: 'telemetry-element', glyph: 'T', name: 'ACS-0009'}
]"></div>
<div class="l-breadcrumb s-breadcrumb">
<span
class="l-breadcrumb-item s-breadcrumb-item"
ng-repeat="bcItem in bcItems"
>
<a><span class="ui-symbol icon {{bcItem.type}}">{{bcItem.glyph}}</span>{{bcItem.name}}</a> <span class="ui-symbol sep">}</span>
</span>
</div>

View File

@ -0,0 +1,69 @@
<!--
NOTES
Ticks:
The thinking is to divide whatever the current time span is by 5,
and assign values accordingly to 5 statically-positioned ticks. So the tick x-position is a static percentage
of the total width available, and the labels change dynamically. This is consistent
with our current approach to the time axis of plots.
I'm keeping the number of ticks low so that when the view portal gets narrow,
the tick labels won't collide with each other. For extra credit, add/remove ticks as the user resizes the view area.
Note: this eval needs to be based on the whatever is containing the
time-controller component, not the whole browser window.
Range indicator and slider knobs:
The left and right properties used in .slider .range-holder and the .knobs are
CSS offsets from the left and right of their respective containers. You
may want or need to calculate those positions as pure offsets from the start datetime
(or left, as it were) and set them as left properties. No problem if so, but
we'll need to tweak the CSS tiny bit to get the center of the knobs to line up
properly on the range left and right bounds.
-->
<div ng-init="
notes = 'Temporarily using an array to populate ticks so I can see what I\'m doing';
ticks = [
'00:00',
'00:30',
'01:00',
'01:30',
'02:00'
];
"></div>
<div class="l-time-controller">
<div class="l-time-range-inputs-holder">
Start: <input type="date" />
End: <input type="date" />
</div>
<div class="l-time-range-slider-holder">
<div class="l-time-range-slider">
<div class="slider">
<div class="slot range-holder">
<div class="range" style="left: 0%; right: 30%;"></div>
</div>
<div class="knob knob-l" style="left: 0%;">
<div class="range-value">05/22 14:46</div>
</div>
<div class="knob knob-r" style="right: 30%;">
<div class="range-value">07/22 01:21</div>
</div>
</div>
</div>
</div>
<div class="l-time-range-ticks-holder">
<div class="l-time-range-ticks">
<div
ng-repeat="tick in ticks"
ng-style="{ left: $index * 25 + '%' }"
class="tick tick-x"
>
<span class="l-time-range-tick-label">{{tick}}</span>
</div>
</div>
</div>
</div>

View File

@ -12,6 +12,11 @@
"implementation": "CompositionMutabilityPolicy.js",
"message": "Objects of this type cannot be modified."
},
{
"category": "composition",
"implementation": "CompositionModelPolicy.js",
"message": "Objects of this type cannot contain other objects."
},
{
"category": "action",
"implementation": "ComposeActionPolicy.js",

View File

@ -0,0 +1,28 @@
/*global define*/
define(
[],
function () {
"use strict";
/**
* Policy allowing composition only for domain object types which
* have a composition property.
*/
function CompositionModelPolicy() {
return {
/**
* Is the type identified by the candidate allowed to
* contain the type described by the context?
*/
allow: function (candidate, context) {
return Array.isArray(
(candidate.getInitialModel() || {}).composition
);
}
};
}
return CompositionModelPolicy;
}
);

View File

@ -0,0 +1,26 @@
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
define(
["../src/CompositionModelPolicy"],
function (CompositionModelPolicy) {
"use strict";
describe("The composition model policy", function () {
var mockType,
policy;
beforeEach(function () {
mockType = jasmine.createSpyObj('type', ['getInitialModel']);
policy = new CompositionModelPolicy();
});
it("only allows composition for types which will have a composition property", function () {
mockType.getInitialModel.andReturn({});
expect(policy.allow(mockType)).toBeFalsy();
mockType.getInitialModel.andReturn({ composition: [] });
expect(policy.allow(mockType)).toBeTruthy();
});
});
}
);

View File

@ -35,7 +35,7 @@ define(
policy = new CompositionMutabilityPolicy();
});
it("only allows composition for types which will have a composition capability", function () {
it("only allows composition for types which can be created/modified", function () {
expect(policy.allow(mockType)).toBeFalsy();
mockType.hasFeature.andReturn(true);
expect(policy.allow(mockType)).toBeTruthy();

View File

@ -1,6 +1,7 @@
[
"CapabilityTable",
"ComposeActionPolicy",
"CompositionModelPolicy",
"CompositionMutabilityPolicy",
"CompositionPolicy",
"ContainmentTable"

View File

@ -77,7 +77,8 @@ define(
// Get the object's model and clone it, so the
// mutator function has a temporary copy to work with.
var model = domainObject.getModel(),
clone = JSON.parse(JSON.stringify(model));
clone = JSON.parse(JSON.stringify(model)),
useTimestamp = arguments.length > 1;
// Function to handle copying values to the actual
function handleMutation(mutationResult) {
@ -94,8 +95,7 @@ define(
if (model !== result) {
copyValues(model, result);
}
model.modified = (typeof timestamp === 'number') ?
timestamp : now();
model.modified = useTimestamp ? timestamp : now();
}
// Report the result of the mutation

View File

@ -20,27 +20,31 @@
at runtime from the About dialog for additional information.
-->
<div class="w1" ng-controller="TelemetryController as telemetry">
<!-- Dynamically set height based on number of rows desired. In current CSS, each row occupies 18px -->
<div class="w2"
ng-style="{ height: rows.length * 18 + 'px' }"
ng-controller="ScrollingListController">
<div class="tabular">
<div class="tr header">
<!-- Enable sorting by binding click handlers to the <em> element in each <th>. Note that CSS classes must be added dynamically to the current <th> that is sorting. For example, if sorting by ID: <div class="th sort asc"> or <div class="th sort desc">. -->
<div class="th" ng-repeat="header in headers">
<em>{{header}}</em>{{header}}
</div>
</div>
<div class="tr" ng-repeat="row in rows">
<div class="td" ng-repeat="cell in row">
{{cell}}
</div>
</div>
</div>
</div>
<div class="w2"
ng-controller="ScrollingListController">
<!-- To add filtering, add class 'filterable' to <table> and uncomment 2nd <tr> in <thead> -->
<table class="tabular">
<thead>
<tr>
<th ng-repeat="header in headers">
{{header}}
</th>
</tr>
<!--tr>
<th ng-repeat="header in headers">
<input type="text" />
</th>
</tr-->
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="cell in row">
{{cell}}
</td>
</tr>
</tbody>
</table>
</div>
</div>

View File

@ -38,7 +38,7 @@
placeholder="YYYY-DDD"
ng-pattern="/\d\d\d\d-\d\d\d/"
ng-model='datetime.date'
ng-required='true'/>
ng-required='ngRequired || partiallyComplete'/>
</span>
<span class='field control time sm'>
<input type='text'
@ -49,7 +49,7 @@
integer
ng-pattern='/\d+/'
ng-model="datetime.hour"
ng-required='true'/>
ng-required='ngRequired || partiallyComplete'/>
</span>
<span class='field control time sm'>
<input type='text'
@ -60,7 +60,7 @@
integer
ng-pattern='/\d+/'
ng-model="datetime.min"
ng-required='true'/>
ng-required='ngRequired || partiallyComplete'/>
</span>
<span class='field control time sm'>
<input type='text'
@ -71,7 +71,7 @@
integer
ng-pattern='/\d+/'
ng-model="datetime.sec"
ng-required='true'/>
ng-required='ngRequired || partiallyComplete'/>
</span>
<span class='field control timezone'>
UTC

View File

@ -52,15 +52,51 @@ define(
if (fullDateTime.isValid()) {
$scope.ngModel[$scope.field] = fullDateTime.valueOf();
}
// If anything is complete, say so in scope; there are
// ng-required usages that will update off of this (to
// allow datetime to be optional while still permitting
// incomplete input)
$scope.partiallyComplete =
Object.keys($scope.datetime).some(function (key) {
return $scope.datetime[key];
});
// Treat empty input as an undefined value
if (!$scope.partiallyComplete) {
$scope.ngModel[$scope.field] = undefined;
}
}
function updateDateTime(value) {
var m;
if (value !== undefined) {
m = moment.utc(value);
$scope.datetime = {
date: m.format(DATE_FORMAT),
hour: m.format("H"),
min: m.format("m"),
sec: m.format("s")
};
} else {
$scope.datetime = {};
}
}
// ...and update form values when actual field in model changes
$scope.$watch("ngModel[field]", updateDateTime);
// Update value whenever any field changes.
$scope.$watch("datetime.date", update);
$scope.$watch("datetime.hour", update);
$scope.$watch("datetime.min", update);
$scope.$watch("datetime.sec", update);
$scope.datetime = {};
// Initialize forms values
updateDateTime(
($scope.ngModel && $scope.field) ?
$scope.ngModel[$scope.field] : undefined
);
}
return DateTimeController;

View File

@ -57,6 +57,33 @@ define(
expect(mockScope.ngModel.test).toEqual(1417215313000);
});
it("reports when form input is partially complete", function () {
// This is needed to flag the control's state as invalid
// when it is partially complete without having it treated
// as required.
mockScope.ngModel = {};
mockScope.field = "test";
mockScope.datetime.date = "2014-332";
mockScope.datetime.hour = 22;
mockScope.datetime.min = 55;
// mockScope.datetime.sec = 13;
mockScope.$watch.mostRecentCall.args[1]();
expect(mockScope.partiallyComplete).toBeTruthy();
});
it("reports 'undefined' for empty input", function () {
mockScope.ngModel = { test: 12345 };
mockScope.field = "test";
mockScope.$watch.mostRecentCall.args[1]();
// Clear all inputs
mockScope.datetime = {};
mockScope.$watch.mostRecentCall.args[1]();
// Should have cleared out the time stamp
expect(mockScope.ngModel.test).toBeUndefined();
});
});
}
);

View File

@ -17,15 +17,18 @@
},
{
"key": "ELASTIC_ROOT",
"value": "/elastic"
"value": "/elastic",
"priority": "fallback"
},
{
"key": "ELASTIC_PATH",
"value": "mct/domain_object"
"value": "mct/domain_object",
"priority": "fallback"
},
{
"key": "ELASTIC_INDICATOR_INTERVAL",
"value": 15000
"value": 15000,
"priority": "fallback"
}
],
"indicators": [

View File

@ -160,6 +160,8 @@
<sourceJsFolder>${basedir}</sourceJsFolder>
<excludes>
<exclude>**/lib/**</exclude>
<exclude>app.js</exclude>
<exclude>node_modules/**/*</exclude>
</excludes>
</configuration>
<executions>